Developer Interface

Messages

Adapted shamelessly from Django 3.2.9.

airmailer.message.utf8_charset = utf-8

Our utf-8 charset definition. This differs from the default in that we configure it to not BASE64-encode UTF-8 messages so that we avoid unwanted attention from : some spam filters.

airmailer.message.utf8_charset_qp = utf-8

A specific utf-8 charset definition that we use when one or more of the lines in our message headers or body is longer than RFC5322_EMAIL_LINE_LENGTH_LIMIT : This sets the body encoding to Charset.QP (quoted-printable) to ensure that the message is still delivered. Quoted-printable encoding has the side effect of shortening the long lines.

airmailer.message.DEFAULT_ATTACHMENT_MIME_TYPE: str = 'application/octet-stream'

Default MIME type to use on attachments (if it is not explicitly given and cannot be guessed).

airmailer.message.RFC5322_EMAIL_LINE_LENGTH_LIMIT: int = 998

The maximum number of bytes allowed in a single header line, as per RFC 5322

exception airmailer.message.BadHeaderError[source]
airmailer.message.ADDRESS_HEADERS: Set[str] = {'bcc', 'cc', 'from', 'reply-to', 'resent-bcc', 'resent-cc', 'resent-from', 'resent-sender', 'resent-to', 'sender', 'to'}

Header names that contain structured address data (RFC #5322)

airmailer.message.force_str(s: Union[str, bytes], encoding: str = 'utf-8', errors: str = 'strict') str[source]

Given a string-like object, return the string version of it, encoded as specified in encoding.

Parameters
  • s – the string-like object

  • encoding – the encoding to use to decode the bytestring, if s is a bytestring

  • errors – how to handle errors in decoding the bytestring

Returns

The decoded string.

airmailer.message.forbid_multi_line_headers(name: str, val: str, encoding: Optional[str]) Tuple[str, str][source]

Forbid multi-line headers to prevent header injection.

If name is in ADDRESS_HEADERS, each address in val is run through sanitize_address.

Given a header name and header value, check if there are any newline characters in it. If there are, raise a BadHeaderError exception.

Parameters
  • name – the header name

  • val – the header value

  • encoding – the encoding to use to decode val, if ‘ascii’ encoding fails

Raises

BadHeaderError – if there are any newline characters in the header value

Returns

Sanitized header name and value.

airmailer.message.sanitize_address(addr: Union[str, Tuple[str, str]], encoding: str) str[source]

Format a pair of (name, address) or an email address string.

Parameters
  • addr – the address to sanitize

  • encoding – the encoding to use re-encode the address if ‘ascii’ is not sufficient

Raises

ValueError – if the address is not a valid email address

Returns

A santiized email address.

class airmailer.message.MIMEMixin[source]

A mixin for Message that provides methods for converting the message to string or bytes in ways the rest of the code expects.

as_string(unixfrom: bool = False, linesep: str = '\n') str[source]

Return the entire formatted message as a string.

Keyword Arguments
  • unixfrom – if True, include the Unix From_ envelope header

  • linesep – the line separator to use in the returned string

Returns

The entire formatted message as a string.

as_bytes(unixfrom: bool = False, linesep: str = '\n') bytes[source]

Return the entire formatted message as bytes.

Keyword Arguments
  • unixfrom – if True, include the Unix From_ envelope header

  • linesep – the line separator to use in the returned string

Returns

The entire formatted message as a string.

class airmailer.message.SafeMIMEMessage(_msg, _subtype='rfc822', *, policy=None)[source]

A email.message.Message subclass that sanitizes any headers before they are added to the message.

class airmailer.message.SafeMIMEText(_text: str, _subtype='plain', _charset=None)[source]

A email.mime.text.MIMEText subclass doe some payload sanitization.

  • If the payload contains any lines longer than RFC5322_EMAIL_LINE_LENGTH_LIMIT, use quoted-printable encoding for the body.

  • Sanitize any headers before they are added to the message.

set_payload(payload: str, charset: Optional[Union[str, Charset]] = None)[source]

If the payload contains any lines longer than RFC5322_EMAIL_LINE_LENGTH_LIMIT, the payload will be encoded using quoted-printable encoding.

Parameters
  • payload – the payload to set

  • charset – the charset to use to encode the payload

class airmailer.message.SafeMIMEMultipart(_subtype: str = 'mixed', boundary: Optional[str] = None, _subparts=None, encoding: Optional[str] = None, **_params)[source]

A mulitpart MIME message that sanitizes any headers before they are added.

class airmailer.message.EmailMessage(subject: str = '', body: str = '', from_email: Optional[str] = None, to: Optional[Iterable[str]] = None, bcc: Optional[Iterable[str]] = None, attachments: Optional[List[Union[MIMEBase, str, bytes, bytearray, Tuple[str, bytes, str]]]] = None, headers: Optional[Dict[str, str]] = None, cc: Optional[Iterable[str]] = None, reply_to: Optional[Iterable[str]] = None)[source]

A container class for email information. We use this instead of email.message.Message directly so that we can send the same message to multiple recipients and to ease the construction of the complicated Message object.

content_subtype: str = 'plain'

When constructing the mimetype for the message body, use this subtype of “text”. Default is “plain”, which means that the message body will be specified as “text/plain”.

mixed_subtype: str = 'mixed'
encoding: str = 'utf-8'

Use this as the default encoding for our message body.

message()[source]
recipients()[source]

Return a list of all recipients of the email (includes direct addressees as well as Cc and Bcc entries).

attach(filename: Optional[Union[Path, str]] = None, content: Optional[Union[MIMEBase, str, bytes, bytearray]] = None, mimetype: Optional[str] = None)[source]

Attach a file with the given filename and content. The filename can be omitted and the mimetype is guessed, if not provided.

If the first parameter is a email.mime.base.MIMEBase subclass, insert it directly into the resulting message attachments.

For a text/* mimetype (guessed or specified), when a bytes object is specified as content, decode it as UTF-8. If that fails, set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE and don’t decode the content.

attach_file(path: Union[Path, str], mimetype: Optional[str] = None)[source]

Attach a file from the filesystem.

Set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE if it isn’t specified and cannot be guessed.

For a text/* mimetype (guessed or specified), decode the file’s content as UTF-8. If that fails, set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE and don’t decode the content.

class airmailer.message.EmailMultiAlternatives(subject: str = '', body: str = '', from_email: Optional[str] = None, to: Optional[Iterable[str]] = None, bcc: Optional[Iterable[str]] = None, attachments: Optional[List[Union[MIMEBase, str, bytes, bytearray, Tuple[str, bytes, str]]]] = None, headers: Optional[Dict[str, str]] = None, alternatives=None, cc: Optional[Iterable[str]] = None, reply_to: Optional[Iterable[str]] = None)[source]

A version of EmailMessage that makes it easy to send multipart/alternative messages. For example, including text and HTML versions of the text is made easier.

alternative_subtype: str = 'alternative'
attach_alternative(content, mimetype)[source]

Attach an alternative content representation.

Backends

class airmailer.backend.base.BaseEmailBackend(fail_silently=False, **kwargs)[source]

Base class for email backend implementations.

Subclasses must at least overwrite send_messages

open and close can be called indirectly by using a backend object as a context manager:

with backend as connection:
    # do something with connection
    pass
open()[source]

Open a network connection.

This method can be overwritten by backend implementations to open a network connection.

It’s up to the backend implementation to track the status of a network connection if it’s needed by the backend.

This method can be called by applications to force a single network connection to be used when sending mails. See the airmailer.backend.smtp.SMTPEmailBackend.send_messages method of the SMTP backend for a reference implementation.

The default implementation does nothing.

close()[source]

Close a network connection.

send_messages(email_messages)[source]

Send one or more airmailer.message.EmailMessage objects and return the number of email messages sent.

send_mail(subject: str, message, from_email: str, recipient_list: Iterable[str], html_message: Optional[str] = None)[source]

Easy wrapper for sending a single message to a recipient list. All members of the recipient list will see the other recipients in the ‘To’ field.

class airmailer.backend.smtp.SMTPEmailBackend(host, port=None, username=None, password=None, use_tls=None, fail_silently=False, use_ssl=None, timeout=None, ssl_keyfile=None, ssl_certfile=None, **kwargs)[source]

A wrapper that manages the SMTP network connection.

property connection_class
open()[source]

Open a connection to the email server.

Returns

Return True if a new connection was required, False if not, None if we had an exception and fail_silently is True

Return type

bool or None

close()[source]

Close the connection to the email server.

send_messages(email_messages)[source]

Sends one or more messages returns the number of email messages sent.

Parameters

email_messages (List[airmailer.message.EmailMessage]) – A list of emails to send

Returns

count of messages sent

Return type

int

class airmailer.backend.aws.SESEmailBackend(fail_silently: bool = False, aws_access_key_id: Optional[str] = None, aws_secret_access_key: Optional[str] = None, aws_region_name: Optional[str] = None, configuration_set_name: Optional[str] = None, aws_region_endpoint: Optional[str] = None, aws_config=None, ses_from_arn: Optional[str] = None, ses_source_arn: Optional[str] = None, ses_return_path_arn: Optional[str] = None, ses_tags: Optional[Dict[str, str]] = None, **kwargs)[source]

Send mails using the AWS SES API.

open() bool[source]

Opens a connection to the AWS SES API.

Returns

True if the connection was opened successfully, False otherwise.

close() None[source]

Close the connection to the AWS SES API.

send_messages(email_messages: List[EmailMessage]) int[source]

Sends one or more messages returns the number of email messages sent.

Parameters

email_messages – A list of emails to send

Raises
  • botocore.exceptions.ClientError – AWS SES had an issue

  • botocore.exceptions.BotoCoreError – AWS SES had an issue

Returns

The number of messages sent