При использовании учетной записи службы с Gmail API . Вам необходимо установить делегирование по всему домену , которое позволяет учетной записи службы выдавать себя за любого пользователя в вашем G Suite домене . Следовательно, вы должны иметь учетную запись G Suite, чтобы иметь возможность использовать широкое делегирование домена, как говорят документы:
Если у вас есть домен G Suite, например, если вы используете G Suite, Администратор домена G Suite может авторизовать приложение для доступа к пользовательским данным от имени пользователей в домене G Suite.
Итак, зачем вам выдавать себя за пользователя (реального человека)? это связано с тем, что служебная учетная запись - это бот (а не реальный человек), который используется для взаимодействия между серверами, благодаря чему ваше приложение вызывает API-интерфейсы Google, и хотя учетная запись службы имеет параметр client_email
, который имеет структура, подобная name@project-randomnumber.iam.gserviceaccount.com
, это не реальная электронная почта, которая принадлежит реальному человеку (я знаю, что это немного сбивает с толку).
Сказав это, я внес некоторые изменения в ваш код. Во-первых, я изменил вашу функцию validationService
, чтобы создать службу с использованием делегирования на уровне домена.
def validationService():
# Set the crendentials
credentials = service_account.Credentials.\
from_service_account_file(SERVICE_ACCOUNT_FILE, scopes= SCOPES)
# Delegate the credentials to the user you want to impersonate
delegated_credentials = credentials.with_subject(USER_EMAIL)
service = discovery.build('gmail', 'v1', credentials=delegated_credentials)
return service
В вашей функции SendMessage
необязательно передавать пользователя, который собирается отправлять электронную почту. , Использование me достаточно в качестве Users.messages: send Параметры состояние:
userId string Адрес электронной почты пользователя. Специальное значение me может использоваться для обозначения аутентифицированного пользователя.
def SendMessage(service, message):
message = service.users().messages().send(userId="me", body=message).execute()
return message
Весь код в конце может выглядеть так:
from googleapiclient import discovery, errors
from oauth2client import file, client, tools
from google.oauth2 import service_account
from email.mime.text import MIMEText
import base64
SERVICE_ACCOUNT_FILE = 'service_account.json'
SCOPES = [' https://mail.google.com/']
# The user we want to "impersonate"
USER_EMAIL = "user@domain"
def validationService():
# Set the crendentials
credentials = service_account.Credentials.\
from_service_account_file(SERVICE_ACCOUNT_FILE, scopes= SCOPES)
# Delegate the credentials to the user you want to impersonate
delegated_credentials = credentials.with_subject(USER_EMAIL)
service = discovery.build('gmail', 'v1', credentials=delegated_credentials)
return service
def SendMessage(service, message):
message = service.users().messages().send(userId="me", body=message).execute()
return message
def CreateMessage(sender, to, subject, message_text):
message = MIMEText(message_text)
message['to'] = to
message['from'] = sender
message['subject'] = subject
return {'raw': base64.urlsafe_b64encode(message.as_string().encode()).decode()}
def main():
try:
service = validationService()
email = CreateMessage(USER_EMAIL, "receiverrmail@domain", "Test", "This is a test")
email_sent = SendMessage(service, email)
print('Message Id:', email_sent['id'])
except errors.HttpError as err:
print('\n---------------You have the following error-------------')
print(err)
print('---------------You have the following error-------------\n')
if __name__ == '__main__':
main()
Notice
Вам также необходимо разрешить вашей учетной записи службы получать доступ к API Google при использовании делегирования по всему домену, установив Управление доступом клиента API в своей учетной записи G Suite.