# comail ZDS uses [Comail](https://comail.at/) as its default email delivery provider. Comail is cooperative email infrastructure for atproto identities: a sending domain is enrolled under an atproto DID, and requests to send mail authenticate with both an API key and that DID. ZDS uses Comail for account and identity email tokens: - account email confirmation - email update confirmation - PLC operation confirmation These emails are user-triggered transactional messages. ZDS sends them through Comail's HTTP Send API with `category: "verification"`, which tells Comail the message is part of an auth or verification flow rather than broadcast mail. ## identity model ZDS keeps the PDS service identity separate from the Comail sending identity. - `ZDS_SERVER_DID` is the PDS service DID, usually `did:web:`. - `ZDS_COMAIL_DID` is the atproto DID that enrolled the sending domain with Comail. - `ZDS_EMAIL_FROM` is the bare sender address on that enrolled domain. For the hosted `pds.zat.dev` deployment: ```sh ZDS_MAIL_PROVIDER=comail ZDS_COMAIL_DID=did:plc:mkqt76xvfgxuemlwlx6ruc3w ZDS_EMAIL_FROM=noreply@zat.dev ``` That means mail is sent as `noreply@zat.dev`, authorized by the `zat.dev` account DID. It does not mean mail is sent by `did:web:pds.zat.dev`. ## configuration The Comail provider uses these ZDS settings: ```sh ZDS_MAIL_PROVIDER=comail ZDS_COMAIL_API_KEY=... ZDS_COMAIL_DID=did:plc:... ZDS_EMAIL_FROM=noreply@example.com ``` `ZDS_EMAIL_FROM` must be a bare email address. Comail rejects display-name forms such as: ```sh ZDS_EMAIL_FROM='ZDS ' ``` That form is accepted by some providers, including Resend, but Comail returns `INVALID_REQUEST`. ## request shape All provider-specific behavior stays in `src/core/mail.zig`. The rest of ZDS calls `mail.sendCode(...)` and does not know which provider is active. For Comail, ZDS sends: ```http POST https://smtp.atmos.email/v1/send Authorization: Bearer X-Atmos-DID: Content-Type: application/json ``` with JSON shaped like: ```json { "from": "noreply@example.com", "to": "user@example.com", "subject": "Confirm email", "text": "Hello handle. Your email confirmation code is ABCDE-FGHIJ. This code will expire in ten minutes.", "category": "verification" } ``` ZDS does not log successful message bodies or tokens in production. If Comail returns a non-2xx response, ZDS logs the provider, status code, and a short response excerpt so operators can diagnose configuration or delivery issues. ## local development Local development can run without Comail secrets. When `ZDS_PUBLIC_URL` is a localhost URL and mail config is incomplete, ZDS logs the generated code instead of sending mail. For non-local deployments, incomplete mail config is a hard failure. This is intentional: a production PDS should not tell clients that verification mail was sent when the provider was not configured. ## operational notes - The sending domain must be enrolled in Comail before production delivery will work. - New domains start in Comail's warming tiers. Verification emails are low volume, but repeated manual retries can still consume the early hourly/daily allowance. - Keep `ZDS_COMAIL_API_KEY` in deployment secrets, not in committed files. - If Bluesky reports "Failed to send email", check Fly logs for `mail delivery failed provider=comail`. Useful Comail docs: - [HTTP Send API](https://comail.at/docs/send-api) - [DNS records](https://comail.at/docs/dns) - [Warming tiers](https://comail.at/docs/warming)