与Gmail一起进行邮件批处理对SMTP失败,而对Google API进行成功

时间:2018-10-25 09:14:06

标签: oauth-2.0 gmail javamail google-authentication completable-future

我有一个Node.js批处理,该批处理处理用户列表,并为每个用户向Java后端进行API调用。 Node.js批处理和Java后端都使用G-Suite帐户向用户发送邮件。

Node.js没问题,所有邮件都成功。关于Java,在发送了一定数量的邮件之后,以下邮件失败,并显示以下消息:

org.springframework.mail.MailAuthenticationException: Authentication
failed; nested exception is javax.mail.AuthenticationFailedException:
334
eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
;   nested exception is:    javax.mail.AuthenticationFailedException:
OAUTH2 asked for more   at
org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:424)
at
org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:345)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)

Base64解码后给出的内容:

  

{“状态”:“ 400”,“方案”:“承载者”,“范围”:“ https://mail.google.com/”}

以下是我实现的一些细节。

@Service
public class MailServiceImpl implements MailService {

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${fr.app.email.service-account}")
    private String serviceAccount;

    @Value("${fr.app.email.scope}")
    private String scope;

    private Credential creds;

    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy à HH:mm");

    @Async
    public CompletableFuture<Void> sendSimpleMail(String email, String subject, String text) throws Exception {

        if(creds == null) {
            final HttpTransport TRANSPORT = new NetHttpTransport();
            final JsonFactory JSON_FACTORY = new JacksonFactory();
            final URL URL = Thread.currentThread().getContextClassLoader().getResource("MyApp-d8a5d9785c54.p12");

            creds = new GoogleCredential.Builder()
                .setTransport(TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(serviceAccount)
                .setServiceAccountPrivateKeyFromP12File(new File(URL.getFile()))
                .setServiceAccountScopes(Collections.singleton(scope))
                .setServiceAccountUser(((JavaMailSenderImpl)javaMailSender).getUsername())
                .build();
        }

        if(creds.getExpiresInSeconds() != null && creds.getExpiresInSeconds() < 0 || creds.getAccessToken() == null) {
            creds.refreshToken();
        }

        try {

            ((JavaMailSenderImpl)javaMailSender).setDefaultEncoding("UTF-8");
            ((JavaMailSenderImpl)javaMailSender).setPassword(creds.getAccessToken());
            Message message = new MimeMessage(((JavaMailSenderImpl)javaMailSender).getSession());
            message.setFrom(new InternetAddress(((JavaMailSenderImpl)javaMailSender).getUsername()));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email));
            message.setSubject(subject);
            message.setContent(text, "text/html; charset=UTF-8");

            javaMailSender.send((MimeMessage)message);

            return CompletableFuture.completedFuture(null);

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
}

以及有效的Node.js实现:

const { google } = require('googleapis');

// configure a JWT auth client
let jwtClient = new google.auth.JWT(
    config.appServiceAccount,
    config.googleKeyFile,
    null,
    [config.googleScope],
    config.appMail
);

logger.info('Gmail client created!');

const gmail = google.gmail({ version: "v1", auth: jwtClient });

function sendMail(gmail, jwtClient, to, subject, message) {

    let headers = {
        "To": to,
        "Subject": subject,
        "Content-Type": "text/html; charset=UTF-8"
    }

    let email = '';
    for (var header in headers)
        email += header += ": " + headers[header] + "\r\n";

    email += "\r\n" + message;

    return gmail.users.messages.send({
        auth: jwtClient,
        userId: config.appMail,
        requestBody: {
            raw: btoa(email).replace(/\+/g, '-').replace(/\//g, '_')
        }
    });
}

由于有了mail.debug=true配置键,我有了有关该错误的更多详细信息:前80条消息产生以下输出:

DEBUG SMTP: protocolConnect login, host=smtp.gmail.com,
user=contact@example.com, password=<non-null> DEBUG SMTP: Attempt to
authenticate using mechanisms: XOAUTH2 DEBUG SMTP: Using mechanism
XOAUTH2 AUTH XOAUTH2 <access_token>
235 2.7.0 Accepted

以下消息产生输出:

DEBUG SMTP: protocolConnect login, host=smtp.gmail.com,
user=contact@example.com, password=<non-null> DEBUG SMTP: Attempt to
authenticate using mechanisms: XOAUTH2 DEBUG SMTP: Using mechanism
XOAUTH2 AUTH XOAUTH2 <exact same access_token>
334
eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
DEBUG SMTP: AUTH XOAUTH2 failed, THROW:
javax.mail.AuthenticationFailedException: OAUTH2 asked for more
        at com.sun.mail.smtp.SMTPTransport$OAuth2Authenticator.doAuth(SMTPTransport.java:1095)
        at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:909)
        at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:843)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:748)

关于the Node.js client implementation,主要区别在于Node.js似乎没有使用SMTP,而是调用了API。

我已经读过here,对于SMTP有特定的限制,但是由于错误消息非常不清楚(DDoS,每10分钟的消息,...),我无法确定达到了哪个限制。

0 个答案:

没有答案