0
votes

I am using the Gmail API to create drafts. When I create a draft message where the recipient is my own email (the one that generates the credential), everything works fine but when I try to use a different email, the following message is printed:

{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "Delegation denied for [email protected]",
    "reason" : "forbidden"
  } ],
  "message" : "Delegation denied for [email protected]",
  "status" : "PERMISSION_DENIED"
}
    at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)

That's how I'm assembling my MimeMessage:

val props = Properties()
val session = Session.getDefaultInstance(props, null)
val message = MimeMessage(session)
message.setFrom(message.sender)
message.addRecipient(JavaxMessage.RecipientType.TO, InternetAddress("[email protected]"))
message.subject = subject

The scopes I am using:

// "https://www.googleapis.com/auth/gmail.compose"
GmailScopes.GMAIL_COMPOSE

I've tried a lot of stuff to make it work, but I didn't have any success.

2

2 Answers

2
votes

Delegation denied for [email protected]

This email appears to be a standard gmail email address. You appear to be trying to delegate a service account to a user with a standard gmail email address.

Service accounts only work with google workspace email accounts. You need to set up domain wide delegation to the serveries account and then you can set the delegation user.

If you want to use a standard gmail account you will need to authorize the user using Oauth2.

private fun getCredentials(httpTransport: NetHttpTransport): Credential? {
    val inputStream = File("credentials.json").inputStream()
    val clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, InputStreamReader(inputStream))
    val flow = GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(FileDataStoreFactory(File(TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline")
            .build()
    val receiver = LocalServerReceiver.Builder().setPort(8888).build()
    return AuthorizationCodeInstalledApp(flow, receiver).authorize("user")
}



 public static MimeMessage createEmail(String to,
                                          String from,
                                          String subject,
                                          String bodyText)
            throws MessagingException {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        MimeMessage email = new MimeMessage(session);

        email.setFrom(new InternetAddress(from));
        email.addRecipient(javax.mail.Message.RecipientType.TO,
                new InternetAddress(to));
        email.setSubject(subject);
        email.setText(bodyText);
        return email;
    }

Sending

0
votes

Thank you @DaImTo for your reply and all the info provided.


Based on the info provided, to those who have the same problem as I do, I've found a nice workaround:

  • set the "TO" recipient to the user's email;
  • add a "BCC" recipient to the actual recipient email.

Here's the code to demonstrate it:

    val meProfile = gmail.users().getProfile("me").execute()
    val toRecipient = InternetAddress(meProfile.emailAddress)
    val ccRecipient = InternetAddress(to)

    val props = Properties()
    val session = Session.getDefaultInstance(props, null)
    val message = MimeMessage(session)
    message.setFrom(message.sender)

    // here's the magic :D
    message.addRecipient(JavaxMessage.RecipientType.TO, toRecipient)
    message.addRecipient(JavaxMessage.RecipientType.BCC, ccRecipient)

    message.subject = subject