python-o365
python-o365 copied to clipboard
Transient Error
Sending email with attachment inside 1 out of 3 times will result in Transient Error and email wont be send. Here is the full error trace:
[2021-08-06 19:16:49,244: ERROR/ForkPoolWorker-2] Task api.outlook_sender.send_email[9e07c7a4-3a0a-4634-bcfe-d33ec91fd92c] raised unexpected: HTTPError('403 Client Error: Forbidden for url: https://graph.microsoft.com/v1.0/me/sendMail | Error Message: Cannot send this mail due to a transient error. Please try again later (0x00004000)., WASCL UserAction verdict is not None. Actual verdict is TransientError.')
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/celery/app/trace.py", line 385, in trace_task
R = retval = fun(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/celery/app/trace.py", line 648, in __protected_call__
return self.run(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/sentry_sdk/integrations/celery.py", line 186, in _inner
reraise(*exc_info)
File "/usr/local/lib/python3.8/dist-packages/sentry_sdk/_compat.py", line 55, in reraise
raise value
File "/usr/local/lib/python3.8/dist-packages/sentry_sdk/integrations/celery.py", line 181, in _inner
return f(*args, **kwargs)
File "/app/backend/stylelab/api/outlook_sender.py", line 170, in send_email
result = send_message(profile, msg)
File "/app/backend/stylelab/api/outlook_sender.py", line 69, in send_message
result = msg.send()
File "/usr/local/lib/python3.8/dist-packages/O365/message.py", line 699, in send
response = self.con.post(url, data=data)
File "/usr/local/lib/python3.8/dist-packages/O365/connection.py", line 822, in post
return self.oauth_request(url, 'post', data=data, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/O365/connection.py", line 800, in oauth_request
return self._internal_request(self.session, url, method, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/O365/connection.py", line 762, in _internal_request
raise HTTPError('{} | Error Message: {}'.format(e.args[0], error_message), response=response) from None
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://graph.microsoft.com/v1.0/me/sendMail | Error Message: Cannot send this mail due to a transient error. Please try again later (0x00004000)., WASCL UserAction verdict is not None. Actual verdict is TransientError.
Here is the code I use to do it
def parse_attachment(dir_path, att):
try:
if (att == None):
return None
content = urllib.urlopen(att.file.url, timeout = 10).read()
with open(os.path.join(dir_path, att.file.name), 'wb') as temp_file:
temp_file.write(content)
return os.path.join(dir_path, att.file.name)
except Exception as e:
logger.error(f'Could not upload the attachment, Error: {e}')
return None
def remove_attachment(dir_path):
if dir_path != None and len(dir_path) != 0 and os.path.exists(dir_path):
shutil.rmtree(dir_path)
def send_message(profile, message):
try:
from api.views import CustomTokenBackend
logger.info(f"sending outlook from {profile.email_line()}")
token_backend = CustomTokenBackend(profile=profile)
account = Account(credentials=settings.OUTLOOK_CREDENTIALS, scopes=SCOPES, token_backend=token_backend)
msg = account.new_message()
msg.to.add(message["to"])
msg.subject = message["subject"]
msg.body = message["body"]
temp_dir_name = tempfile.mkdtemp()
path_to_att = parse_attachment(temp_dir_name, message['attachment'])
if path_to_att != None and len(path_to_att) != 0:
msg.attachments.add(path_to_att)
result = msg.send()
remove_attachment(temp_dir_name)
return result
except errors.HttpError:
return 'Error'
I have no clue... I've never seen this error. The fact that is a 403 error is strange.
I've read on google that this could be caused by some special chars being used in some of the provided fields like "to addresess", subject and so.
@janscas Yea, thats a weird error. I solved it by adding exponential backoff retry as was recommended on microsoft graph api page.