十三、使用SpringBoot發(fā)送mail郵件

1、前言

發(fā)送郵件應(yīng)該是網(wǎng)站的必備拓展功能之一,注冊(cè)驗(yàn)證,忘記密碼或者是給用戶發(fā)送營(yíng)銷信息。正常我們會(huì)用JavaMail相關(guān)api來(lái)寫發(fā)送郵件的相關(guān)代碼,但現(xiàn)在springboot提供了一套更簡(jiǎn)易使用的封裝。

2、Mail依賴

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

來(lái)看看其依賴樹:

spring-boot-starter-mail依賴樹.png

可以看到spring-boot-starter-mail-xxx.jar對(duì)Sun公司的郵件api功能進(jìn)行了相應(yīng)的封裝。

3、Mail自動(dòng)配置類: MailSenderAutoConfiguration

其實(shí)肯定可以猜到Spring Boot對(duì)Mail功能已經(jīng)配置了相關(guān)的基本配置信息,它是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...
}

首先,它會(huì)通過注入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自動(dòng)配置類中,創(chuàng)建了一個(gè)Bean,其類為JavaMailSenderImpl,它是Spring專門用來(lái)發(fā)送Mail郵件的服務(wù)類,SpringBoot也使用它來(lái)發(fā)送郵件。它是JavaMailSender接口的實(shí)現(xiàn)類,通過它的send()方法來(lái)發(fā)送不同類型的郵件,主要分為兩類,一類是簡(jiǎn)單的文本郵件,不帶任何html格式,不帶附件,不帶圖片等簡(jiǎn)單郵件,還有一類則是帶有html格式文本或者鏈接,有附件或者圖片的復(fù)雜郵件。

4、發(fā)送郵件

通用配置application.properties:

# 設(shè)置郵箱主機(jī)
spring.mail.host=smtp.qq.com

# 設(shè)置用戶名
spring.mail.username=xxxxxx@qq.com

# 設(shè)置密碼,該處的密碼是QQ郵箱開啟SMTP的授權(quán)碼而非QQ密碼
spring.mail.password=pwvtabrwxogxidac

# 設(shè)置是否需要認(rèn)證,如果為true,那么用戶名和密碼就必須的,
# 如果設(shè)置false,可以不設(shè)置用戶名和密碼,當(dāng)然也得看你的對(duì)接的平臺(tái)是否支持無(wú)密碼進(jìn)行訪問的。
spring.mail.properties.mail.smtp.auth=true

# STARTTLS[1]  是對(duì)純文本通信協(xié)議的擴(kuò)展。它提供一種方式將純文本連接升級(jí)為加密連接(TLS或SSL),而不是另外使用一個(gè)端口作加密通信。
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

mail.from=${spring.mail.username}
mail.to=yyyyyy@qq.com

由于使用QQ郵箱的用戶占多數(shù),所以這里選擇QQ郵箱作為測(cè)試。還有注意的是spring.mail.password這個(gè)值不是QQ郵箱的密碼,而是QQ郵箱給第三方客戶端郵箱生成的授權(quán)碼。具體要登錄QQ郵箱,點(diǎn)擊設(shè)置,找到SMTP服務(wù):

獲取SMTP服務(wù)授權(quán)碼.png

默認(rèn)SMTP服務(wù)是關(guān)閉的,即默認(rèn)狀態(tài)為關(guān)閉狀態(tài),如果是第一次操作,點(diǎn)擊開啟后,會(huì)通過驗(yàn)證會(huì)獲取到授權(quán)碼;而我之前已經(jīng)開啟過SMTP服務(wù),所以直接點(diǎn)擊生成授權(quán)碼后通過驗(yàn)證獲取到授權(quán)碼。

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

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

    private String from;

    private String to;

   //getter and setter...
}

4.1、測(cè)試發(fā)送簡(jiǎn)單文本郵件

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

    @Autowired
    private MailService mailService;

    @Test
    public void sendMail(){

        mailService.sendSimpleMail("測(cè)試Springboot發(fā)送郵件", "發(fā)送郵件...");
    }
}

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);
}

觀察結(jié)果:

簡(jiǎn)單文本郵件效果圖.png

4.2、測(cè)試發(fā)送帶有鏈接和附件的復(fù)雜郵件

事先準(zhǔn)備一個(gè)文件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的絕對(duì)路徑");

        mailService.sendHtmlMail("測(cè)試Springboot發(fā)送帶附件的郵件", "歡迎進(jìn)入<a href=\"http://www.baidu.com\">百度首頁(yè)</a>", attachmentMap);

    }
}

sendHtmlMail():

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

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

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

    messageHelper.setSubject(subject);
    messageHelper.setText(text, true);//重點(diǎn),默認(rèn)為false,顯示原始html代碼,無(wú)效果

    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);
}

觀察結(jié)果:

復(fù)雜郵件效果圖.png

4.3、測(cè)試發(fā)送模版郵件

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

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

事先準(zhǔn)備一個(gè)模版文件mail.ftl

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

模版測(cè)試類:

@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("測(cè)試Springboot發(fā)送模版郵件", 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);//重點(diǎn),默認(rèn)為false,顯示原始html代碼,無(wú)效果

    javaMailSender.send(mimeMessage);
}

觀察結(jié)果:


發(fā)送模版郵件效果圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 目錄 電子郵件與Java發(fā)送郵件的歷史 電子郵件原理電子郵件服務(wù)器電子郵箱郵件客戶端郵件傳輸協(xié)議郵件格式電子郵件發(fā)...
    西召閱讀 1,216評(píng)論 0 2
  • 從古代的八百里加急,到現(xiàn)在的電子郵件,郵件的發(fā)展見證了上下五千年的發(fā)展史,這些當(dāng)然是廢話,只是要說(shuō)說(shuō)郵件的重要性。...
    大牧莫邪閱讀 1,654評(píng)論 0 13
  • 燈光滅宵早,月色破窗深。 獨(dú)坐人還醉,相望心共吟。 憑誰(shuí)思往事,借此慰幽襟。 雖在暮春里,夏來(lái)仍可尋。
    雪窗_武立之閱讀 267評(píng)論 0 1
  • 一如圍城深似海 能否開小差? 圍城是場(chǎng)馬拉松 理解尊重是助跑劑 楊瀾說(shuō),在婚姻里不僅有愛,應(yīng)該有肝膽相照的義氣,不...
    踐行途中閱讀 709評(píng)論 0 0
  • 因?yàn)榻裉煸缟习职种蛋啵坏搅c(diǎn)已經(jīng)離開家,所以沒有看到姐姐和妹妹,也沒有看到媽媽,早上起來(lái)就走了,對(duì)三位女生還是挺...
    雷登張閱讀 168評(píng)論 0 0

友情鏈接更多精彩內(nèi)容