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 thanRFC5322_EMAIL_LINE_LENGTH_LIMIT
: This sets the body encoding toCharset.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
- 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 inADDRESS_HEADERS
, each address inval
is run throughsanitize_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 UnixFrom_
envelope headerlinesep – 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 UnixFrom_
envelope headerlinesep – 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 complicatedMessage
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”.
- 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 toDEFAULT_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 toDEFAULT_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.
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
andclose
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.
- send_messages(email_messages)[source]
Send one or more
airmailer.message.EmailMessage
objects and return the number of email messages sent.
- 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
- 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
- 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.
- 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