Collect Inbound Email Using Python and Flask


Posted on

FlaskOur Inbound Parse Webhook allows your app to receive an email formatted as a JSON object for easy processing. Any script will do for creating the webhook endpoint, but in this tutorial I’ll share a simple Python microframework called Flask.

Set Up and Configure your SendGrid Account

The Incoming Parse Webhook is available through our free, Silver and higher plans. If you don’t have a SendGrid account, go ahead and sign up here.

After completing your SendGrid account setup, we will need to create an email address to be used for receiving emails. This is achieved by setting your MX records to point at mx.sendgrid.net. Each host will have a different method, so please check with your provider.

You may not want all of your incoming emails to be processed by SendGrid, so I suggest you set up a subdomain such as email.yourdomain.com. If you want to start testing right away, you can use ByMail.in–check out the the five minute approach.

Before moving to the next step, please verify that the MX record has propagated or use the ByMail.in address.

Next, you will need to set up the Incoming Parse Webhook’s settings at your SendGrid account. The hostname is the domain you set the MX records to point to or the ByMail.in address. The URL will be where we will post the incoming emails. Additional details can be found at our documentation.

Set Up the Listening Server

Parse diagram

Next, we will need a server to consume the incoming emails. Since we are using Flask, we need to make sure our server meets the minimum requirements (Python 2.6 or higher). I recommend Heroku as a host. For testing locally, check out localtunnel or ngrok.

Consume the Incoming Emails

Now that we have the host setup, it’s time to write the code that will accept the incoming email. If you are new to Flask, I suggest you work through their quickstart tutorial first.

You will need to include the simplejson library for this example.

First, we need to set up a route that matches the URL we specified in our SendGrid settings. For example, if your URL is yourdomain.com/parse

@app.route('/parse', methods=['POST'])

Directly under that line of code, define the function that will do the parsing:

def parser():
# Required response to SendGrid.com’s Parse API
print "HTTP/1.1 200 OK"

# Consume the entire email
envelope = simplejson.loads(request.form.get(‘envelope’))

# Get some header information
to_address = envelope['to'][0]
from_address = envelope['from']

# Now, onto the body
text = request.form.get(‘text’)
html = request.form.get(‘html’)
subject = request.form.get(‘subject’)

# Process the attachements, if any
num_attachments = int(request.form.get(‘attachments’, 0))
attachments = []
if num_attachments > 0:
for num in range(1, (num_attachments + 1)):
attachment = request.files.get((‘attachment%d’ % num))
attachments.append(attachment.read())

Now, you can manipulate the variables to your app’s needs. If you want your app to send a reply email, check out our Python library. For a complete listing of all accessible Incoming Parse Webhook parameters, check out our documentation.

Continue the Journey

Now it’s time for you to create a new awesome customer experience! If you aren’t so sure about Flash, see how easy it is to receive email in Rails. Or, for further inspiration, see how Kunal finds text in email attachments.

We would love to hear what you come up with, so go ahead and share your idea or completed project with us in the comments. Don’t hesitate to reach out if you run into any issues or if you have any suggestions. Have fun!


Elmer Thomas is SendGrid's Hacker in Residence. His mission is to help SendGrid live up to its slogan: "Email Delivery. Simplified" by improving the lives of developers, both internally and externally. Via all sorts of hackery, of course. Follow his exploits on Twitter and GitHub.

Elmer Thomas on Twitter

One thought on “Collect Inbound Email Using Python and Flask

  1. Pingback: Make a Twitter Clone With This Flask Tutorial

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>