Gmail (for business) API doesn't allow to send email from Alias?
Asked Answered
F

3

6

I want to email my customers using different "roles" (e.g. info@ , customer-support@, tech-support@, no-reply@).

I've tried 2 approaches:

  1. Multiple "users"/accounts in my Gmail for business application.
  2. Single gmail account with multiple aliases.

I started by setting up a Service Account with global delegation for my Gmail for Business application.

To test that it works, I've set up 2 users: [email protected] and [email protected]. Indeed, I can successfully send email both from lev@ and root@.

However, when I tried adding 5 distinct user accounts for my application, Gmail got paranoid of bots/abuse and asked me to prove that all the accounts are "human" including setting up passwords, signing in and SMS-text validation via phone. Moreover, they require different phones for different accounts to prove it's a different person. So the setup of the accounts becomes a major issue.

I also want to avoid creating multiple accounts since I'm paying for each one, and since semantically, all the roles are just a single account. So aliases seem like a better idea.

The problem is that when I'm trying to send email and set the "from" field to the alias (e.g. from:[email protected]), I'm getting the following exception:

Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "Delegation denied for [email protected]",
    "reason" : "forbidden"
  } ],
  "message" : "Delegation denied for [email protected]"
}

Anyone faced and solved this issue?

The authentication/credential code is as follows:

/*
 * Set up a hashmap HashMap<String, Gmail> gmailServiceByAccount where
 * gmailServiceByAccount.get(emailAccount) contains an authorized Gmail service
 */
private void prepareService(String emailAccount) throws Exception {
    if (gmailServiceByAccount.containsKey(emailAccount)) {
        return;
    }
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

    GoogleCredential credential = new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(jsonFactory)
    .setServiceAccountId(Config.getInstance().getProperty(Config.gmail_service_account))
    .setServiceAccountPrivateKeyFromP12File(new File(Config.getInstance().getPathToGmailCredential()))
    .setServiceAccountScopes(Arrays.asList(GmailScopes.GMAIL_COMPOSE))
    .setServiceAccountUser(emailAccount)
    .build();        


    gmailServiceByAccount.put(
        emailAccount,
        new Gmail.Builder(httpTransport, jsonFactory, credential)
            .setApplicationName(Config.getInstance().getProperty(Config.google_client_api_application_name))
            .build());
}

And the code which sends the email is as follows:

/**
 * Send an email using the parameters provided.
 *
 * @param fromPersonalName : the free text description of the "from" address (e.g. "Customer Suppport" or "No Reply").
 * @param fromAddress : the email address of the sender, the mailbox account (e.g. [email protected]).
 * @param to : the email address of the recepient.
 * @param subject : Subject of the email.
 * @param htmlContent : (may be null) The HTML-styled body text of the email.
 * @param plainTextContent : (may be null)  The plain text body of the email (e.g if the customer email client does not support or disables html email).
 */
public void sendMail(String fromPersonalName, String fromAddress, String to, String subject, String htmlContent, String plainTextContent) 
        throws Exception {
    prepareService(fromAddress);
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    MimeMessage email = new MimeMessage(session);
    InternetAddress tAddress = new InternetAddress(to);
    InternetAddress fAddress = new InternetAddress(fromAddress);
    fAddress.setPersonal(fromPersonalName);
    email.setFrom(fAddress);
    email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
    email.setSubject(subject);

    Multipart multiPart = new MimeMultipart("alternative");
    if (!StringValidation.isEmpty(plainTextContent)) {
        MimeBodyPart textPart = new MimeBodyPart();
        textPart.setContent(plainTextContent, "text/plain");
        textPart.setHeader("Content-Type", "text/plain; charset=\"UTF-8\"");
        multiPart.addBodyPart(textPart); 
    }

    if (!StringValidation.isEmpty(htmlContent)) {
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(htmlContent, "text/html; charset=\"UTF-8\"");
        multiPart.addBodyPart(htmlPart);
    }        
    email.setContent(multiPart);


    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    email.writeTo(bytes);
    String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
    Message message = new Message();
    message.setRaw(encodedEmail);
    gmailServiceByAccount.get(fromAddress).users().messages().send(fromAddress, message).execute();

}
Fortenberry answered 18/12, 2015 at 4:11 Comment(4)
Could you show the code? What you are saying should work.Cyr
Thanks @Tholle, I've added the code to my question body. It's a bit involved, but I hope easy to read. Let me know what you think.Fortenberry
Sorry for not getting back to you Lev. I can't see anything wrong. Hopefully a pro can chime in. :)Cyr
Yeah, @Cyr , I'm afraid it's a lost cause. I decided to just use multiple users. Aliases won't work.Fortenberry
F
1

After additional research, it looks like the only option is to have multiple users.

The code I've posted indeed works for multiple users, but not for anything else.

I've tried multiple options including aliases and group email accounts. I'd either get "delegation denied" or "invalid grant" errors.

I've tried contacting Google For Business customer and tech support, but they don't support the API.

There's a great workaround to creating several users without having to go through phone validation. Just specify these users as "existing users" when you're signing into Google For Business initially, and activate them before you even transfer the domain.

For the account I've created without pre-existing users, I had to ask my friend's phones for phone validation.

Fortenberry answered 22/12, 2015 at 13:45 Comment(2)
I think sendgrid is a better solution, and it is free for 12,000 emails per month/. Also Amazon, and I am sure many others, offer this kind of service.Gratulant
Thanks @BenBrahim, I've already implemented the gMail solution and using it for a while. I'll keep SendGrid in mind. Amazon was a great option, but I recall looking into it and preferring gMail.Fortenberry
S
1

You can now send emails using aliases as long as those aliases are defined for the user whose login credentials you're using.

This works for the Gmail for business only.

Setting up aliases to non-existent address can be tricky, so have a look at this how to set up a catch-all routing:

catchall-for-domain-aliases-in-gsuite-gmail

Sextillion answered 26/2, 2018 at 16:18 Comment(0)
B
0

Just additionally to Ladi's post, it seem to be easier to setup now. Make an alias account and configure it so you can send emails (https://support.google.com/domains/answer/9437157?hl=en&ref_topic=6293345) and set the 'from' field on the message to the alias (but still use 'me' on the API call)

Bently answered 26/2, 2021 at 1:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.