1
0
Fork 0

Adding file-based transports including Maildir, Mbox, Babyl, MH, and MMDF.

This commit is contained in:
Adam Coddington 2012-06-30 22:30:13 -07:00
parent 6a0305f944
commit aa0b79b36f
13 changed files with 174 additions and 77 deletions

View file

@ -4,7 +4,9 @@ import urllib
import urlparse
from django.db import models
from django_mailbox.transports import PopMailEnumerator, ImapMailEnumerator
from django_mailbox.transports import Pop3Transport, ImapTransport,\
MaildirTransport, MboxTransport, BabylTransport, MHTransport, \
MMDFTransport
from django_mailbox.signals import message_received
class Mailbox(models.Model):
@ -12,10 +14,10 @@ class Mailbox(models.Model):
uri = models.CharField(
max_length=255,
help_text="""
Start your URI with imap://, imap+ssl://, pop3://, or pop3+ssl://.
Example: imap+ssl://myusername:mypassword@someserver
<br />
<br />
Example: imap://myusername:mypassword@someserver
Internet transports include 'imap' and 'pop3'; common local file transports include 'maildir', 'mbox', and less commonly 'babyl', 'mh', and 'mmdf'.
<br />
<br />
Be sure to urlencode your username and password should they
@ -60,18 +62,29 @@ class Mailbox(models.Model):
def get_connection(self):
if self.type == 'imap':
conn = ImapMailEnumerator(
conn = ImapTransport(
self.location,
port=self.port if self.port else None,
ssl=self.use_ssl
)
conn.connect(self.username, self.password)
elif self.type == 'pop3':
conn = PopMailEnumerator(
conn = Pop3Transport(
self.location,
port=self.port if self.port else None,
ssl=self.use_ssl
)
conn.connect(self.username, self.password)
conn.connect(self.username, self.password)
elif self.type == 'maildir':
conn = MaildirTransport(self.location)
elif self.type == 'mbox':
conn = MboxTransport(self.location)
elif self.type == 'babyl':
conn = BabylTransport(self.location)
elif self.type == 'mh':
conn = MHTransport(self.location)
elif self.type == 'mmdf':
conn = MMDFTransport(self.location)
return conn
def get_new_mail(self):
@ -79,10 +92,11 @@ class Mailbox(models.Model):
new_mail = []
for message in connection.get_message():
msg = Message()
print msg
msg.mailbox = self
msg.subject = message['subject']
msg.message_id = message['message-id']
msg.from_address = rfc822.parseaddr(message['from'])[1]
msg.subject = message['subject'][0:255]
msg.message_id = message['message-id'][0:255]
msg.from_address = rfc822.parseaddr(message['from'])[1][0:255]
msg.body = message.as_string()
msg.save()
new_mail.append(msg)

View file

@ -1,66 +1 @@
import email
from imaplib import IMAP4, IMAP4_SSL
from poplib import POP3, POP3_SSL
class PopMailEnumerator(object):
def __init__(self, hostname, port=None, ssl=False):
self.hostname = hostname
self.port = port
if ssl:
self.transport = POP3_SSL
if not self.port:
self.port = 995
else:
self.transport = POP3
if not self.port:
self.port = 110
def connect(self, username, password):
self.server = self.transport(self.hostname, self.port)
self.server.user(username)
self.server.pass_(password)
def get_message(self):
message_count = len(self.server.list()[1])
for i in range(message_count):
try:
msg_contents = "\r\n".join(self.server.retr(i + 1)[1])
message = email.message_from_string(msg_contents)
yield message
except email.Errors.MessageParseError:
continue
self.server.dele(i + 1)
self.server.quit()
return
class ImapMailEnumerator(object):
def __init__(self, hostname, port=None, ssl=False):
self.hostname = hostname
self.port = port
if ssl:
self.transport = IMAP4_SSL
if not self.port:
self.port = 993
else:
self.transport = IMAP4
if not self.port:
self.port = 143
def connect(self, username, password):
self.server = self.transport(self.hostname, self.port)
typ, msg = self.server.login(username, password)
self.server.select()
def get_message(self):
typ, inbox = self.server.search(None, 'ALL')
for key in inbox[0].split():
try:
typ, msg_contents = self.server.fetch(key, '(RFC822)')
message = email.message_from_string(msg_contents[0][1])
yield message
except email.Errors.MessageParseError:
continue
self.server.store(key, "+FLAGS", "\\Deleted");
self.server.expunge()
return

View file

@ -0,0 +1,7 @@
from django_mailbox.transports.imap import ImapTransport
from django_mailbox.transports.pop3 import Pop3Transport
from django_mailbox.transports.maildir import MaildirTransport
from django_mailbox.transports.mbox import MboxTransport
from django_mailbox.transports.babyl import BabylTransport
from django_mailbox.transports.mh import MHTransport
from django_mailbox.transports.mmdf import MMDFTransport

View file

@ -0,0 +1,5 @@
from mailbox import Babyl
from django_mailbox.transports.generic import GenericFileMailbox
class BabylTransport(GenericFileMailbox):
_variant = Babyl

View file

@ -0,0 +1,18 @@
class GenericFileMailbox(object):
_variant = None
_path = None
def __init__(self, path):
super(GenericFileMailbox, self).__init__()
self._path = path
def get_instance(self):
return self._variant(self._path)
def get_message(self):
repository = self.get_instance()
repository.lock()
for key, message in repository.items():
repository.remove(key)
yield message
repository.unlock()

View file

@ -0,0 +1,33 @@
import email
from imaplib import IMAP4, IMAP4_SSL
class ImapTransport(object):
def __init__(self, hostname, port=None, ssl=False):
self.hostname = hostname
self.port = port
if ssl:
self.transport = IMAP4_SSL
if not self.port:
self.port = 993
else:
self.transport = IMAP4
if not self.port:
self.port = 143
def connect(self, username, password):
self.server = self.transport(self.hostname, self.port)
typ, msg = self.server.login(username, password)
self.server.select()
def get_message(self):
typ, inbox = self.server.search(None, 'ALL')
for key in inbox[0].split():
try:
typ, msg_contents = self.server.fetch(key, '(RFC822)')
message = email.message_from_string(msg_contents[0][1])
yield message
except email.Errors.MessageParseError:
continue
self.server.store(key, "+FLAGS", "\\Deleted");
self.server.expunge()
return

View file

@ -0,0 +1,8 @@
from mailbox import Maildir
from django_mailbox.transports.generic import GenericFileMailbox
class MaildirTransport(GenericFileMailbox):
_variant = Maildir
def get_instance(self):
return self._variant(self._path, None)

View file

@ -0,0 +1,5 @@
from mailbox import mbox
from django_mailbox.transports.generic import GenericFileMailbox
class MboxTransport(GenericFileMailbox):
_variant = mbox

View file

@ -0,0 +1,5 @@
from mailbox import MH
from django_mailbox.transports.generic import GenericFileMailbox
class MHTransport(GenericFileMailbox):
_variant = MH

View file

@ -0,0 +1,5 @@
from mailbox import MMDF
from django_mailbox.transports.generic import GenericFileMailbox
class MMDFTransport(GenericFileMailbox):
_variant = MMDF

View file

@ -0,0 +1,33 @@
import email
from poplib import POP3, POP3_SSL
class Pop3Transport(object):
def __init__(self, hostname, port=None, ssl=False):
self.hostname = hostname
self.port = port
if ssl:
self.transport = POP3_SSL
if not self.port:
self.port = 995
else:
self.transport = POP3
if not self.port:
self.port = 110
def connect(self, username, password):
self.server = self.transport(self.hostname, self.port)
self.server.user(username)
self.server.pass_(password)
def get_message(self):
message_count = len(self.server.list()[1])
for i in range(message_count):
try:
msg_contents = "\r\n".join(self.server.retr(i + 1)[1])
message = email.message_from_string(msg_contents)
yield message
except email.Errors.MessageParseError:
continue
self.server.dele(i + 1)
self.server.quit()
return

View file

@ -7,8 +7,27 @@ This small Django application will allow you to specify IMAP or POP3 mailboxes t
WARNING! This app will delete any messages it can find in the inbox you specify-- please make sure you don't have anything important in there.
URI Examples
============
Setting up your mailbox
=======================
Django Mailbox supports both common internet mailboxes like POP3 and IMAP as well as local file-based mailboxes.
.. table:: Protocol Options
============ ============== =========================================
Mailbox Type 'Protocol' Notes
============ ============== =========================================
POP3 ``pop3://`` Can also specify SSL with ``pop3+ssl://``
IMAP ``imap://`` Can also specify SSL with ``imap+ssl://``
Maildir ``maildir://``
Mbox ``mbox://``
Babyl ``babyl://``
MH ``mh://``
MMDF ``mmdf://``
============ ============== =========================================
POP3 and IMAP Mailboxes
-----------------------
Mailbox URIs are in the normal URI format::
@ -23,6 +42,16 @@ If you have an account named 'contemporanea@gmail.com' with a password of '1234'
pop3+ssl://contemporanea%40gmail.com:1234@pop.gmail.com
Local File-based Mailboxes
--------------------------
If you happen to want to consume a file-based mailbox like an Maildir, Mbox, Babyl, MH, or MMDF mailbox, you can use this too by entering the appropriate 'protocol' in the URI. If you had a maildir, for example, at @/var/mail/@, you would enter a URI like::
maildir:///var/mail
.. important::
Note that there are three slashes in the above URI.
Subscribing to the incoming mail signal
=======================================

View file

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name='django_mailbox',
version='0.2',
version='1.0',
url='http://bitbucket.org/latestrevision/django-mailbox/',
description='Automatically import mail from POP3 or IMAP into Django',
author='Adam Coddington',