結合Spring發送郵件的四種正確姿式,你知道幾種?

一 前言

測試所使用的環境

測試使用的環境是企業主流的SSM 框架即 SpringMVC+Spring+Mybatis。爲了節省時間,我直接使用的是我上次的「SSM項目中整合Echarts開發」該項目已經搭建完成的SSM環境。html

標題說的四種姿式指的是哪四種姿式?

  1. 發送text格式的郵件
  2. 發送HTML格式的郵件
  3. 基於FreeMarker模板引擎發送郵件
  4. 基於Velocity模板引擎發送郵件

如何獲取以及運行個人Demo

Github地址:https://github.com/Snailclimb/J2ee-Advancedjava

你能夠選擇直接下載或者直接在DOS窗口運行:git clone https://github.com/Snailclimb/J2ee-Advanced.git命令,這樣項目就被拷貝到你的電腦了。
git

而後選擇導入Maven項目便可(不懂Maven的能夠自行百度學習).github

二 準備工做

既然要發送郵件,那麼你首先要提供一個能在第三方軟件上發送郵件功能的帳號。在這裏,我選擇的網易郵箱帳號。面試

我拿網易郵箱帳號舉例子,那麼咱們如何才能讓你的郵箱帳號能夠利用第三方發送郵件(這裏的第三方就是咱們即將編寫的程序)。spring

你們應該清楚:客戶端和後臺交互數據的時候用到了Http協議,那麼相應的,郵箱傳輸也有本身的一套協議,如SMTP,POP3,IMAP。apache

開啓POP3/SMTP/IMAP服務

因此,咱們第一步首先要去開啓這些服務,以下圖所示:後端

開啓服務

若是你未開啓該服務的話,運行程序會報以下錯誤(配置文件中配置的密碼是你的受權碼而不是你登陸郵箱的密碼,受權碼是你第三方登陸的憑證):服務器

HTTP Status 500 - Request processing failed; nested exception is org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: 550 User has no permission

JavaMail介紹

咱們須要用到的發郵件的核心jar包,因此這裏好好介紹一下。微信

JavaMail是由Sun定義的一套收發電子郵件的API,不一樣的廠商能夠提供本身的實現類。但它並無包含在JDK中,而是做爲JavaEE的一部分。廠商所提供的JavaMail服務程序能夠有選擇地實現某些郵件協議,常見的郵件協議包括:

  • SMTP:簡單郵件傳輸協議,用於發送電子郵件的傳輸協議;
  • POP3:用於接收電子郵件的標準協議;
  • IMAP:互聯網消息協議,是POP3的替代協議。

這三種協議都有對應SSL加密傳輸的協議,分別是SMTPS,POP3S和IMAPS。

咱們若是要使用JavaMail的話,須要本身引用相應的jar包,以下圖所示:

<dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>

相關配置文件

下圖是除了pom.xml以外用到的其餘全部配置文件
配置文件

pom.xml

須要用到的jar包。

<!--spring支持-->
        <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context-support</artifactId>
              <version>5.0.0.RELEASE</version>
        </dependency>
        <!-- 發送郵件 -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <!-- Freemarker -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
        <!-- velocity模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-tools</artifactId>
            <version>2.0</version>
        </dependency>

mail.properties

#服務器主機名
mail.smtp.host=smtp.163.com
#你的郵箱地址
mail.smtp.username=koushuangbwcx@163.com
#你的受權碼
mail.smtp.password=cSdN153963000
#編碼格式
mail.smtp.defaultEncoding=utf-8
#是否進行用戶名密碼校驗
mail.smtp.auth=true
#設置超時時間
mail.smtp.timeout=20000

若是你的受權碼填寫錯誤的話,會報以下錯誤:

TTP Status 500 - Request processing failed; nested exception is org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: 535 Error: authentication failed

velocity.properties

input.encoding=UTF-8  
output.encoding=UTF-8  
contentType=ext/html;charset=UTF-8
directive.foreach.counter.name=loopCounter  
directive.foreach.counter.initial.value=0

applicationContext-email.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/aop    
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

    <!--郵件配置 -->
    <context:property-placeholder location="classpath:mail.properties"
        ignore-unresolvable="true" />

    <!--配置郵件接口 -->
    <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="${mail.smtp.host}" />
        <property name="username" value="${mail.smtp.username}" />
        <property name="password" value="${mail.smtp.password}" />
        <property name="defaultEncoding" value="${mail.smtp.defaultEncoding}" />
        <property name="javaMailProperties">
            <props>
                <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
                <prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop>
            </props>
        </property>
    </bean>
    <!-- freemarker -->
    <bean id="configuration"
        class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
        <property name="templateLoaderPath" value="/WEB-INF/freemarker/" />
        <!-- 設置FreeMarker環境變量 -->
        <property name="freemarkerSettings">
            <props>
                <prop key="default_encoding">UTF-8</prop>
            </props>
        </property>
    </bean>


    <!-- velocity -->
    <bean id="velocityEngine"
        class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
        <property name="resourceLoaderPath" value="/WEB-INF/velocity/" /><!-- 
            模板存放的路徑 -->
        <property name="configLocation" value="classpath:velocity.properties" /><!-- 
            Velocity的配置文件 -->
    </bean>

</beans>

三 開始編寫工具類

我這裏說是工具類,其實只是我本身作了簡單的封裝,實際項目使用的話,可能會須要根據須要簡單修改一下。

全部用到的類以下圖所示:
全部用到的類

發送Text或者HTML格式的郵件的方法

/**
     * 
     * Text或者HTML格式郵件的方法
     * 
     * @param text
     *            要發送的內容
     * @param subject
     *            郵件的主題也就是郵件的標題
     * @param location
     *            文件的地址
     * @param emailAdress
     *            目的地
     * @param javaMailSender
     *            發送郵件的核心類(在xml文件中已經配置好了)
     * @param type
     *            若是爲true則表明發送HTML格式的文本
     * @return
     * @throws TemplateException
     */
    public String sendMail(String text, String subject, String location, String emailAdress,
            JavaMailSender javaMailSender, Boolean type) {
        MimeMessage mMessage = javaMailSender.createMimeMessage();// 建立郵件對象
        MimeMessageHelper mMessageHelper;
        Properties prop = new Properties();
        try {
            // 從配置文件中拿到發件人郵箱地址
            prop.load(this.getClass().getResourceAsStream("/mail.properties"));
            String from = prop.get("mail.smtp.username") + "";
            mMessageHelper = new MimeMessageHelper(mMessage, true, "UTF-8");
            // 發件人郵箱
            mMessageHelper.setFrom(from);
            // 收件人郵箱
            mMessageHelper.setTo(emailAdress);
            // 郵件的主題也就是郵件的標題
            mMessageHelper.setSubject(subject);
            // 郵件的文本內容,true表示文本以html格式打開
            if (type) {
                mMessageHelper.setText(text, true);
            } else {
                mMessageHelper.setText(text, false);
            }

            // 經過文件路徑獲取文件名字
            String filename = StringUtils.getFileName(location);
            // 定義要發送的資源位置
            File file = new File(location);
            FileSystemResource resource = new FileSystemResource(file);
            FileSystemResource resource2 = new FileSystemResource("D:/email.txt");
            mMessageHelper.addAttachment(filename, resource);// 在郵件中添加一個附件
            mMessageHelper.addAttachment("JavaApiRename.txt", resource2);//
            // 在郵件中添加一個附件
            javaMailSender.send(mMessage);// 發送郵件
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "發送成功";
    }

我在sendMail()方法中添加了一個boolean類型的變量type做爲標誌,若是爲ture就表示發送html格式的郵件不然直接發送text格式的郵件。實現起來很簡單,咱們經過下面的判斷語句就能夠實現了

if (type) {
                //表示文本以html格式打開
                mMessageHelper.setText(text, true);
            } else {
                mMessageHelper.setText(text, false);
            }

效果:

基於FreeMarker模板引擎發送郵件

下圖是咱們用到的FreeMarker模板文件以及Velocity模板文件的位置。

/**
     * FreeMarker模板格式的郵件的方法
     * 
     * @param subject
     *            郵件的主題也就是郵件的標題
     * @param location
     *            文件的地址
     * @param emailAdress
     *            目的地
     * @param javaMailSender
     *            發送郵件的核心類(在xml文件中已經配置好了)
     * @param freeMarkerConfiguration
     *            freemarker配置管理類
     * @return
     * @throws TemplateException
     */
    public String sendMailFreeMarker(String subject, String location, String emailAdress, JavaMailSender javaMailSender,
            Configuration freeMarkerConfiguration) {
        MimeMessage mMessage = javaMailSender.createMimeMessage();// 建立郵件對象
        MimeMessageHelper mMessageHelper;
        Properties prop = new Properties();
        try {
            // 從配置文件中拿到發件人郵箱地址
            prop.load(this.getClass().getResourceAsStream("/mail.properties"));
            String from = prop.get("mail.smtp.username") + "";
            mMessageHelper = new MimeMessageHelper(mMessage, true);
            // 發件人郵箱
            mMessageHelper.setFrom(from);
            // 收件人郵箱
            mMessageHelper.setTo(emailAdress);
            // 郵件的主題也就是郵件的標題
            mMessageHelper.setSubject(subject);
            // 解析模板文件
            mMessageHelper.setText(getText(freeMarkerConfiguration), true);
            // 經過文件路徑獲取文件名字
            String filename = StringUtils.getFileName(location);
            // 定義要發送的資源位置
            File file = new File(location);
            FileSystemResource resource = new FileSystemResource(file);
            mMessageHelper.addAttachment(filename, resource);// 在郵件中添加一個附件
            javaMailSender.send(mMessage);// 發送郵件
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "發送成功";
    }
    
      /**
     * 讀取freemarker模板的方法
     */
    private String getText(Configuration freeMarkerConfiguration) {
        String txt = "";
        try {
            Template template = freeMarkerConfiguration.getTemplate("email.ftl");
            // 經過map傳遞動態數據
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("user", "Snailclimb");
            // 解析模板文件
            txt = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            System.out.println("getText()->>>>>>>>>");// 輸出的是HTML格式的文檔
            System.out.println(txt);
        } catch (IOException e) {
            // TODO 異常執行塊!
            e.printStackTrace();
        } catch (TemplateException e) {
            // TODO 異常執行塊!
            e.printStackTrace();
        }

        return txt;
    }

咱們經過getText(Configuration freeMarkerConfiguration)方法讀取freemarker模板,返回的格式以下圖所示:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>測試</title>
</head>

<body>
<h1>你好Snailclimb</h1>
</body>
</html>

其實就是HTML,而後咱們就能夠像前面發送HTML格式郵件的方式發送這端消息了。

email.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>測試</title>
</head>

<body>
<h1>你好${user}</h1>
</body>
</html>

效果:

不知道爲啥,騰訊每次把我使用模板引擎發的郵件直接放到垃圾箱。你們若是遇到接收不到郵件,可是又沒報錯的狀況,能夠看看是否是到了本身郵箱的垃圾箱。

基於Velocity模板引擎發送郵件

/**
     * 
     * @param subject
     *            郵件主題
     * @param location
     *            收件人地址
     * @param emailAdress
     *            目的地
     * @param javaMailSender
     *            發送郵件的核心類(在xml文件中已經配置好了)
     * @param velocityEngine
     *            Velocity模板引擎
     * @return
     */
    public String sendMailVelocity(String subject, String location, String emailAdress, JavaMailSender javaMailSender,
            VelocityEngine velocityEngine) {
        MimeMessage mMessage = javaMailSender.createMimeMessage();// 建立郵件對象
        MimeMessageHelper mMessageHelper;
        Properties prop = new Properties();
        try {
            // 從配置文件中拿到發件人郵箱地址
            prop.load(this.getClass().getResourceAsStream("/mail.properties"));
            System.out.println(this.getClass().getResourceAsStream("/mail.properties"));
            String from = prop.get("mail.smtp.username") + "";
            mMessageHelper = new MimeMessageHelper(mMessage, true, "UTF-8");
            // 發件人郵箱
            mMessageHelper.setFrom(from);
            // 收件人郵箱
            mMessageHelper.setTo(emailAdress);
            // 郵件的主題也就是郵件的標題
            mMessageHelper.setSubject(subject);
            Map<String, Object> map = new HashMap<>();
            // 獲取日期並格式化
            Date date = new Date();
            DateFormat bf = new SimpleDateFormat("yyyy-MM-dd E a HH:mm:ss");
            String str = bf.format(date);
            map.put("date", str);
            String content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "email.vm", "UTF-8", map);
            mMessageHelper.setText(content, true);
            // 經過文件路徑獲取文件名字
            String filename = StringUtils.getFileName(location);
            // 定義要發送的資源位置
            File file = new File(location);
            FileSystemResource resource = new FileSystemResource(file);
            mMessageHelper.addAttachment(filename, resource);// 在郵件中添加一個附件
            // mMessageHelper.addAttachment("JavaApiRename.txt", resource2);//
            // 在郵件中添加一個附件
            javaMailSender.send(mMessage);// 發送郵件
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "發送成功";
    }

email.vm

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
 
<body>
<h3>今天的日期是:${date}</h3>

</body>
</html>

效果:

controller層

/**
 * 測試郵件發送controller
 * @author Snailclimb
 */
@RestController
@RequestMapping("mail")
public class SendMailController {
    @Autowired
    private JavaMailSender javaMailSender;// 在spring中配置的郵件發送的bean
    @Autowired
    private Configuration configuration;
    @Autowired
    private VelocityEngine velocityEngine;

    // text
    @RequestMapping("send")
    public String sendEmail() {
        EmailUtils emailUtils = new EmailUtils();
        return emailUtils.sendMail("大傻子大傻子大傻子,你好!!!", "發送給我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com",
                javaMailSender, false);
    }

    // html
    @RequestMapping("send2")
    public String sendEmail2() {
        EmailUtils emailUtils = new EmailUtils();
        return emailUtils.sendMail(
                "<p>大傻子大傻子大傻子,你好!!!</p><br/>" + "<a href='https://github.com/Snailclimb'>點擊打開個人Github!</a><br/>",
                "發送給我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com", javaMailSender, true);
    }

    // freemarker
    @RequestMapping("send3")
    public String sendEmail3() {
        EmailUtils emailUtils = new EmailUtils();
        return emailUtils.sendMailFreeMarker("發送給我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com", javaMailSender,
                configuration);

    }

    // velocity
    @RequestMapping("send4")
    public String sendEmail4() {
        EmailUtils emailUtils = new EmailUtils();
        return emailUtils.sendMailVelocity("發送給我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com", javaMailSender,
                velocityEngine);

    }
}

四 總結

上面咱們總結了Spring發送郵件的四種正確姿式,而且將核心代碼提供給了你們。代碼中有我很詳細的註釋,因此我對於代碼以及相關類的講解不多,感興趣的同窗能夠自行學習。最後,本項目Github地址:https://github.com/Snailclimb/J2ee-Advanced

五 推薦一個本身的開源的後端文檔

Java-Guide: Java面試通關手冊(Java學習指南)。(star:1.4k)

Github地址:https://github.com/Snailclimb/Java-Guide

文檔定位:一個專門爲Java後端工程師準備的開源文檔,相信不論你是Java新手仍是已經成爲一名Java工程師都能從這份文檔中收穫到一些東西。

你若怒放,清風自來。 歡迎關注個人微信公衆號:「Java面試通關手冊」,一個有溫度的微信公衆號。公衆號有大量資料,回覆關鍵字「1」你可能看到想要的東西哦!

相關文章
相關標籤/搜索