mirror of
https://github.com/coddingtonbear/django-mailbox.git
synced 2026-07-09 22:38:19 +02:00
Actually fixing Python 3 support; verified both IMAP and POP3. Fixes #13 (seriously this time).
This commit is contained in:
parent
4002d5c222
commit
3b2d60a903
9 changed files with 145 additions and 16 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,5 +2,7 @@
|
|||
bin/*
|
||||
lib/*
|
||||
src/*
|
||||
dist/*
|
||||
include/*
|
||||
.Python
|
||||
*egg*
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from .test_mailbox import *
|
||||
from .test_message_flattening import *
|
||||
from .test_process_email import *
|
||||
from .test_transports import *
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import email
|
||||
import os.path
|
||||
|
||||
import six
|
||||
|
||||
from django.test import TestCase
|
||||
import sys
|
||||
|
||||
from django_mailbox import models
|
||||
from django_mailbox.models import Mailbox, Message
|
||||
|
|
@ -22,7 +23,7 @@ class EmailMessageTestCase(TestCase):
|
|||
self.mailbox = Mailbox.objects.create()
|
||||
super(EmailMessageTestCase, self).setUp()
|
||||
|
||||
def _get_email_object(self, name):
|
||||
def _get_email_as_text(self, name):
|
||||
with open(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
|
|
@ -31,10 +32,14 @@ class EmailMessageTestCase(TestCase):
|
|||
),
|
||||
'rb'
|
||||
) as f:
|
||||
if sys.version_info < (3, 0):
|
||||
return email.message_from_string(f.read())
|
||||
else:
|
||||
return email.message_from_bytes(f.read())
|
||||
return f.read()
|
||||
|
||||
def _get_email_object(self, name):
|
||||
copy = self._get_email_as_text(name)
|
||||
if six.PY3:
|
||||
return email.message_from_bytes(copy)
|
||||
else:
|
||||
return email.message_from_string(copy)
|
||||
|
||||
def _headers_identical(self, left, right, header=None):
|
||||
""" Check if headers are (close enough to) identical.
|
||||
|
|
|
|||
87
django_mailbox/tests/test_transports.py
Normal file
87
django_mailbox/tests/test_transports.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import mock
|
||||
import six
|
||||
|
||||
from django_mailbox.tests.base import EmailMessageTestCase
|
||||
from django_mailbox.transports import ImapTransport, Pop3Transport
|
||||
|
||||
|
||||
class TestImapTransport(EmailMessageTestCase):
|
||||
def setUp(self):
|
||||
self.arbitrary_hostname = 'one.two.three'
|
||||
self.arbitrary_port = 100
|
||||
self.ssl = False
|
||||
self.transport = ImapTransport(
|
||||
self.arbitrary_hostname,
|
||||
self.arbitrary_port,
|
||||
self.ssl
|
||||
)
|
||||
self.transport.server = None
|
||||
super(TestImapTransport, self).setUp()
|
||||
|
||||
def test_get_email_message(self):
|
||||
with mock.patch.object(self.transport, 'server') as server:
|
||||
server.search.return_value = (
|
||||
'OK',
|
||||
[
|
||||
'One', # This is totally arbitrary
|
||||
]
|
||||
)
|
||||
server.fetch.return_value = (
|
||||
'OK',
|
||||
[
|
||||
[
|
||||
'1 (RFC822 {8190}', # Wat?
|
||||
self._get_email_as_text('generic_message.eml')
|
||||
],
|
||||
')',
|
||||
]
|
||||
)
|
||||
|
||||
actual_messages = list(self.transport.get_message())
|
||||
|
||||
self.assertEqual(len(actual_messages), 1)
|
||||
|
||||
actual_message = actual_messages[0]
|
||||
expected_message = self._get_email_object('generic_message.eml')
|
||||
|
||||
self.assertEqual(expected_message, actual_message)
|
||||
|
||||
|
||||
|
||||
class TestPop3Transport(EmailMessageTestCase):
|
||||
def setUp(self):
|
||||
self.arbitrary_hostname = 'one.two.three'
|
||||
self.arbitrary_port = 100
|
||||
self.ssl = False
|
||||
self.transport = Pop3Transport(
|
||||
self.arbitrary_hostname,
|
||||
self.arbitrary_port,
|
||||
self.ssl
|
||||
)
|
||||
self.transport.server = None
|
||||
super(TestPop3Transport, self).setUp()
|
||||
|
||||
def test_get_email_message(self):
|
||||
with mock.patch.object(self.transport, 'server') as server:
|
||||
# Consider this value arbitrary, the second parameter
|
||||
# should have one entry per message in the inbox
|
||||
server.list.return_value = [None, ['some_msg']]
|
||||
server.retr.return_value = [
|
||||
'+OK message follows',
|
||||
[
|
||||
line.encode('ascii')
|
||||
for line in self._get_email_as_text(
|
||||
'generic_message.eml'
|
||||
).decode('ascii').split('\n')
|
||||
],
|
||||
10018, # Some arbitrary size, ideally matching the above
|
||||
]
|
||||
|
||||
actual_messages = list(self.transport.get_message())
|
||||
|
||||
self.assertEqual(len(actual_messages), 1)
|
||||
|
||||
actual_message = actual_messages[0]
|
||||
expected_message = self._get_email_object('generic_message.eml')
|
||||
|
||||
self.assertEqual(expected_message, actual_message)
|
||||
19
django_mailbox/transports/base.py
Normal file
19
django_mailbox/transports/base.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import email
|
||||
|
||||
import six
|
||||
|
||||
# Do *not* remove this, we need to use this in subclasses of EmailTransport
|
||||
if six.PY3:
|
||||
from email.errors import MessageParseError
|
||||
else:
|
||||
from email.Errors import MessageParseError
|
||||
|
||||
|
||||
class EmailTransport(object):
|
||||
def get_email_from_bytes(self, contents):
|
||||
if six.PY3:
|
||||
message = email.message_from_bytes(contents)
|
||||
else:
|
||||
message = email.message_from_string(contents)
|
||||
|
||||
return message
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
class GenericFileMailbox(object):
|
||||
from .base import EmailTransport
|
||||
|
||||
|
||||
class GenericFileMailbox(EmailTransport):
|
||||
_variant = None
|
||||
_path = None
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import email
|
||||
from imaplib import IMAP4, IMAP4_SSL
|
||||
|
||||
from .base import EmailTransport, MessageParseError
|
||||
|
||||
class ImapTransport(object):
|
||||
|
||||
class ImapTransport(EmailTransport):
|
||||
def __init__(self, hostname, port=None, ssl=False):
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
|
|
@ -29,9 +30,9 @@ class ImapTransport(object):
|
|||
for key in inbox[0].split():
|
||||
try:
|
||||
typ, msg_contents = self.server.fetch(key, '(RFC822)')
|
||||
message = email.message_from_string(msg_contents[0][1])
|
||||
message = self.get_email_from_bytes(msg_contents[0][1])
|
||||
yield message
|
||||
except email.Errors.MessageParseError:
|
||||
except MessageParseError:
|
||||
continue
|
||||
self.server.store(key, "+FLAGS", "\\Deleted")
|
||||
self.server.expunge()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import email
|
||||
import six
|
||||
|
||||
from poplib import POP3, POP3_SSL
|
||||
|
||||
from .base import EmailTransport, MessageParseError
|
||||
|
||||
class Pop3Transport(object):
|
||||
|
||||
class Pop3Transport(EmailTransport):
|
||||
def __init__(self, hostname, port=None, ssl=False):
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
|
|
@ -20,14 +23,21 @@ class Pop3Transport(object):
|
|||
self.server.user(username)
|
||||
self.server.pass_(password)
|
||||
|
||||
def get_message_body(self, message_lines):
|
||||
if six.PY3:
|
||||
return six.binary_type('\r\n', 'ascii').join(message_lines)
|
||||
return '\r\n'.join(message_lines)
|
||||
|
||||
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)
|
||||
msg_contents = self.get_message_body(
|
||||
self.server.retr(i + 1)[1]
|
||||
)
|
||||
message = self.get_email_from_bytes(msg_contents)
|
||||
yield message
|
||||
except email.Errors.MessageParseError:
|
||||
except MessageParseError:
|
||||
continue
|
||||
self.server.dele(i + 1)
|
||||
self.server.quit()
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -2,6 +2,7 @@ from setuptools import setup
|
|||
|
||||
tests_require = [
|
||||
'django',
|
||||
'mock',
|
||||
]
|
||||
|
||||
setup(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue