diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 2c7a497..df09868 100644 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -216,24 +216,24 @@ class Mailbox(models.Model): archive=self.archive ) conn.connect(self.username, self.password) - elif self.type == 'office365': - conn = Office365Transport( - self.location, - port=self.port if self.port else None, - tls=self.use_tls, - ssl=self.use_ssl, - archive=self.archive, - folder=self.folder - ) - conn.connect(self.username, self.password) # elif self.type == 'office365': # conn = Office365Transport( # self.location, - # self.username, - # folder=self.folder, - # archive=self.archive + # port=self.port if self.port else None, + # tls=self.use_tls, + # ssl=self.use_ssl, + # archive=self.archive, + # folder=self.folder # ) - # conn.connect() + # conn.connect(self.username, self.password) + elif self.type == 'office365': + conn = Office365Transport( + self.location, + self.username, + folder=self.folder, + archive=self.archive + ) + conn.connect() elif self.type == 'pop3': conn = Pop3Transport( self.location, diff --git a/django_mailbox/transports/office365.py b/django_mailbox/transports/office365.py index c889e11..62bb615 100644 --- a/django_mailbox/transports/office365.py +++ b/django_mailbox/transports/office365.py @@ -1,137 +1,137 @@ -import logging -import urllib3 -import json - -from django_mailbox.transports.imap import ImapTransport -from django.conf import settings - - -logger = logging.getLogger(__name__) - - -class Office365Transport(ImapTransport): - def connect(self, username, password): - # Try to use oauth2 first. It's much safer - try: - self._connect_oauth(username) - except (TypeError, ValueError) as e: - logger.warning("Couldn't do oauth2 because %s" % e) - self.server = self.transport(self.hostname, self.port) - typ, msg = self.server.login(username, password) - self.server.select() - - def _connect_oauth(self, username): - # username should be an email address that has already been authorized - # for office365 access - - access_token = None - while access_token is None: - try: - access_token = self.get_office365_access_token() - except Exception as e: - raise ValueError( - f"Could not acquire the access token for {username} exception details={e}" - ) - - auth_string = 'user={}\1auth=Bearer {}\1\1'.format( - username, - access_token - ) - - logger.info(f'[_connect_oauth] port = {self.port}') - self.server = self.transport(self.hostname, self.port) - logger.info(f'[_connect_oauth] hostname = {self.hostname}') - logger.info(f'[_connect_oauth] auth string is: {auth_string}') - typ, dat = self.server.authenticate("XOAUTH2", lambda x: auth_string) - logger.info(f'[_connect_oauth] auth string is: {auth_string} and typ={typ} dat={dat}') - self.server.select() - - def get_office365_access_token(self): - url = f"https://login.microsoftonline.com/{settings.MICROSOFT_O365_TENENT_ID}/oauth2/v2.0/token" - oauth_params = { - "client_id": settings.MICROSOFT_O365_CLIENT_ID, - "client_secret": settings.MICROSOFT_O365_CLIENT_SECRET, - "grant_type": "client_credentials", - "scope": "https://graph.microsoft.com/.default", - } - http = urllib3.PoolManager() - response = http.request("POST", url, oauth_params) - if response.status == 200: - token = json.loads(response.data).get("access_token") - logger.info(f"[get_office365_access_token] token aquired") - return token - else: - raise Exception( - f"[get_office365_access_token] Failed to authenticate with O365 {response.data}" - ) - # import logging -# import os +# import urllib3 +# import json +# from django_mailbox.transports.imap import ImapTransport # from django.conf import settings -# from .base import EmailTransport, MessageParseError # logger = logging.getLogger(__name__) -# class Office365Transport(EmailTransport): -# def __init__( -# self, hostname, username, archive='', folder=None -# ): -# self.integration_testing_subject = getattr( -# settings, -# 'DJANGO_MAILBOX_INTEGRATION_TESTING_SUBJECT', -# None -# ) -# self.hostname = hostname -# self.username = username -# self.archive = archive -# self.folder = folder - -# def connect(self): +# class Office365Transport(ImapTransport): +# def connect(self, username, password): +# # Try to use oauth2 first. It's much safer # try: -# import O365 -# except ImportError: -# raise ValueError( -# "Install o365 to use oauth2 auth for office365" +# self._connect_oauth(username) +# except (TypeError, ValueError) as e: +# logger.warning("Couldn't do oauth2 because %s" % e) +# self.server = self.transport(self.hostname, self.port) +# typ, msg = self.server.login(username, password) +# self.server.select() + +# def _connect_oauth(self, username): +# # username should be an email address that has already been authorized +# # for office365 access + +# access_token = None +# while access_token is None: +# try: +# access_token = self.get_office365_access_token() +# except Exception as e: +# raise ValueError( +# f"Could not acquire the access token for {username} exception details={e}" +# ) + +# auth_string = 'user={}\1auth=Bearer {}\1\1'.format( +# username, +# access_token +# ) + +# logger.info(f'[_connect_oauth] port = {self.port}') +# self.server = self.transport(self.hostname, self.port) +# logger.info(f'[_connect_oauth] hostname = {self.hostname}') +# logger.info(f'[_connect_oauth] auth string is: {auth_string}') +# typ, dat = self.server.authenticate("XOAUTH2", lambda x: auth_string) +# logger.info(f'[_connect_oauth] auth string is: {auth_string} and typ={typ} dat={dat}') +# self.server.select() + +# def get_office365_access_token(self): +# url = f"https://login.microsoftonline.com/{settings.MICROSOFT_O365_TENENT_ID}/oauth2/v2.0/token" +# oauth_params = { +# "client_id": settings.MICROSOFT_O365_CLIENT_ID, +# "client_secret": settings.MICROSOFT_O365_CLIENT_SECRET, +# "grant_type": "client_credentials", +# "scope": "https://graph.microsoft.com/.default", +# } +# http = urllib3.PoolManager() +# response = http.request("POST", url, oauth_params) +# if response.status == 200: +# token = json.loads(response.data).get("access_token") +# logger.info(f"[get_office365_access_token] token aquired") +# return token +# else: +# raise Exception( +# f"[get_office365_access_token] Failed to authenticate with O365 {response.data}" # ) -# credentials = (settings.MICROSOFT_O365_CLIENT_ID, settings.MICROSOFT_O365_CLIENT_SECRET) +import logging +import os -# if not os.path.isdir(settings.O365_TOKEN_PATH): -# os.mkdir(settings.O365_TOKEN_PATH) +from django.conf import settings -# token_path=os.path.join(settings.O365_TOKEN_PATH, 'token.txt') -# self.account = O365.Account(credentials, auth_flow_type='credentials', tenant_id=settings.MICROSOFT_O365_TENENT_ID, token_path=token_path) -# self.account.authenticate() +from .base import EmailTransport, MessageParseError -# self.mailbox = self.account.mailbox(resource=self.username) -# self.mailbox_folder = self.mailbox.inbox_folder() -# if self.folder: -# self.mailbox_folder = self.mailbox.get_folder(folder_name=self.folder) +logger = logging.getLogger(__name__) -# def get_message(self, condition=None): -# archive_folder = None -# if self.archive: -# archive_folder = self.mailbox.get_folder(folder_name=self.archive) -# if not archive_folder: -# archive_folder = self.mailbox.create_child_folder(self.archive) -# for o365message in self.mailbox_folder.get_messages(order_by='receivedDateTime'): -# try: -# mime_content = o365message.get_mime_content() -# message = self.get_email_from_bytes(mime_content) +class Office365Transport(EmailTransport): + def __init__( + self, hostname, username, archive='', folder=None + ): + self.integration_testing_subject = getattr( + settings, + 'DJANGO_MAILBOX_INTEGRATION_TESTING_SUBJECT', + None + ) + self.hostname = hostname + self.username = username + self.archive = archive + self.folder = folder -# if condition and not condition(message): -# continue + def connect(self): + try: + import O365 + except ImportError: + raise ValueError( + "Install o365 to use oauth2 auth for office365" + ) -# yield message -# except MessageParseError: -# continue + credentials = (settings.MICROSOFT_O365_CLIENT_ID, settings.MICROSOFT_O365_CLIENT_SECRET) -# if self.archive and archive_folder: -# o365message.copy(archive_folder) + if not os.path.isdir(settings.O365_TOKEN_PATH): + os.mkdir(settings.O365_TOKEN_PATH) -# o365message.delete() -# return + token_path=os.path.join(settings.O365_TOKEN_PATH, 'token.txt') + self.account = O365.Account(credentials, auth_flow_type='credentials', tenant_id=settings.MICROSOFT_O365_TENENT_ID, token_path=token_path) + self.account.authenticate() + + self.mailbox = self.account.mailbox(resource=self.username) + self.mailbox_folder = self.mailbox.inbox_folder() + if self.folder: + self.mailbox_folder = self.mailbox.get_folder(folder_name=self.folder) + + def get_message(self, condition=None): + archive_folder = None + if self.archive: + archive_folder = self.mailbox.get_folder(folder_name=self.archive) + if not archive_folder: + archive_folder = self.mailbox.create_child_folder(self.archive) + + for o365message in self.mailbox_folder.get_messages(order_by='receivedDateTime'): + try: + mime_content = o365message.get_mime_content() + message = self.get_email_from_bytes(mime_content) + + if condition and not condition(message): + continue + + yield message + except MessageParseError: + continue + + if self.archive and archive_folder: + o365message.copy(archive_folder) + + o365message.delete() + return