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
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
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.
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 messagerecipient
- 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.