Thursday, August 1st, 2013

Have Django respond to Email in real-time

It's been a long time since I wrote a new article on Python Diary, and I do apologize for the lack of content recently. Hopefully this interesting article will make up for that.

Have you ever wanted Django to parse an incoming Email in real-time as soon as it comes into your server? Look no further than this handy solution here. In order to use this solution, you will need to configure a local Postfix server, it doesn't need to be-able to send outbound email, only receive new messages for your domain. Although being able to send messages will make it easier to reply back to the user's whom are sending the server messages.

You will first need to create a short Python script which Postfix will deliver the actual message to:

import sys
import urllib2

req = urllib2.Request(url='[Django URL]',
f = urllib2.urlopen(req)

This script submits the entire message unmodified directly to any web address you give the script, preferably a Django URL. Notice that I am not using the standard form encoding, as there is no need to add additional overhead when all we want to do is have Django process an entire message. The main reason why this script exists, is because this script will run normally as nobody:nogroup, so it will not be-able to easily talk with your local Django app directly using say, a management script. Sending the data directly over HTTP to the Django instance is simple and should have very little overhead and integrate easily with existing solutions.

from django.views.decorators.csrf import csrf_exempt
from email import message_from_string
from django.http import HttpResponse

def mail_parse(req):
  msg = message_from_string(req.body)
  # Process data from msg here!
  return HttpResponse("OK", content_type="text/plain")

Here is the Django view which will receive the raw message data and parse it. You should read the Python documentation on the subject to learn how to extract the headers, body, and attachments you want to parse. Finally, here is what you should place in your /etc/aliases:

api:         |/[path to script].py

Be sure to run newaliases afterwards to rebuild the hash table. This alias here makes anything api@[domain] submit to your Django site. Enjoy!

Python Powered | © 2012-2014 Kevin Veroneau