Gmail API 配置问题(在 Java 中)

2022-09-04 22:32:00

这是我的Gmail服务配置/工厂类:

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.GmailScopes;

public class GmailServiceFactoryBean {

    private @Autowired Environment env;

    private final NetHttpTransport transport;
    private final JacksonFactory jacksonFactory;

    public GmailServiceFactoryBean() throws GeneralSecurityException, IOException {
        this.transport = GoogleNetHttpTransport.newTrustedTransport();
        this.jacksonFactory = JacksonFactory.getDefaultInstance();
    }

    public Gmail getGmailService() throws IOException, GeneralSecurityException {
        return new Gmail.Builder(transport, jacksonFactory, getCredential())
                .setApplicationName(env.getProperty("gmail.api.application.name")).build();
    }

    private HttpRequestInitializer getCredential() throws IOException, GeneralSecurityException {
        File p12File = new File(this.getClass().getClassLoader().getResource("google-key.p12").getFile());

        Credential credential = new GoogleCredential.Builder()
            .setServiceAccountId(env.getProperty("gmail.api.service.account.email"))
            .setServiceAccountPrivateKeyId(env.getProperty("gmail.api.private.key.id"))
            .setServiceAccountPrivateKeyFromP12File(p12File)
            .setTransport(transport)
            .setJsonFactory(jacksonFactory)
            .setServiceAccountScopes(GmailScopes.all())
            //.setServiceAccountUser(env.getProperty("gmail.api.user.email"))
            .build();

        credential.refreshToken();

        return credential;
    }

}

这是我的内部邮件服务,它在引擎盖下使用以前的bean:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.Message;
import com.example.factory.GmailServiceFactoryBean;
import com.example.service.MailService;
import com.example.service.exception.MailServiceException;

@Service
public class MailServiceImpl implements MailService {

    private @Autowired GmailServiceFactoryBean gmailServiceFactoryBean;
    private @Autowired Environment env;

    @Override
    public void send(com.example.model.Message message, String recipient) throws MailServiceException {
        try {
            Gmail gmailService = gmailServiceFactoryBean.getGmailService();
            MimeMessage mimeMessage = createMimeMessage(message, recipient);
            Message gMessage = createMessageWithEmail(mimeMessage);
            gmailService.users().messages().send("me", gMessage).execute();
        } catch(MessagingException | IOException | GeneralSecurityException e) {
            throw new MailServiceException(e.getMessage(), e.getCause());
        }
    }

    @Override
    public void send(com.example.model.Message message, List<String> recipients) throws MailServiceException {
        for (String recipient : recipients) {
            send(message, recipient);
        }
    }

    private MimeMessage createMimeMessage(com.example.model.Message message, String recipient) throws MessagingException {
        Session session = Session.getDefaultInstance(new Properties());

        MimeMessage email = new MimeMessage(session);
        InternetAddress toAddress = new InternetAddress(recipient);
        InternetAddress fromAddress = new InternetAddress(env.getProperty("gmail.api.service.account.email"));

        email.setFrom(fromAddress);
        email.addRecipient(RecipientType.TO, toAddress);
        email.setSubject(message.getTitle());
        email.setText(message.getContent(), env.getProperty("application.encoding"));

        return email;
    }

    private Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        email.writeTo(baos);
        return new Message().setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray()));
    }
}

当我执行类的方法时,我得到以下响应:send(Message message, String recipient)MailServiceImpl

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

有谁知道出了什么问题?


答案 1

要使 GMail API 正常工作,您必须在 Google Apps 帐号中“将网域范围的权限委托给服务帐号”。

服务帐号并不代表 Google 个人帐号。您也不能将权限委托给整个Google domain(***@gmail.com)。

另一种出路可能是使用OAuth 2.0 for Web Server ApplicationsJava Mail api。

欲了解更多信息,请查看: GMail REST API: 使用谷歌凭据而不冒充


答案 2

检查您是否已启用 gmail 以使用第三方应用程序发送邮件。

转到我的帐户 - >登录和安全 - >连接的应用程序现在滚动到页面底部,您将获得安全性较低的应用程序 - >将其更改为打开!!希望这将起作用


推荐