使用带有服务帐户的 Gmail API 发送邮件

Posted

技术标签:

【中文标题】使用带有服务帐户的 Gmail API 发送邮件【英文标题】:Send mail using Gmail API with service account 【发布时间】:2021-03-15 01:43:03 【问题描述】:

这是我的准系统代码。我想作为我域的用户之一发送电子邮件。每次通话的电子邮件可能都不同。

const  google  = require('googleapis');

function makeBody(to, from, subject, message) 
    const str = [
        'Content-Type: text/plain; charset="UTF-8"\n',
        'MIME-Version: 1.0\n',
        'Content-Transfer-Encoding: 7bit\n',
        'to: ', to, '\n',
        'from: ', from, '\n',
        'subject: ', subject, '\n\n',
        message,
    ].join('');

    return Buffer.from(str).toString("base64").replace(/\+/g, '-').replace(/\//g, '_');


class MailProvider 
    gmail = google.gmail(
        version: 'v1',
        auth: new google.auth.GoogleAuth(
            keyFile: '../../assets/secrets/google.json', // See below
            scopes: [
                'https://mail.google.com/',
                'https://www.googleapis.com/auth/gmail.addons.current.action.compose',
                'https://www.googleapis.com/auth/gmail.compose',
                'https://www.googleapis.com/auth/gmail.modify',
                'https://www.googleapis.com/auth/gmail.send',
            ],
        ),
    );

    async sendMail(sendAs, sendTo) 
        return this.gmail.users.messages.send(
            userId: sendAs,
            requestBody: 
                raw: makeBody(sendTo, sendAs, 'Test subject', 'Test body'),
            ,
        ).catch(console.error);
    


new MailProvider().sendMail('noreply@mydomain.cz', 'akxe@seznam.cz');

截尾google.json:


  "type": "service_account",
  "project_id": "firm-aria-ID",
  "private_key_id": "ID",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...key...\n-----END PRIVATE KEY-----\n",
  "client_email": "rita-sm@firm-aria-ID.iam.gserviceaccount.com",
  "client_id": "ID",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/rita-sm%40firm-aria-ID.iam.gserviceaccount.com"

我收到failedPrecondition 错误。我不知道该做什么了……我在这玩了超过一整天……

错误:


  // ...
  code: 400,
  errors: [
    
      message: 'Precondition check failed.',
      domain: 'global',
      reason: 'failedPrecondition'
    
  ]

【问题讨论】:

你试过了吗:***.com/questions/29327846/… 当您说“您的域”时,您是指您的 Google Workspace 的用户成员吗?如果是,您是否设置了域范围委派? @JohnHanley 我不确定。我们是一家有 10 名员工的公司。我确实使用管理员帐户为 api 创建了一个服务帐户,什么是域范围委派。 @HarshanaSerasinghe 我确实看到了,但这是针对 javascript 的,我没有看到相同的设置选项。 查看我的答案,以获取使用 Python 中的服务帐户的 Gmail 示例:***.com/a/55367351/8016720 您需要在代码中添加另一个步骤以添加要模拟的身份。我的示例显示了此步骤。有关域范围委派的详细信息,请参阅此文档:developers.google.com/admin-sdk/directory/v1/guides/delegation 要模拟您的 Google Workspace 域中的用户,服务帐户需要域范围委派。 【参考方案1】:

您不能使用服务帐户发送电子邮件。您需要使用 3 legged oauth 并代表最终用户发送电子邮件。

【讨论】:

以上是关于使用带有服务帐户的 Gmail API 发送邮件的主要内容,如果未能解决你的问题,请参考以下文章

Gmail API - PHP - 使用服务帐户发送电子邮件

Gmail API - 从 g-suite 服务帐户发送邮件时设置发件人名称

当我尝试使用我的 Google 服务帐户通过 Gmail API 发送电子邮件时,“myemail@mydomain.com”的委派被拒绝

如何从企业帐户发送带有烧瓶邮件的电子邮件?

向 Gmail 帐户发送邮件

使用 Gmail api 通过 Android 应用发送邮件