this may have been asked before but I haven't seen this specific issue, at least not recognizably
I finally figured out how to send an email through the Gmail API, and now need to add attachments, so I edited the code found on Google's API guide basically just adding some arguments and adding in the "message.add_attachment()" part you see below. the issue is that when "message.to_bytes" is called, it starts some infinite loop and I simply cant understand the literature on these two methods. can anyone help me encode this email object so I can send it with the attachments?
my code:
from __future__ import print_function
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import base64
from email.message import EmailMessage
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
SCOPES = ['https://www.googleapis.com/auth/gmail.send']
def send_message(message:str , subject:str, to_email:str, attachments: list=None):
"""Create and send an email message
Print the returned message id
Returns: Message object, including message id """
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
try:
service = build('gmail', 'v1', credentials=creds)
message = EmailMessage()
message.set_content(message)
# I added this part
if attachments:
for attachment in attachments:
with open(attachment, 'rb') as content_file:
content = content_file.read()
message.add_attachment(content, maintype='application', subtype= (attachment.split('.')[1]), filename=attachment)
message['To'] = to_email
message['From'] = '[email protected]'
message['Subject'] = subject
# encoded message
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {
'raw': message
}
# pylint: disable=E1101
send_message = (service.users().messages().send
(userId="me", body=create_message).execute())
print(F'Message Id: {send_message["id"]}')
except HttpError as error:
print(F'An error occurred: {error}')
send_message = None
return send_message
the error message
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 116, in flatten
self._write(msg)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 181, in _write
self._dispatch(msg)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 218, in _dispatch
meth(msg)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 362, in _handle_message g.flatten(msg.get_payload(0), unixfrom=False, linesep=self._NL)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 116, in flatten
self._write(msg)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 181, in _write
self._dispatch(msg)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\generator.py", line 209, in _dispatch
main = msg.get_content_maintype()
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\message.py", line 594, in get_content_maintype
ctype = self.get_content_type()
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\message.py", line 578, in get_content_type
value = self.get('content-type', missing)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\message.py", line 471, in get
return self.policy.header_fetch_parse(k, v)
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\policy.py", line 159, in header_fetch_parse if hasattr(value, 'name'):
File "C:\Users\Cosmo Staff\AppData\Local\Programs\Python\Python310\lib\email\headerregistry.py", line 205, in name
@property
File "c:\Users\Cosmo Staff\.vscode\extensions\ms-python.python-2022.12.0\pythonFiles\lib\python\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_trace_dispatch_regular.py", line 469, in __call__
return None if event == 'call' else NO_FTRACE
RecursionError: maximum recursion depth exceeded in comparison
the full terminal has allot more of that but its allot so I pasted the last few lines
CodePudding user response:
Modification points:
In your script,
message
is used withdef send_message(message:str , subject:str, to_email:str, attachments: list=None):
andmessage = EmailMessage()
. I think that the reason for your current issue ofdef send_message(message:str , subject:str, to_email:str, attachments: list=None):
is due to this.And also, I think that at
create_message = {'raw': message}
, an error occurs. Becausemessage
is not URL safe base64. I thought that in this case,encoded_message
ofencoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
should be used here. I thought that this will be your 2nd issue.
When these points are reflected in your script, it becomes as follows.
Modified script:
def send_message(messageBody:str , subject:str, to_email:str, attachments: list=None):
"""Create and send an email message
Print the returned message id
Returns: Message object, including message id """
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
try:
service = build('gmail', 'v1', credentials=creds)
message = EmailMessage()
message.set_content(messageBody)
# I added this part
if attachments:
for attachment in attachments:
with open(attachment, 'rb') as content_file:
content = content_file.read()
message.add_attachment(content, maintype='application', subtype= (attachment.split('.')[1]), filename=attachment)
message['To'] = to_email
message['From'] = '[email protected]'
message['Subject'] = subject
# encoded message
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {
'raw': encoded_message
}
# pylint: disable=E1101
send_message = (service.users().messages().send
(userId="me", body=create_message).execute())
print(F'Message Id: {send_message["id"]}')
except HttpError as error:
print(F'An error occurred: {error}')
send_message = None
return send_message
- In this modification,
message
ofdef send_message(message:str , subject:str, to_email:str, attachments: list=None):
is modified tomessageBody
. And,create_message = {'raw': message}
is modified tocreate_message = {"raw": encoded_message}
.
Note:
- When I tested the modified script in my environment, I confirmed that the modified script worked. If another error occurs, please show the error message.