From 01984e2ba89bf3a6123877063fd6e6bba181c9a4 Mon Sep 17 00:00:00 2001
From: Pietro Mingo
Date: Tue, 26 Jul 2022 21:32:10 +0200
Subject: [PATCH] Update models.py, __init__.py, and office365.py
---
django_mailbox/models.py | 5 +-
django_mailbox/transports/__init__.py | 1 +
django_mailbox/transports/office365.py | 129 +++++++++++++++++++++++++
3 files changed, 134 insertions(+), 1 deletion(-)
create mode 100644 django_mailbox/transports/office365.py
diff --git a/django_mailbox/models.py b/django_mailbox/models.py
index 0f0ac9d..9ef29ac 100644
--- a/django_mailbox/models.py
+++ b/django_mailbox/models.py
@@ -31,7 +31,7 @@ from django_mailbox import utils
from django_mailbox.signals import message_received
from django_mailbox.transports import Pop3Transport, ImapTransport, \
MaildirTransport, MboxTransport, BabylTransport, MHTransport, \
- MMDFTransport, GmailImapTransport
+ MMDFTransport, GmailImapTransport, Office365Transport
logger = logging.getLogger(__name__)
@@ -223,6 +223,9 @@ class Mailbox(models.Model):
ssl=self.use_ssl
)
conn.connect(self.username, self.password)
+ elif self.type == 'office365':
+ conn = Office365Transport(self.location)
+ conn.connect(self.username, self.password)
elif self.type == 'maildir':
conn = MaildirTransport(self.location)
elif self.type == 'mbox':
diff --git a/django_mailbox/transports/__init__.py b/django_mailbox/transports/__init__.py
index 7aeef95..9f733e3 100644
--- a/django_mailbox/transports/__init__.py
+++ b/django_mailbox/transports/__init__.py
@@ -8,3 +8,4 @@ from django_mailbox.transports.babyl import BabylTransport
from django_mailbox.transports.mh import MHTransport
from django_mailbox.transports.mmdf import MMDFTransport
from django_mailbox.transports.gmail import GmailImapTransport
+from django_mailbox.transports.office365 import Office365Transport
diff --git a/django_mailbox/transports/office365.py b/django_mailbox/transports/office365.py
new file mode 100644
index 0000000..8ce5554
--- /dev/null
+++ b/django_mailbox/transports/office365.py
@@ -0,0 +1,129 @@
+import O365
+import logging
+
+from django.conf import settings
+
+from .base import EmailTransport, MessageParseError
+
+logger = logging.getLogger(__name__)
+
+
+class Office365Transport(EmailTransport):
+ def __init__(
+ self, hostname, port=None, ssl=False, tls=False,
+ archive='', folder=None,
+ ):
+ self.max_message_size = getattr(
+ settings,
+ 'DJANGO_MAILBOX_MAX_MESSAGE_SIZE',
+ False
+ )
+ self.integration_testing_subject = getattr(
+ settings,
+ 'DJANGO_MAILBOX_INTEGRATION_TESTING_SUBJECT',
+ None
+ )
+ # self.hostname = hostname
+ # self.port = port
+ # self.archive = archive
+ # self.folder = folder
+ # self.tls = tls
+ # if ssl:
+ # # self.transport = imaplib.IMAP4_SSL
+ # if not self.port:
+ # self.port = 993
+ # else:
+ # self.transport = imaplib.IMAP4
+ # if not self.port:
+ # self.port = 143
+
+ def connect(self, username, password):
+ # self.server = self.transport(self.hostname, self.port)
+ # if self.tls:
+ # self.server.starttls()
+ # typ, msg = self.server.login(username, password)
+ #
+ # if self.folder:
+ # self.server.select(self.folder)
+ # else:
+ # self.server.select()
+
+ def _get_all_message_ids(self):
+ # # Fetch all the message uids
+ # response, message_ids = self.server.uid('search', None, 'ALL')
+ # message_id_string = message_ids[0].strip()
+ # # Usually `message_id_string` will be a list of space-separated
+ # # ids; we must make sure that it isn't an empty string before
+ # # splitting into individual UIDs.
+ # if message_id_string:
+ # return message_id_string.decode().split(' ')
+ # return []
+
+ def _get_small_message_ids(self, message_ids):
+ # Using existing message uids, get the sizes and
+ # return only those that are under the size
+ # limit
+ safe_message_ids = []
+
+ status, data = self.server.uid(
+ 'fetch',
+ ','.join(message_ids),
+ '(RFC822.SIZE)'
+ )
+
+ for each_msg in data:
+ each_msg = each_msg.decode()
+ try:
+ uid = each_msg.split(' ')[2]
+ size = each_msg.split(' ')[4].rstrip(')')
+ if int(size) <= int(self.max_message_size):
+ safe_message_ids.append(uid)
+ except ValueError as e:
+ logger.warning(
+ "ValueError: {} working on {}".format(e, each_msg[0])
+ )
+ pass
+ return safe_message_ids
+
+ def get_message(self, condition=None):
+ message_ids = self._get_all_message_ids()
+
+ if not message_ids:
+ return
+
+ # Limit the uids to the small ones if we care about that
+ if self.max_message_size:
+ message_ids = self._get_small_message_ids(message_ids)
+
+ if self.archive:
+ typ, folders = self.server.list(pattern=self.archive)
+ if folders[0] is None:
+ # If the archive folder does not exist, create it
+ self.server.create(self.archive)
+
+ for uid in message_ids:
+ try:
+ typ, msg_contents = self.server.uid('fetch', uid, '(RFC822)')
+ if not msg_contents:
+ continue
+ try:
+ message = self.get_email_from_bytes(msg_contents[0][1])
+ except TypeError:
+ # This happens if another thread/process deletes the
+ # message between our generating the ID list and our
+ # processing it here.
+ continue
+
+ if condition and not condition(message):
+ continue
+
+ yield message
+ except MessageParseError:
+ continue
+
+ if self.archive:
+ self.server.uid('copy', uid, self.archive)
+
+ self.server.uid('store', uid, "+FLAGS", "(\\Deleted)")
+ self.server.expunge()
+ return