Send mail via Google Apps Gmail using service account domain wide delegation in nodejs

后端 未结 2 935
名媛妹妹
名媛妹妹 2020-12-02 02:13

I\'ve been reading tutorials and seeing examples for 2 days already, with no success. I want to send an email using Google Apps Gmail account in NodeJS environment, however,

相关标签:
2条回答
  • 2020-12-02 02:50

    So I was half-step close to the solution, the problem was that while creating const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], null); i did not mention the account to be impersonated.

    The correct initialization should be: const jwtClient = new google.auth.JWT(googleKey.client_email, null, googleKey.private_key, ['https://www.googleapis.com/auth/gmail.send'], 'user@domain.com');

    To summarize, the correct steps are:

    1. Created a project in Google Cloud Platform
    2. Created a service account
    3. Enabled Domain Wide Delegation for the service account
    4. Downloaded the key for the service account in JSON format
    5. API Manager > Credentials i have created OAuth 2.0 Client ID
    6. Enabled Gmail API for the project

    In Google Apps Admin console:

    1. In Security > Advanced Settings > Manage API client access i have added the Client ID from step 4 above
    2. I have added all possible scopes for the Client ID

    This is the code that sends mails:

    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);
         }
     });
    

    Hope that would be helpful for others

    0 讨论(0)
  • 2020-12-02 02:58

    Thanks very much @agoldis. Both the summary steps and the code were very helpful.

    It helped me pick up on a few things I needed to fix on both the GoogleWorkspace and the ApplicationCode end of the communication path. Below is my c# implementation for anyone who needs it.

    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("=", "" );
    }
    
    0 讨论(0)
提交回复
热议问题