bonzo.server – Non-blocking SMTP server

A non-blocking, single-threaded SMTP server.

class bonzo.server.SMTPConnection(stream, address, request_callback)[source]

Bases: object

Handles a connection to an SMTP client, executing SMTP commands.

This class uses its COMMAND and DATA attributes as a simple “enum” to manage the connection state.

COMMAND = 0

Used to set the state to receive any command.

DATA = 1

Used to set the state to receive data.

close()[source]

Close the stream.

async command_data(arg)[source]

Handles the DATA SMTP command.

async command_helo(arg)[source]

Handles the HELO SMTP command.

async command_mail(arg)[source]

Handles the MAIL SMTP command.

async command_noop(arg)[source]

Handles the NOOP SMTP command.

async command_quit(arg)[source]

Handles the QUIT SMTP command.

async command_rcpt(arg)[source]

Handles the RCPT SMTP command.

async command_rset(arg)[source]

Handles the RSET SMTP command.

finish()[source]

Finishes the request by closing the connection.

async run()[source]

Runs the SMTP command loop for this connection.

set_close_callback(callback)[source]

Sets a callback that will be run when the connection is closed.

async write(chunk)[source]

Writes a chunk of output to the stream.

async write_ok(message='Ok')[source]

Writes a successful 250 status response.

class bonzo.server.SMTPRequest(connection, remote_ip, command, hostname=None, mail=None, rcpt=None, data=None)[source]

Bases: object

A single SMTP request.

finish()[source]

Writes a successful response to the connection.

async finish_async()[source]

Writes a successful response to the connection.

property message

Returns an instance of a subclass from the email.mime.base.MIMEBase class. It’s actually parsed from the data received using the message_from_string() method.

class bonzo.server.SMTPServer(request_callback, **kwargs)[source]

Bases: TCPServer

A non-blocking, single-threaded SMTP server.

A server is defined by a request callback that takes an instance of SMTPRequest as an argument.

A simple example server that handles the request with the received message:

import asyncio
from bonzo.server import SMTPServer

async def handle_request(request):
    do_something_with_the_message(request.message)
    await request.finish_async()

async def main():
    smtp_server = SMTPServer(handle_request)
    smtp_server.listen(2525)
    await asyncio.Event().wait()

asyncio.run(main())
async handle_stream(stream, address)[source]

Handles the stream by executing the request callback.