SMTP Email Support

The Smarter framework includes built-in support for sending emails via SMTP, with the email service of the infrastructure services, SMTPEmailService. SMTP works with any SMTP server, so email does not depend on the cloud provider.

Configuration

SMTP is optional, locally and in production. Without SMTP credentials the platform runs, but no email is sent: each email that is not sent logs a console error that names it, its recipients, and the settings below. smarter_settings.smtp_is_configured is True once the username, password, host and port are all set, and none is a placeholder such as SET-ME-PLEASE.

Set the following environment variables to configure SMTP email sending. These will be consumed by Smarter Settings.

SMTP_SENDER=local.platform.smarter.sh
SMTP_PASSWORD=<YOUR_SMTP_PASSWORD (AWS_SES_SMTP_PASSWORD)>
SMTP_USERNAME=<YOUR_SMTP_USERNAME (AWS_SES_SMTP_USERNAME)>
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_USE_TLS=True
SMTP_FROM_EMAIL=no-reply@platform.example.com

SMTP_HOST defaults to the AWS Simple Email Service endpoint of AWS_REGION, email-smtp.<AWS_REGION>.amazonaws.com, and SMTP_FROM_EMAIL defaults to no-reply@ the platform’s domain.

Also see Cloud infrastructure for configuring AWS Simple Email Service (SES) as your SMTP provider.

Basic Usage

from smarter.apps.infrastructure.services import infrastructure

infrastructure.email.send_email(
    subject="Welcome!",
    body="Hello and welcome to Smarter.",
    to="user@example.com",
    html=True,
    from_email="support@smarter.com"
)

Each email is blind copied to the platform’s admin, SMARTER_EMAIL_ADMIN. The copy is added to the SMTP envelope only, so recipients never see the admin’s address. Emails that carry a secret, such as a password reset link, an account activation link, or a new user’s password, pass bcc_admin=False, so that only their recipient receives them.

Delivery failures are logged, and sent as the email_failed signal, rather than raised, so that email never breaks the request that sends it. In the unit tests, nothing is sent, so that tests never email real people. Tests can replace the service with InMemoryEmailService, whose outbox holds what was sent.

Technical Reference

class smarter.apps.infrastructure.services.email.EmailService(provider_name, *args, **kwargs)[source]

Bases: InfrastructureService

The platform’s outgoing email.

static admin_bcc(recipients)[source]

The blind copy to the platform’s admin, smarter_settings.email_admin.

Parameters:

recipients (list[str]) – The email’s recipients, who need no copy.

Return type:

list[str]

Returns:

The admin’s address, or nothing if there is no valid admin address, or the admin is a recipient.

error_class

alias of EmailServiceError

log_not_sent(subject, to)[source]

Log an email that was not sent because the service is not ready.

Parameters:
  • subject (str) – The email’s subject.

  • to (str | List[str]) – The email’s recipients.

Return type:

None

message(subject, body, to, html=False, from_email=None)[source]

Return a message, from smarter_settings.smtp_from_email unless from_email is given.

It has no Bcc header: blind copies are added to the envelope by _deliver().

Return type:

MIMEMultipart

send_email(subject, body, to, html=False, from_email=None, quiet=False, bcc_admin=True)[source]

Send an email.

Failures are logged, and announced with email_failed, rather than raised, so that email never breaks the request that sends it.

Parameters:
  • subject (str) – The subject.

  • body (str) – The body, HTML if html is True.

  • to (str | List[str]) – The recipient, or recipients. Invalid addresses are dropped.

  • html (bool) – True if the body is HTML.

  • from_email (str | None) – The sender, by default smarter_settings.smtp_from_email.

  • quiet (bool) – True to only log what would have been sent.

  • bcc_admin (bool) – Send a blind copy to the platform’s admin, smarter_settings.email_admin. Pass False for an email that carries a secret, e.g. a password reset link, which only its recipient may see.

Return type:

bool

Returns:

True if the email was sent.

service_name: str = 'email'

The name of the service in signals and logs, see InfrastructureServiceNames.

static validate_mail_list(emails, quiet=False)[source]

Return the valid email addresses of a list.

Parameters:
  • emails (str | List[str]) – An email address, or a list of them.

  • quiet (bool) – True to not log invalid addresses.

Return type:

List[str] | None

Returns:

The valid addresses, or None if there are none.

class smarter.apps.infrastructure.services.email.SMTPEmailService(allow_in_tests=False, smtp_class=<class 'smtplib.SMTP'>, **kwargs)[source]

Bases: EmailService

Email, with SMTP, configured by the smtp_* settings of smarter_settings.

In the unit tests, nothing is sent, unless allow_in_tests is True, so that tests never email real people.

Parameters:
  • allow_in_tests (bool) – Send email in the unit tests.

  • smtp_class (Callable[..., SMTP]) – The SMTP client class, e.g. a fake.

__init__(allow_in_tests=False, smtp_class=<class 'smtplib.SMTP'>, **kwargs)[source]
log_not_sent(subject, to)[source]

Log an email that was not sent, with instructions for configuring SMTP.

SMTP is optional, so this is logged for each email that is not sent, rather than raised. In the unit tests, where email is never sent, a one-line warning is logged instead.

Return type:

None

property ready: bool

Whether the service is authenticated and connected, i.e. it can be used.