1
0
Fork 1
mirror of https://github.com/coddingtonbear/django-mailbox.git synced 2026-07-09 22:38:19 +02:00

Merge branch 'master' of github.com:nickmccullum/django-mailbox

This commit is contained in:
Nick McCullum 2021-10-18 08:52:36 -03:00
commit 44f517b34e
52 changed files with 323 additions and 384 deletions

View file

@ -1,8 +1,7 @@
[bumpversion] [bumpversion]
current_version = 4.7.2 current_version = 4.8.2
commit = True commit = True
tag = True tag = True
tag_name = {new_version} tag_name = {new_version}
[bumpversion:file:django_mailbox/__init__.py] [bumpversion:file:django_mailbox/__init__.py]

View file

@ -1,48 +1,46 @@
version: ~> 1.0
os: linux
language: python language: python
python:
- '2.7'
- '3.4'
- '3.5'
- '3.6'
env: jobs:
matrix: - env: TOX_ENV=docs
- DJANGO='>=1.7,<1.8' python: 3.8
- DJANGO='>=1.8,<1.9' # sort by django version, next to by python version
- DJANGO='>=1.9,<1.10' # Django 1.11 support all supported Python interpreter
- DJANGO='>=1.10,<1.11' - env: TOX_ENV=django111-py35
- DJANGO='>=1.11,<2.0' python: 3.5
- DJANGO='>=2.0,<2.1' - env: TOX_ENV=django111-py36
global: python: 3.6
- secure: aswHU7pQroGM+GHoYlhXzzk2FYfqxXJORjqXPsbgoHAIu4Bssaj8+YAzIcdy3j9kSt4I8VBpjnn8H/wzQXki75JBZOosQrIeMK018+uR+ZMONBLqDYW/N7EJHLgZt9QXxQNKeZygrD4GN/Dc4gLHGvPQC/RfPuuHcnF0Liaahoo= # Django 2.0 support 3.5, 3.6
- secure: RZ6M6984P885GRoyx9n/WCCWGoFAzYpS8sZkXu3e/HK9oPXfaM2IEHjkq03jIC/FcWn/QMtFjOUBqQU94rnqdivFdFkeZHk1WUQgC0hztH3Qhh9zu2PNIrYUDpVD5dJqBpprWbSwFP8yNsJlP9A2RUubTlZblKHuaBhhiuNN+kU= - env: TOX_ENV=django20-py35
- secure: gsAAl/RaTodLJDHWOuHZWtooa9/psyXBONF7ElZOTki3WvH+KugtjuXn3pXBGbUhvGqd5qfgPqX7WQOFP9KTdkXBbkU20rCHLh3SV8V2vRkGFAFiGPBTFfSA83zFNMvmgEnTww4OzYsfs4wHTEyxBeQkggnB5bXEvqkFVrHBjuQ= python: 3.5
- secure: mMa7UUt+CQDB52fGM1T3oRL67OzQzRIc+BQCOqUEUhBV7p5g7Y1Hv6NTdVZTvK16x3DsP+5kFNd1v7rsTFw2qzP3hOxIv2BtMPuSzZdnN85Zd/nGwnztxzj/rqw7TMBaYvIdEZZbpRF/K0p0Xr6LJK2s9UkPXPUaLqly7kNi360= - env: TOX_ENV=django20-py36
matrix: python: 3.6
exclude:
# sort by django version, next to by python version # Django 2.1 support Python 3.5, 3.6, 3.7
# Django 1.7 support Python 2.7, 3.4 - env: TOX_ENV=django21-py35
- env: DJANGO='>=1.7,<1.8' python: 3.5
python: '3.5' - env: TOX_ENV=django21-py36
- env: DJANGO='>=1.7,<1.8' python: 3.6
python: '3.6' - env: TOX_ENV=django21-py37
# Django 1.8 support Python 2.7, 3.4, 3.5 python: 3.7
- env: DJANGO='>=1.8,<1.9' # Django 2.2 support Python 3.5, 3.6, 3.7
python: '3.6' - env: TOX_ENV=django22-py35
# Django 1.9 support Python 2.7, 3.4, 3.5 python: 3.5
- env: DJANGO='>=1.9,<1.10' - env: TOX_ENV=django22-py36
python: '3.6' python: 3.6
# Django 1.10 support Python 2.7, 3.4, 3.5 - env: TOX_ENV=django22-py37
- env: DJANGO='>=1.10,<1.11' python: 3.7
python: '3.6' # Django 3.0 (beta) support Python 3.6, 3.7, 3.8
# Django 1.11 support all supported Python interpreter - env: TOX_ENV=django30-py36
# Django 2.0 support Python 3.4, 3.5, 3.6 python: 3.6
- env: DJANGO='>=2.0,<2.1' - env: TOX_ENV=django30-py37
python: '2.7' python: 3.7
- env: TOX_ENV=django30-py38 INTEGRATION=1
python: 3.8
install: install:
- pip install -q Django$DJANGO - pip install tox
- pip install -r test_requirements.txt
- pip install -q -e .
script: script:
- python manage.py test - tox -e $TOX_ENV
sudo: false

View file

@ -1,6 +1,19 @@
Changelog Changelog
========= =========
4.8.1
-----
* Add missing migration
4.8.0
-----
* ```django_mailbox.models.Mailbox.get_new_mail``` become generator
* Added to ```django_mailbox.models.Message.mailbox``` in-memory caches of result
* Added to command ```processincomingmessage``` argument to pass mailbox name
* Improved tests, especially different Django & Python version
4.6.1 4.6.1
----- -----
@ -33,7 +46,7 @@ Changelog
4.0 4.0
--- ---
* Adds ``html`` property returning the HTML contents of * Adds ``html`` property returning the HTML contents of
``django_mailbox.models.Message`` instances. ``django_mailbox.models.Message`` instances.
Thanks `@ariel17 <https://github.com/ariel17>`_! Thanks `@ariel17 <https://github.com/ariel17>`_!
* Adds translation support. * Adds translation support.

View file

@ -1,3 +1,3 @@
__version__ = "5.0.1" __version__ = "4.8.2"
default_app_config = "django_mailbox.apps.MailBoxConfig" default_app_config = "django_mailbox.apps.MailBoxConfig"

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
""" """
Model configuration in application ``django_mailbox`` for administration Model configuration in application ``django_mailbox`` for administration
@ -10,7 +9,7 @@ import logging
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_mailbox.models import MessageAttachment, Message, Mailbox from django_mailbox.models import MessageAttachment, Message, Mailbox
from django_mailbox.signals import message_received from django_mailbox.signals import message_received
@ -21,9 +20,7 @@ logger = logging.getLogger(__name__)
def get_new_mail(mailbox_admin, request, queryset): def get_new_mail(mailbox_admin, request, queryset):
for mailbox in queryset.all(): queryset.get_new_mail()
logger.debug('Receiving mail for %s' % mailbox)
mailbox.get_new_mail()
get_new_mail.short_description = _('Get new mail') get_new_mail.short_description = _('Get new mail')
@ -74,7 +71,7 @@ class MessageAdmin(admin.ModelAdmin):
def envelope_headers(self, msg): def envelope_headers(self, msg):
email = msg.get_email_object() email = msg.get_email_object()
return '\n'.join( return '\n'.join(
[('%s: %s' % (h, v)) for h, v in email.items()] [('{}: {}'.format(h, v)) for h, v in email.items()]
) )
inlines = [ inlines = [

View file

@ -1,5 +1,5 @@
from django.apps import AppConfig from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
class MailBoxConfig(AppConfig): class MailBoxConfig(AppConfig):

View file

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations from django.db import models, migrations

View file

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations from django.db import models, migrations

View file

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations from django.db import models, migrations

View file

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations from django.db import models, migrations

View file

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
import django_mailbox.utils import django_mailbox.utils

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.8 on 2016-08-15 22:39 # Generated by Django 1.9.8 on 2016-08-15 22:39
from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-04-21 00:26 # Generated by Django 1.10.7 on 2018-04-21 00:26
from __future__ import unicode_literals
from django.db import migrations from django.db import migrations

View file

@ -0,0 +1,23 @@
# Generated by Django 2.1.7 on 2019-02-19 14:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_mailbox', '0007_auto_20180421_0026'),
]
operations = [
migrations.AlterField(
model_name='mailbox',
name='active',
field=models.BooleanField(blank=True, default=True, help_text='Check this e-mail inbox for new e-mail messages during polling cycles. This checkbox does not have an effect upon whether mail is collected here when this mailbox receives mail from a pipe, and does not affect whether e-mail messages can be dispatched from this mailbox. ', verbose_name='Active'),
),
migrations.AlterField(
model_name='message',
name='outgoing',
field=models.BooleanField(blank=True, default=False, verbose_name='Outgoing'),
),
]

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
""" """
Models declaration for application ``django_mailbox``. Models declaration for application ``django_mailbox``.
@ -8,7 +7,9 @@ import gzip
from email.encoders import encode_base64 from email.encoders import encode_base64
from email.message import Message as EmailMessage from email.message import Message as EmailMessage
from email.utils import formatdate, parseaddr from email.utils import formatdate, parseaddr
from urllib.parse import parse_qs, unquote, urlparse
from quopri import encode as encode_quopri from quopri import encode as encode_quopri
from io import BytesIO
import base64 import base64
import email import email
import logging import logging
@ -18,17 +19,13 @@ import sys
import uuid import uuid
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
import six
from six.moves.urllib.parse import parse_qs, unquote, urlparse
import django import django
from django.conf import settings as django_settings from django.conf import settings as django_settings
from django.core.files.base import ContentFile, File from django.core.files.base import ContentFile, File
from django.core.mail.message import make_msgid from django.core.mail.message import make_msgid
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.encoding import python_2_unicode_compatible
from django_mailbox import utils from django_mailbox import utils
from django_mailbox.signals import message_received from django_mailbox.signals import message_received
@ -39,22 +36,35 @@ from django_mailbox.transports import Pop3Transport, ImapTransport, \
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ActiveMailboxManager(models.Manager): class MailboxQuerySet(models.QuerySet):
def get_new_mail(self):
count = 0
for mailbox in self.all():
logger.debug('Receiving mail for %s' % mailbox)
count += sum(1 for i in mailbox.get_new_mail())
logger.debug('Received %d %s.', count, 'mails' if count != 1 else 'mail')
class MailboxManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(ActiveMailboxManager, self).get_queryset().filter( return MailboxQuerySet(self.model, using=self._db)
class ActiveMailboxManager(MailboxManager):
def get_queryset(self):
return super().get_queryset().filter(
active=True, active=True,
) )
@python_2_unicode_compatible
class Mailbox(models.Model): class Mailbox(models.Model):
name = models.CharField( name = models.CharField(
_(u'Name'), _('Name'),
max_length=255, max_length=255,
) )
uri = models.CharField( uri = models.CharField(
_(u'URI'), _('URI'),
max_length=255, max_length=255,
help_text=(_( help_text=(_(
"Example: imap+ssl://myusername:mypassword@someserver <br />" "Example: imap+ssl://myusername:mypassword@someserver <br />"
@ -72,7 +82,7 @@ class Mailbox(models.Model):
) )
from_email = models.CharField( from_email = models.CharField(
_(u'From email'), _('From email'),
max_length=255, max_length=255,
help_text=(_( help_text=(_(
"Example: MailBot &lt;mailbot@yourdomain.com&gt;<br />" "Example: MailBot &lt;mailbot@yourdomain.com&gt;<br />"
@ -89,7 +99,7 @@ class Mailbox(models.Model):
) )
active = models.BooleanField( active = models.BooleanField(
_(u'Active'), _('Active'),
help_text=(_( help_text=(_(
"Check this e-mail inbox for new e-mail messages during polling " "Check this e-mail inbox for new e-mail messages during polling "
"cycles. This checkbox does not have an effect upon whether " "cycles. This checkbox does not have an effect upon whether "
@ -102,7 +112,7 @@ class Mailbox(models.Model):
) )
last_polling = models.DateTimeField( last_polling = models.DateTimeField(
_(u"Last polling"), _("Last polling"),
help_text=(_("The time of last successful polling for messages." help_text=(_("The time of last successful polling for messages."
"It is blank for new mailboxes and is not set for " "It is blank for new mailboxes and is not set for "
"mailboxes that only receive messages via a pipe.")), "mailboxes that only receive messages via a pipe.")),
@ -110,7 +120,7 @@ class Mailbox(models.Model):
null=True null=True
) )
objects = models.Manager() objects = MailboxManager()
active_mailboxes = ActiveMailboxManager() active_mailboxes = ActiveMailboxManager()
@property @property
@ -294,7 +304,7 @@ class Mailbox(models.Model):
attachment.document.save( attachment.document.save(
uuid.uuid4().hex + extension, uuid.uuid4().hex + extension,
ContentFile( ContentFile(
six.BytesIO( BytesIO(
msg.get_payload(decode=True) msg.get_payload(decode=True)
).getvalue() ).getvalue()
) )
@ -397,7 +407,7 @@ class Mailbox(models.Model):
with gzip.GzipFile(fileobj=fp_tmp, mode="w") as fp: with gzip.GzipFile(fileobj=fp_tmp, mode="w") as fp:
fp.write(message.as_string().encode('utf-8')) fp.write(message.as_string().encode('utf-8'))
msg.eml.save( msg.eml.save(
"%s.eml.gz" % (uuid.uuid4(), ), "{}.eml.gz".format(uuid.uuid4()),
File(fp_tmp), File(fp_tmp),
save=False save=False
) )
@ -435,41 +445,40 @@ class Mailbox(models.Model):
class IncomingMessageManager(models.Manager): class IncomingMessageManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(IncomingMessageManager, self).get_queryset().filter( return super().get_queryset().filter(
outgoing=False, outgoing=False,
) )
class OutgoingMessageManager(models.Manager): class OutgoingMessageManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(OutgoingMessageManager, self).get_queryset().filter( return super().get_queryset().filter(
outgoing=True, outgoing=True,
) )
class UnreadMessageManager(models.Manager): class UnreadMessageManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(UnreadMessageManager, self).get_queryset().filter( return super().get_queryset().filter(
read=None read=None
) )
@python_2_unicode_compatible
class Message(models.Model): class Message(models.Model):
mailbox = models.ForeignKey( mailbox = models.ForeignKey(
Mailbox, Mailbox,
related_name='messages', related_name='messages',
verbose_name=_(u'Mailbox'), verbose_name=_('Mailbox'),
on_delete=models.CASCADE on_delete=models.CASCADE
) )
subject = models.CharField( subject = models.CharField(
_(u'Subject'), _('Subject'),
max_length=255 max_length=255
) )
message_id = models.CharField( message_id = models.CharField(
_(u'Message ID'), _('Message ID'),
max_length=255 max_length=255
) )
@ -478,7 +487,7 @@ class Message(models.Model):
related_name='replies', related_name='replies',
blank=True, blank=True,
null=True, null=True,
verbose_name=_(u'In reply to'), verbose_name=_('In reply to'),
on_delete=models.CASCADE on_delete=models.CASCADE
) )
@ -488,21 +497,21 @@ class Message(models.Model):
) )
to_header = models.TextField( to_header = models.TextField(
_(u'To header'), _('To header'),
) )
outgoing = models.BooleanField( outgoing = models.BooleanField(
_(u'Outgoing'), _('Outgoing'),
default=False, default=False,
blank=True, blank=True,
) )
body = models.TextField( body = models.TextField(
_(u'Body'), _('Body'),
) )
encoded = models.BooleanField( encoded = models.BooleanField(
_(u'Encoded'), _('Encoded'),
default=False, default=False,
help_text=_('True if the e-mail body is Base64 encoded'), help_text=_('True if the e-mail body is Base64 encoded'),
) )
@ -513,17 +522,17 @@ class Message(models.Model):
) )
read = models.DateTimeField( read = models.DateTimeField(
_(u'Read'), _('Read'),
default=None, default=None,
blank=True, blank=True,
null=True, null=True,
) )
eml = models.FileField( eml = models.FileField(
_(u'Raw message contents'), _('Raw message contents'),
null=True, null=True,
upload_to="messages", upload_to="messages",
help_text=_(u'Original full content of message') help_text=_('Original full content of message')
) )
objects = models.Manager() objects = models.Manager()
unread_messages = UnreadMessageManager() unread_messages = UnreadMessageManager()
@ -639,9 +648,9 @@ class Message(models.Model):
if encoding and encoding.lower() == 'quoted-printable': if encoding and encoding.lower() == 'quoted-printable':
# Cannot use `email.encoders.encode_quopri due to # Cannot use `email.encoders.encode_quopri due to
# bug 14360: http://bugs.python.org/issue14360 # bug 14360: http://bugs.python.org/issue14360
output = six.BytesIO() output = BytesIO()
encode_quopri( encode_quopri(
six.BytesIO( BytesIO(
attachment.document.read() attachment.document.read()
), ),
output, output,
@ -693,17 +702,15 @@ class Message(models.Model):
no fields existed for storing arbitrary bytes. no fields existed for storing arbitrary bytes.
""" """
if six.PY3:
body = body.encode('utf-8')
self.encoded = True self.encoded = True
self.body = base64.b64encode(body).decode('ascii') self.body = base64.b64encode(body.encode('utf-8')).decode('ascii')
def get_email_object(self): def get_email_object(self):
"""Returns an `email.message.Message` instance representing the """Returns an `email.message.EmailMessage` instance representing the
contents of this message and all attachments. contents of this message and all attachments.
See [email.Message.Message]_ for more information as to what methods See [email.message.EmailMessage]_ for more information as to what methods
and properties are available on `email.message.Message` instances. and properties are available on `email.message.EmailMessage` instances.
.. note:: .. note::
@ -713,8 +720,8 @@ class Message(models.Model):
using stored attachments, or read the message contents stored using stored attachments, or read the message contents stored
on-disk. on-disk.
.. [email.Message.Message]: Python's `email.message.Message` docs .. [email.message.EmailMessage] Python's `email.message.EmailMessage` docs
(https://docs.python.org/2/library/email.message.html) (https://docs.python.org/3/library/email.message.html)
""" """
if not hasattr(self, '_email_object'): # Cache fill if not hasattr(self, '_email_object'): # Cache fill
@ -727,10 +734,7 @@ class Message(models.Model):
self.eml.close() self.eml.close()
else: else:
body = self.get_body() body = self.get_body()
if six.PY3: flat = email.message_from_bytes(body)
flat = email.message_from_bytes(body)
else:
flat = email.message_from_string(body)
self._email_object = self._rehydrate(flat) self._email_object = self._rehydrate(flat)
return self._email_object return self._email_object
@ -739,7 +743,7 @@ class Message(models.Model):
for attachment in self.attachments.all(): for attachment in self.attachments.all():
# This attachment is attached only to this message. # This attachment is attached only to this message.
attachment.delete() attachment.delete()
return super(Message, self).delete(*args, **kwargs) return super().delete(*args, **kwargs)
def __str__(self): def __str__(self):
return self.subject return self.subject
@ -749,7 +753,6 @@ class Message(models.Model):
verbose_name_plural = _('E-mail messages') verbose_name_plural = _('E-mail messages')
@python_2_unicode_compatible
class MessageAttachment(models.Model): class MessageAttachment(models.Model):
message = models.ForeignKey( message = models.ForeignKey(
Message, Message,
@ -761,30 +764,25 @@ class MessageAttachment(models.Model):
) )
headers = models.TextField( headers = models.TextField(
_(u'Headers'), _('Headers'),
null=True, null=True,
blank=True, blank=True,
) )
document = models.FileField( document = models.FileField(
_(u'Document'), _('Document'),
upload_to=utils.get_attachment_save_path, upload_to=utils.get_attachment_save_path,
) )
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
"""Deletes the attachment.""" """Deletes the attachment."""
self.document.delete() self.document.delete()
return super(MessageAttachment, self).delete(*args, **kwargs) return super().delete(*args, **kwargs)
def _get_rehydrated_headers(self): def _get_rehydrated_headers(self):
headers = self.headers headers = self.headers
if headers is None: if headers is None:
return EmailMessage() return EmailMessage()
if sys.version_info < (3, 0):
try:
headers = headers.encode('utf-8')
except UnicodeDecodeError:
headers = headers.decode('utf-8').encode('utf-8')
return email.message_from_string(headers) return email.message_from_string(headers)
def _set_dehydrated_headers(self, email_object): def _set_dehydrated_headers(self, email_object):
@ -803,7 +801,7 @@ class MessageAttachment(models.Model):
def get_filename(self): def get_filename(self):
"""Returns the original filename of this attachment.""" """Returns the original filename of this attachment."""
file_name = self._get_rehydrated_headers().get_filename() file_name = self._get_rehydrated_headers().get_filename()
if isinstance(file_name, six.string_types): if isinstance(file_name, str):
result = utils.convert_header_to_unicode(file_name) result = utils.convert_header_to_unicode(file_name)
if result is None: if result is None:
return file_name return file_name

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
import email import email
from south.db import db from south.db import db

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# encoding: utf-8
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration
@ -9,33 +8,33 @@ class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding field 'MessageAttachment.message' # Adding field 'MessageAttachment.message'
db.add_column(u'django_mailbox_messageattachment', 'message', db.add_column('django_mailbox_messageattachment', 'message',
self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='attachments', null=True, to=orm['django_mailbox.Message']), self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='attachments', null=True, to=orm['django_mailbox.Message']),
keep_default=False) keep_default=False)
def backwards(self, orm): def backwards(self, orm):
# Deleting field 'MessageAttachment.message' # Deleting field 'MessageAttachment.message'
db.delete_column(u'django_mailbox_messageattachment', 'message_id') db.delete_column('django_mailbox_messageattachment', 'message_id')
models = { models = {
u'django_mailbox.mailbox': { 'django_mailbox.mailbox': {
'Meta': {'object_name': 'Mailbox'}, 'Meta': {'object_name': 'Mailbox'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'})
}, },
u'django_mailbox.message': { 'django_mailbox.message': {
'Meta': {'object_name': 'Message'}, 'Meta': {'object_name': 'Message'},
'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': u"orm['django_mailbox.MessageAttachment']"}), 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': "orm['django_mailbox.MessageAttachment']"}),
'body': ('django.db.models.fields.TextField', [], {}), 'body': ('django.db.models.fields.TextField', [], {}),
'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}),
'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
@ -43,11 +42,11 @@ class Migration(SchemaMigration):
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'to_header': ('django.db.models.fields.TextField', [], {}) 'to_header': ('django.db.models.fields.TextField', [], {})
}, },
u'django_mailbox.messageattachment': { 'django_mailbox.messageattachment': {
'Meta': {'object_name': 'MessageAttachment'}, 'Meta': {'object_name': 'MessageAttachment'},
'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': "orm['django_mailbox.Message']"})
} }
} }

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration
@ -21,22 +20,22 @@ class Migration(SchemaMigration):
) )
models = { models = {
u'django_mailbox.mailbox': { 'django_mailbox.mailbox': {
'Meta': {'object_name': 'Mailbox'}, 'Meta': {'object_name': 'Mailbox'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'})
}, },
u'django_mailbox.message': { 'django_mailbox.message': {
'Meta': {'object_name': 'Message'}, 'Meta': {'object_name': 'Message'},
'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': u"orm['django_mailbox.MessageAttachment']"}), 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': "orm['django_mailbox.MessageAttachment']"}),
'body': ('django.db.models.fields.TextField', [], {}), 'body': ('django.db.models.fields.TextField', [], {}),
'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}),
'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
@ -44,11 +43,11 @@ class Migration(SchemaMigration):
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'to_header': ('django.db.models.fields.TextField', [], {}) 'to_header': ('django.db.models.fields.TextField', [], {})
}, },
u'django_mailbox.messageattachment': { 'django_mailbox.messageattachment': {
'Meta': {'object_name': 'MessageAttachment'}, 'Meta': {'object_name': 'MessageAttachment'},
'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': "orm['django_mailbox.Message']"})
} }
} }

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration
@ -12,40 +11,40 @@ class Migration(SchemaMigration):
db.delete_table('django_mailbox_message_attachments') db.delete_table('django_mailbox_message_attachments')
# Adding field 'MessageAttachment.headers' # Adding field 'MessageAttachment.headers'
db.add_column(u'django_mailbox_messageattachment', 'headers', db.add_column('django_mailbox_messageattachment', 'headers',
self.gf('django.db.models.fields.TextField')(null=True, blank=True), self.gf('django.db.models.fields.TextField')(null=True, blank=True),
keep_default=False) keep_default=False)
def backwards(self, orm): def backwards(self, orm):
# Adding M2M table for field attachments on 'Message' # Adding M2M table for field attachments on 'Message'
db.create_table(u'django_mailbox_message_attachments', ( db.create_table('django_mailbox_message_attachments', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('message', models.ForeignKey(orm[u'django_mailbox.message'], null=False)), ('message', models.ForeignKey(orm['django_mailbox.message'], null=False)),
('messageattachment', models.ForeignKey(orm[u'django_mailbox.messageattachment'], null=False)) ('messageattachment', models.ForeignKey(orm['django_mailbox.messageattachment'], null=False))
)) ))
db.create_unique(u'django_mailbox_message_attachments', ['message_id', 'messageattachment_id']) db.create_unique('django_mailbox_message_attachments', ['message_id', 'messageattachment_id'])
# Deleting field 'MessageAttachment.headers' # Deleting field 'MessageAttachment.headers'
db.delete_column(u'django_mailbox_messageattachment', 'headers') db.delete_column('django_mailbox_messageattachment', 'headers')
models = { models = {
u'django_mailbox.mailbox': { 'django_mailbox.mailbox': {
'Meta': {'object_name': 'Mailbox'}, 'Meta': {'object_name': 'Mailbox'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'})
}, },
u'django_mailbox.message': { 'django_mailbox.message': {
'Meta': {'object_name': 'Message'}, 'Meta': {'object_name': 'Message'},
'body': ('django.db.models.fields.TextField', [], {}), 'body': ('django.db.models.fields.TextField', [], {}),
'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}),
'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
@ -53,12 +52,12 @@ class Migration(SchemaMigration):
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'to_header': ('django.db.models.fields.TextField', [], {}) 'to_header': ('django.db.models.fields.TextField', [], {})
}, },
u'django_mailbox.messageattachment': { 'django_mailbox.messageattachment': {
'Meta': {'object_name': 'MessageAttachment'}, 'Meta': {'object_name': 'MessageAttachment'},
'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"})
} }
} }

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration
@ -9,33 +8,33 @@ class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding field 'Message.encoded' # Adding field 'Message.encoded'
db.add_column(u'django_mailbox_message', 'encoded', db.add_column('django_mailbox_message', 'encoded',
self.gf('django.db.models.fields.BooleanField')(default=False), self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False) keep_default=False)
def backwards(self, orm): def backwards(self, orm):
# Deleting field 'Message.encoded' # Deleting field 'Message.encoded'
db.delete_column(u'django_mailbox_message', 'encoded') db.delete_column('django_mailbox_message', 'encoded')
models = { models = {
u'django_mailbox.mailbox': { 'django_mailbox.mailbox': {
'Meta': {'object_name': 'Mailbox'}, 'Meta': {'object_name': 'Mailbox'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'})
}, },
u'django_mailbox.message': { 'django_mailbox.message': {
'Meta': {'object_name': 'Message'}, 'Meta': {'object_name': 'Message'},
'body': ('django.db.models.fields.TextField', [], {}), 'body': ('django.db.models.fields.TextField', [], {}),
'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}),
'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
@ -43,12 +42,12 @@ class Migration(SchemaMigration):
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'to_header': ('django.db.models.fields.TextField', [], {}) 'to_header': ('django.db.models.fields.TextField', [], {})
}, },
u'django_mailbox.messageattachment': { 'django_mailbox.messageattachment': {
'Meta': {'object_name': 'MessageAttachment'}, 'Meta': {'object_name': 'MessageAttachment'},
'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"})
} }
} }

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime from south.utils import datetime_utils as datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration
@ -9,34 +8,34 @@ class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding field 'Message.eml' # Adding field 'Message.eml'
db.add_column(u'django_mailbox_message', 'eml', db.add_column('django_mailbox_message', 'eml',
self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True), self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True),
keep_default=False) keep_default=False)
def backwards(self, orm): def backwards(self, orm):
# Deleting field 'Message.eml' # Deleting field 'Message.eml'
db.delete_column(u'django_mailbox_message', 'eml') db.delete_column('django_mailbox_message', 'eml')
models = { models = {
u'django_mailbox.mailbox': { 'django_mailbox.mailbox': {
'Meta': {'object_name': 'Mailbox'}, 'Meta': {'object_name': 'Mailbox'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'})
}, },
u'django_mailbox.message': { 'django_mailbox.message': {
'Meta': {'object_name': 'Message'}, 'Meta': {'object_name': 'Message'},
'body': ('django.db.models.fields.TextField', [], {}), 'body': ('django.db.models.fields.TextField', [], {}),
'eml': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True'}), 'eml': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True'}),
'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}),
'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}),
'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
@ -44,12 +43,12 @@ class Migration(SchemaMigration):
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'to_header': ('django.db.models.fields.TextField', [], {}) 'to_header': ('django.db.models.fields.TextField', [], {})
}, },
u'django_mailbox.messageattachment': { 'django_mailbox.messageattachment': {
'Meta': {'object_name': 'MessageAttachment'}, 'Meta': {'object_name': 'MessageAttachment'},
'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"})
} }
} }

View file

@ -2,8 +2,6 @@ import email
import os.path import os.path
import time import time
import six
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
@ -57,7 +55,7 @@ class EmailMessageTestCase(TestCase):
settings.EMAIL_HOST_USER = self.test_account settings.EMAIL_HOST_USER = self.test_account
settings.EMAIL_HOST_PASSWORD = self.test_password settings.EMAIL_HOST_PASSWORD = self.test_password
settings.EMAIL_USE_TLS = True settings.EMAIL_USE_TLS = True
super(EmailMessageTestCase, self).setUp() super().setUp()
def _get_new_messages(self, mailbox, condition=None): def _get_new_messages(self, mailbox, condition=None):
start_time = time.time() start_time = time.time()
@ -70,8 +68,7 @@ class EmailMessageTestCase(TestCase):
# check if generator contains at least one element # check if generator contains at least one element
message = next(messages) message = next(messages)
yield message yield message
for message in messages: yield from messages
yield message
return return
except StopIteration: except StopIteration:
@ -92,10 +89,7 @@ class EmailMessageTestCase(TestCase):
def _get_email_object(self, name): def _get_email_object(self, name):
copy = self._get_email_as_text(name) copy = self._get_email_as_text(name)
if six.PY3: return email.message_from_bytes(copy)
return email.message_from_bytes(copy)
else:
return email.message_from_string(copy)
def _headers_identical(self, left, right, header=None): def _headers_identical(self, left, right, header=None):
""" Check if headers are (close enough to) identical. """ Check if headers are (close enough to) identical.
@ -131,7 +125,7 @@ class EmailMessageTestCase(TestCase):
raise AssertionError("Extra header '%s'" % key) raise AssertionError("Extra header '%s'" % key)
if not self._headers_identical(right[key], value, header=key): if not self._headers_identical(right[key], value, header=key):
raise AssertionError( raise AssertionError(
"Header '%s' unequal:\n%s\n%s" % ( "Header '{}' unequal:\n{}\n{}".format(
key, key,
repr(value), repr(value),
repr(right[key]), repr(right[key]),
@ -144,7 +138,7 @@ class EmailMessageTestCase(TestCase):
raise AssertionError("Extra header '%s'" % key) raise AssertionError("Extra header '%s'" % key)
if not self._headers_identical(left[key], value, header=key): if not self._headers_identical(left[key], value, header=key):
raise AssertionError( raise AssertionError(
"Header '%s' unequal:\n%s\n%s" % ( "Header '{}' unequal:\n{}\n{}".format(
key, key,
repr(value), repr(value),
repr(right[key]), repr(right[key]),
@ -175,7 +169,7 @@ class EmailMessageTestCase(TestCase):
def _raise_mismatched(self, left, right): def _raise_mismatched(self, left, right):
raise AssertionError( raise AssertionError(
"Message payloads do not match:\n%s\n%s" % ( "Message payloads do not match:\n{}\n{}".format(
left.as_string(), left.as_string(),
right.as_string() right.as_string()
) )
@ -183,7 +177,7 @@ class EmailMessageTestCase(TestCase):
def assertEqual(self, left, right): # noqa: N802 def assertEqual(self, left, right): # noqa: N802
if not isinstance(left, email.message.Message): if not isinstance(left, email.message.Message):
return super(EmailMessageTestCase, self).assertEqual(left, right) return super().assertEqual(left, right)
return self.compare_email_objects(left, right) return self.compare_email_objects(left, right)
def tearDown(self): def tearDown(self):
@ -194,4 +188,4 @@ class EmailMessageTestCase(TestCase):
models.TEXT_STORED_MIMETYPES = self._TEXT_STORED_MIMETYPES models.TEXT_STORED_MIMETYPES = self._TEXT_STORED_MIMETYPES
self.mailbox.delete() self.mailbox.delete()
super(EmailMessageTestCase, self).tearDown() super().tearDown()

View file

@ -1,7 +1,6 @@
import os import os
import uuid import uuid
from urllib import parse
from six.moves.urllib import parse
from django.core.mail import EmailMultiAlternatives from django.core.mail import EmailMultiAlternatives
@ -14,7 +13,7 @@ __all__ = ['TestImap']
class TestImap(EmailMessageTestCase): class TestImap(EmailMessageTestCase):
def setUp(self): def setUp(self):
super(TestImap, self).setUp() super().setUp()
self.test_imap_server = ( self.test_imap_server = (
os.environ.get('EMAIL_IMAP_SERVER') os.environ.get('EMAIL_IMAP_SERVER')

View file

@ -34,3 +34,13 @@ class TestMailbox(TestCase):
self.assertEqual(mailbox.last_polling, None) self.assertEqual(mailbox.last_polling, None)
list(mailbox.get_new_mail()) list(mailbox.get_new_mail())
self.assertNotEqual(mailbox.last_polling, None) self.assertNotEqual(mailbox.last_polling, None)
def test_queryset_get_new_mail(self):
mailbox = Mailbox.objects.create(uri="mbox://" + os.path.join(
os.path.dirname(__file__),
'messages',
'generic_message.eml',
))
Mailbox.objects.filter(pk=mailbox.pk).get_new_mail()
mailbox.refresh_from_db()
self.assertNotEqual(mailbox.last_polling, None)

View file

@ -1,6 +1,6 @@
import copy import copy
import mock from unittest import mock
from django_mailbox import models, utils from django_mailbox import models, utils
from django_mailbox.models import Message from django_mailbox.models import Message

View file

@ -3,8 +3,7 @@ import os.path
import sys import sys
import copy import copy
import mock from unittest import mock
import six
from django_mailbox.models import Mailbox, Message from django_mailbox.models import Mailbox, Message
from django_mailbox.utils import convert_header_to_unicode from django_mailbox.utils import convert_header_to_unicode
@ -54,18 +53,18 @@ class TestProcessEmail(EmailMessageTestCase):
attachments = msg.attachments.order_by('pk').all() attachments = msg.attachments.order_by('pk').all()
self.assertEqual( self.assertEqual(
u'\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b' '\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b'
u'\u043e\u0436\u0435\u043d\u0438\u0439 HSE Career Fair 8 \u0430' '\u043e\u0436\u0435\u043d\u0438\u0439 HSE Career Fair 8 \u0430'
u'\u043f\u0440\u0435\u043b\u044f 2016.pdf', '\u043f\u0440\u0435\u043b\u044f 2016.pdf',
attachments[0].get_filename() attachments[0].get_filename()
) )
self.assertEqual( self.assertEqual(
u'\u0412\u0435\u0434\u043e\u043c\u043e\u0441\u0442\u0438.pdf', '\u0412\u0435\u0434\u043e\u043c\u043e\u0441\u0442\u0438.pdf',
attachments[1].get_filename() attachments[1].get_filename()
) )
self.assertEqual( self.assertEqual(
u'\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b' '\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b'
u'\u043e\u0436\u0435\u043d\u0438\u0439 2016.pptx', '\u043e\u0436\u0435\u043d\u0438\u0439 2016.pptx',
attachments[2].get_filename() attachments[2].get_filename()
) )
@ -89,33 +88,6 @@ class TestProcessEmail(EmailMessageTestCase):
'heart.png', 'heart.png',
) )
def test_message_with_not_decoded_attachment_header(self):
if sys.version_info > (3, 0):
self.skipTest(
"This test is only relevant on Python 2.x."
)
email_object = self._get_email_object(
'message_with_not_decoded_attachment_header.eml',
)
mailbox = Mailbox.objects.create()
msg = mailbox.process_incoming_message(email_object)
expected_count = 1
actual_count = msg.attachments.count()
self.assertEqual(
expected_count,
actual_count,
)
attachment = msg.attachments.all()[0]
self.assertEqual(
attachment.get_filename(),
u'\xc3\xb0\xcc\x9eo\xce\xb2\xcc\x9ele.png',
)
def test_message_with_utf8_attachment_header(self): def test_message_with_utf8_attachment_header(self):
""" Ensure that we properly handle UTF-8 encoded attachment """ Ensure that we properly handle UTF-8 encoded attachment
@ -138,13 +110,13 @@ class TestProcessEmail(EmailMessageTestCase):
attachment = msg.attachments.all()[0] attachment = msg.attachments.all()[0]
self.assertEqual( self.assertEqual(
attachment.get_filename(), attachment.get_filename(),
u'pi\u0142kochwyty.jpg' 'pi\u0142kochwyty.jpg'
) )
attachment = msg.attachments.all()[1] attachment = msg.attachments.all()[1]
self.assertEqual( self.assertEqual(
attachment.get_filename(), attachment.get_filename(),
u'odpowied\u017a Burmistrza.jpg' 'odpowied\u017a Burmistrza.jpg'
) )
def test_message_get_text_body(self): def test_message_get_text_body(self):
@ -187,7 +159,7 @@ class TestProcessEmail(EmailMessageTestCase):
'messages/generic_message.eml' 'messages/generic_message.eml'
) )
) as f: ) as f:
unicode_body = six.u(f.read()) unicode_body = f.read()
message = Message() message = Message()
message.body = unicode_body message.body = unicode_body
@ -281,10 +253,8 @@ class TestProcessEmail(EmailMessageTestCase):
msg = self.mailbox.process_incoming_message(email_object) msg = self.mailbox.process_incoming_message(email_object)
expected_text = six.u( expected_text = 'This message contains funny UTF16 characters ' + \
'This message contains funny UTF16 characters like this one: ' 'like this one: "\xc2\xa0" and this one "\xe2\x9c\xbf".'
'"\xc2\xa0" and this one "\xe2\x9c\xbf".'
)
actual_text = msg.text actual_text = msg.text
self.assertEqual( self.assertEqual(
@ -320,14 +290,12 @@ class TestProcessEmail(EmailMessageTestCase):
msg = self.mailbox.process_incoming_message(email_object) msg = self.mailbox.process_incoming_message(email_object)
actual_text = msg.text actual_text = msg.text
expected_body = six.u( expected_body = '\u042d\u0442\u043e ' + \
'\u042d\u0442\u043e ' '\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 ' + \
'\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 ' '\u0438\u043c\u0435\u0435\u0442 ' + \
'\u0438\u043c\u0435\u0435\u0442 ' '\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d' + \
'\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d' '\u0443\u044e ' + \
'\u0443\u044e '
'\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430.' '\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430.'
)
self.assertEqual( self.assertEqual(
actual_text, actual_text,
@ -341,23 +309,15 @@ class TestProcessEmail(EmailMessageTestCase):
msg = self.mailbox.process_incoming_message(email_object) msg = self.mailbox.process_incoming_message(email_object)
expected_subject = six.u( expected_subject = '\u00D3\u00E7\u00ED\u00E0\u00E9 \u00EA\u00E0\u00EA ' + \
'\u00D3\u00E7\u00ED\u00E0\u00E9 \u00EA\u00E0\u00EA ' '\u00E7\u00E0\u00F0\u00E0\u00E1\u00E0\u00F2\u00FB\u00E2' + \
'\u00E7\u00E0\u00F0\u00E0\u00E1\u00E0\u00F2\u00FB\u00E2' '\u00E0\u00F2\u00FC \u00EE\u00F2 1000$ \u00E2 ' + \
'\u00E0\u00F2\u00FC \u00EE\u00F2 1000$ \u00E2 '
'\u00ED\u00E5\u00E4\u00E5\u00EB\u00FE!' '\u00ED\u00E5\u00E4\u00E5\u00EB\u00FE!'
)
actual_subject = msg.subject actual_subject = msg.subject
self.assertEqual(actual_subject, expected_subject) self.assertEqual(actual_subject, expected_subject)
if sys.version_info >= (3, 3): expected_from = 'test test <mr.test32@mail.ru>'
# There were various bugfixes in Py3k's email module,
# this is apparently one of them.
expected_from = six.u('test test <mr.test32@mail.ru>')
else:
expected_from = six.u('test test<mr.test32@mail.ru>')
actual_from = msg.from_header actual_from = msg.from_header
self.assertEqual(expected_from, actual_from) self.assertEqual(expected_from, actual_from)
def test_message_reply(self): def test_message_reply(self):
@ -426,15 +386,15 @@ class TestProcessEmail(EmailMessageTestCase):
msg = self.mailbox.process_incoming_message(message) msg = self.mailbox.process_incoming_message(message)
actual_email_object = msg.get_email_object()
self.assertNotEquals(msg.eml, None) self.assertNotEquals(msg.eml, None)
self.assertTrue(msg.eml.name.endswith('.eml')) self.assertTrue(msg.eml.name.endswith('.eml'))
with open(msg.eml.name, 'rb') as f: with open(msg.eml.name, 'rb') as f:
self.assertEqual(f.read(), self.assertEqual(
self._get_email_as_text('generic_message.eml')) f.read(),
self._get_email_as_text('generic_message.eml')
)
def test_message_saving_ignored(self): def test_message_saving_ignored(self):
message = self._get_email_object('generic_message.eml') message = self._get_email_object('generic_message.eml')

View file

@ -1,5 +1,5 @@
from distutils.version import LooseVersion from distutils.version import LooseVersion
import mock from unittest import mock
from django.core.management import call_command, CommandError from django.core.management import call_command, CommandError
from django.test import TestCase from django.test import TestCase

View file

@ -1,5 +1,4 @@
import mock from unittest import mock
import six
from django.test.utils import override_settings from django.test.utils import override_settings
@ -9,24 +8,22 @@ from django_mailbox.transports import ImapTransport, Pop3Transport
FAKE_UID_SEARCH_ANSWER = ( FAKE_UID_SEARCH_ANSWER = (
'OK', 'OK',
[ [
six.b( b'18 19 20 21 22 23 24 25 26 27 28 29 ' +
'18 19 20 21 22 23 24 25 26 27 28 29 ' b'30 31 32 33 34 35 36 37 38 39 40 41 42 43 44'
'30 31 32 33 34 35 36 37 38 39 40 41 42 43 44'
)
] ]
) )
FAKE_UID_FETCH_SIZES = ( FAKE_UID_FETCH_SIZES = (
'OK', 'OK',
[ [
six.b('1 (UID 18 RFC822.SIZE 58070000000)'), b'1 (UID 18 RFC822.SIZE 58070000000)',
six.b('2 (UID 19 RFC822.SIZE 2593)') b'2 (UID 19 RFC822.SIZE 2593)'
] ]
) )
FAKE_UID_FETCH_MSG = ( FAKE_UID_FETCH_MSG = (
'OK', 'OK',
[ [
( (
six.b('1 (UID 18 RFC822 {5807}'), b'1 (UID 18 RFC822 {5807}',
get_email_as_text('generic_message.eml') get_email_as_text('generic_message.eml')
), ),
] ]
@ -34,13 +31,13 @@ FAKE_UID_FETCH_MSG = (
FAKE_UID_COPY_MSG = ( FAKE_UID_COPY_MSG = (
'OK', 'OK',
[ [
six.b('[COPYUID 1 2 2] (Success)') b'[COPYUID 1 2 2] (Success)'
] ]
) )
FAKE_LIST_ARCHIVE_FOLDERS_ANSWERS = ( FAKE_LIST_ARCHIVE_FOLDERS_ANSWERS = (
'OK', 'OK',
[ [
six.b('(\\HasNoChildren \\All) "/" "[Gmail]/All Mail"') b'(\\HasNoChildren \\All) "/" "[Gmail]/All Mail"'
] ]
) )
@ -66,12 +63,12 @@ class IMAPTestCase(EmailMessageTestCase):
self.imap_server = mock.Mock() self.imap_server = mock.Mock()
self.imap_server.uid = imap_server_uid_method self.imap_server.uid = imap_server_uid_method
self.imap_server.list = imap_server_list_method self.imap_server.list = imap_server_list_method
super(IMAPTestCase, self).setUp() super().setUp()
class TestImapTransport(IMAPTestCase): class TestImapTransport(IMAPTestCase):
def setUp(self): def setUp(self):
super(TestImapTransport, self).setUp() super().setUp()
self.arbitrary_hostname = 'one.two.three' self.arbitrary_hostname = 'one.two.three'
self.arbitrary_port = 100 self.arbitrary_port = 100
self.ssl = False self.ssl = False
@ -92,7 +89,7 @@ class TestImapTransport(IMAPTestCase):
class TestImapArchivedTransport(TestImapTransport): class TestImapArchivedTransport(TestImapTransport):
def setUp(self): def setUp(self):
super(TestImapArchivedTransport, self).setUp() super().setUp()
self.archive = 'Archive' self.archive = 'Archive'
self.transport = ImapTransport( self.transport = ImapTransport(
self.arbitrary_hostname, self.arbitrary_hostname,
@ -107,7 +104,7 @@ class TestMaxSizeImapTransport(TestImapTransport):
@override_settings(DJANGO_MAILBOX_MAX_MESSAGE_SIZE=5807) @override_settings(DJANGO_MAILBOX_MAX_MESSAGE_SIZE=5807)
def setUp(self): def setUp(self):
super(TestMaxSizeImapTransport, self).setUp() super().setUp()
self.transport = ImapTransport( self.transport = ImapTransport(
self.arbitrary_hostname, self.arbitrary_hostname,
@ -142,7 +139,7 @@ class TestPop3Transport(EmailMessageTestCase):
self.ssl self.ssl
) )
self.transport.server = None self.transport.server = None
super(TestPop3Transport, self).setUp() super().setUp()
def test_get_email_message(self): def test_get_email_message(self):
with mock.patch.object(self.transport, 'server') as server: with mock.patch.object(self.transport, 'server') as server:

View file

@ -1,19 +1,11 @@
import email import email
import six
# Do *not* remove this, we need to use this in subclasses of EmailTransport # Do *not* remove this, we need to use this in subclasses of EmailTransport
if six.PY3: from email.errors import MessageParseError # noqa: F401
from email.errors import MessageParseError # noqa: F401
else:
from email.Errors import MessageParseError # noqa: F401
class EmailTransport(object): class EmailTransport:
def get_email_from_bytes(self, contents): def get_email_from_bytes(self, contents):
if six.PY3: message = email.message_from_bytes(contents)
message = email.message_from_bytes(contents)
else:
message = email.message_from_string(contents)
return message return message

View file

@ -1,5 +1,4 @@
import sys import sys
import six
from .base import EmailTransport from .base import EmailTransport
@ -9,13 +8,8 @@ class GenericFileMailbox(EmailTransport):
_path = None _path = None
def __init__(self, path): def __init__(self, path):
super(GenericFileMailbox, self).__init__() super().__init__()
if six.PY2: self._path = path
self._path = path.encode(
sys.getfilesystemencoding()
)
else:
self._path = path
def get_instance(self): def get_instance(self):
return self._variant(self._path) return self._variant(self._path)

View file

@ -48,7 +48,7 @@ class GmailImapTransport(ImapTransport):
) )
) )
auth_string = 'user=%s\1auth=Bearer %s\1\1' % ( auth_string = 'user={}\1auth=Bearer {}\1\1'.format(
google_email_address, google_email_address,
access_token access_token
) )

View file

@ -88,7 +88,7 @@ class ImapTransport(EmailTransport):
safe_message_ids.append(uid) safe_message_ids.append(uid)
except ValueError as e: except ValueError as e:
logger.warning( logger.warning(
"ValueError: %s working on %s" % (e, each_msg[0]) "ValueError: {} working on {}".format(e, each_msg[0])
) )
pass pass
return safe_message_ids return safe_message_ids

View file

@ -1,5 +1,3 @@
import six
from poplib import POP3, POP3_SSL from poplib import POP3, POP3_SSL
from .base import EmailTransport, MessageParseError from .base import EmailTransport, MessageParseError
@ -24,9 +22,7 @@ class Pop3Transport(EmailTransport):
self.server.pass_(password) self.server.pass_(password)
def get_message_body(self, message_lines): def get_message_body(self, message_lines):
if six.PY3: return bytes('\r\n', 'ascii').join(message_lines)
return six.binary_type('\r\n', 'ascii').join(message_lines)
return '\r\n'.join(message_lines)
def get_message(self, condition=None): def get_message(self, condition=None):
message_count = len(self.server.list()[1]) message_count = len(self.server.list()[1])

View file

@ -3,8 +3,6 @@ import email.header
import logging import logging
import os import os
import six
from django.conf import settings from django.conf import settings
@ -75,11 +73,8 @@ def get_settings():
def convert_header_to_unicode(header): def convert_header_to_unicode(header):
default_charset = get_settings()['default_charset'] default_charset = get_settings()['default_charset']
if six.PY2 and isinstance(header, six.text_type):
return header
def _decode(value, encoding): def _decode(value, encoding):
if isinstance(value, six.text_type): if isinstance(value, str):
return value return value
if not encoding or encoding == 'unknown-8bit': if not encoding or encoding == 'unknown-8bit':
encoding = default_charset encoding = default_charset
@ -106,7 +101,7 @@ def get_body_from_message(message, maintype, subtype):
""" """
Fetchs the body message matching main/sub content type. Fetchs the body message matching main/sub content type.
""" """
body = six.text_type('') body = ''
for part in message.walk(): for part in message.walk():
if part.get('content-disposition', '').startswith('attachment;'): if part.get('content-disposition', '').startswith('attachment;'):
continue continue

View file

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# #
# django-mailbox documentation build configuration file, created by # django-mailbox documentation build configuration file, created by
# sphinx-quickstart on Tue Jan 22 20:29:12 2013. # sphinx-quickstart on Tue Jan 22 20:29:12 2013.
@ -40,8 +39,8 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'
# General information about the project. # General information about the project.
project = u'django-mailbox' project = 'django-mailbox'
copyright = u'2014, Adam Coddington' copyright = '2020, Adam Coddington'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -120,7 +119,7 @@ html_theme = 'default'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] # html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format. # using the given strftime format.
@ -183,8 +182,8 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'django-mailbox.tex', u'django-mailbox Documentation', ('index', 'django-mailbox.tex', 'django-mailbox Documentation',
u'Adam Coddington', 'manual'), 'Adam Coddington', 'manual'),
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
@ -213,8 +212,8 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'django-mailbox', u'django-mailbox Documentation', ('index', 'django-mailbox', 'django-mailbox Documentation',
[u'Adam Coddington'], 1) ['Adam Coddington'], 1)
] ]
# If true, show URL addresses after external links. # If true, show URL addresses after external links.
@ -227,8 +226,8 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
('index', 'django-mailbox', u'django-mailbox Documentation', ('index', 'django-mailbox', 'django-mailbox Documentation',
u'Adam Coddington', 'django-mailbox', 'One line description of project.', 'Adam Coddington', 'django-mailbox', 'One line description of project.',
'Miscellaneous'), 'Miscellaneous'),
] ]
@ -275,18 +274,18 @@ def process_docstring(app, what, name, obj, options, lines):
if help_text: if help_text:
# Add the model field to the end of the docstring as a param # Add the model field to the end of the docstring as a param
# using the help text as the description # using the help text as the description
lines.append(u':param %s: %s' % (field.attname, help_text)) lines.append(':param {}: {}'.format(field.attname, help_text))
else: else:
# Add the model field to the end of the docstring as a param # Add the model field to the end of the docstring as a param
# using the verbose name as the description # using the verbose name as the description
lines.append(u':param %s: %s' % (field.attname, verbose_name)) lines.append(':param {}: {}'.format(field.attname, verbose_name))
# Add the field's type to the docstring # Add the field's type to the docstring
if isinstance(field, models.ForeignKey): if isinstance(field, models.ForeignKey):
to = field.rel.to to = field.related_model
lines.append(u':type %s: %s to :class:`~%s.%s`' % (field.attname, type(field).__name__, to.__module__, to.__name__)) lines.append(':type {}: {} to :class:`~{}.{}`'.format(field.attname, type(field).__name__, to.__module__, to.__name__))
else: else:
lines.append(u':type %s: %s' % (field.attname, type(field).__name__)) lines.append(':type {}: {}'.format(field.attname, type(field).__name__))
# Return the extended docstring # Return the extended docstring
return lines return lines

View file

@ -5,7 +5,7 @@ Message Storage Details
First, it may be helpful to know a little bit about how e-mail messages First, it may be helpful to know a little bit about how e-mail messages
are actually sent across the wire: are actually sent across the wire:
.. code-block:: http .. code-block::
MIME-Version: 1.0 MIME-Version: 1.0
Received: by 10.221.0.211 with HTTP; Sun, 20 Jan 2013 12:07:07 -0800 (PST) Received: by 10.221.0.211 with HTTP; Sun, 20 Jan 2013 12:07:07 -0800 (PST)
@ -52,7 +52,7 @@ and alter the message body removing the original payload component, but writing
a custom header providing the library enough information to re-build the a custom header providing the library enough information to re-build the
message in the event that one needs a python ``email.message.Message`` object. message in the event that one needs a python ``email.message.Message`` object.
.. code-block:: http .. code-block::
MIME-Version: 1.0 MIME-Version: 1.0
Received: by 10.221.0.211 with HTTP; Sun, 20 Jan 2013 12:07:07 -0800 (PST) Received: by 10.221.0.211 with HTTP; Sun, 20 Jan 2013 12:07:07 -0800 (PST)
@ -113,7 +113,7 @@ in the place of the original attachment, the attachment was stored in a
And were one to run the ``django_mailbox.Message`` instance's And were one to run the ``django_mailbox.Message`` instance's
``get_email_object`` method, the following message will be returned: ``get_email_object`` method, the following message will be returned:
.. code-block:: http .. code-block::
MIME-Version: 1.0 MIME-Version: 1.0
Received: by 10.221.0.211 with HTTP; Sun, 20 Jan 2013 12:07:07 -0800 (PST) Received: by 10.221.0.211 with HTTP; Sun, 20 Jan 2013 12:07:07 -0800 (PST)

View file

@ -44,7 +44,7 @@ To enroll a new release you should perform the following task:
* Push a new release to PyPI - ``python setup.py sdist bdist_wheel upload``. * Push a new release to PyPI - ``python setup.py sdist bdist_wheel upload``.
How to add support for a new Django version? How to add support for a new Django version?
------------------------------------------ --------------------------------------------
Changes are only necessary for new minor or major Django versions. Changes are only necessary for new minor or major Django versions.

View file

@ -56,7 +56,7 @@ SSL) and you would like to fetch new emails from folder named `Myfolder` and arc
into a folder named ``Archived``, you into a folder named ``Archived``, you
would enter the following as your URI:: would enter the following as your URI::
imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?archive=Archived imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?archive=Archived&folder=Myfolder
Additional IMAP Mailbox Features Additional IMAP Mailbox Features
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -76,6 +76,8 @@ to the end of your URI::
imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?folder=MyFolder imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?folder=MyFolder
.. _gmail-oauth:
Specifying an archive folder Specifying an archive folder
++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++
@ -91,7 +93,9 @@ after processing, add ``?archive=myarchivefolder`` to the end of the URI::
imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?archive=myarchivefolder imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?archive=myarchivefolder
.. _gmail-oauth: If you want to specifying both folder use ``&``::
imap+ssl://youremailaddress%40gmail.com:1234@imap.gmail.com?archive=myarchivefolder&folder=MyFolder
Gmail IMAP with Oauth2 authentication Gmail IMAP with Oauth2 authentication
------------------------------------- -------------------------------------

View file

@ -1,2 +1,2 @@
django>=1.9,<1.10 django>=3.1.1,<3.2
six six

View file

@ -27,24 +27,25 @@ setup(
extras_require={ extras_require={
'gmail-oauth2': gmail_oauth2_require 'gmail-oauth2': gmail_oauth2_require
}, },
python_requires=">=3",
classifiers=[ classifiers=[
'Framework :: Django', 'Framework :: Django',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Framework :: Django', 'Framework :: Django',
'Framework :: Django :: 1.7',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11', 'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Topic :: Communications :: Email', 'Topic :: Communications :: Email',
'Topic :: Communications :: Email :: Post-Office', 'Topic :: Communications :: Email :: Post-Office',
'Topic :: Communications :: Email :: Post-Office :: IMAP', 'Topic :: Communications :: Email :: Post-Office :: IMAP',

38
tox.ini
View file

@ -2,28 +2,34 @@
# sort by django version, next by python version # sort by django version, next by python version
envlist= envlist=
flake8 flake8
py{27,34}-django17 py{35,36}-django111
py{34,35}-django18 py{35,36}-django20
py{27,34,35}-django19 py{35,36,37}-django21
py{27,34,35}-django110 py{35,36,37}-django22
py{27,34,35,36}-django111 py{36,37,38}-django30
py{34,35,36}-django20
[testenv] [testenv]
passenv=EMAIL_IMAP_SERVER EMAIL_ACCOUNT EMAIL_PASSWORD EMAIL_SMTP_SERVER
deps= deps=
django17: django>=1.7,<1.8 django111: django==1.11.*
django18: django>=1.8,<1.9 django20: django==2.0.*
django19: django>=1.9,<1.10 django21: django==2.0.*
django110: django>=1.10,<1.11 django22: django==2.0.*
django111: django>=1.11,<2.0 django30: django==3.0b1
django20: django>=2.0,<2.1
-r{toxinidir}/test_requirements.txt -r{toxinidir}/test_requirements.txt
sitepackages=False sitepackages=False
commands= commands=
django110: python {toxinidir}/manage.py makemigrations --check --dry-run python {toxinidir}/manage.py makemigrations --check --dry-run
django111: python {toxinidir}/manage.py makemigrations --check --dry-run python -Wd manage.py test -v2 {posargs}
django20: python {toxinidir}/manage.py makemigrations --check --dry-run
python manage.py test {posargs} [testenv:docs]
deps=
sphinx
-r{toxinidir}/rtd_requirements.txt
.
commands=make html clean SPHINXOPTS="-W --keep-going"
changedir={toxinidir}/docs
allowlist_externals=make
[testenv:flake8] [testenv:flake8]
deps=flake8 deps=flake8