Developer Interface
Messages
Adapted shamelessly from Django 3.2.9.
- airmailer.message.utf8_charset = utf-8
Our
utf-8charset 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-8charset 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
nameis inADDRESS_HEADERS, each address invalis run throughsanitize_address.Given a header name and header value, check if there are any newline characters in it. If there are, raise a
BadHeaderErrorexception.- 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
Messagethat 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.Messagesubclass 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.MIMETextsubclass 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.Messagedirectly so that we can send the same message to multiple recipients and to ease the construction of the complicatedMessageobject.- 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.MIMEBasesubclass, 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_TYPEand 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_TYPEif 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_TYPEand 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
EmailMessagethat 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_messagesopenandclosecan 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_messagesmethod of the SMTP backend for a reference implementation.The default implementation does nothing.
- send_messages(email_messages)[source]
Send one or more
airmailer.message.EmailMessageobjects 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
Trueif the connection was opened successfully,Falseotherwise.
- 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