Email Services¶
The hosted email providers people actually reach for, pre-assessed. The pattern across this whole page: every one of these services publishes an SMTP endpoint, and every SMTP route works today with an ordinary transport = 'smtp' profile — the recipes below are p_profile blocks ready for create_profile(). Several also publish REST APIs; where one is a good webhook-transport fit it's noted as a planned adapter, but no email service on this page requires waiting for one. (Wire-level detail per provider lives in pg_relay's provider recipe chapters; this page is the notifier-side summary.)
For all of them: the message block is the standard one (to/cc/bcc, subject, body_text/body_html, attachments), secrets are _env: references, and the universal first stumble is sender verification — each service rejects a from it hasn't verified, as a permanent failure. Verify the domain or address in the provider's console before the first send.
Amazon SES — works today¶
{"host": "email-smtp.ap-southeast-2.amazonaws.com", "port": 587,
"security": "starttls", "auth": "plain",
"username": "AKIAIOSFODNN7EXAMPLE", "password": "_env:SES_SMTP_PASSWORD",
"from": "notify@yourdomain.com", "timeout_seconds": 30}
Host is region-specific (email-smtp.<region>.amazonaws.com — use the region your identities live in; 465 + tls also answers). The credentials are SMTP credentials generated in the SES console (SMTP settings → Create SMTP credentials) — derived from an IAM user but not that user's access key pair. New accounts start in the sandbox (verified recipients only) — request production access first. Throttling arrives as 4xx (transient, retries handle it); an unverified sender as 5xx (permanent).
SES's REST API is excluded, permanently: every request must be SigV4-signed — rolling per-request HMACs, not a static credential any auth style can carry. Nothing is lost; the SMTP endpoint reaches the same infrastructure and quotas.
SendGrid — works today (SMTP); REST assessed¶
{"host": "smtp.sendgrid.net", "port": 587, "security": "starttls", "auth": "plain",
"username": "apikey", "password": "_env:SENDGRID_API_KEY",
"from": "notify@yourdomain.com"}
The username is the literal string apikey. The password is an API key created with the Mail Send permission. Its v3 REST API is a clean webhook fit (bearer auth; success is an empty 202 with the id in the x-message-id response header) — a viable future adapter, though SMTP loses you nothing today.
Postmark — works today (SMTP); REST assessed¶
{"host": "smtp.postmarkapp.com", "port": 587, "security": "starttls", "auth": "plain",
"username": "_env:POSTMARK_SERVER_TOKEN", "password": "_env:POSTMARK_SERVER_TOKEN",
"from": "notify@yourdomain.com"}
Postmark's quirk: the Server API Token is both username and password — the same _env: variable twice is correct (_env: resolution covers every profile string, not just password). Port 2525 answers if 587 is blocked. from must be a confirmed Sender Signature; transactional mail belongs on the default outbound message stream.
Mailgun — works today (SMTP only)¶
{"host": "smtp.mailgun.org", "port": 587, "security": "starttls", "auth": "plain",
"username": "postmaster@mg.yourdomain.com", "password": "_env:MAILGUN_SMTP_PASSWORD",
"from": "notify@mg.yourdomain.com"}
EU-region domains use smtp.eu.mailgun.org — the region belongs to the sending domain, so match it. Credentials are per-domain SMTP credentials (Domain settings → SMTP credentials), not your account password or API key. Mailgun's REST API is excluded: it takes multipart/form-data, which the webhook transport deliberately doesn't speak — SMTP is the route, and it reaches the same domains, suppressions, and analytics.
SMTP2GO — works today (SMTP); REST assessed¶
{"host": "mail.smtp2go.com", "port": 2525, "security": "starttls", "auth": "plain",
"username": "_env:SMTP2GO_USERNAME", "password": "_env:SMTP2GO_PASSWORD",
"from": "notify@yourdomain.com"}
Its signature feature is port spread — 2525, 587, 8025 (STARTTLS), 465 (tls) — there's nearly always one a firewall allows. Credentials are a dashboard-created SMTP user, distinct from your login. Its v3 REST API (custom X-Smtp2go-Api-Key header) is also a clean webhook fit.
Resend — works today (SMTP and REST adapter)¶
{"host": "smtp.resend.com", "port": 587, "security": "starttls", "auth": "plain",
"username": "resend", "password": "_env:RESEND_API_KEY",
"from": "notify@yourdomain.com"}
Username is the literal string resend; the password is the API key. Until the sending domain is verified in the Resend dashboard, only its onboarding test address is accepted.
Resend's REST API is also a shipped adapter: create_profile(..., p_transport => 'webhook', p_provider => 'resend', ...) with the same API key as a bearer secret — full setup in Resend, Telnyx, and PagerDuty. SMTP vs REST is a per-profile choice with the same message semantics; the REST route additionally records Resend's email id as the provider reference and reads Resend's own error messages into status_detail.
Gmail / Google Workspace — all SMTP routes work today; REST transport planned¶
Three ways into a Google mailbox, per pg_relay's Gmail guidance:
- App Password — works today. A mailbox with 2-Step Verification generates an App Password; ordinary
auth: "plain"againstsmtp.gmail.com:587,starttls. Zero ceremony, unless Workspace policy disables App Passwords. - Workspace SMTP relay by source IP — works today.
smtp-relay.gmail.comconfigured (admin console) to accept your fixed egress IP:auth: "none",security: "starttls". - OAuth2 SMTP — works today.
auth: "oauth2"with the per-mailbox refresh-token grant — full worked example in SMTP Endpoints. (ThegmailREST transport remains planned — see the overview — but it sends byte-for-byte the same message the SMTP routes do, so nothing is waiting on it.)
Either way from must be the mailbox itself or one of its configured Send As aliases, and Google's daily sending caps apply — a mailbox is not a transactional email service. Volume anywhere near the cap is the signal to use SES, ACS, or another verified-domain service instead.
Microsoft 365 / Exchange Online — shipped¶
The m365 transport (Graph API, client-credentials OAuth2) is a first-class transport of this extension — full setup in Microsoft 365 Endpoints. The SMTP AUTH OAuth2 alternative route into Exchange Online also works today — the client-credentials example in SMTP Endpoints is exactly that.
Azure Communication Services — SMTP relay works today; REST transport planned¶
Azure's purpose-built transactional email service — the natural recommendation when Gmail's caps or a mailbox-shaped sender stop being appropriate and your stack is Azure-friendly. pg_relay's Processor reaches it two ways. The ACS SMTP relay works today: auth: "oauth2" with the client-credentials grant — the ACS-specific values slot into the same recipe as Exchange Online's, worked in SMTP Endpoints. The acs REST transport (pg_relay's chapter) remains planned — it needs this extension's transport list to grow a fourth value; its practical additions over the relay are the operation id as provider reference and both bodies sent when text and HTML are both supplied.
Next: Chat Platforms — Slack (shipped), and the two platforms most often asked about after it.