The SMTP driver
On this page
The SMTP driver sends your app's email through a mail server you name. A
connection with driver: Driver.smtp gives:
host:, the server's name, written out or read from a setting built onText;port:, which is 587 when you leave it out: the submission port, which Cloudflare Workers allows;credential: { username: password: }, each read from a setting, the password from a secret one.
A mistake in any of them is connection.key_invalid,
connection.key_missing or connection.value_invalid
(Connecting in app.jadpo).
application { connections: { mail: { driver: Driver.smtp host: config.smtp_host port: 587 credential: { username: config.smtp_username password: config.smtp_password } } } email: { connection: mail from: config.mail_sender }}
TLS
The driver always uses TLS, except to a server on the same machine. It
upgrades the connection with STARTTLS, or speaks TLS from the start on
port 465, and checks the server's certificate and name. Anywhere else, a
server that offers no TLS, or whose certificate fails the check, makes
the send misconfigured, so a credential never goes in the clear.
A server on the same machine (localhost, 127.0.0.1, ::1) is spoken
to without STARTTLS, whether it offers it or not, as a database there
is (PostgreSQL over TLS). A stock
Postfix offers STARTTLS with a self-signed certificate that no check
passes.
The message it writes
Lines end in CRLF and every part is in base64. The text and the HTML go
as multipart/alternative, with attachments beside them in
multipart/mixed. A subject that isn't plain ASCII is written as RFC
2047 encoded words, and Date: comes from the host's clock. The server
adds the Message-ID:, as RFC 6409 says a submission server does.
When a send goes wrong
The driver classifies what happened as every driver does (The seam every outside call goes through):
- A server that can't be reached, refuses for now (
4xx), or drops the connection before the end of the message went out surely took nothing, so the delivery is retried. - Once the end of the message went out, no answer may still mean the
message was taken. SMTP takes no idempotency key, so the delivery is
parked as
outcome_unknown. - A recipient refused for good (
5xx) fails asrecipient_rejected, and a refused message asmessage_rejected. - A refused credential or sender is
misconfigured.
Markdown for agents: /docs/the-smtp-driver.md.Built from Jadpo main at a707efb.