Documentation
Everything you need to send email through Atmosphere Mail.
Quick start
- Sign in with your atproto handle at /enroll. Any handle works (
person.bsky.social, your custom domain, anything that resolves to a DID). - Enroll a domain you want to send from. Prove ownership via DNS and receive an API key.
- Add the DKIM and SPF records to that domain's DNS. See DNS records.
- Send via SMTP or the HTTP API.
New domains go through a warming period that protects the shared IP's reputation.
Identity and sending domains
Your atproto identity and your sending domain are two different things.
- Your identity is a DID, addressed by a handle. The handle can be a bsky.social address (
person.bsky.social), a custom domain (scottlanoue.com), or any handle that resolves to a DID. This is what you sign in with. - Your sending domains are the domains you want email to come from. They live separately from your identity. You enroll them one at a time and prove ownership via DNS.
So someone with the handle person.bsky.social can sign up and send mail from news.example.com, billing.example.com, or any other domain they control. The handle and the sending domain do not need to match.
One DID can hold up to two sending domains during the alpha. To enroll an additional domain, sign into /account and use "Add another domain". See Multiple domains below for what changes.
Guides
- HTTP Send API: a JSON endpoint for sending from any language or runtime.
- SMTP submission: connect any app that speaks SMTP.
- DNS records: DKIM, SPF, DMARC, and how to verify alignment.
- Warming tiers: rate limits, durations, and what happens at each stage.
- Reply forwarding: how replies to your sent mail reach you.
- Bounces and suppression: DSN format, the suppression list, and bounce-rate auto-suspension.
- Atproto labels: what the labeler publishes and how to query it.
- Troubleshooting: common errors and how to fix them.
Authentication
Both SMTP and the HTTP API use the same credentials: your DID as the username and your API key as the password. Your API key was shown once during enrollment. If you've lost it, sign into /account to regenerate it.
API keys are bcrypt-hashed at rest; the relay never stores plaintext keys.
Multiple domains
One atproto DID can enroll multiple sending domains. During the alpha the limit is two domains per DID; this will lift later.
- Each domain has its own DKIM keys, its own SPF and DMARC records, and its own warming tier (each starts cold).
- Each domain has its own reply-forwarding mailbox. See Reply forwarding.
- The API key is per-DID, not per-domain. The same key authenticates sends from any of your enrolled domains; the relay routes by the
From:address. - Send activity, bounce rates, and suppression lists are tracked per-DID across all your domains. A high bounce rate on one domain affects your overall standing.
Add a domain at /account under "Add another domain".
Tracking message status
Per-message delivery status (sent, deferred, bounced) lives in /account after you sign in. There is no programmatic API for individual message status today.
Aggregate metrics are available via two API-key-authenticated endpoints:
GET /member/status?did=...: total sends, bounces, and current rate-limit budget.GET /member/deliverability?did=...: rolling 14-day bounce count and complaint count.
Both return JSON. A per-message lookup endpoint may land later; the data is recorded in the relay's store, just not exposed.
Reliability
When the relay accepts a message (250 OK on SMTP or 200 on the HTTP API), the message is fsynced to disk before the response returns. Power loss or a relay crash between acceptance and delivery cannot lose the message.
Retries
If the recipient's MX returns a transient error (4xx) or the connection fails, the relay retries automatically:
- Backoff: 1 minute, then 5, 15, 30, 60 minutes
- Maximum 5 attempts before the message bounces back as a DSN
Across deploys
Relay restarts do not lose accepted mail. Listeners close first so no new messages are accepted mid-shutdown; in-flight deliveries finish; anything still queued is on disk in the spool. The new binary reloads the spool on startup and resumes delivery.
Status vocabulary
You'll see these states in /account for each message:
| Status | Meaning |
|---|---|
accepted |
Queued for delivery |
deferred |
Recipient MX returned 4xx; will retry |
sent |
Delivered to recipient MX |
bounced |
Max retries exceeded or recipient returned 5xx; DSN sent to your domain |
When to retry from your side
Retry on 5xx responses or 451 (queue full / transient submission error). Don't retry on 4xx permanent errors like DOMAIN_MISMATCH or INVALID_DID. Fix the input instead. See the error code table for what's retryable.
Source
Atmosphere Mail is open source under AGPL-3.0. Browse the code at tangled.org.