You are currently viewing the new Anvil Editor Docs.
Switch to the Classic Editor Docs
You are currently viewing the Classic Editor Docs.
Switch to the new Anvil Editor Docs

Sending and Receiving Email in your Apps

Enabling the Email Service

To enable the Email Service, click the ‘plus’ next to services in the App Browser:

To enable the Email Service, click the blue plus button + in the Sidebar Menu, then choose Email.

Sending Email

To send an email, use the function, passing in data as keyword parameters. This can only be called from a Server Module.

On the Free Plan, all emails are redirected to the app owner, unless you choose to set up your personal SMTP server in the Email service. Full Email service is available on the Personal Plan and above. Each plan has a different email quota.

See the API docs for for the full list of parameters.
  from_name="MyApp Support",
  subject="Welcome to MyApp",

Receiving Email

To receive emails to your app, register a server function to handle incoming messages using the decorator. Any emails sent to (or anything@YOUR_CUSTOM_DOMAIN) will be passed to the decorated function.

This example stores incoming email messages and attachments in Data Tables and sends a reply to each message.
def handle_incoming_emails(msg):
  msg.reply(text="Thank you for your message.")

  msg_row = app_tables.received_messages.add_row(
  for a in msg.attachments:

The msg argument is of type See the API docs for full details of the Message object.


The msg.addressees object contains all the parsed addressees of the message. This saves you from having to parse addresses like "John.Doe <>" manually. The addressees object has three attributes:

  • from_address - A parsed address from the FROM header.
  • to_addresses - A list of parsed addresses from the TO headers.
  • cc_addresses - A list of parsed addresses from the CC headers.

Parsed addresses have three attributes:

  • address - The plain email address of this addressee, e.g.
  • name - The display name of this addressee, e.g. John Doe.
  • raw_value - A single string containing both address and display name, e.g. John Doe <>.

In the following example, we use the parsed name of the sender to greet them by name in the reply.
  def handle_incoming_emails(msg):
    msg.reply(text=f"Hi {}, thank you for your message.")

Rejecting email

To reject an incoming email, raise an exception. This will return an SMTP failure response, which will usually cause a “bounce” email to be sent to the original sender.

You may specify a message, which will usually appear in that “bounce” email

You may also supply an SMTP error code, which suggests whether the sending mail server should reattempt delivery later. The default error code is 554 (a permanent error).
  def handle_incoming_emails(msg):
    raise"Delivery failed, try again later", 451)

If your messaging handling function raises an error, Anvil will generate a temporary SMTP error code (451), which invites the sending system to try delivering that message again later.

Test Mode

When test mode is enabled, all outgoing email will be sent to the owner of the app instead of the specified recipients. This allows you to test changes to your app without accidentally emailing your real users.

The Email Service view, showing a checked checkbox saying 'test mode' and a notification informing you that sent emails will go to your address.

Custom Mail Server

You can configure the Email Service to use your own SMTP server if you wish. Simply tick “Use Custom Mail Server”, then enter your SMTP connection settings. The password will be encrypted and stored using the same mechanism as used by the Secrets Service. After entering the settings, click “Test settings” to check that they work.

Email sent through a custom SMTP server does not count towards your monthly quota.

The Email Service view, showing a checked checkbox saying 'custom mail server' and a form where you can enter your SMTP server settings.


Outgoing email is subject to a monthly quota, depending on your account plan.

If you exceed your monthly quota, all outgoing emails will be re-routed to the app owner, just like in Test Mode. Your monthly quota resets on the 1st of each month.

Email sent through a custom SMTP server does not count towards your monthly quota.

Do you still have questions?

Our Community Forum is full of helpful information and Anvil experts.