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

1、前言

發(fā)送郵件應(yīng)該是網(wǎng)站的必備拓展功能之一笛匙,注冊(cè)驗(yàn)證侨把,忘記密碼或者是給用戶發(fā)送營(yíng)銷信息。正常我們會(huì)用JavaMail相關(guān)api來寫發(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>

來看看其依賴樹:

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專門用來發(fā)送Mail郵件的服務(wù)類,SpringBoot也使用它來發(fā)送郵件说榆。它是JavaMailSender接口的實(shí)現(xiàn)類虚吟,通過它的send()方法來發(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)是否支持無密碼進(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\">百度首頁</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代碼鬓催,無效果

    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代碼课舍,無效果

    javaMailSender.send(mimeMessage);
}

觀察結(jié)果:


發(fā)送模版郵件效果圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末塌西,一起剝皮案震驚了整個(gè)濱河市他挎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捡需,老刑警劉巖办桨,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異站辉,居然都是意外死亡呢撞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門饰剥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來殊霞,“玉大人,你說我怎么就攤上這事捐川∨Ь椋” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵古沥,是天一觀的道長(zhǎng)瘸右。 經(jīng)常有香客問我,道長(zhǎng)岩齿,這世上最難降的妖魔是什么太颤? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮盹沈,結(jié)果婚禮上龄章,老公的妹妹穿的比我還像新娘。我一直安慰自己乞封,他們只是感情好做裙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肃晚,像睡著了一般锚贱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上关串,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天拧廊,我揣著相機(jī)與錄音,去河邊找鬼晋修。 笑死吧碾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的墓卦。 我是一名探鬼主播倦春,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了睁本?” 一聲冷哼從身側(cè)響起山叮,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎添履,沒想到半個(gè)月后屁倔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡暮胧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年锐借,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片往衷。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钞翔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出席舍,到底是詐尸還是另有隱情布轿,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布来颤,位于F島的核電站汰扭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏福铅。R本人自食惡果不足惜萝毛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滑黔。 院中可真熱鬧笆包,春花似錦、人聲如沸略荡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汛兜。三九已至巴粪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間序无,已是汗流浹背验毡。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工衡创, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帝嗡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓璃氢,卻偏偏與公主長(zhǎng)得像哟玷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

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