Sending and responding to email in code
Email is the most popular messaging platform on Earth. We use email to arrange events, to exchange files, and to notify each other when something happens.
You should be able to email your applications too. But to receive email, you need to set up a server somewhere, run an SMTP daemon, and somehow connect that to your code.
We’re here to fix that. Today, we’re delighted to show you the easiest way to build email-driven apps. All you need to do is write a Python function. For example, here’s all the code you need to receive emails and store them in a database:
@anvil.email.handle_message def incoming_email(msg): app_tables.incoming_messages.add_row( from_addr=msg.envelope.from_address, text=msg.text ) msg.reply(text="Thank you for your message.")
Sending is just as simple:
anvil.email.send( to="email@example.com", subject="New message", text="This is awesome", html="This is <b>awesome</b>" )
Despite its simplicity, it’s also fully featured - you can handle attachments, recipients, and even use DKIM to check that a message is genuine before trusting what it says.
You can scroll down for a cookbook of common examples, or watch as I build a full disposable-email-address service, and publish it on the web, in four minutes:
Video example: Disposable Email
Note: This guide includes screenshots of the Classic Editor. Since we created this guide, we've released the new Anvil Editor, which is more powerful and easier to use.
All the code in this guide will work, but the Anvil Editor will look a little different to the screenshots you see here!
Sample Email Code
Here are a few things you might want to do with email. You can follow along from these code snippets, or view them all in the Anvil editor:
1. Receiving email and saving it in a database
@anvil.email.handle_message def incoming_email(msg): app_tables.incoming_messages.add_row( from_addr=msg.envelope.sender, text=msg.text )
2. Replying to an email you’ve received
@anvil.email.handle_message def incoming_email(msg): msg.reply(text="Thank you for your message.")
3. Sending email
@anvil.server.callable def send_a_message(txt): anvil.email.send( to=["firstname.lastname@example.org"], cc=["Someone Else <email@example.com>"], subject="Hello World", text="Hi there!" )
4. Handling attachments
All attachments are Anvil Media objects. This means you can upload them from web browsers, store them in databases, make them downloadable, and more.
@anvil.server.callable def send_by_email(file): anvil.email.send( to="firstname.lastname@example.org", subject="New upload", attachments=[file] )
Incoming attachments are just as straightforward. Here’s how to save all attachments in a database:
@anvil.email.handle_message def incoming_email(msg): for f in msg.attachments: app_tables.files.add_row(file=f)
5. Authenticating senders
Email has historically been easy to spoof. Helpfully, many providers now support DKIM, which lets you verify that the email actually came from the domain it says it did.
dkim property of the message contains details about all that message’s valid DKIM signatures, and a shortcut to check whether it’s signed by the address in
@anvil.email.handle_message def incoming_email(msg): if msg.envelope.from_address == 'email@example.com' and msg.dkim.valid_from_sender: msg.reply(text="You're the real deal!")
There’s a shorthand, if you only want to accept DKIM-authenticated messages (and reject all others):
@anvil.email.handle_message(require_dkim=True) def incoming_email(msg): if msg.envelope.from_address == 'firstname.lastname@example.org': msg.reply(text="You're the real deal!")
6. Rejecting (“bouncing”) messages
@anvil.email.handle_message def incoming_email(msg): raise anvil.email.DeliveryFailure("Nope")
Try it yourself
Start writing email-driven apps for free with Anvil:
You can also read more about the Email service in the Anvil reference docs.