[英]How to configure spring to send SMTP emails through Annotations without using XML?
[英]Send emails with Spring by using Java annotations
如何使用基於純注釋的方法(根據Java配置規則)發送Spring 4 (和Spring Boot )的電子郵件?
一個簡單的解決方案(您將使用沒有身份驗證的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
。 查看本文檔的這一部分。 從文檔中可以看出,啟動和運行幾乎不需要任何配置!
在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("foo@example.com");
message.setTo("bar@example.com");
message.setSubject("hello");
mailSender.send(message);
}
}
就個人而言,我建議運行localhost MTA,並使用它轉發到您真正的MTA(如Gmail或SES,或您自己的)。 這為您提供了“免費”異步隊列,並集中配置。 我喜歡OpenSMTP。
使用Spring-Boot,它幾乎是微不足道的,smtp.office365.com郵件服務器需要進行一次調整 - 這是該公司正在使用的。
在進行此調整之前,對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,則不需要,但在我的情況下,我將MailSenderAutoConfiguration.class添加到@Import注釋中課程列表。
我創建了一個簡單的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是一個lombok注釋,而@Subscribe是用於Guava的EventBus,這個應用程序讓EmailSender知道有一條消息要發送。 我使用了一個簡單的EmailMessageEvent POJO,它有一個主題和消息文本 - 足以滿足這個應用程序的需要。
MessageConfig類只是簡單地設置消息默認值以及應用程序配置的其余部分,並且它具有使用Office365 SMTP服務器,自定義javax.mail.Session所需的一個特殊功能。實例注冊為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注釋 - 自動添加mutator和accessor方法,toString(),equals()和hashCode()等。
Spring的JavaMailSender(JavaMailSenderImpl)的限制是它的Session不能直接配置,特別是沒有辦法通過屬性啟用TLS身份驗證。 但是,如果在上下文中注冊了javax.mail.Session Bean,則會將其注入(有條件地自動裝入)到MailSenderAutoConfiguration中,然后用於構造JavaMailSenderImpl實例。
所以我們通過getSession()方法注冊這樣一個Bean。 為了更好地衡量,我們將我們在此構造的Session作為JVM的默認值 - 如果您不想要這種行為,請將其更改為調用getInstance()。
添加此Session @Bean后一切正常。
使用Spring Boot 1.2,可以為您自動配置JavaMailSender。 我已經有了這個視頻,解釋了如何使用Spring Boot 1.2向前發送郵件。 Spring Lemon的源代碼可以參考具體細節。
除了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的方法中設置主機,端口,用戶名和密碼,因為它不會直接使用屬性中設置的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.