1
0
Fork 0

Initial commit.

This commit is contained in:
Adam Coddington 2012-06-27 20:45:01 -07:00
commit 413b60e35f
13 changed files with 340 additions and 0 deletions

View file

29
django_mailbox/admin.py Normal file
View file

@ -0,0 +1,29 @@
from django.conf import settings
from django.contrib import admin
from django_mailbox.models import Message, Mailbox
def get_new_mail(mailbox_admin, request, queryset):
for mailbox in queryset.all():
mailbox.get_new_mail()
get_new_mail.short_description = 'Get new mail'
class MailboxAdmin(admin.ModelAdmin):
list_display = (
'name',
'uri',
)
actions = [get_new_mail]
class MessageAdmin(admin.ModelAdmin):
list_display = (
'subject',
'from_address',
'received',
'mailbox',
)
ordering = ['-received']
if getattr(settings, 'DJANGO_MAILBOX_ADMIN_ENABLED', True):
admin.site.register(Message, MessageAdmin)
admin.site.register(Mailbox, MailboxAdmin)

View file

View file

@ -0,0 +1,18 @@
from django.core.management.base import BaseCommand
from django.dispatch import receiver
from django_mailbox.models import Mailbox
from django_mailbox.signals import message_received
class Command(BaseCommand):
def handle(self, *args, **options):
mailboxes = Mailbox.objects.all()
if args:
mailboxes = mailboxes.filter(name = ' '.join(args))
for mailbox in mailboxes:
self.stdout.write('Gathering messages for %s\n' % mailbox.name)
mailbox.get_new_mail()
@receiver(message_received)
def incoming_message(self, sender, message, **kwargs):
self.stdout.write('Received %s\n' % message.subject)

View file

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Mailbox'
db.create_table('django_mailbox_mailbox', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
('uri', self.gf('django.db.models.fields.CharField')(max_length=255)),
))
db.send_create_signal('django_mailbox', ['Mailbox'])
# Adding model 'Message'
db.create_table('django_mailbox_message', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('mailbox', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['django_mailbox.Mailbox'])),
('subject', self.gf('django.db.models.fields.CharField')(max_length=255)),
('message_id', self.gf('django.db.models.fields.CharField')(max_length=255)),
('from_address', self.gf('django.db.models.fields.CharField')(max_length=255)),
('body', self.gf('django.db.models.fields.TextField')()),
('received', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
))
db.send_create_signal('django_mailbox', ['Message'])
def backwards(self, orm):
# Deleting model 'Mailbox'
db.delete_table('django_mailbox_mailbox')
# Deleting model 'Message'
db.delete_table('django_mailbox_message')
models = {
'django_mailbox.mailbox': {
'Meta': {'object_name': 'Mailbox'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uri': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'django_mailbox.message': {
'Meta': {'object_name': 'Message'},
'body': ('django.db.models.fields.TextField', [], {}),
'from_address': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['django_mailbox.Mailbox']"}),
'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'received': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'})
}
}
complete_apps = ['django_mailbox']

View file

105
django_mailbox/models.py Normal file
View file

@ -0,0 +1,105 @@
import email
import rfc822
import urllib
import urlparse
from django.db import models
from django_mailbox.transports import PopMailEnumerator, ImapMailEnumerator
from django_mailbox.signals import message_received
class Mailbox(models.Model):
name = models.CharField(max_length=255)
uri = models.CharField(
max_length=255,
help_text="""
Start your URI with imap:// or pop3://.
<br />
<br />
Example: imap://myusername:mypassword@someserver
<br />
<br />
Be sure to urlencode your username and password should they
contain illegal characters (like @, :, etc).
"""
)
@property
def _protocol_info(self):
return urlparse.urlparse(self.uri)
@property
def _domain(self):
return self._protocol_info.hostname
@property
def port(self):
return self._protocol_info.port
@property
def username(self):
return urllib.unquote(self._protocol_info.username)
@property
def password(self):
return urllib.unquote(self._protocol_info.password)
@property
def location(self):
return self._domain if self._domain else '' + self._protocol_info.path
@property
def type(self):
return self._protocol_info.scheme.lower()
def get_connection(self):
if self.type == 'imap':
conn = ImapMailEnumerator(
self.location,
self.port if self.port else 143
)
elif self.type == 'pop3':
conn = PopMailEnumerator(
self.location,
self.port if self.port else 110
)
conn.connect(self.username, self.password)
return conn
def get_new_mail(self):
connection = self.get_connection()
new_mail = []
for message in connection.get_message():
msg = Message()
msg.mailbox = self
msg.subject = message['subject']
msg.message_id = message['message-id']
msg.from_address = rfc822.parseaddr(message['from'])[1]
msg.body = message.as_string()
msg.save()
new_mail.append(msg)
message_received.send(sender=self, message=msg)
return new_mail
def __unicode__(self):
return self.name
class Meta:
verbose_name_plural = "Mailboxes"
class Message(models.Model):
mailbox = models.ForeignKey(Mailbox, related_name='messages')
subject = models.CharField(max_length=255)
message_id = models.CharField(max_length=255)
from_address = models.CharField(max_length=255)
body = models.TextField()
received = models.DateTimeField(
auto_now_add=True
)
def get_email_object(self):
return email.message_from_string(self.body)
def __unicode__(self):
return self.subject

View file

@ -0,0 +1,3 @@
from django.dispatch.dispatcher import Signal
message_received = Signal(providing_args=['message'])

View file

@ -0,0 +1,50 @@
import email
from imaplib import IMAP4
from poplib import POP3
class PopMailEnumerator(object):
def __init__(self, hostname, port):
self.hostname = hostname
self.port = port
def connect(self, username, password):
self.server = POP3(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):
self.hostname = hostname
self.port = port
def connect(self, username, password):
self.server = IMAP4(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