So I am trying to send an email via the Gmail API. I have all the relevant credentials set up and I know the API connection is working because I am able to send a call to display emails from my inbox (for instance). However, when it comes to sending an email, I keep getting errors.
The code I have is as below:
class GoogleMailClient:
def __init__(self):
self.SCOPES = ['https://www.googleapis.com/auth/gmail.modify']
self.creds = self.get_credentials()
self.service = self.build_gmail_service()
def get_credentials(self):
creds = None
if os.path.exists('gmail_token.pickle'):
with open('gmail_token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', self.SCOPES)
creds = flow.run_local_server(port=0)
with open('gmail_token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
def build_gmail_service(self):
return build('gmail', 'v1', credentials=self.creds)
def send_email(self, message_body):
message = {'raw': message_body}
self.service.users().messages().send(userId='me', body=message).execute()
def list_messages(self):
results = self.service.users().messages().list(userId='me').execute()
messages = results.get('messages', [])
return messages
def get_message(self, message_id):
message = self.service.users().messages().get(userId='me', id=message_id).execute()
return message
def mark_as_read(self, message_id):
self.service.users().messages().modify(userId='me', id=message_id, body={'removeLabelIds': ['UNREAD']}).execute()
def delete_message(self, message_id):
self.service.users().messages().delete(userId='me', id=message_id).execute()
gmail_client = GoogleMailClient()
The first code I tried is:
# Compose your email message
subject = "Your Subject Here"
body = "Hey, this is your message body."
# Create the message using the email library
message = email.message.EmailMessage()
message['to'] = "XXX@hotmail.com"
message['subject'] = subject
message.set_content(body)
# Convert the message to a string
message_as_string = message.as_string()
# Encode the message as base64
message_bytes = message_as_string.encode("utf-8")
message_base64 = base64.urlsafe_b64encode(message_bytes).decode("utf-8")
# Create the message in the correct format
message = {'raw': message_base64}
# Send the email
gmail_client.send_email(message)
The error I get is:
HttpError: <HttpError 400 when requesting https://gmail.googleapis.com/gmail/v1/users/me/messages/send?alt=json returned "Invalid value at 'message' (raw), Starting an object on a scalar field". Details: "[{'message': "Invalid value at 'message' (raw), Starting an object on a scalar field", 'reason': 'invalid'}]">
The second code I tried is:
# Assuming you have already initialized the gmail_client and authorized it.
# Compose your email message
subject = "Your Subject Here"
body = "Hey, this is your message body."
# Create the message using the email library
message = email.message.EmailMessage()
message['to'] = "XXX@hotmail.com"
message['subject'] = subject
message.set_content(body)
# Convert the message to a string
message_as_string = message.as_string()
# Encode the message as base64
message_bytes = message_as_string.encode("utf-8")
message_base64 = base64.urlsafe_b64encode(message_bytes).decode("utf-8")
# Create the message in the correct format
message = {'raw': message_base64}
# Send the email using the Gmail API
try:
gmail_client.users().messages().send_mail(message_body=message).execute()
print("Email sent successfully!")
except Exception as e:
print(f"An error occurred: {e}")
The error I get is:
An error occurred: 'GoogleMailClient' object has no attribute 'users'
How can I fix this?
If you want to use the script of The first code I tried is:
, how about the following modification?
# Create the message in the correct format
message = {'raw': message_base64}
# Send the email
gmail_client.send_email(message)
gmail_client.send_email(message_base64)
I thought that in your function send_email
, the value of message_body
has already been put into a value of raw
with message = {'raw': message_body}
. So, in your script, I thought that message_base64
can be directly used instead of {'raw': message_base64}
.
When I tested this modification using my account, I confirmed that an email could be sent.
About The second code I tried is:
, I thought that userId='me'
is required to be added like gmail_client.users().messages().send_mail(userId='me', message_body=message).execute()
.