Authentication System

aiosmtpd provides a framework for SMTP Authentication that fully complies with RFC 4954.

Activating Authentication

aiosmtpd authentication is always activated, but attempts to authenticate will always be rejected unless the authenticator parameter of SMTP is set to a valid & working Authenticator Callback.

AUTH API

The aiosmtpd Authentication Framework comprises several components, who are collectivelly called the “AUTH API”.

AUTH Handler Hook

async handle_AUTH(server: SMTP, session: Session, envelope: Envelope, args)

Called to handle AUTH command, if you need custom AUTH behavior.

Most of the time, you will NOT need to implement this hook; AUTH Mechanism Hooks are provided to override/implement selective SMTP AUTH mechanisms (see below).

If you do implement this hook:

You MUST comply with RFC 4954.

args will contain the list of words following the AUTH command.

You will have to leverage the SMTP.push() and SMTP.challenge_auth() methods to interact with the clients.

You will need to modify the session.auth_data and session.authenticated attributes.

You may ignore the envelope.

AUTH Mechanism Hooks

Separately from AUTH Handler Hook, aiosmtpd also implement support for “AUTH Mechanism Hooks”. These async hooks will implement the logic for SMTP Authentication Mechanisms.

Every AUTH Mechanism Hook is named auth_MECHANISM where MECHANISM is the all-uppercase name of the mechanism that the hook will implement.

(Mechanism is the word following the AUTH command sent by client.)

Important

If MECHANISM has a dash within its name, use double-underscore to represent the dash. For example, to implement a MECH-WITH-DASHES mechanism, name the AUTH hook as auth_MECH__WITH__DASHES.

Single underscores will not be modified. So a hook named auth_MECH_WITH_UNDERSCORE will implement the MECH_WITH_UNDERSCORE mechanism.

(If in the future a SASL mechanism with double underscores in its name gets defined, this name-mangling mechanism will be revisited. That is very unlikely to happen, though.)

Alternatively, you can also use the auth_mechanism() decorator, which you can import from the aiosmtpd.smtp module.

The SMTP class provides built-in AUTH hooks for the LOGIN and PLAIN mechanisms, named auth_LOGIN and auth_PLAIN, respectively. If the handler class implements auth_LOGIN and/or auth_PLAIN, then the methods of the handler instance will override the built-in methods.

async auth_MECHANISM(server: SMTP, args: List[str]) aiosmtpd.smtp.AuthResult
Parameters:
  • server – The instance of the SMTP class invoking the AUTH Mechanism hook

  • args – A list of string split from the characters following the AUTH command. args[0] is usually equal to MECHANISM (unless the auth_mechanism() decorator has been used).

The AUTH hook MUST perform the actual validation of AUTH credentials.

In the built-in AUTH hooks, this is done by invoking the function specified by the authenticator initialization argument.

AUTH Mechanism Hooks in handlers are NOT required to do the same, and MAY implement their own authenticator system.

The AUTH Mechanism Hook MUST return an instance of AuthResult containing the result of the Authentication process.

Important

Defining additional AUTH hooks in your handler will NOT disable the built-in LOGIN and PLAIN hooks; if you do not want to offer the LOGIN and PLAIN mechanisms, specify them in the auth_exclude_mechanism parameter of the SMTP class.

Authenticator Callback

Authenticator(server, session, envelope, mechanism, auth_data) AuthResult
Parameters:
  • server – The SMTP instance that invoked the authenticator

  • session – A Session instance containing session data so far

  • envelope – An Envelope instance containing transaction data so far

  • mechanism (str) – name of the AUTH Mechanism chosen by the client

  • auth_data – A data structure containing authentication data gathered by the AUTH Mechanism

Returns:

Result of authentication

Return type:

AuthResult

This function would be invoked during or at the end of an Authentication Process by AUTH Mechanisms. Based on mechanism and auth_data, this function should return a decision on whether Authentication has been successful or not.

This function SHOULD NOT modify the attributes of session and envelope.

The type and contents of the auth_data parameter is wholly at the discretion of the calling AUTH Mechanism. For the built-in LOGIN and PLAIN Mechanisms, the type of data will be aiosmtpd.smtp.LoginPassword

New in version 1.3.

AuthResult API

class AuthResult(*, success, handled, message, auth_data)
success: bool

This attribute indicates whether Authentication is successful or not.

handled: bool = True

This attribute indicates whether Authenticator Decision process (e.g., sending of status codes) have been carried out by Authenticator or not.

If set to True, smtp_AUTH() will not perform additional processing and will simply exits.

Applicable only if success=False

message: str | None = None

The message to send back to client, regardless of success status.

This message will be sent as-is; as such, it MUST be prefixed with the correct SMTP Status Code and optionally, SMTP Extended Status Code.

If not given (set/kept to None), smtp_AUTH() will use standard SMTP Status Code & Message.

auth_data: Any = None

Optional free-form authentication data. This will be saved by smtp_AUTH() into the session.auth_data attribute.

If auth_data has the attribute login, then smtp_AUTH() will save auth_data.login into session.login_data as well. This is to cater for possible backward-compatibility requirements, where legacy handlers might be looking for session.login_data for some reasons.

Security Considerations

We have taken steps to prevent leakage of sensitive information (i.e., password) through logging by overriding the __repr__ and __str__ methods of the AuthResult and LoginPassword classes.

However, we have no control on the (logging) output of your custom hooks. Please be very careful emitting/recording AUTH information to prevent leakage.

Example

An example is provided in examples/authenticated_relayer.