Sovite.Core.Router (sovite v0.2.0)

Copy Markdown View Source

Decides, at delivery time, where each recipient's mail goes.

  1. The address is checked (Sovite.Core.Recipients.check/2): unknown users and users who moved fail.
  2. Its domain class picks a transport: routing.local_transport, routing.mailbox_transport, routing.relay_transport, or routing.remote_transport (see Sovite.Core.Transport).
  3. The transports table (sovitectl transport) may override it. Patterns, in order: user+ext@domain, user@domain, domain, then each parent domain as .parent (subdomains only), then *.
  4. SMTP without a next hop goes to the relay host the sender relays table (sovitectl sender-relay) gives for the sender (by address, then @domain), else to delivery.relayhost, else to the MX hosts of the recipient's domain (or the address in an address literal).

LMTP, Maildir (local and mailbox), and pipe deliveries are final: see Sovite.Core.Delivery.

SMTP deliveries also get the source address to connect from (the sender relays table, else delivery.source_address) and, for explicit next hops, credentials from the sender relays table, or delivery.relayhost_username for delivery.relayhost.

Recipients with the same destination are delivered together, and per-destination concurrency limits apply to the destination.

Summary

Types

Where a delivery goes

A next hop

Functions

Returns a destination or next hop as text, for logs: "example.com", "[192.0.2.1]", or the host as configured ("[smtp.example.com]:587"). LMTP destinations are the socket path or host:port, the others "local", "mailbox", or "pipe:<name>".

Routes recipient of a message from sender.

Types

destination()

@type destination() ::
  %{
    transport: :smtp,
    nexthop: nexthop(),
    source: %{optional(:ipv4 | :ipv6) => :inet.ip_address()},
    auth: %{username: String.t(), password: String.t()} | nil
  }
  | %{
      transport: :lmtp,
      nexthop: {:unix, Path.t()} | {:host, Sovite.Core.Transport.host()}
    }
  | %{transport: :local | :mailbox}
  | %{transport: :pipe, name: String.t()}

Where a delivery goes:

  • SMTP: the next hop, the local addresses to connect from, and the credentials to log in with.
  • LMTP: a Unix socket or a host (never looked up in MX records).
  • :local and :mailbox: Maildir delivery.
  • :pipe: the command of the [pipe.<name>] config section.

nexthop()

@type nexthop() ::
  {:mx, String.t()}
  | {:host, Sovite.Core.Transport.host()}
  | {:literal, :inet.ip_address()}

A next hop:

  • {:mx, domain} - the MX hosts of domain.
  • {:host, %{host, port, mx}} - a relay host or transport map next hop; mx: true looks up the MX hosts of host.
  • {:literal, ip} - an address literal in the recipient.

route()

@type route() ::
  {:deliver, destination()}
  | {:defer, String.t(), String.t()}
  | {:fail, String.t(), String.t()}
  | {:discard, String.t()}

Functions

name(arg1)

@spec name(destination() | nexthop()) :: String.t()

Returns a destination or next hop as text, for logs: "example.com", "[192.0.2.1]", or the host as configured ("[smtp.example.com]:587"). LMTP destinations are the socket path or host:port, the others "local", "mailbox", or "pipe:<name>".

route(routing, sender, recipient)

@spec route(Sovite.Core.Routing.t(), String.t(), String.t()) :: route()

Routes recipient of a message from sender.