mail.smtp.server
import mail
Everything here is re-exported by
import mailis enough and the names are called asmail.*. Importingmail.smtp.serveron its own works too and reaches the same definitions.
The receiving end of SMTP.
SmtpServer accepts connections, runs the ESMTP conversation, and asks
handlers of your own what to do at each stage: whether to take this
sender, this recipient, this message. It knows the protocol; everything
about policy is yours.
import mail.smtp { SmtpServer }
var server = SmtpServer({ port: 2525, hostname: 'mail.example.com' })
server.on_rcpt(@(session, recipient) {
if !recipient.domain.ends_with('example.com') {
return { code: 550, message: 'not a local address' }
}
})
server.on_data(@(session, raw) {
store.deliver(session.recipients, raw)
})
server.listen()
A handler that returns nothing accepts. One that returns a code and a message refuses, with those. One that raises is a failure on the server’s side, and the sender is told to try again later.
Constants
MECHANISMS
mail.MECHANISMS = [...]
DEFAULT_MAX_SIZE
mail.DEFAULT_MAX_SIZE = 35882577
DEFAULT_MAX_RECIPIENTS
mail.DEFAULT_MAX_RECIPIENTS = 100
MAX_ERRORS
mail.MAX_ERRORS = 10
MAX_DATA_LINE
mail.MAX_DATA_LINE = 4096
Classes
SmtpSession
class mail.SmtpSession
One connection, and everything known about it so far.
Handlers are given this and may put their own values on it through
state, which starts empty and lives as long as the connection.
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
mail.SmtpSession(peer: string, secure: bool)
sender is the Address the transaction is from, nil before one has
started, and an empty string for the null path a bounce comes from.
recipients is the Address values accepted so far.
Parameters
peer(string) — The address the connection came from.secure(bool) — Whether it is encrypted.
SmtpSession.is_authenticated()
mail.SmtpSession.is_authenticated() -> bool
Whether the client has authenticated.
Returns bool
SmtpSession.is_secure()
mail.SmtpSession.is_secure() -> bool
Whether the connection is encrypted.
Returns bool
SmtpSession.reset()
mail.SmtpSession.reset()
SmtpSession.to_string()
mail.SmtpSession.to_string()
SmtpServer
class mail.SmtpServer
A server that accepts mail.
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
mail.SmtpServer(options: ?dict)
| option | default | what it does |
|---|---|---|
host | 127.0.0.1 | the address to bind |
port | 25 | the port to bind |
hostname | the machine’s own | the name to greet clients with |
max_size | 35 MB | the largest message to take |
max_recipients | 100 | recipients one message may have |
timeout | 300000 | milliseconds a client may go quiet |
require_tls | false | refuse mail on an unencrypted connection |
require_auth | false | refuse mail from a client that has not authenticated |
banner | none | extra text on the greeting line |
Parameters
options(?dict)
SmtpServer.on_connect()
mail.SmtpServer.on_connect(handler) -> SmtpServer
Called when a connection opens, with the session. Refusing here closes the connection before the greeting.
Parameters
handler(function(1))
Returns SmtpServer — itself.
SmtpServer.on_mail()
mail.SmtpServer.on_mail(handler) -> SmtpServer
Called with the session and the sender Address when a transaction
starts.
Parameters
handler(function(2))
Returns SmtpServer — itself.
SmtpServer.on_rcpt()
mail.SmtpServer.on_rcpt(handler) -> SmtpServer
Called with the session and each recipient Address. This is where a
server decides whether it has anywhere to put the message.
Parameters
handler(function(2))
Returns SmtpServer — itself.
SmtpServer.on_data()
mail.SmtpServer.on_data(handler) -> SmtpServer
Called with the session and the message, as bytes, once the whole of it has arrived. This is where a message is delivered.
Parameters
handler(function(2))
Returns SmtpServer — itself.
SmtpServer.on_auth()
mail.SmtpServer.on_auth(handler) -> SmtpServer
Called with the session and { mechanism, username, password }.
Returning nothing accepts.
Without this handler the server advertises no authentication at all, and a client that tries anyway is told so.
Parameters
handler(function(2))
Returns SmtpServer — itself.
SmtpServer.on_password()
mail.SmtpServer.on_password(handler) -> SmtpServer
Called with a username, and returns that account’s password or nil.
CRAM-MD5 proves the password without sending it, which means the
server has to work out the same digest and therefore has to know the
password. A server that cannot supply one does not offer the mechanism.
Parameters
handler(function(1))
Returns SmtpServer — itself.
SmtpServer.on_close()
mail.SmtpServer.on_close(handler) -> SmtpServer
Called with the session when a connection closes, however it closed.
Parameters
handler(function(1))
Returns SmtpServer — itself.
SmtpServer.on_error()
mail.SmtpServer.on_error(handler) -> SmtpServer
Called with the error and the session when something inside the server fails. Without it, failures are silent and the client is told to try again later.
Parameters
handler(function(2))
Returns SmtpServer — itself.
SmtpServer.use_tls()
mail.SmtpServer.use_tls(cert_chain: string, private_key: string) -> SmtpServer
Gives the server a certificate, which is what lets it offer STARTTLS.
Parameters
cert_chain(string) — The certificate chain, PEM encoded.private_key(string) — The key, PEM encoded.
Returns SmtpServer — itself.
SmtpServer.set_tls_config()
mail.SmtpServer.set_tls_config(config) -> SmtpServer
Gives the server a TLS configuration built elsewhere.
Parameters
config(TlsConfig)
Returns SmtpServer — itself.
SmtpServer.is_secure()
mail.SmtpServer.is_secure() -> bool
Whether the server can offer STARTTLS.
Returns bool
SmtpServer.bind()
mail.SmtpServer.bind() -> SmtpServer
Binds the listening socket without accepting anything yet, so that the address is known before the first connection.
Returns SmtpServer — itself.
SmtpServer.address()
mail.SmtpServer.address() -> SocketAddr
The address the server is listening on, which is how a port of 0 is
turned into the one the system chose.
Returns SocketAddr
SmtpServer.accept()
mail.SmtpServer.accept() -> SmtpServer
Accepts one connection and serves it to the end.
Returns SmtpServer — itself.
SmtpServer.listen()
mail.SmtpServer.listen() -> SmtpServer
Accepts connections one after another until close().
One connection is served at a time. To serve several at once, run
serve() instead, which puts a pool of isolates behind the same socket.
Returns SmtpServer — itself.
SmtpServer.close()
mail.SmtpServer.close() -> SmtpServer
Stops the accept loop and closes the listening socket.
Returns SmtpServer — itself.
SmtpServer.is_listening()
mail.SmtpServer.is_listening() -> bool
Whether the accept loop is running.
Returns bool
SmtpServer.serve_connection()
mail.SmtpServer.serve_connection(client) -> SmtpServer
Serves one already-accepted connection to the end, then closes it.
This is the whole conversation: the greeting, every command, and the close. Call it directly to put a server behind a socket something else accepted.
Parameters
client(TcpStream)
Returns SmtpServer — itself.
SmtpServer.to_string()
mail.SmtpServer.to_string()
2026, Richard Ore and Zuri contributors