Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Built-in services

Built-in services

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 on Text;
  • 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).

example
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 as recipient_rejected, and a refused message as message_rejected.
  • A refused credential or sender is misconfigured.

Markdown for agents: /docs/the-smtp-driver.md.Built from Jadpo main at a707efb.