Relay services are given an existing message and attempt to delivery it to the message’s next destination. In a traditional MTA, this next destination will be looked up by the recipient’s domain MX record and delivery is done with SMTP. In other cases, such as when acting as an MDA, slimta is the final destination and delivery occurs locally with something like courier-maildrop.
In any case, the relay will report either its attempt was a success or whether failure was permanent or transient.
SMTP Smart-Host Relaying¶
A very common type of relaying is sending all mail through to a single destination. This could be a local mail server that delivers all mail to its ISP mail servers, or it could be useful for a “front-line” of email servers whose sole purpose is spam scanning before handing off for real processing and routing. This static delivery is generally called Smart-Hosting
Smart-Host relaying can be done with the
StaticSmtpRelay class, which will maintain
a pool of connections to the destination that will be re-used if idle. For
example, to ensure no more than one open connection to a destination is open at
from slimta.relay.smtp.static import StaticSmtpRelay relay = StaticSmtpRelay('smarthost.example.com', pool_size=1)
SMTP MX Relaying¶
Email messages destined for a recipient address hosted elsewhere on the Internet are relayed by querying the recipient domain’s MX records. The result is a prioritized list of hostnames that should be considered the next hop for the message. The highest priority (given by the lowest MX preference number) hostname is tried first, and lower priority hostnames should be tried subsequently. MX relaying always uses port 25.
MX relaying can be done with the
class, which will automatically cache MX records until their TTL and will
StaticSmtpRelay object for each
destination, so that connections are re-used:
from slimta.relay.smtp.mx import MxSmtpRelay relay = MxSmtpRelay()
Recipient domains can be configured to ignore MX records and permanently
deliver to a certain hostname using the
Changing Source IP¶
The source IP address of delivered mail is often hugely important, since one
wrong move and you may find your IP on one of hundreds of spam blacklists. With
more complex setups, an MTA will often have a pool of IP addresses to send
from. SMTP relays (
MxSmtpRelay allow a constructor argument
socket_creator that allows you to control socket bind address:
import random source_ips = ['126.96.36.199', '188.8.131.52', '184.108.40.206'] def _socket_creator(address): bind_ip = random.choice(source_ips) return create_connection(address, source_address=(bind_ip, 0)) mx = MxSmtpRelay(socket_creator=_socket_creator)
In this example, every outbound relay attempt will call
before connecting, passing in the destination
address tuple (host and
port). The function should return an open and connected socket, ready for data.
Because SMTP relay connections were designed to be pooled and recycled,
Envelope deliveries before disconnecting, the
objects are not passed in to the
socket_creator call. If you need access
to message data, such as recipients, your best option may be to create an
Relay class that implements your logic and then calls
The LMTP protocol is designed for delivering a message to its final destination. It’s greatest strength in this regard over SMTP is that it can report success or failure on a per-recipient basis.
LMTP relaying is available with the
StaticLmtpRelay class, which is behaves very
similarly to static SMTP relaying:
from slimta.relay.smtp.static import StaticLmtpRelay relay = StaticLmtpRelay()
Similar to the HTTP Edge, HTTP can be used to relay messages
as the data payload of a request. The EHLO, sender, and recipients information
usually transferred in the SMTP request are sent as headers in the request.
Refer to the
slimta.relay.http module for more information on how this
request is constructed.
If the remote host is an HTTP Edge, the response to the
request will most likely have an
X-Smtp-Reply header that is used as the
Reply when returning to the queue. If the response does not
have this header, then
PermanentRelayError is raised for
4XX codes and
TransientRelayError is raised for
HTTP relays are set up by creating a
from slimta.relay.http import HttpRelay relay = HttpRelay('http://example.com:8025/messages/')
External Process Relaying¶
When slimta is configured to be the final destination for the email message,
it can stream a message to an external process to locally deliver the message.
This is how applications like courier-maildrop and dovecot-lda are given
messages. This method is modeled off the pipe daemon from postfix. This
type of relay is provided in the
slimta.relay.pipe module. Here’s an
example of delivery to the
from slimta.relay.pipe import MaildropRelay relay = MaildropRelay(timeout=10.0)