JHipster MailService — javax.mail.SendFailedException: нет адресов получателей

ОБНОВЛЕНИЕ: Здравствуйте, ребята!

Наконец-то я смог решить эту проблему, изменив способ добавления получателя. Не уверен, почему это работает, в отличие от плиты котла, но это позволило мне преодолеть это препятствие. Надеюсь, это поможет тем, кто сталкивается с подобными проблемами.

@Async
public void sendEmail(String to, String sendFrom, String subject, String content) {
    log.debug("Send e-mail to '{}' with subject '{}' and content={}",
            to, subject, content);

    // Prepare message using a Spring helper
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    try {
        mimeMessage.setRecipients(Message.RecipientType.TO, to);
        mimeMessage.setContent(content, MediaType.TEXT_HTML_VALUE);
        mimeMessage.setFrom(new InternetAddress(sendFrom));
        mimeMessage.setSubject(subject);

        javaMailSender.send(mimeMessage);
        log.debug("Sent e-mail to '{}'", to);
    } catch (Exception e) {
        log.warn("E-mail could not be sent to '{}', exception is: {}", to, e.getMessage());
    }
}

ИСХОДНОЕ СООБЩЕНИЕ

После нескольких дней исследований и обращения к более старшим разработчикам, которых я знаю, я, наконец, пришел сюда за помощью. Любой вклад или помощь очень ценятся!

Я использую MailService, поставляемый со стеком JHipster.

Приложение использует мою личную электронную почту. Он имеет двухэтапную аутентификацию, поэтому мне не нужно разрешать менее безопасные приложения, поскольку я напрямую даю своему приложению пароль через пароли приложений. IMAP и POP включены.

Из того, что я могу сказать, я могу правильно подключиться, я просто не могу отправить получателю. Я пробовал разные электронные письма на разных доменах, но безуспешно. Если я изменю пароль приложения на свой необработанный пароль, он жалуется, говоря, что должен использовать пароль для конкретного приложения. Итак, это заставляет меня убедиться, что я правильно аутентифицируюсь/подключаюсь.

Извлечение исходных кодов и отладка привели меня к doSend в JavaMailSenderImpl, и ошибка была вызвана методом mimeMessage.getAllRecipients().

Моя консоль показывает:

[DEBUG] com.myapp.aop.logging.LoggingAspect - Enter: com.myapp.service.MailService.sendEmail() with argument[s] = [[email protected], [email protected], hi, false, true]
[DEBUG] com.myapp.service.MailService - Send e-mail[multipart 'false' and html 'true'] to '[email protected]' with subject 'subjecthi' and content=hi
[DEBUG] com.sun.mail.smtp - useEhlo true, useAuth true
[DEBUG] com.sun.mail.smtp - trying to connect to host "smtp.gmail.com", port 587, isSSL false
[DEBUG] com.sun.mail.smtp - connected to host "smtp.gmail.com", port: 587

[DEBUG] com.sun.mail.smtp - Found extension "SIZE", arg "35882577"
[DEBUG] com.sun.mail.smtp - Found extension "8BITMIME", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "STARTTLS", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "ENHANCEDSTATUSCODES", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "PIPELINING", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "CHUNKING", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "SMTPUTF8", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "SIZE", arg "35882577"
[DEBUG] com.sun.mail.smtp - Found extension "8BITMIME", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN XOAUTH"
[DEBUG] com.sun.mail.smtp - Found extension "ENHANCEDSTATUSCODES", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "PIPELINING", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "CHUNKING", arg ""
[DEBUG] com.sun.mail.smtp - Found extension "SMTPUTF8", arg ""
[DEBUG] com.sun.mail.smtp - Attempt to authenticate using mechanisms: LOGIN     PLAIN DIGEST-MD5 NTLM 
[WARN] com.myapp.service.MailService - E-mail could not be sent to user     '[email protected]', exception is: Failed messages:     javax.mail.SendFailedException: No recipient addresses
[DEBUG] com.myapp.aop.logging.LoggingAspect - Exit:     com.myapp.service.MailService.sendEmail() with result = null

Предоставляю следующие файлы:

  • приложение.yml
  • MailConfiguration.java
  • MailService.java
  • вызов из моего OrderResource.java в MailService

application.yml

# Disable the spring security default configuration from spring-boot-actuator
management.security.enabled: true
security.basic.enabled: false

# Disable Jolokia - An http/json bridge for remote JMX access
endpoints.jolokia.enabled: false

# security configuration (this key should be unique for your application, and kept secret)
jhipster.security.rememberme.key: securitykey

StripeSecretApiKey: mystripekey

async:
    corePoolSize: 2
    maxPoolSize: 50
    queueCapacity: 10000

mail:
    host: smtp.gmail.com
    port: 587
    username: [email protected]
    password: myapppassword
    protocol: smtp
    tls: true
    auth: true
    from: [email protected]

authentication:
    oauth:
        clientid: mydomainapp
        secret: mysecret
        # Token is valid 2 hours
        tokenValidityInSeconds: 7200

swagger:
    title: mydomain API
    description: mydomain applications and beyond!
    termsOfServiceUrl: http://jhipster.github.io/
    contact:
    license: Apache 2.0
    licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.html

Вызов OrderResource.java для почтовой службы

mailService.sendEmail("[email protected]", "subject hi", "hi",false, true);

MailConfiguration.java

package com.myapp.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import java.util.Properties;

@Configuration
public class MailConfiguration implements EnvironmentAware {

    private static final String ENV_SPRING_MAIL = "mail.";
    private static final String DEFAULT_HOST = "127.0.0.1";
    private static final String PROP_HOST = "host";
    private static final String DEFAULT_PROP_HOST = "localhost";
    private static final String PROP_PORT = "port";
    private static final String PROP_USER = "username";
    private static final String PROP_PASSWORD = "password";
    private static final String PROP_PROTO = "protocol";
    private static final String PROP_TLS = "tls";
    private static final String PROP_AUTH = "auth";
    private static final String PROP_SMTP_AUTH = "mail.smtp.auth";
    private static final String PROP_STARTTLS = "mail.smtp.starttls.enable";
    private static final String PROP_TRANSPORT_PROTO =         "mail.transport.protocol";

    private final Logger log = LoggerFactory.getLogger(MailConfiguration.class);

    private RelaxedPropertyResolver propertyResolver;

    @Override
    public void setEnvironment(Environment environment) {
    this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_SPRING_MAIL);
    }

    @Bean
    public JavaMailSenderImpl javaMailSender() {
        log.debug("Configuring mail server");
    String host = propertyResolver.getProperty(PROP_HOST, DEFAULT_PROP_HOST);
    int port = propertyResolver.getProperty(PROP_PORT, Integer.class, 0);
    String user = propertyResolver.getProperty(PROP_USER);
    String password = propertyResolver.getProperty(PROP_PASSWORD);
    String protocol = propertyResolver.getProperty(PROP_PROTO);
    Boolean tls = propertyResolver.getProperty(PROP_TLS, Boolean.class, false);
    Boolean auth = propertyResolver.getProperty(PROP_AUTH, Boolean.class, false);

    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    if (host != null && !host.isEmpty()) {
        sender.setHost(host);
    } else {
        log.warn("Warning! Your SMTP server is not configured. We will try to use one on localhost.");
        log.debug("Did you configure your SMTP settings in your application.yml?");
        sender.setHost(DEFAULT_HOST);
    }

    sender.setPort(port);
    sender.setUsername(user);
    sender.setPassword(password);

    Properties sendProperties = new Properties();
    sendProperties.setProperty(PROP_SMTP_AUTH, auth.toString());
    sendProperties.setProperty(PROP_STARTTLS, tls.toString());
    sendProperties.setProperty(PROP_TRANSPORT_PROTO, protocol);
    sender.setJavaMailProperties(sendProperties);
    return sender;
   }
}

MailService.java

package com.myapp.service;

import com.myapp.domain.User;
import org.apache.commons.lang.CharEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.core.env.Environment;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.mail.Message;
import javax.mail.SendFailedException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Locale;

/**
 * Service for sending e-mails.
 * <p/>
 * <p>
 * We use the @Async annotation to send e-mails asynchronously.
 * </p>
 */
@Service
public class MailService {

    private final Logger log = LoggerFactory.getLogger(MailService.class);

    @Inject
    private Environment env;

    @Inject
    private JavaMailSenderImpl javaMailSender;

    @Inject
    private MessageSource messageSource;

    @Inject
    private SpringTemplateEngine templateEngine;

    /**
     * System default email address that sends the e-mails.
     */
    private String from;

    @PostConstruct
    public void init() {
        this.from = env.getProperty("mail.from");
    }

    @Async
    public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
        log.debug("Send e-mail[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
            isMultipart, isHtml, to, subject, content);

        // Prepare message using a Spring helper
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
            message.setTo(to);
            message.setFrom(from);
            message.setSubject(subject);
            message.setText(content, isHtml);
            javaMailSender.send(message.getMimeMessage());
            log.debug("Sent e-mail to User '{}'", to);
        } catch (Exception e) {
            log.warn("E-mail could not be sent to user '{}', exception is: {}", to, e.getMessage());
        }
    }

    @Async
    public void sendPurchaseEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
        log.debug("Send e-mail[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
        isMultipart, isHtml, to, subject, content);

        // Prepare message using a Spring helper
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
            message.setTo(to);
            message.setFrom(from);
            message.setSubject(subject);
            message.setText(content, isHtml);
            javaMailSender.send(message.getMimeMessage());
            log.debug("Sent purchase e-mail to '{}'", to);
        } catch (Exception e) {
            log.warn("E-mail could not be sent to '{}', exception is: {}", to, e.getMessage());
        }
    }

    @Async
    public void sendActivationEmail(User user, String baseUrl) {
        log.debug("Sending activation e-mail to '{}'", user.getEmail());
        Locale locale = Locale.forLanguageTag(user.getLangKey());
        Context context = new Context(locale);
        context.setVariable("user", user);
        context.setVariable("baseUrl", baseUrl);
        String content = templateEngine.process("activationEmail", context);
        String subject = messageSource.getMessage("email.activation.title", null, locale);
        sendEmail(user.getEmail(), subject, content, false, true);
    }

    @Async
    public void sendPurchaseNotificationEmail(String orderId, String email, String baseUrl) {
        log.debug("Sending activation e-mail to '{}'", email);
        Locale locale = Locale.forLanguageTag(Locale.ENGLISH.getLanguage());

        String title = messageSource.getMessage("email.purchase.title", null, locale);

        Context context = new Context(locale);
        context.setVariable("orderId", orderId);
        context.setVariable("baseUrl", baseUrl);
        context.setVariable("subject", title);
        context.setVariable("greeting", messageSource.getMessage("email.purchase.greeting", null, locale));
        context.setVariable("text1", messageSource.getMessage("email.purchase.text1", null, locale));
        context.setVariable("text2", messageSource.getMessage("email.purchase.text2", null, locale));
        context.setVariable("signature", messageSource.getMessage("email.purchase.signature", null, locale));

        String content = templateEngine.process("purchaseEmail", context);
        sendPurchaseEmail(email, title, content, false, true);
    }
}

person Eric Foster    schedule 26.06.2015    source источник
comment
у вас это сработало? Та же проблема   -  person Sami    schedule 05.09.2015
comment
Да, смотрите мое обновление выше. Извините, что не вернулся и не обновил это раньше.   -  person Eric Foster    schedule 07.09.2015
comment
Спасибо! Итак, в чем заключалась последняя ошибка? Я тоже пытаюсь использовать gmail-адрес, но не использую oauth. Я могу подключиться к smtp-серверу, но отправка не работает. Что именно вы изменили, чтобы это заработало?   -  person Sami    schedule 07.09.2015
comment
Да, я никогда не мог на самом деле отследить первопричину. Похоже, это проблема с использованием MimeMessageHelper. Я смог отследить, что на самом деле я не добавлял получателей, когда использовал setTo. Но почему я не могу понять.   -  person Eric Foster    schedule 08.09.2015


Ответы (1)


Еще одно обновление: сегодня я наткнулся на этот пост, в котором я узнал о добавлении одной строки mimeMessage.saveChanges(), которое, по-видимому, решает мою предыдущую проблему. Престижность @dkar за его ответ, который, наконец, решил эту проблему и для меня. Прочитайте его ответ здесь: Исходный ответ

@Async
public void sendEmail(String to, String sendFrom, String subject, String content) {
    log.debug("Send e-mail to '{}' with subject '{}' and content={}",
            to, subject, content);

    // Prepare message using a Spring helper
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    try {
        MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, CharEncoding.UTF_8);
        message.setTo(to);
        message.setFrom(sendFrom);
        message.setSubject(subject);
        message.setText(content, true);
        mimeMessage.saveChanges();
        javaMailSender.send(message.getMimeMessage());
        log.debug("Sent e-mail to User '{}'", to);
    } catch (Exception e) {
        log.warn("E-mail could not be sent to user '{}', exception is: {}", to, e.getMessage());
    }
}
person Eric Foster    schedule 13.09.2015