API Reference

This section documents the public API of the python-emails library.

Message

The Message class is the main entry point for creating and sending emails.

class Message(\*\*kwargs)

Create a new email message.

Parameters:
  • html (str or None) – HTML body content (string or file-like object).

  • text (str or None) – Plain text body content (string or file-like object).

  • subject (str or None) – Email subject line. Supports template rendering.

  • mail_from (str or tuple or None) – Sender address. Accepts a string "user@example.com" or a tuple ("Display Name", "user@example.com").

  • mail_to (str or tuple or list or None) – Recipient address(es). Accepts a string, tuple, or list of strings/tuples.

  • cc (str or tuple or list or None) – CC recipient(s). Same format as mail_to.

  • bcc (str or tuple or list or None) – BCC recipient(s). Same format as mail_to.

  • reply_to (str or tuple or list or None) – Reply-To address(es). Same format as mail_to.

  • headers (dict or None) – Custom email headers as a dictionary.

  • headers_encoding (str or None) – Encoding for email headers (default: 'ascii').

  • attachments (list or None) – List of attachments (dicts or BaseFile objects).

  • charset (str or None) – Message character set (default: 'utf-8').

  • message_id (str or MessageID or bool or None) – Message-ID header value. Can be a string, a MessageID instance, False to omit, or None to auto-generate.

  • date (str or datetime or float or bool or callable or None) – Date header value. Accepts a string, datetime, float (timestamp), False to omit, or a callable that returns one of these types.

Example:

import emails

msg = emails.Message(
    html="<p>Hello, World!</p>",
    subject="Test Email",
    mail_from=("Sender", "sender@example.com"),
    mail_to="recipient@example.com"
)

Message Methods

Message.send(to=None, set_mail_to=True, mail_from=None, set_mail_from=False, render=None, smtp_mail_options=None, smtp_rcpt_options=None, smtp=None)

Send the message via SMTP.

Parameters:
  • to – Override recipient address(es).

  • set_mail_to – If True, update the message’s mail_to with to.

  • mail_from – Override sender address.

  • set_mail_from – If True, update the message’s mail_from.

  • render – Dictionary of template variables for rendering.

  • smtp_mail_options – SMTP MAIL command options.

  • smtp_rcpt_options – SMTP RCPT command options.

  • smtp – SMTP configuration. Either a dict with connection parameters (host, port, ssl, tls, user, password, timeout) or an SMTPBackend instance.

Returns:

SMTPResponse or None

Example:

response = msg.send(
    to="user@example.com",
    smtp={"host": "smtp.example.com", "port": 587, "tls": True,
          "user": "login", "password": "secret"}
)
Message.send_async(to=None, set_mail_to=True, mail_from=None, set_mail_from=False, render=None, smtp_mail_options=None, smtp_rcpt_options=None, smtp=None)

Send the message via SMTP asynchronously. Requires aiosmtplib (install with pip install "emails[async]").

Parameters are the same as send(), except smtp accepts a dict or an AsyncSMTPBackend instance.

When smtp is a dict, a temporary AsyncSMTPBackend is created and closed after sending. When an existing backend is passed, the caller is responsible for closing it.

Returns:

SMTPResponse or None

Example:

response = await msg.send_async(
    to="user@example.com",
    smtp={"host": "smtp.example.com", "port": 587, "tls": True,
          "user": "login", "password": "secret"}
)

Using a shared backend for multiple sends:

from emails.backend.smtp.aio_backend import AsyncSMTPBackend

async with AsyncSMTPBackend(host="smtp.example.com", port=587,
                            tls=True, user="login",
                            password="secret") as backend:
    for msg in messages:
        await msg.send_async(smtp=backend)
Message.attach(\*\*kwargs)

Attach a file to the message. Sets content_disposition to 'attachment' by default.

Parameters:
  • filename – Name of the attached file.

  • data – File content as bytes or a file-like object.

  • content_disposition'attachment' (default) or 'inline'.

  • mime_type – MIME type of the file. Auto-detected from filename if not specified.

Example:

msg.attach(filename="report.pdf", data=open("report.pdf", "rb"))
msg.attach(filename="logo.png", data=img_data, content_disposition="inline")
Message.render(\*\*kwargs)

Set template rendering data. Template variables are substituted when accessing html_body, text_body, or subject.

Parameters:

kwargs – Key-value pairs used as template context.

Example:

msg = emails.Message(
    html=emails.template.JinjaTemplate("<p>Hello {{ name }}</p>"),
    subject=emails.template.JinjaTemplate("Welcome, {{ name }}")
)
msg.render(name="World")
Message.as_string(message_cls=None)

Return the message as a string, including DKIM signature if configured.

Parameters:

message_cls – Optional custom MIME message class.

Returns:

Message as a string.

Return type:

str

Message.as_bytes(message_cls=None)

Return the message as bytes with CRLF line endings, including DKIM signature if configured.

Parameters:

message_cls – Optional custom MIME message class.

Returns:

Message as bytes.

Return type:

bytes

Message.as_message(message_cls=None)

Return the underlying MIME message object.

Parameters:

message_cls – Optional custom MIME message class.

Returns:

MIME message object.

Message.transform(\*\*kwargs)

Apply HTML transformations to the message body. Loads and processes the HTML content through the transformer.

See the HTML Transformations section for available parameters.

Message.dkim(key, domain, selector, ignore_sign_errors=False, \*\*kwargs)

Configure DKIM signing for the message. The signature is applied when the message is serialized via as_string(), as_bytes(), or send().

This method is also available as sign().

Parameters:
  • key – Private key for signing (PEM format). String, bytes, or file-like object.

  • domain – DKIM domain (e.g., "example.com").

  • selector – DKIM selector (e.g., "default").

  • ignore_sign_errors – If True, suppress signing exceptions.

Returns:

The message instance (for chaining).

Return type:

Message

Example:

msg.dkim(key=open("private.pem"), domain="example.com", selector="default")

Message Properties

Message.html

Get or set the HTML body content.

Message.text

Get or set the plain text body content.

Message.html_body

The rendered HTML body (read-only). If templates are used, returns the rendered result; otherwise returns the raw HTML.

Message.text_body

The rendered text body (read-only). If templates are used, returns the rendered result; otherwise returns the raw text.

Message.mail_from

Get or set the sender address. Returns a (name, email) tuple.

Message.mail_to

Get or set the recipient address(es). Returns a list of (name, email) tuples.

Message.cc

Get or set CC recipient(s). Returns a list of (name, email) tuples.

Message.bcc

Get or set BCC recipient(s). Returns a list of (name, email) tuples.

Message.reply_to

Get or set Reply-To address(es). Returns a list of (name, email) tuples.

Message.subject

Get or set the email subject. Supports template rendering.

Message.message_id

Get or set the Message-ID header value.

Message.date

Get or set the Date header value.

Message.charset

Get or set the message character set (default: 'utf-8').

Message.headers_encoding

Get or set the encoding for email headers (default: 'ascii').

Message.attachments

Access the attachment store (MemoryFileStore). Lazily initialized.

Message.render_data

Get or set the template rendering context dictionary.

Message.transformer

Access the HTML transformer for custom image/link transformations. Lazily created on first access. See the HTML Transformations section for usage examples.

SMTPResponse

Returned by Message.send(). Contains information about the SMTP transaction.

class SMTPResponse
status_code

The SMTP status code from the last command (e.g., 250 for success). None if the transaction was not completed.

status_text

The SMTP status text from the last command, as bytes.

success

True if the message was sent successfully (status code is 250 and the transaction completed).

error

The exception object if an error occurred, or None.

refused_recipients

A dictionary mapping refused recipient email addresses to (code, message) tuples.

last_command

The last SMTP command that was sent (e.g., 'mail', 'rcpt', 'data').

Example:

response = msg.send(smtp={"host": "localhost"})
if response.success:
    print("Sent!")
else:
    print(f"Failed: {response.status_code} {response.status_text}")
    if response.error:
        print(f"Error: {response.error}")
    if response.refused_recipients:
        print(f"Refused: {response.refused_recipients}")

AsyncSMTPBackend

For async sending via Message.send_async(). Requires aiosmtplib (install with pip install "emails[async]").

class emails.backend.smtp.aio_backend.AsyncSMTPBackend(ssl=False, fail_silently=True, mail_options=None, \*\*kwargs)

Manages an async SMTP connection. Supports async with for automatic cleanup.

Parameters:
  • host – SMTP server hostname.

  • port – SMTP server port.

  • ssl – Use implicit TLS (SMTPS).

  • tls – Use STARTTLS after connecting.

  • user – SMTP username for authentication.

  • password – SMTP password for authentication.

  • timeout – Connection timeout in seconds (default: 5).

  • fail_silently – If True (default), SMTP errors are captured in the response rather than raised.

  • mail_options – Default SMTP MAIL command options.

async sendmail(from_addr, to_addrs, msg, mail_options=None, rcpt_options=None)

Send a message. Automatically retries once on server disconnect.

Returns:

SMTPResponse or None

async close()

Close the SMTP connection.

Example:

from emails.backend.smtp.aio_backend import AsyncSMTPBackend

async with AsyncSMTPBackend(host="smtp.example.com", port=587,
                            tls=True, user="me",
                            password="secret") as backend:
    response = await backend.sendmail(
        from_addr="sender@example.com",
        to_addrs=["recipient@example.com"],
        msg=message
    )

Loaders

Loader functions create Message instances from various sources.

All loaders are available in the emails.loader module.

emails.loader.from_html(html, text=None, base_url=None, message_params=None, local_loader=None, template_cls=None, message_cls=None, source_filename=None, requests_params=None, \*\*kwargs)

Create a message from an HTML string. Images and stylesheets referenced in the HTML can be automatically loaded and embedded.

Parameters:
  • html – HTML content as a string.

  • text – Optional plain text alternative.

  • base_url – Base URL for resolving relative URLs in the HTML.

  • message_params – Additional parameters passed to the Message constructor.

  • local_loader – A loader instance for resolving local file references.

  • template_cls – Template class to use for the HTML body.

  • message_cls – Custom Message class to instantiate.

  • source_filename – Filename hint for the source HTML.

  • requests_params – Parameters passed to HTTP requests when fetching resources.

  • kwargs – Additional transformer options.

Returns:

A Message instance.

from_string is an alias for this function.

emails.loader.from_url(url, requests_params=None, \*\*kwargs)

Create a message by downloading an HTML page from a URL. Images and stylesheets are fetched and embedded.

Parameters:
  • url – URL of the HTML page.

  • requests_params – Parameters passed to HTTP requests.

  • kwargs – Additional transformer options.

Returns:

A Message instance.

load_url is an alias for this function.

emails.loader.from_directory(directory, loader_cls=None, \*\*kwargs)

Create a message from a local directory. The directory should contain an HTML file and any referenced images or attachments.

Parameters:
  • directory – Path to the directory.

  • loader_cls – Custom loader class.

  • kwargs – Additional options (html_filename, text_filename, message_params).

Returns:

A Message instance.

emails.loader.from_zip(zip_file, loader_cls=None, \*\*kwargs)

Create a message from a ZIP archive containing HTML and resources.

Parameters:
  • zip_file – Path to ZIP file or a file-like object.

  • loader_cls – Custom loader class.

  • kwargs – Additional options (html_filename, text_filename, message_params).

Returns:

A Message instance.

emails.loader.from_file(filename, \*\*kwargs)

Create a message from a single HTML file.

Parameters:
  • filename – Path to the HTML file.

  • kwargs – Additional options (message_params).

Returns:

A Message instance.

emails.loader.from_rfc822(msg, loader_cls=None, message_params=None, parse_headers=False)

Create a message from an RFC 822 email object (e.g., from email.message). Primarily intended for demonstration and testing purposes.

Parameters:
  • msg – An email.message.Message object.

  • loader_cls – Custom loader class.

  • message_params – Additional parameters for the Message constructor.

  • parse_headers – If True, parse and transfer email headers.

Returns:

A Message instance.

Loader Exceptions

exception emails.loader.LoadError

Base exception for all loader errors.

exception emails.loader.IndexFileNotFound

Raised when the loader cannot find an HTML index file in the source. Subclass of LoadError.

exception emails.loader.InvalidHtmlFile

Raised when the HTML content cannot be parsed. Subclass of LoadError.

Templates

Template classes allow dynamic content in email bodies and subjects. Pass a template instance as the html, text, or subject parameter of Message.

Install template dependencies with extras:

pip install "emails[jinja]"   # for JinjaTemplate
class emails.template.JinjaTemplate(template_text, environment=None)

Template using Jinja2 syntax.

Parameters:
  • template_text – Jinja2 template string.

  • environment – Optional jinja2.Environment instance.

Example:

from emails.template import JinjaTemplate

msg = emails.Message(
    html=JinjaTemplate("<p>Hello {{ name }}!</p>"),
    subject=JinjaTemplate("Welcome, {{ name }}"),
    mail_from="noreply@example.com"
)
msg.send(render={"name": "Alice"}, smtp={"host": "localhost"})
class emails.template.StringTemplate(template_text, safe_substitute=True)

Template using Python’s string.Template syntax ($variable or ${variable}).

Parameters:
  • template_text – Template string.

  • safe_substitute – If True (default), undefined variables are left as-is. If False, undefined variables raise KeyError.

Example:

from emails.template import StringTemplate

msg = emails.Message(
    html=StringTemplate("<p>Hello $name!</p>"),
    mail_from="noreply@example.com"
)
class emails.template.MakoTemplate(template_text, \*\*kwargs)

Template using Mako syntax. Requires the mako package.

Parameters:
  • template_text – Mako template string.

  • kwargs – Additional parameters passed to mako.template.Template.

DjangoMessage

A Message subclass for use with Django’s email backend.

class emails.django.DjangoMessage(\*\*kwargs)

Accepts the same parameters as Message. Integrates with Django’s email sending infrastructure.

send(mail_to=None, set_mail_to=True, mail_from=None, set_mail_from=False, context=None, connection=None, to=None)

Send the message through Django’s email backend.

Parameters:
  • context – Dictionary of template rendering variables (equivalent to render in Message.send()).

  • connection – A Django email backend connection instance (e.g., from django.core.mail.get_connection()). If None, uses the default backend.

  • to – Alias for mail_to.

Returns:

1 if the message was sent successfully, 0 otherwise.

Return type:

int

Example:

from emails.django import DjangoMessage

msg = DjangoMessage(
    html="<p>Hello {{ name }}</p>",
    subject="Welcome",
    mail_from="noreply@example.com"
)
msg.send(to="user@example.com", context={"name": "Alice"})

DKIM

DKIM (DomainKeys Identified Mail) signing is configured via the Message.dkim() method (or its alias Message.sign()).

Parameters:

  • key – Private key in PEM format. Accepts a string, bytes, or file-like object.

  • domain – The signing domain (e.g., "example.com").

  • selector – The DKIM selector (e.g., "default").

  • ignore_sign_errors – If True, silently ignore signing errors instead of raising exceptions.

  • Additional keyword arguments are passed to the DKIM library (e.g., canonicalize, signature_algorithm).

Returns the message instance (for chaining).

Example:

import emails

msg = emails.Message(
    html="<p>Signed message</p>",
    mail_from=("Sender", "sender@example.com"),
    subject="DKIM Test"
)
msg.dkim(
    key=open("private.pem").read(),
    domain="example.com",
    selector="default"
)
msg.send(to="recipient@example.com", smtp={"host": "localhost"})

The signature is automatically applied when the message is serialized (via as_string(), as_bytes(), or send()).

Exceptions

exception emails.HTTPLoaderError

Raised when loading content from a URL fails (e.g., HTTP error, connection timeout).

exception emails.BadHeaderError

Raised when an email header contains invalid characters (such as newlines or carriage returns).

exception emails.IncompleteMessage

Raised when attempting to send a message that lacks required content (no HTML and no text body).

See also the Loader Exceptions section for loader-specific exceptions: LoadError, IndexFileNotFound, InvalidHtmlFile.

Utilities

class emails.utils.MessageID(domain=None, idstring=None)

Generator for RFC 2822 compliant Message-ID values.

Parameters:
  • domain – Domain part of the Message-ID. Defaults to the machine’s FQDN.

  • idstring – Optional additional string to strengthen uniqueness.

The instance is callable — each call generates a new unique Message-ID.

Example:

from emails.utils import MessageID

# Auto-generate a new Message-ID for each send
msg = emails.Message(
    message_id=MessageID(domain="example.com"),
    html="<p>Hello</p>",
    mail_from="sender@example.com"
)
emails.html(\*\*kwargs)

Convenience function that creates and returns a Message instance. Accepts all the same parameters as the Message constructor.

Example:

msg = emails.html(
    html="<p>Hello!</p>",
    subject="Test",
    mail_from="sender@example.com"
)