salmon.server module

The majority of the server related things Salmon needs to run, like receivers, relays, and queue processors.

class salmon.server.LMTPReceiver(host='127.0.0.1', port=8824, socket=None)[source]

Bases: lmtpd.LMTPServer

Receives emails and hands it to the Router for further processing.

Initializes to bind on the given port and host/IP address. Remember that LMTP isn’t for use over a WAN, so bind it to either a LAN address or localhost. If socket is not None, it will be assumed to be a path name and a UNIX socket will be set up instead.

This uses lmtpd.LMTPServer in the __init__, which means that you have to call this far after you use python-daemonize or else daemonize will close the socket.

close()[source]

Doesn’t do anything except log who called this, since nobody should. Ever.

process_message(Peer, From, To, Data, **kwargs)[source]

Called by lmtpd.LMTPServer when there’s a message received.

start()[source]

Kicks everything into gear and starts listening on the port. This fires off threads and waits until they are done.

class salmon.server.QueueReceiver(queue_dir, sleep=10, size_limit=0, oversize_dir=None, workers=10)[source]

Bases: object

Rather than listen on a socket this will watch a queue directory and process messages it receives from that. It works in almost the exact same way otherwise.

The router should be fully configured and ready to work, the queue_dir can be a fully qualified path or relative. The option workers dictates how many threads are started to process messages. Consider adding @nolocking to your handlers if you are able to.

process_message(msg)[source]

Exactly the same as SMTPReceiver.process_message but just designed for the queue’s quirks.

start(one_shot=False)[source]

Start simply loops indefinitely sleeping and pulling messages off for processing when they are available.

If you give one_shot=True it will stop once it has exhausted the queue

class salmon.server.Relay(host='127.0.0.1', port=25, username=None, password=None, ssl=False, starttls=False, debug=0, lmtp=False)[source]

Bases: object

Used to talk to your “relay server” or smart host, this is probably the most important class in the handlers next to the salmon.routing.Router. It supports a few simple operations for sending mail, replying, and can log the protocol it uses to stderr if you set debug=1 on __init__.

The hostname and port we’re connecting to, and the debug level (default to 0). Optional username and password for smtp authentication. If ssl is True smtplib.SMTP_SSL will be used. If starttls is True (and ssl False), smtp connection will be put in TLS mode. If lmtp is true, then smtplib.LMTP will be used. Mutually exclusive with ssl.

configure_relay(hostname)[source]
deliver(message, To=None, From=None)[source]

Takes a fully formed email message and delivers it to the configured relay server.

You can pass in an alternate To and From, which will be used in the SMTP/LMTP send lines rather than what’s in the message.

reply(original, From, Subject, Body)[source]

Calls self.send but with the from and to of the original message reversed.

resolve_relay_host(To)[source]
send(To, From, Subject, Body)[source]

Does what it says, sends an email. If you need something more complex then look at salmon.mail.MailResponse.

class salmon.server.SMTPChannel(server, conn, addr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)[source]

Bases: smtpd.SMTPChannel

Replaces the standard SMTPChannel with one that rejects more than one recipient

smtp_RCPT(arg)[source]
exception salmon.server.SMTPError(code, message=None)[source]

Bases: Exception

You can raise this error when you want to abort with a SMTP error code to the client. This is really only relevant when you’re using the SMTPReceiver and the client understands the error.

If you give a message than it’ll use that, but it’ll also produce a consistent error message based on your code. It uses the errors in salmon.bounce to produce them.

error_for_code(code)[source]
class salmon.server.SMTPReceiver(host='127.0.0.1', port=8825)[source]

Bases: smtpd.SMTPServer

Receives emails and hands it to the Router for further processing.

Initializes to bind on the given port and host/IP address. Typically in deployment you’d give 0.0.0.0 for “all internet devices” but consult your operating system.

This uses smtpd.SMTPServer in the __init__, which means that you have to call this far after you use python-daemonize or else daemonize will close the socket.

close()[source]

Doesn’t do anything except log who called this, since nobody should. Ever.

handle_accept()[source]
process_message(Peer, From, To, Data, **kwargs)[source]

Called by smtpd.SMTPServer when there’s a message received.

start()[source]

Kicks everything into gear and starts listening on the port. This fires off threads and waits until they are done.

salmon.server.undeliverable_message(raw_message, failure_type)[source]

Used universally in this file to shove totally screwed messages into the routing.Router.UNDELIVERABLE_QUEUE (if it’s set).