SMTP Submission
Connect any app or service that speaks SMTP.
Connection details
| Host | smtp.atmos.email |
| Port | 587 (STARTTLS) |
| Security | STARTTLS required |
| Username | Your atproto handle (e.g. yourdomain.com) |
| Password | Your API key (atmos_…) |
How it works
- Your app connects to
smtp.atmos.email:587and upgrades to TLS via STARTTLS. - Your app authenticates with PLAIN or LOGIN using your handle and API key.
- Your app sends the message using standard SMTP commands (MAIL FROM, RCPT TO, DATA).
- The relay applies dual DKIM signatures, checks warming limits, and delivers to the recipient's MX.
Configuration examples
Nodemailer (Node.js)
const transporter = nodemailer.createTransport({
host: "smtp.atmos.email",
port: 587,
secure: false, // STARTTLS
auth: {
user: "yourdomain.com",
pass: "atmos_your-api-key",
},
});
Python (smtplib)
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "you@yourdomain.com"
msg["To"] = "friend@example.com"
msg["Subject"] = "Hello"
msg.set_content("Sent via Atmosphere Mail")
with smtplib.SMTP("smtp.atmos.email", 587) as server:
server.starttls()
server.login("yourdomain.com", "atmos_your-api-key")
server.send_message(msg)
Go (net/smtp)
auth := smtp.PlainAuth("", "yourdomain.com", "atmos_your-api-key", "smtp.atmos.email")
err := smtp.SendMail("smtp.atmos.email:587", auth, "you@yourdomain.com",
[]string{"friend@example.com"}, []byte(msg))
PDS configuration
If you run a self-hosted atproto PDS that sends email (verification, notifications), point its SMTP config at the relay:
PDS_EMAIL_SMTP_URL=smtps://yourdomain.com:atmos_your-api-key@smtp.atmos.email:587
The relay handles DKIM signing. No additional DNS records beyond the ones from enrollment.
Notes
- The
MAIL FROMdomain must match a domain enrolled under the authenticated DID. See Identity and sending domains. - Port 465 (implicit TLS) is unavailable. Use port 587 with STARTTLS.
- Messages hit warming tier rate limits during the first 14 days.
- The relay adds
List-Unsubscribeheaders to non-transactional mail per RFC 8058. One-click unsubscribes add the recipient to your suppression list. - Prefer the HTTP API from serverless environments (Cloudflare Workers, Vercel Edge) where raw TCP sockets are unavailable.
- Accepted messages (
250 OK) are fsynced before the response. The relay retries failed deliveries. See Reliability for the retry schedule and status vocabulary. - Stuck? See Troubleshooting.