std/net/smtp

Standard Library documentation

low-level mail delivery.

Module

Name
std/net/smtp
Area
Standard Library
Source
modules/std/net/smtp.zzm

NAME

std/net/smtp - low-level mail delivery.

SYNOPSIS

  from std/net/smtp import Mailer, MailResult;

  let headers := new PairList();
  headers.add( "From", "sender@example.test" );
  headers.add( "To", "recipient@example.test" );
  headers.add( "Subject", "Example" );
  headers.add( "Message-ID", "<example-1@example.test>" );

  let mailer := new Mailer(
    transport: "smtp",
    host: "127.0.0.1",
    port: 2525
  );

  let result := mailer.send(
    "sender@example.test",
    [ "recipient@example.test" ],
    headers,
    to_binary( "Hello\r\n" )
  );

IMPLEMENTATION SUPPORT

This module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Node and Electron. It is not supported by zuzu-js in the browser.

DESCRIPTION

This runtime-supported module provides a deliberately low-level mail delivery API. It works with an explicit envelope sender, explicit envelope recipients, ordered message headers, and a raw BinaryString body.

It does not construct MIME messages, encode display names, generate a Message-ID, derive recipients from To, Cc, or Bcc headers, or add attachments. Higher-level composition modules should build the headers and body, then call this module.

EXPORTS

Classes

  • Mailer

    Configured sender class.

    • Mailer.capabilities()

      Parameters: none. Returns: Dict. Reports backend delivery, TLS, authentication, and async support.

    • Mailer({ transport?: String, host?: String, port?: Number, ... })

      Constructs a sender from named options. Returns: Mailer.

    • mailer.send(envelope_from, envelope_to, headers, body, options := {})

      Parameters: envelope_from is the sender address, envelope_to is a string or array of recipient addresses, headers is a PairList, body is a BinaryString, and options controls sending. Returns: MailResult. Sends one message.

    • mailer.send_async(envelope_from, envelope_to, headers, body, options := {})

      Parameters: same as send. Returns: Task. Asynchronously sends one message.

  • MailResult

    Result object returned by successful deliveries.

    • result.transport()

      Parameters: none. Returns: String. Returns the delivery transport.

    • result.accepted()

      Parameters: none. Returns: Array. Returns accepted envelope recipients.

    • result.rejected()

      Parameters: none. Returns: Array. Returns rejected envelope recipients.

    • result.message_id()

      Parameters: none. Returns: String or null. Returns the supplied Message-ID header value when present.

    • result.response()

      Parameters: none. Returns: String or null. Returns the backend delivery response text.

    • result.to_Dict()

      Parameters: none. Returns: Dict. Converts the result to a dictionary.

The module does not export a module-level capabilities() function. Use Mailer.capabilities().

CAPABILITIES

Mailer.capabilities() returns a Dict with stable keys:

  {
    smtp: true,
    sendmail: true,
    tls: true,
    starttls: true,
    auth: [ "plain", "login", "xoauth2" ],
    async: true,
  }

Backends report false or an empty array for features they cannot honestly provide. Browser hosts are importable but report no real delivery support.

MAILER OPTIONS

Create a sender with named options:

  let mailer := new Mailer(
    transport: "sendmail",
    sendmail_path: "/usr/sbin/sendmail"
  );

Supported options include:

  • transport

    "smtp" or "sendmail". Defaults to "smtp".

  • host, port, timeout

    SMTP host, port, and command timeout. Defaults are localhost, 25, and 30 seconds.

  • submission

    Uses submission-style defaults: port 587 and STARTTLS requested. Backends without STARTTLS support will reject sending clearly.

  • tls, starttls, tls_verify, tls_server_name

    TLS policy fields. tls_verify defaults to true.

  • username, password, auth

    Authentication fields. auth may be plain, login, or xoauth2. Authentication on a plaintext connection requires explicit allow_insecure_auth: true.

  • smtputf8

    Permit non-ASCII envelope addresses only when the backend and server can honour SMTPUTF8.

  • reject_partial

    For SMTP, throw if any recipient is rejected. The default returns a MailResult when at least one recipient is accepted.

  • sendmail_path, sendmail_args

    Sendmail-compatible binary path and extra fixed argument-vector items. The backend invokes:

      sendmail_path sendmail_args... -i -f ENVELOPE_FROM RECIPIENT...

    No shell interpolation is used.

SENDING

  mailer.send(envelope_from, envelope_to, headers, body, options := {})
  mailer.send_async(envelope_from, envelope_to, headers, body, options := {})

envelope_to may be a single string or an array of strings. These are the only delivery recipients. Header fields are never used as envelope recipients.

headers must be a PairList, preserving order and duplicate fields. Dict headers are rejected. Header names must be strict RFC 5322 field name tokens with no colon or control characters. Header values must be String or BinaryString values and must not contain CR or LF.

body must be a BinaryString. Passing a String throws a clear type error so callers do not accidentally depend on host text encoding.

Serialization is:

  • 1.

    Headers in PairList order using CRLF line endings.

  • 2.

    One blank CRLF separator.

  • 3.

    The body bytes exactly as supplied.

SMTP dot-stuffing is a wire encoding detail and does not mutate caller bytes.

MAIL RESULT

A successful send returns a MailResult with public fields:

  {
    transport: "smtp",
    accepted: [ "recipient@example.test" ],
    rejected: [],
    message_id: "<example-1@example.test>",
    response: "250 queued",
  }

message_id is copied from a supplied Message-ID header when one is present. This module never generates one automatically.

COPYRIGHT AND LICENCE

std/net/smtp is copyright Toby Inkster.

It is free software; you may redistribute it and/or modify it under the terms of either the Artistic License 1.0 or the GNU General Public License version 2.