Implements an algorithm to query and pick an MX record to delivery a message. The MX record is calculated by pulling the domain-name from the recipient’s email address (or first recipient, if multiple) and querying DNS for the domain MX email routing records. If multiple records exist, the pick is made by using the number of delivery attempts to cycle through the options.

class[context=None[, **client_kwargs]])

Bases: slimta.relay.Relay

Delivers messages based on the MX records of their recipients. Keeps an expiring cache of resolved MX records to prevent DNS overuse, and uses a StaticSmtpRelay object for each destination to recycle and limit connections.

All arguments are optional.

  • context (SSLContext) – Used to wrap sockets with SSL encryption, when STARTTLS is advertised, rather than the default context.

  • auth_mechanism (bytes) – Force the use of the given AUTH mechanism, instead of the best available.

  • tls_immediately – If True, the socket will be encrypted immediately on connection rather than looking for the STARTTLS extension.

  • tls_required – If given and True, it should be considered a delivery failure if TLS cannot be negotiated by the client.

  • connect_timeout – Timeout in seconds to wait for a client connection to be successful before issuing a transient failure.

  • command_timeout – Timeout in seconds to wait for a reply to each SMTP command before issuing a transient failure.

  • data_timeout – Timeout in seconds to wait for a reply to message data before issuing a transient failure.

  • idle_timeout – Timeout in seconds after a message is delivered before a QUIT command is sent and the connection terminated. If another message should be delivered before this timeout expires, the connection will be re-used. By default, QUIT is sent immediately and connections are never re-used.

  • socket_creator – Optional function to use instead of create_connection() for creating sockets.

  • ehlo_as – The string to send as the EHLO or HELO string. Defaults to the FQDN of the system. This may also be given as a function that will be executed with the destination address at the beginning of each connection.

  • binary_encoder – Optional function from email.encoders used as an argument to encode_7bit() when conversion is necessary for the remote server.

new_static_relay(destination, port)

Return a new StaticSmtpRelay object for the given destination. This method can be overridden to provide extra arguments, such as limiting the number of concurrent connections.

  • destination – The hostname to relay to.

  • port – The delivery port on the destination.

choose_mx(records, attempts)

Chooses a record based on the number of delivery attempts on the message. As provided, this method cycle through the records trying each one once, but this method can be overridden.

  • records – List of tuples (pref, host) sorted by preference.

  • attempts – The number of delivery attempts this message has undergone.


The host that was picked from the list.

Return type


force_mx(domain, destination[, port=25])

Do not do MX record lookups for the given domain, instead always use destination for delivery.

  • domain – Domain to force.

  • destination – Destination hostname.

  • port – Port number on the destination.

attempt(envelope, attempts)

This method must be overridden by sub-classes in order to be passed in to the Queue constructor.

The result of a successful relay attempt is either None or a Reply object. The result of a failing relay attempt is either a PermanentRelayFailure or TransientRelayFailure error.

If the result applies to the entire envelope and all its recipients, implementations may return the successful result or raise the failure. If the result is different per-recipient, then implementations may return a dictionary where the key is a recipient from recipients and the value is the relay result (successful or failing).

  • envelopeEnvelope to attempt delivery for.

  • attempts – Number of times the envelope has attempted delivery.


The relay result, as described above.


PermanentRelayError, TransientRelayError