SMTP
SMTP is a second front door onto POST /v1/send. Apps
that only have host / port / user / password fields (Twenty, WordPress,
Laravel, PHPMailer) can send through Letter without calling HTTP. The mail
uses the same project API key, the same verified sending domain, the same
suppression and plan gates, and lands in the same transactional log.
If you can use an SDK or POST /v1/send, do that. SMTP exists for software
you do not control.
Prerequisites
- A project API key (
lt_live_…) from Settings → Project tokens - A verified sending domain (Letter subdomain or your own)
Settings
| Host | smtp.letter.app |
| Port | 465 (implicit TLS). Alternate: 2465 if 465 is blocked. |
| Username | letter |
| Password | your project API key |
| Encryption | SSL / TLS |
There is no separate SMTP user. Identity is the API key.
Port 587 (STARTTLS) is not on v1. Twenty, WordPress, and Laravel all accept 465 with SSL.
Quick start
Point the app at the table above. The From address must be on this project’s verified sending domain (the same From you configured under Settings → Domain).
Twenty
In Settings → Admin Panel → EMAIL_SETTINGS:
EMAIL_DRIVER=smtp
EMAIL_SMTP_HOST=smtp.letter.app
EMAIL_SMTP_PORT=465
EMAIL_SMTP_USER=letter
EMAIL_SMTP_PASSWORD=lt_live_…
EMAIL_SMTP_NO_TLS=false
EMAIL_FROM_ADDRESS=hello@your-verified-domain
EMAIL_FROM_NAME=You
WordPress (WP Mail SMTP)
Mailer: Other SMTP. Host smtp.letter.app, encryption SSL, port
465, Auto TLS on, authentication on, username letter, password the API
key.
Laravel
MAIL_MAILER=smtp
MAIL_HOST=smtp.letter.app
MAIL_PORT=465
MAIL_USERNAME=letter
MAIL_PASSWORD=lt_live_…
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=hello@your-verified-domain
MAIL_FROM_NAME="${APP_NAME}"
What happens on send
- AUTH PLAIN/LOGIN — username must be
letter; password is the project key. - One
RCPT TO. A second recipient is refused (552). - The MIME body is flattened to
to,from,subject,html/text, and optional headers, then posted to/v1/sendwithtag: smtp. - The
Toaddress is upserted as a contact (source: "api"). An existing contact is reused. A new address when the workspace is at its contact cap is refused (554, same as403 contact_quota_exceededon HTTP). - The monthly email cap, daily shared-domain cap, suppressions, and suspension gates are the HTTP ones.
Attachments are refused (552), not dropped. v1 is SES Simple: one
recipient, html/text, no Cc/Bcc. Bodies are capped at 500 KB.
Idempotency
Set X-Letter-Idempotency-Key or Letter-Idempotency-Key (8–128 characters)
to make client retries safe. If neither is present, a Message-ID in that
length range is used.
Custom headers
Passed through to /v1/send (max 20). Envelope headers and
List-Unsubscribe* are reserved — same list as the HTTP route.
Errors
SMTP reply codes are the HTTP errors in envelope form. Look up the send in the dashboard; there are no SMTP server logs.
| SMTP | HTTP | When |
|---|---|---|
535 | 401 | Bad username or API key |
550 | 403 suppressed | Recipient bounced, complained, or was admin-suppressed |
554 | 403 / 400 | Contact cap, email quota, daily cap, suspended, billing, bad From, validation |
552 | — | Second recipient, attachment, or oversized body |
421 | 429 | Rate limited. Retry later |
451 | 5xx | Temporary failure. Retry with the same idempotency key |
403 reasons from the API (contact_quota_exceeded, email_quota_exceeded,
daily_cap, billing_required, account_suspended, suppressed) apply
unchanged.
FAQ
Where do I see the email? The project’s Transactional page, or
GET /v1/projects/{slug}/messages / letter messages list. SMTP sends are
tagged smtp.
Do rate limits apply? Yes — the same per-key limit as /v1/send.
Can I use SMTP from Rails? Prefer the Ruby SDK
ActionMailer :letter delivery method. SMTP is for apps you cannot change.
Do you offer IMAP or inbound SMTP? No.