web-dev-qa-db-ja.com

Javaアノテーションを使用してSpringでメールを送信する

純粋な注釈ベースのアプローチ(Javaによる)を使用してSpring 4(およびSpring Boot)でメールを送信するにはどうすればよいですか?構成ルール)?

17
vdenotaris

電子メールサービスを構成するための簡単なソリューション(認証なしでSMTPサーバーを使用する場合)は、

@Configuration 
public class MailConfig {

    @Value("${email.Host}")
    private String Host;

    @Value("${email.port}")
    private Integer port;

    @Bean
    public JavaMailSender javaMailService() {
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();

        javaMailSender.setHost(Host);
        javaMailSender.setPort(port);

        javaMailSender.setJavaMailProperties(getMailProperties());

        return javaMailSender;
    }

    private Properties getMailProperties() {
        Properties properties = new Properties();
        properties.setProperty("mail.transport.protocol", "smtp");
        properties.setProperty("mail.smtp.auth", "false");
        properties.setProperty("mail.smtp.starttls.enable", "false");
        properties.setProperty("mail.debug", "false");
        return properties;
    }
}

Springはプロパティを解決できる必要がありますemail.Hostおよびemail.port通常の方法で(Spring Bootの場合、最も簡単なのはapplication.propertiesに入れることです)

JavaMailSenderのサービスを必要とするクラスでは、通常の方法(@Autowired private JavaMailSender javaMailSender


[〜#〜] update [〜#〜]

バージョン1.2.0.RC1以降、Spring BootはJavaMailSenderを自動設定できることに注意してください。 this ドキュメントの一部をご覧ください。ドキュメントからわかるように、起動して実行するための設定はほとんど必要ありません!

33
geoand

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

application.properties

spring.mail.Host=...
spring.mail.port=...

Foo.Java

@Component
public class Foo {

    @Autowired
    private JavaMailSender mailSender;

    public void send() {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("[email protected]");
        message.setTo("[email protected]");
        message.setSubject("hello");
        mailSender.send(message);
    }
}

個人的には、ローカルホストMTAを実行し、それを使用して実際のMTA(Gmail、SES、または独自のMTA)に中継することをお勧めします。これにより、「無料の」非同期キューが提供され、構成が一元化されます。 OpenSMTPが好きです。

10
Neil McGuigan

Spring-Bootでは、smtp.office365.comメールサーバーに1つの調整が必要であり、これはこの会社が使用しているものであり、些細なことでした。

この調整を行う前に、Office365 SMTPサーバーに対する認証が失敗し続け、次の行に沿ってエラーが発生しました。

org.springframework.mail.MailSendException: Failed messages: com.Sun.mail.smtp.SMTPSendFailedException: 530 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.Java:474)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.Java:307)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.Java:296)

これは、SpringのMailPropertiesクラスによって正しく選択されるユーザー名とパスワードを設定していた場合でも同じでした。

Office365ではTLS認証を有効にする必要があり、Springの現在のJavaMail実装には、プロパティでそれを行う簡単な方法がありません。解決策は、独自のjavax.mail.Sessionインスタンスを作成し、Springに登録することです。

全体像が続きます。

Pom.xmlファイルで、次を追加します。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
        <version>${spring-boot.version}</version>
    </dependency>

Spring-boot.versionが他の場所(この場合は親pom)で定義されており、この場合の値は1.3.1.RELEASEです

メインアプリケーションでそれらを項目化する場合は、パッケージおよび/または自動構成クラスを含めるようにしてください-デフォルトの@SpringBootApplicationを使用する場合、これは必要ありませんが、私の場合は@ImportアノテーションにMailSenderAutoConfiguration.classを追加しましたクラスのリスト。

簡単なEmailSenderクラスを作成しました。

@SuppressWarnings("SpringJavaAutowiringInspection")
@Slf4j
@Service
@ConditionalOnClass(JavaMailSender.class)
public class EmailSender {

    @Autowired
    private EventBus mmEventBus;

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private MessageConfig messageConfig;

    @Subscribe
    public void sendEmail(EmailMessageEvent eme) {
        log.info("{}", eme);

        SimpleMailMessage msg = new SimpleMailMessage(messageConfig.getMessageTemplate());
        msg.setSubject(eme.getSubject());
        msg.setText(eme.getMessage());

        try {
            mailSender.send(msg);
        } catch (MailException ex) {
            log.error("Error sending mail message: " + eme.toString(), ex);
        }
    }

    @PostConstruct
    public void start() throws MessagingException {
        mmEventBus.register(this);
    }

}

@ Slf4jはロンボクアノテーションで、@ SubscribeはGuavaのEventBus用です。これは、このアプリがEmailSenderに送信するメッセージがあることを知らせる方法です。このアプリの目的には十分な、件名とメッセージテキストを含む簡単なEmailMessageEvent POJOを使用します。

MessageConfigクラスは、アプリケーションの残りの構成とともにメッセージのデフォルトを簡単に設定できるようにします。また、Office365 SMTPサーバーでこのjavax.mail.Sessionを機能させるために必要な特別なソースが1つあります。 Spring Beanとして登録されたインスタンス:

@Data
@Component
@ConfigurationProperties(prefix = "spring.message", ignoreUnknownFields = false)
@Slf4j
public class MessageConfig {

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    private MailProperties mailProperties;

    private String from;
    private String subject;
    private String[] recipients;

    private SimpleMailMessage messageTemplate;

    public void setRecipients(String... r) {
        this.recipients = r;
    }

    @PostConstruct
    public void createTemplate() {
        messageTemplate = new SimpleMailMessage();
        messageTemplate.setFrom(from);
        messageTemplate.setSubject(subject);
        messageTemplate.setTo(recipients);

        log.debug("Email Message Template defaults: {}", messageTemplate);
    }

    @Bean
    public SimpleMailMessage getMessageTemplate() {
        return messageTemplate;
    }

    @Bean
    public Session getSession() {
        log.debug("Creating javax.mail.Session with TLS enabled.");
        // We could be more flexible and have auth based on whether there's a username and starttls based on a property.
        Properties p = new Properties();
        p.setProperty("mail.smtp.auth", "true");
        p.setProperty("mail.smtp.starttls.enable", "true");
        p.setProperty("mail.smtp.Host", mailProperties.getHost());
        p.setProperty("mail.smtp.port", mailProperties.getPort().toString());
        return Session.getDefaultInstance(p, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(mailProperties.getUsername(), mailProperties.getPassword());
            }
        });
    }

}

@Dataは再びLombokアノテーションです-ミューテーターおよびアクセサーメソッド、toString()、equals()およびhashCode()などを自動的に追加します。

SpringのJavaMailSender(JavaMailSenderImpl)の制限は、そのSessionを直接構成できないことです。特に、プロパティを介してTLS認証を有効にする方法はありません。ただし、コンテキストにjavax.mail.Session Beanが登録されている場合、それはMailSenderAutoConfigurationに注入(条件付きで自動接続)され、JavaMailSenderImplインスタンスの構築に使用されます。

そのため、getSession()メソッドを介してそのようなBeanを登録します。適切な測定のために、ここで構築するセッションをJVMのデフォルトのものにします。その動作を望まない場合はgetInstance()を呼び出すように変更します。

このSession @Beanを追加すると、すべてが機能しました。

7
sofend

Spring Boot 1.2以降を使用すると、JavaMailSenderを自動構成できます。 このビデオ Spring Boot 1.2以降を使用してメールを送信する方法を正確に説明しています。 Spring Lemon のソースコードを参照して、詳細を確認してください。

2
Sanjay

Geoandの答えに加えて、メールプロパティをハードコーディングしたり、XMLを記述したくない場合は、リソースのファイル(たとえば、mail.properties)にプロパティを追加し、この種類のコードをMailConfigクラス:

@Resource(name = "mailProperties")
private Properties mailProperties;

@Bean(name = "mailProperties")
public PropertiesFactoryBean mapper() {
    PropertiesFactoryBean bean = new PropertiesFactoryBean();
    bean.setLocation(new ClassPathResource("mail.properties"));
    return bean;
}

使用できるプロパティの範囲はすべてこれらのページで定義されています

https://javamail.Java.net/nonav/docs/api/

https://javamail.Java.net/nonav/docs/api/com/Sun/mail/smtp/package-summary.html

ただし、プロパティで設定されたものを直接使用しないため、JavaMailSenderImplのメソッドからホスト、ポート、ユーザー名、およびパスワードを設定する必要があります。

1
Geoffrey