繁体   English   中英

使用服务帐户和谷歌发送邮件 api python

[英]send mail using service account and google api python

编辑:接受答案后:我的问题是关于一个免费的 Gmail 帐户(我不知道有什么区别),答案是关于一个付费帐户(这是一个正确的帐户),答案告诉我有一个区别,它让我对我的情况做出了正确的回答——使用密码

我正在尝试使用 google API 和服务帐户发送邮件,但出现以下错误:

An error occurred: <HttpError 400 when requesting https://gmail.googleapis.com/gmail/v1/users/me/drafts?alt=json returned "Precondition check failed.". Details: "[{'message': 'Precondition check failed.', 'domain': 'global', 'reason': 'failedPrecondition'}]">

这是我的代码:

from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from oauth2client.service_account import ServiceAccountCredentials

import base64
from email.message import EmailMessage


# If modifying these scopes, delete the file token.json.
SCOPES = ['https://mail.google.com/']


def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
       creds = ServiceAccountCredentials.from_json_keyfile_name(
        """path_to_cred_file.json""", SCOPES)

    try:
        # Call the Gmail API
        service = build('gmail', 'v1', credentials=creds)
        message = EmailMessage()
        message.set_content('This is automated draft mail')
        message['To'] = 'somemail@gmail.com'
        message['From'] = 'somemail@gmail.com'
        message['Subject'] = 'Automated draft'

        # encoded message
        encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()

        create_message = {
            'message': {
                'raw': encoded_message
            }
        }
        # pylint: disable=E1101
        draft = service.users().drafts().create(userId="me",
                                                body=create_message).execute()
    except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
        print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

“Precondition check failed”通常意味着您正在尝试做一些无法完成的事情。 在这种情况下,您尝试服务帐户发送 email,这是不可能的。 此答案包含指向 Google 文档中相关主题的链接。 他们说:

服务帐户不能与 gmail 一起使用,除非您将全域委托设置为 Gsuite 帐户。 原因是服务帐户是它自己的用户,您需要委托其访问您的 gmail 帐户的权限。 这仅适用于 gsuite 域 email 地址。

这意味着服务帐户本身不能发送消息,而是需要将访问权限委托给普通用户帐户才能发送电子邮件。 为此,您可以在creds之后添加以下行:

    delegated_creds=credentials.with_subject("someuser@yourdomain.com")

    #where someuser@ is the email of the user that you're sending email as

之后,您可以使用delegated_creds而不是creds来调用服务。

此外,您似乎已经从 Google 的 指南中获得了示例,但请注意,您的示例创建了草稿而不是发送 email。发送电子邮件的 API 调用略有不同。 考虑到这一点,这是一个基于您的代码的完整示例,它对我有用:

#all the imports

SCOPES = ['https://mail.google.com/']

def main():

    creds = None
       creds = ServiceAccountCredentials.from_json_keyfile_name(
        """path_to_cred_file.json""", SCOPES)
     
       delegated_creds=credentials.with_subject("someuser@yourdomain.com")

    try:
        # Call the Gmail API
        service = build('gmail', 'v1', credentials=delegated_creds) 
        message = EmailMessage()
        message.set_content('This is automated draft mail')
        message['To'] = 'somemail@gmail.com'
        message['From'] = 'somemail@gmail.com'
        message['Subject'] = 'Automated draft'

        encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()

        create_message = {
            'raw': encoded_message
        }

        email = service.users().messages().send(userId="me", 
                                                body=create_message).execute()
        except HttpError as error:
            # TODO(developer) - Handle errors from gmail API.
            print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

最后,正如我链接的主题中所解释的那样,这仅适用于 Google Workspace 帐户,您不能将访问权限委托给免费的 Gmail 帐户,因此请记住这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM