Пакетирование почты с помощью Gmail завершается с ошибкой с SMTP, успешно с Google API - PullRequest
0 голосов
/ 25 октября 2018

У меня есть пакет Node.js, который обрабатывает список пользователей и выполняет вызовы API для бэкэнда Java для каждого пользователя.Пакет 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 дает:

{"status": "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);
        }
    }
}

И рабочий узел.Реализация 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)

Относительно реализации клиента Node.js , основное отличие состоит в том, что Node.js, кажется, не использует SMTP, а вместо этого вызывает API.

Я прочитал здесь , что существуют определенные ограничения для SMTP, но я не могу понять, какое ограничение я достиг, потому что сообщение об ошибке очень неясно (DDoS, сообщений на 10минут, ...).

...