1. 程式人生 > >【Spring Boot】(31)、使用SpringBoot傳送mail郵件

【Spring Boot】(31)、使用SpringBoot傳送mail郵件

1、前言

傳送郵件應該是網站的必備拓展功能之一,註冊驗證,忘記密碼或者是給使用者傳送營銷資訊。正常我們會用JavaMail相關api來寫傳送郵件的相關程式碼,但現在springboot提供了一套更簡易使用的封裝。

 

2、Mail依賴

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

來看看其依賴樹:

可以看到spring-boot-starter-mail-xxx.jar對Sun公司的郵件api功能進行了相應的封裝。

 

3、Mail自動配置類: MailSenderAutoConfiguration

其實肯定可以猜到Spring Boot對Mail功能已經配置了相關的基本配置資訊,它是Spring Boot官方提供,其類為MailSenderAutoConfiguration

//MailSenderAutoConfiguration
@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import(JndiSessionConfiguration.class)
public class MailSenderAutoConfiguration {

    private final MailProperties properties;

	private final Session session;

	public MailSenderAutoConfiguration(MailProperties properties,
			ObjectProvider<Session> session) {
		this.properties = properties;
		this.session = session.getIfAvailable();
	}

	@Bean
	public JavaMailSenderImpl mailSender() {
		JavaMailSenderImpl sender = new JavaMailSenderImpl();
		if (this.session != null) {
			sender.setSession(this.session);
		}
		else {
			applyProperties(sender);
		}
		return sender;
	}
    
    //other code...
}

首先,它會通過注入Mail的屬性配置類MailProperties

@ConfigurationProperties(prefix = "spring.mail")
public class MailProperties {

	private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

	/**
	 * SMTP server host.
	 */
	private String host;

	/**
	 * SMTP server port.
	 */
	private Integer port;

	/**
	 * Login user of the SMTP server.
	 */
	private String username;

	/**
	 * Login password of the SMTP server.
	 */
	private String password;

	/**
	 * Protocol used by the SMTP server.
	 */
	private String protocol = "smtp";

	/**
	 * Default MimeMessage encoding.
	 */
	private Charset defaultEncoding = DEFAULT_CHARSET;

	/**
	 * Additional JavaMail session properties.
	 */
	private Map<String, String> properties = new HashMap<String, String>();

	/**
	 * Session JNDI name. When set, takes precedence to others mail settings.
	 */
	private String jndiName;

	/**
	 * Test that the mail server is available on startup.
	 */
	private boolean testConnection;
    
    //other code...
    
}

MailSenderAutoConfiguration自動配置類中,建立了一個Bean,其類為JavaMailSenderImpl,它是Spring專門用來發送Mail郵件的服務類,SpringBoot也使用它來發送郵件。它是JavaMailSender介面的實現類,通過它的send()方法來發送不同型別的郵件,主要分為兩類,一類是簡單的文字郵件,不帶任何html格式,不帶附件,不帶圖片等簡單郵件,還有一類則是帶有html格式文字或者連結,有附件或者圖片的複雜郵件。

 

4、傳送郵件

通用配置application.properties:

# 設定郵箱主機
spring.mail.host=smtp.qq.com

# 設定使用者名稱
[email protected]

# 設定密碼,該處的密碼是QQ郵箱開啟SMTP的授權碼而非QQ密碼
spring.mail.password=pwvtabrwxogxidac

# 設定是否需要認證,如果為true,那麼使用者名稱和密碼就必須的,
# 如果設定false,可以不設定使用者名稱和密碼,當然也得看你的對接的平臺是否支援無密碼進行訪問的。
spring.mail.properties.mail.smtp.auth=true

# STARTTLS[1]  是對純文字通訊協議的擴充套件。它提供一種方式將純文字連線升級為加密連線(TLS或SSL),而不是另外使用一個埠作加密通訊。
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

mail.from=${spring.mail.username}
[email protected]

由於使用QQ郵箱的使用者佔多數,所以這裡選擇QQ郵箱作為測試。還有注意的是spring.mail.password這個值不是QQ郵箱的密碼,而是QQ郵箱給第三方客戶端郵箱生成的授權碼。具體要登入QQ郵箱,點選設定,找到SMTP服務:

預設SMTP服務是關閉的,即預設狀態為關閉狀態,如果是第一次操作,點選開啟後,會通過驗證會獲取到授權碼;而我之前已經開啟過SMTP服務,所以直接點選生成授權碼後通過驗證獲取到授權碼。

 

自定義的MailProperties配置類,用於解析mail開頭的配置屬性:

@Component
@ConfigurationProperties(prefix = "mail")
public class MailProperties {

    private String from;

    private String to;

   //getter and setter...
}

 

4.1、測試傳送簡單文字郵件

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class SimpleMailTest {

	@Autowired
	private MailService mailService;

	@Test
	public void sendMail(){

		mailService.sendSimpleMail("測試Springboot傳送郵件", "傳送郵件...");
	}
}

sendSimpleMail()

@Override
public void sendSimpleMail(String subject, String text) {
    SimpleMailMessage mailMessage = new SimpleMailMessage();
    mailMessage.setFrom(mailProperties.getFrom());
    mailMessage.setTo(mailProperties.getTo());

    mailMessage.setSubject(subject);
    mailMessage.setText(text);

    javaMailSender.send(mailMessage);
}

觀察結果:

4.2、測試傳送帶有連結和附件的複雜郵件

事先準備一個檔案file.txt,放在resources/public/目錄下。

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MimeMailTest {

	@Autowired
	private MailService mailService;

	@Test
	public void testMail() throws MessagingException {

		Map<String, String> attachmentMap = new HashMap<>();
		attachmentMap.put("附件", "file.txt的絕對路徑");

		mailService.sendHtmlMail("測試Springboot傳送帶附件的郵件", "歡迎進入<a href=\"http://www.baidu.com\">百度首頁</a>", attachmentMap);

	}
}

sendHtmlMail():

@Override
public void sendHtmlMail(String subject, String text, Map<String, String> attachmentMap) throws MessagingException {
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();

    //是否傳送的郵件是富文字(附件,圖片,html等)
    MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);

    messageHelper.setFrom(mailProperties.getFrom());
    messageHelper.setTo(mailProperties.getTo());

    messageHelper.setSubject(subject);
    messageHelper.setText(text, true);//重點,預設為false,顯示原始html程式碼,無效果

    if(attachmentMap != null){
        attachmentMap.entrySet().stream().forEach(entrySet -> {
            try {
                File file = new File(entrySet.getValue());
                if(file.exists()){
                    messageHelper.addAttachment(entrySet.getKey(), new FileSystemResource(file));
                }
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        });
    }

    javaMailSender.send(mimeMessage);
}

觀察結果:

4.3、測試傳送模版郵件

這裡使用Freemarker作為模版引擎。

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

事先準備一個模版檔案mail.ftl

<html>
<body>
	<h3>你好, <span style="color: red;">${username}</span>, 這是一封模板郵件!</h3>
</body>
</html>

模版測試類:

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MailTemplateTest {

	@Autowired
	private MailService mailService;

	@Test
	public void testFreemarkerMail() throws MessagingException, IOException, TemplateException {

		Map<String, Object> params = new HashMap<>();
		params.put("username", "Cay");

		mailService.sendTemplateMail("測試Springboot傳送模版郵件", params);

	}
}

sendTemplateMail():

@Override
public void sendTemplateMail(String subject, Map<String, Object> params) throws MessagingException, IOException, TemplateException {
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();

    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);

    helper.setFrom(mailProperties.getFrom());
    helper.setTo(mailProperties.getTo());

    Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
    configuration.setClassForTemplateLoading(this.getClass(), "/templates");

    String html = FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate("mail.ftl"), params);

    helper.setSubject(subject);
    helper.setText(html, true);//重點,預設為false,顯示原始html程式碼,無效果

    javaMailSender.send(mimeMessage);
}

觀察結果:

====================打個廣告,歡迎關注====================

QQ:

412425870

微信公眾號:Cay課堂

csdn部落格:

http://blog.csdn.net/caychen

碼雲:

https://gitee.com/caychen/

github:

https://github.com/caychen

點選群號或者掃描二維碼即可加入QQ群:

328243383(1群)

 

點選群號或者掃描二維碼即可加入QQ群:
180479701(2群)