【问题标题】:Send mail via Google Apps Gmail using service account domain wide delegation in nodejs使用 nodejs 中的服务帐户域范围委派通过 Google Apps Gmail 发送邮件
【发布时间】:2016-09-11 15:35:04
【问题描述】:

我已经阅读教程和查看示例 2 天了,但没有成功。 我想在 NodeJS 环境中使用 Google Apps Gmail 帐户发送电子邮件,但是,我收到来自 Google API 的400 响应:

{[Error: Bad Request]
code: 400,
errors:
  [{ 
    domain: 'global',
    reason: 'failedPrecondition',
    message: 'Bad Request'
  }]
}

这是我到目前为止所做的:

  1. 在 Google Cloud Platform 中创建了一个项目
  2. 创建了服务帐号
  3. 为服务帐号启用Domain Wide Delegation
  4. 已下载JSON 格式的服务帐号密钥
  5. API Manager > Credentials 我已经创建了OAuth 2.0 client ID
  6. 为项目启用 Gmail API

在 Google Apps 管理控制台中:

  1. 在Security > Advanced Settings > Manage API client access 我从上面的步骤4 添加了Client ID
  2. 我已经为Client ID 添加了所有可能的范围

这是尝试发送电子邮件的代码:

const google = require('googleapis');
const googleKey = require('./google-services.json');
const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], null);

jwtClient.authorize((err, tokens) => {
  if (err) {
    console.err(err);
    return;
  }
  console.log('Google auth success')
  var gmail = google.gmail({version: 'v1', auth: jwtClient})
  var raw = <build base64 string according to RFC 2822 specification>

  var sendMessage = gmail.users.messages.send({
    auth: jwtClient,
    userId: 'user@domain.com',
    message: {
      raw: raw
    }
  }, (err, res) => {
    if (err) {
      console.error(err);
    } else {
      console.log(res);
    }
});

我可以看到Google auth success 消息,并且请求使用正确初始化的令牌发送:

headers:
{ Authorization: 'Bearer ya29.CjLjAtVjGNJ8fcBnMSS8AEXAvIm4TbyNTc6g_S99HTxRVmzKpWrAv9ioTI4BsLKXW7uojQ',
 'User-Agent': 'google-api-nodejs-client/0.9.8',
 host: 'www.googleapis.com',
 accept: 'application/json',
 'content-type': 'application/json',
 'content-length': 2 }

不过,回复还是400

【问题讨论】:

    标签: node.js gmail google-apps jwt service-accounts


    【解决方案1】:

    所以我接近解决方案的一半,问题是在创建 const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], null); 时我没有提到要模拟的帐户。

    正确的初始化应该是: const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], 'user@domain.com');

    总而言之,正确的步骤是:

    1. 在 Google Cloud Platform 中创建了一个项目
    2. 创建了服务帐号
    3. 为服务帐号启用Domain Wide Delegation
    4. 以 JSON 格式下载服务帐号的密钥
    5. API Manager > Credentials 我创建了OAuth 2.0 Client ID
    6. 为项目启用 Gmail API

    在 Google Apps 管理控制台中:

    1. 在Security > Advanced Settings > Manage API client access 我从上面的第 4 步中添加了Client ID
    2. 我已经为Client ID 添加了所有可能的范围

    这是发送邮件的代码:

    const google = require('googleapis');
    const googleKey = require('./google-services.json');
    const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], '<user to impersonate>');
    
    jwtClient.authorize((err, tokens) => {
      if (err) {
        console.err(err);
        return;
      }
      console.log('Google auth success')
      var gmail = google.gmail({version: 'v1'})
      var raw = <build base64 string according to RFC 2822 specification>
    
      var sendMessage = gmail.users.messages.send({
        auth: jwtClient,
        userId: '<user to impersonate>',
        resource: {
          raw: raw
        }
      }, (err, res) => {
         if (err) {
           console.error(err);
         } else {
           console.log(res);
         }
     });
    

    希望对其他人有所帮助

    【讨论】:

    • 嘿伙计,当我尝试您的解决方案时,我不断收到Error: No key or keyFile set.。这是第 3 行 jwtClient 启动的第二个参数。知道这是为什么吗?这不是强制性参数.. :/
    • derp,我正在从 env vars 创建 JWT,我忘记设置了:D 感谢您的示例伙伴!
    【解决方案2】:

    非常感谢@agoldis。总结步骤和代码都非常有帮助。

    它帮助我了解了一些我需要在 GoogleWorkspace 和通信路径的 ApplicationCode 端修复的问题。下面是我的 c# 实现,供任何需要的人使用。

    private static void Try4()
    {
      try {
         //file included in project with properties:  CopyToOutputDirectory = CopyAlways
         var credential = GoogleCredential.FromFile("MyPrj-MyServiceAccount-Credentials.json")       
                          .CreateScoped(new[] { GmailService.Scope.GmailSend })
                          .CreateWithUser("WhoIAmImpersonating@bla.com")
                          .UnderlyingCredential as ServiceAccountCredential;
    
         var service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential });
    
         var nl = Environment.NewLine;
         string plainText =         "From:         WhoIAmImpersonating@bla.com" 
                             + nl + "To:           myfriend@gmail.com,"
                             + nl + "Subject:      This is the Subject" 
                             + nl + "Content-Type: text/html; charset=us-ascii" 
                             + nl 
                             + nl + "This is the message text.";
         var newMsg = new Message() { Raw = Base64UrlEncode(plainText) };
    
         service.Users.Messages.Send(newMsg, "WhoIAmImpersonating@bla.com").Execute();
         Console.WriteLine("Message Sent OK");
      }
      catch (Exception ex) {
          Console.WriteLine("Message failed");
      }
    }
    
    
    
    private static string Base64UrlEncode(string input)
    {
      var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
      return Convert.ToBase64String(inputBytes)
                    .Replace('+', '-')
                    .Replace('/', '_')
                    .Replace("=", "" );
    }
    

    【讨论】:

      猜你喜欢
      • 2016-03-27
      • 2020-09-06
      • 2023-04-03
      • 2012-08-18
      • 1970-01-01
      • 2017-03-13
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多