Sovite.DNS.MX (sovite v0.2.0)

Copy Markdown View Source

Finds the hosts that accept mail for a domain (RFC 5321 §5.1).

{:ok, hosts} = Sovite.DNS.MX.resolve(resolver, "example.com")
#=> [{"mx1.example.com", [{192, 0, 2, 25}, {8193, 3512, 0, 0, 0, 0, 0, 25}]}, ...]

hosts/2 looks up the MX records:

  • Hosts are ordered by preference. Hosts with the same preference are shuffled, to spread load as the RFC asks.
  • A domain with no MX records but with address records is its own mail host (implicit MX).
  • A Null MX (RFC 7505), a single record with exchange ".", means the domain accepts no mail: {:error, :null_mx}.

resolve/3 also looks up each host's addresses.

Summary

Types

Why there are no mail hosts.

An MX host and its preference.

Functions

Looks up the addresses of host for each record type in families, and returns them in that order. An address literal such as "[192.0.2.1]" is returned as is, without a lookup.

Returns the MX hosts for domain, best first.

Returns the mail hosts for domain with their addresses, best first.

Types

error()

@type error() ::
  :null_mx
  | :nxdomain
  | :no_hosts
  | :loops_back
  | :no_addresses
  | {:temporary, Sovite.DNS.Resolver.error()}

Why there are no mail hosts.

  • :null_mx - the domain publishes a Null MX. Permanent.
  • :nxdomain - the domain does not exist. Permanent.
  • :no_hosts - the domain exists but has neither MX nor address records. Permanent.
  • :loops_back - this server is the best MX host (see :exclude). Permanent.
  • :no_addresses - none of the MX hosts has an address. Permanent.
  • {:temporary, reason} - a DNS error; try again later.

mx()

@type mx() :: {preference :: non_neg_integer(), host :: String.t()}

An MX host and its preference.

Functions

addresses(resolver, host, families \\ [:aaaa, :a])

@spec addresses(Sovite.DNS.resolver(), String.t(), [:a | :aaaa]) ::
  {:ok, [:inet.ip_address()]} | {:error, Sovite.DNS.Resolver.error()}

Looks up the addresses of host for each record type in families, and returns them in that order. An address literal such as "[192.0.2.1]" is returned as is, without a lookup.

Returns the addresses found, even if another lookup failed, so a host with only IPv4 addresses gives {:ok, ipv4s}. Without any address, a DNS error other than NXDOMAIN is returned, since a retry might find one; otherwise {:ok, []} (NODATA) or {:error, :nxdomain}.

hosts(resolver, domain, opts \\ [])

@spec hosts(Sovite.DNS.resolver(), String.t(), keyword()) ::
  {:ok, [mx(), ...]} | {:error, error()}

Returns the MX hosts for domain, best first.

Options

  • :exclude - host names that are this server. If one of them is an MX host, it and every host with the same or a worse preference are removed (RFC 5321 §5.1), so a backup MX never relays to itself or to a worse backup.

resolve(resolver, domain, opts \\ [])

@spec resolve(Sovite.DNS.resolver(), String.t(), keyword()) ::
  {:ok, [{String.t(), [:inet.ip_address(), ...]}, ...]} | {:error, error()}

Returns the mail hosts for domain with their addresses, best first.

Hosts without addresses are left out. If no host has an address, the result is {:error, :no_addresses}, or {:error, {:temporary, reason}} if some lookups failed with a DNS error.

Options

  • :exclude - see hosts/3.
  • :families - address types to look up, in order of preference: [:aaaa, :a] (default), [:a, :aaaa], [:a], or [:aaaa].