From 01ed3337b1b4eb2ab824f07ce5e771824d616dbb Mon Sep 17 00:00:00 2001 From: Alireza Lotfi Date: Wed, 14 Sep 2022 12:04:53 -0400 Subject: [PATCH] testing on feature --- django_mailbox/models.py | 28 +-- django_mailbox/transports/office365.py | 235 +++++++++++++------------ 2 files changed, 132 insertions(+), 131 deletions(-) diff --git a/django_mailbox/models.py b/django_mailbox/models.py index e499841..2c7a497 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 = Office365ImapTransport( - # 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 c7dffa9..c889e11 100644 --- a/django_mailbox/transports/office365.py +++ b/django_mailbox/transports/office365.py @@ -1,136 +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 Office365ImapTransport(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 -# ) - -# 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) - - 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 django.conf import settings - 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) +# from .base import EmailTransport, MessageParseError - 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) +# logger = logging.getLogger(__name__) - 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 +# 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 - yield message - except MessageParseError: - continue +# def connect(self): +# try: +# import O365 +# except ImportError: +# raise ValueError( +# "Install o365 to use oauth2 auth for office365" +# ) - if self.archive and archive_folder: - o365message.copy(archive_folder) +# credentials = (settings.MICROSOFT_O365_CLIENT_ID, settings.MICROSOFT_O365_CLIENT_SECRET) - o365message.delete() - return +# if not os.path.isdir(settings.O365_TOKEN_PATH): +# os.mkdir(settings.O365_TOKEN_PATH) + +# 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