5

I understand how sending email works through Django, but I want users to be able to respond to the email. If the email they send (and I receive) contains a message that matches a certain string, I will call a function.

I have done a few google searches but there seems to be no good solution other than to just make the script myself. Please correct me if there is something out there that could do this; otherwise, what could I use to get started on how to write my own script to do this?

Thanks!

  • 1
    I think you'll have to make the script yourself. However, this might be useful for that: http://stackoverflow.com/questions/1225586/checking-email-with-python – Nick ODell Jan 02 '13 at 19:39

3 Answers3

5

We are doing something similar with plone by configuring postfix to do a HTTP request to plone when receiving an email to a specific domain. This should also easily be possible with django, so that you just have to configure your server and write a view in django which receives the email.

That's how you can do it:

1) Set up your DNS so that a MX record for the domain points to your server.

2) Configure a postfix virtual alias /etc/postfix/virtual:

example.com anything
django@example.com django-mail-in

3) and /etc/aliases:

django-mail-in: "|/usr/local/bin/mta2django.py http://127.0.0.1:8000/mail-inbound"

4) The /usr/local/bin/mta2django.py is called by postscript and sends the mail to the mail-inbound django view. This mta2django.py should work:

#!/usr/bin/python

import sys, urllib
import os


def post_message(url, recipient, message_txt):
    """ post an email message to the given url
    """

    if not url:
        print "Invalid url."
        print "usage: mta2django.py url <recipient>"
        sys.exit(64)

    data = {'mail': message_txt}
    if recipient and len(recipient) > 0:
        data ['recipient'] = recipient

    try:
        result = urllib.urlopen(url, urllib.urlencode(data)).read()
    except (IOError,EOFError),e:
        print "error: could not connect to server",e
        sys.exit(73)

    try:
        exitcode, errormsg = result.split(':')
        if exitcode != '0':
            print 'Error %s: %s' % (exitcode, errormsg)
            sys.exit(int(exitcode))
    except ValueError:
        print 'Unknown error.'
        sys.exit(69)

    sys.exit(0)


if __name__ == '__main__':
    # This gets called by the MTA when a new message arrives.
    # The mail message file gets passed in on the stdin

    # Get the raw mail
    message_txt = sys.stdin.read()

    url = ''
    if len(sys.argv)>1:
        url = sys.argv[1]

    recipient = ''
    # If mta2django is executed as external command by the MTA, the
    # environment variable ORIGINAL_RECIPIENT contains the entire
    # recipient address, before any address rewriting or aliasing
    recipient = os.environ.get('ORIGINAL_RECIPIENT')

    if len(sys.argv)>2:
        recipient = sys.argv[2]

    post_message(url, recipient, message_txt)

5) Write a django view /mail-inbound which receives the mail and does the things you need it to do. In the request you have:

  • mail - the full email message
  • recipient - the original recipient (useful when you do not catch a specific email address but the whole domain / subdomain)

You can parse the email using the python email module:

import email

msg = email.message_from_string(request.get('mail'))

As I'm no postfix expert, I'm not sure if editing /etc/postfix/virtual and /etc/aliases is sufficient. Please consult the postfix documentation for details.

jone
  • 1,864
  • 12
  • 11
1

Use Mailgun.

You'll need to give MailGun a URL that it would POST to and you can parse the email message.

http://documentation.mailgun.net/quickstart.html#receiving-and-parsing-email

dannyroa
  • 5,501
  • 6
  • 41
  • 59
0

Django doesn't provide any email receiving support.

Lamson may be a good alternative if you need something more advanced than checking out email using poplib, or something more pythonic than interacting with postfix.

Gonzalo
  • 4,145
  • 2
  • 29
  • 27