• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

结合Spring发送邮件的四种正确姿势,你知道几种?

技术杂谈 勤劳的小蚂蚁 4个月前 (12-30) 81次浏览 已收录 0个评论 扫描二维码

一 前言

测试所使用的环境

测试使用的环境是企业主流的SSM 框架即 SpringMVC+Spring+Mybatis。

标题说的四种姿势指的是哪四种姿势?

  1. 发送text格式的邮件
  2. 发送HTML格式的邮件
  3. 基于FreeMarker模板引擎发送邮件
  4. 基于Velocity模板引擎发送邮件

如何获取以及运行我的Demo

Github地址:https://github.com/Snailclimb/J2ee-Advanced。(说明:相关代码都在ssm-echarts-demo 项目中)
你可以选择直接下载或者直接在DOS窗口运行: git clone https://github.com/Snailclimb/J2ee-Advanced.git命令,这样项目就被拷贝到你的电脑了。
然后选择导入Maven项目即可(不懂Maven的可以自行百度学习).

二 准备工作

既然要发送邮件,那么你首先要提供一个能在第三方软件上发送邮件功能的账号。在这里,我选择的网易邮箱账号。
我拿网易邮箱账号举例子,那么我们如何才能让你的邮箱账号可以利用第三方发送邮件(这里的第三方就是我们即将编写的程序)。
大家应该清楚:客户端和后台交互数据的时候用到了Http协议,那么相应的,邮箱传输也有自己的一套协议,如SMTP,POP3,IMAP。

开启POP3/SMTP/IMAP服务

所以,我们第一步首先要去开启这些服务,如下图所示:
如果你未开启该服务的话,运行程序会报如下错误(配置文件中配置的密码是你的授权码而不是你登录邮箱的密码,授权码是你第三方登录的凭证):
  1. HTTP Status500-Request processing failed; nested exception is org.springframework.mail.MailAuthenticationException:Authentication failed; nested exception is javax.mail.AuthenticationFailedException:550User has no permission

JavaMail介绍

我们需要用到的发邮件的核心jar包,所以这里好好介绍一下。
JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类。但它并没有包含在JDK中,而是作为JavaEE的一部分。厂商所提供的JavaMail服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括:
  • SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;
  • POP3:用于接收电子邮件的标准协议;
  • IMAP:互联网消息协议,是POP3的替代协议。
这三种协议都有对应SSL加密传输的协议,分别是SMTPS,POP3S和IMAPS。
我们如果要使用JavaMail的话,需要自己引用相应的jar包,如下图所示:
  1.        <dependency>
  2.            <groupId>javax.mail</groupId>
  3.            <artifactId>mail</artifactId>
  4.            <version>1.4.7</version>
  5.        </dependency>

相关配置文件

下图是除了pom.xml之外用到的其他所有配置文件

pom.xml

需要用到的jar包。
  1.        <!--spring支持-->
  2.        <dependency>
  3.              <groupId>org.springframework</groupId>
  4.              <artifactId>spring-context-support</artifactId>
  5.              <version>5.0.0.RELEASE</version>
  6.        </dependency>
  7.        <!-- 发送邮件 -->
  8.        <dependency>
  9.            <groupId>javax.mail</groupId>
  10.            <artifactId>mail</artifactId>
  11.            <version>1.4.7</version>
  12.        </dependency>
  13.        <!-- Freemarker -->
  14.        <dependency>
  15.            <groupId>org.freemarker</groupId>
  16.            <artifactId>freemarker</artifactId>
  17.            <version>2.3.23</version>
  18.        </dependency>
  19.        <!-- velocity模板引擎 -->
  20.        <dependency>
  21.            <groupId>org.apache.velocity</groupId>
  22.            <artifactId>velocity</artifactId>
  23.            <version>1.7</version>
  24.        </dependency>
  25.        <dependency>
  26.            <groupId>org.apache.velocity</groupId>
  27.            <artifactId>velocity-tools</artifactId>
  28.            <version>2.0</version>
  29.        </dependency>

mail.properties

  1. #服务器主机名
  2. mail.smtp.host=smtp.163.com
  3. #你的邮箱地址
  4. mail.smtp.username=koushuangbwcx@163.com
  5. #你的授权码
  6. mail.smtp.password=cSdN153963000
  7. #编码格式
  8. mail.smtp.defaultEncoding=utf-8
  9. #是否进行用户名密码校验
  10. mail.smtp.auth=true
  11. #设置超时时间
  12. mail.smtp.timeout=20000
如果你的授权码填写错误的话,会报如下错误:
  1. TTP Status500-Request processing failed; nested exception is org.springframework.mail.MailAuthenticationException:Authentication failed; nested exception is javax.mail.AuthenticationFailedException:535Error: authentication failed

velocity.properties

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

applicationContext-email.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
  4.    xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"
  5.    xmlns:aop="http://www.springframework.org/schema/aop"
  6.    xsi:schemaLocation="
  7.        http://www.springframework.org/schema/beans
  8.        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  9.        http://www.springframework.org/schema/context
  10.        http://www.springframework.org/schema/context/spring-context-4.0.xsd
  11.        http://www.springframework.org/schema/tx
  12.        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
  13.        http://www.springframework.org/schema/aop    
  14.        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
  15.    <!--邮件配置 -->
  16.    <context:property-placeholderlocation="classpath:mail.properties"
  17.        ignore-unresolvable="true"/>
  18.    <!--配置邮件接口 -->
  19.    <beanid="javaMailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl">
  20.        <propertyname="host"value="${mail.smtp.host}"/>
  21.        <propertyname="username"value="${mail.smtp.username}"/>
  22.        <propertyname="password"value="${mail.smtp.password}"/>
  23.        <propertyname="defaultEncoding"value="${mail.smtp.defaultEncoding}"/>
  24.        <propertyname="javaMailProperties">
  25.            <props>
  26.                <propkey="mail.smtp.auth">${mail.smtp.auth}</prop>
  27.                <propkey="mail.smtp.timeout">${mail.smtp.timeout}</prop>
  28.            </props>
  29.        </property>
  30.    </bean>
  31.    <!-- freemarker -->
  32.    <beanid="configuration"
  33.        class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
  34.        <propertyname="templateLoaderPath"value="/WEB-INF/freemarker/"/>
  35.        <!-- 设置FreeMarker环境变量 -->
  36.        <propertyname="freemarkerSettings">
  37.            <props>
  38.                <propkey="default_encoding">UTF-8</prop>
  39.            </props>
  40.        </property>
  41.    </bean>
  42.    <!-- velocity -->
  43.    <beanid="velocityEngine"
  44.        class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
  45.        <propertyname="resourceLoaderPath"value="/WEB-INF/velocity/"/><!--
  46.            模板存放的路径 -->
  47.        <propertyname="configLocation"value="classpath:velocity.properties"/><!--
  48.            Velocity的配置文件 -->
  49.    </bean>
  50. </beans>

三 开始编写工具类

我这里说是工具类,其实只是我自己做了简单的封装,实际项目使用的话,可能会需要根据需要简单修改一下。
所有用到的类如下图所示:

发送Text或者HTML格式的邮件的方法

  1.    /**
  2.     *
  3.     * Text或者HTML格式邮件的方法
  4.     *
  5.     * @param text
  6.     *            要发送的内容
  7.     * @param subject
  8.     *            邮件的主题也就是邮件的标题
  9.     * @param location
  10.     *            文件的地址
  11.     * @param emailAdress
  12.     *            目的地
  13.     * @param javaMailSender
  14.     *            发送邮件的核心类(在xml文件中已经配置好了)
  15.     * @param type
  16.     *            如果为true则代表发送HTML格式的文本
  17.     * @return
  18.     * @throws TemplateException
  19.     */
  20.    publicString sendMail(String text,String subject,String location,String emailAdress,
  21.            JavaMailSender javaMailSender,Boolean type){
  22.        MimeMessage mMessage = javaMailSender.createMimeMessage();// 创建邮件对象
  23.        MimeMessageHelper mMessageHelper;
  24.        Properties prop =newProperties();
  25.        try{
  26.            // 从配置文件中拿到发件人邮箱地址
  27.            prop.load(this.getClass().getResourceAsStream("/mail.properties"));
  28.            String from = prop.get("mail.smtp.username")+"";
  29.            mMessageHelper =newMimeMessageHelper(mMessage,true,"UTF-8");
  30.            // 发件人邮箱
  31.            mMessageHelper.setFrom(from);
  32.            // 收件人邮箱
  33.            mMessageHelper.setTo(emailAdress);
  34.            // 邮件的主题也就是邮件的标题
  35.            mMessageHelper.setSubject(subject);
  36.            // 邮件的文本内容,true表示文本以html格式打开
  37.            if(type){
  38.                mMessageHelper.setText(text,true);
  39.            }else{
  40.                mMessageHelper.setText(text,false);
  41.            }
  42.            // 通过文件路径获取文件名字
  43.            String filename =StringUtils.getFileName(location);
  44.            // 定义要发送的资源位置
  45.            File file =newFile(location);
  46.            FileSystemResource resource =newFileSystemResource(file);
  47.            FileSystemResource resource2 =newFileSystemResource("D:/email.txt");
  48.            mMessageHelper.addAttachment(filename, resource);// 在邮件中添加一个附件
  49.            mMessageHelper.addAttachment("JavaApiRename.txt", resource2);//
  50.            // 在邮件中添加一个附件
  51.            javaMailSender.send(mMessage);// 发送邮件
  52.        }catch(MessagingException e){
  53.            e.printStackTrace();
  54.        }catch(IOException e){
  55.            // TODO Auto-generated catch block
  56.            e.printStackTrace();
  57.        }
  58.        return"发送成功";
  59.    }
我在 sendMail()方法中添加了一个 boolean类型的变量type作为标志,如果为ture就表示发送html格式的邮件否则直接发送text格式的邮件。实现起来很简单,我们通过下面的判断语句就可以实现了
  1.            if(type){
  2.                //表示文本以html格式打开
  3.                mMessageHelper.setText(text,true);
  4.            }else{
  5.                mMessageHelper.setText(text,false);
  6.            }
效果:

基于FreeMarker模板引擎发送邮件

下图是我们用到的FreeMarker模板文件以及Velocity模板文件的位置。
  1.    /**
  2.     * FreeMarker模板格式的邮件的方法
  3.     *
  4.     * @param subject
  5.     *            邮件的主题也就是邮件的标题
  6.     * @param location
  7.     *            文件的地址
  8.     * @param emailAdress
  9.     *            目的地
  10.     * @param javaMailSender
  11.     *            发送邮件的核心类(在xml文件中已经配置好了)
  12.     * @param freeMarkerConfiguration
  13.     *            freemarker配置管理类
  14.     * @return
  15.     * @throws TemplateException
  16.     */
  17.    publicString sendMailFreeMarker(String subject,String location,String emailAdress,JavaMailSender javaMailSender,
  18.            Configuration freeMarkerConfiguration){
  19.        MimeMessage mMessage = javaMailSender.createMimeMessage();// 创建邮件对象
  20.        MimeMessageHelper mMessageHelper;
  21.        Properties prop =newProperties();
  22.        try{
  23.            // 从配置文件中拿到发件人邮箱地址
  24.            prop.load(this.getClass().getResourceAsStream("/mail.properties"));
  25.            String from = prop.get("mail.smtp.username")+"";
  26.            mMessageHelper =newMimeMessageHelper(mMessage,true);
  27.            // 发件人邮箱
  28.            mMessageHelper.setFrom(from);
  29.            // 收件人邮箱
  30.            mMessageHelper.setTo(emailAdress);
  31.            // 邮件的主题也就是邮件的标题
  32.            mMessageHelper.setSubject(subject);
  33.            // 解析模板文件
  34.            mMessageHelper.setText(getText(freeMarkerConfiguration),true);
  35.            // 通过文件路径获取文件名字
  36.            String filename =StringUtils.getFileName(location);
  37.            // 定义要发送的资源位置
  38.            File file =newFile(location);
  39.            FileSystemResource resource =newFileSystemResource(file);
  40.            mMessageHelper.addAttachment(filename, resource);// 在邮件中添加一个附件
  41.            javaMailSender.send(mMessage);// 发送邮件
  42.        }catch(MessagingException e){
  43.            e.printStackTrace();
  44.        }catch(IOException e){
  45.            // TODO Auto-generated catch block
  46.            e.printStackTrace();
  47.        }
  48.        return"发送成功";
  49.    }
  50.      /**
  51.     * 读取freemarker模板的方法
  52.     */
  53.    privateString getText(Configuration freeMarkerConfiguration){
  54.        String txt ="";
  55.        try{
  56.            Template template = freeMarkerConfiguration.getTemplate("email.ftl");
  57.            // 通过map传递动态数据
  58.            Map<String,Object> map =newHashMap<String,Object>();
  59.            map.put("user","Snailclimb");
  60.            // 解析模板文件
  61.            txt =FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
  62.            System.out.println("getText()->>>>>>>>>");// 输出的是HTML格式的文档
  63.            System.out.println(txt);
  64.        }catch(IOException e){
  65.            // TODO 异常执行块!
  66.            e.printStackTrace();
  67.        }catch(TemplateException e){
  68.            // TODO 异常执行块!
  69.            e.printStackTrace();
  70.        }
  71.        return txt;
  72.    }
我们通过 getText(ConfigurationfreeMarkerConfiguration)方法读取freemarker模板,返回的格式如下图所示:
  1. <html>
  2. <head>
  3. <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
  4. <title>测试</title>
  5. </head>
  6. <body>
  7. <h1>你好Snailclimb</h1>
  8. </body>
  9. </html>
其实就是HTML,然后我们就可以像前面发送HTML格式邮件的方式发送这端消息了。
email.ftl
  1. <html>
  2. <head>
  3. <metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
  4. <title>测试</title>
  5. </head>
  6. <body>
  7. <h1>你好${user}</h1>
  8. </body>
  9. </html>
效果:
不知道为啥,腾讯每次把我使用模板引擎发的邮件直接放到垃圾箱。大家如果遇到接收不到邮件,但是又没报错的情况,可以看看是不是到了自己邮箱的垃圾箱。

基于Velocity模板引擎发送邮件

  1.    /**
  2.     *
  3.     * @param subject
  4.     *            邮件主题
  5.     * @param location
  6.     *            收件人地址
  7.     * @param emailAdress
  8.     *            目的地
  9.     * @param javaMailSender
  10.     *            发送邮件的核心类(在xml文件中已经配置好了)
  11.     * @param velocityEngine
  12.     *            Velocity模板引擎
  13.     * @return
  14.     */
  15.    publicString sendMailVelocity(String subject,String location,String emailAdress,JavaMailSender javaMailSender,
  16.            VelocityEngine velocityEngine){
  17.        MimeMessage mMessage = javaMailSender.createMimeMessage();// 创建邮件对象
  18.        MimeMessageHelper mMessageHelper;
  19.        Properties prop =newProperties();
  20.        try{
  21.            // 从配置文件中拿到发件人邮箱地址
  22.            prop.load(this.getClass().getResourceAsStream("/mail.properties"));
  23.            System.out.println(this.getClass().getResourceAsStream("/mail.properties"));
  24.            String from = prop.get("mail.smtp.username")+"";
  25.            mMessageHelper =newMimeMessageHelper(mMessage,true,"UTF-8");
  26.            // 发件人邮箱
  27.            mMessageHelper.setFrom(from);
  28.            // 收件人邮箱
  29.            mMessageHelper.setTo(emailAdress);
  30.            // 邮件的主题也就是邮件的标题
  31.            mMessageHelper.setSubject(subject);
  32.            Map<String,Object> map =newHashMap<>();
  33.            // 获取日期并格式化
  34.            Date date =newDate();
  35.            DateFormat bf =newSimpleDateFormat("yyyy-MM-dd E a HH:mm:ss");
  36.            String str = bf.format(date);
  37.            map.put("date", str);
  38.            String content =VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,"email.vm","UTF-8", map);
  39.            mMessageHelper.setText(content,true);
  40.            // 通过文件路径获取文件名字
  41.            String filename =StringUtils.getFileName(location);
  42.            // 定义要发送的资源位置
  43.            File file =newFile(location);
  44.            FileSystemResource resource =newFileSystemResource(file);
  45.            mMessageHelper.addAttachment(filename, resource);// 在邮件中添加一个附件
  46.            // mMessageHelper.addAttachment("JavaApiRename.txt", resource2);//
  47.            // 在邮件中添加一个附件
  48.            javaMailSender.send(mMessage);// 发送邮件
  49.        }catch(MessagingException e){
  50.            e.printStackTrace();
  51.        }catch(IOException e){
  52.            // TODO Auto-generated catch block
  53.            e.printStackTrace();
  54.        }
  55.        return"发送成功";
  56.    }
email.vm
  1. <!DOCTYPE html>
  2. <html>
  3. <headlang="en">
  4.    <metacharset="UTF-8">
  5.    <title></title>
  6. <body>
  7. <h3>今天的日期是:${date}</h3>
  8. </body>
  9. </html>
效果:

controller层

  1. /**
  2. * 测试邮件发送controller
  3. * @author Snailclimb
  4. */
  5. @RestController
  6. @RequestMapping("mail")
  7. publicclassSendMailController{
  8.    @Autowired
  9.    privateJavaMailSender javaMailSender;// 在spring中配置的邮件发送的bean
  10.    @Autowired
  11.    privateConfiguration configuration;
  12.    @Autowired
  13.    privateVelocityEngine velocityEngine;
  14.    // text
  15.    @RequestMapping("send")
  16.    publicString sendEmail(){
  17.        EmailUtils emailUtils =newEmailUtils();
  18.        return emailUtils.sendMail("大傻子大傻子大傻子,你好!!!","发送给我家大傻子的~","D:/picture/meizi.jpg","1361583339@qq.com",
  19.                javaMailSender,false);
  20.    }
  21.    // html
  22.    @RequestMapping("send2")
  23.    publicString sendEmail2(){
  24.        EmailUtils emailUtils =newEmailUtils();
  25.        return emailUtils.sendMail(
  26.                "<p>大傻子大傻子大傻子,你好!!!</p><br/>"+"<a href='https://github.com/Snailclimb'>点击打开我的Github!</a><br/>",
  27.                "发送给我家大傻子的~","D:/picture/meizi.jpg","1361583339@qq.com", javaMailSender,true);
  28.    }
  29.    // freemarker
  30.    @RequestMapping("send3")
  31.    publicString sendEmail3(){
  32.        EmailUtils emailUtils =newEmailUtils();
  33.        return emailUtils.sendMailFreeMarker("发送给我家大傻子的~","D:/picture/meizi.jpg","1361583339@qq.com", javaMailSender,
  34.                configuration);
  35.    }
  36.    // velocity
  37.    @RequestMapping("send4")
  38.    publicString sendEmail4(){
  39.        EmailUtils emailUtils =newEmailUtils();
  40.        return emailUtils.sendMailVelocity("发送给我家大傻子的~","D:/picture/meizi.jpg","1361583339@qq.com", javaMailSender,
  41.                velocityEngine);
  42.    }
  43. }

四 总结

上面我们总结了Spring发送邮件的四种正确姿势,并且将核心代码提供给了大家。代码中有我很详细的注释,所以我对于代码以及相关类的讲解很少,感兴趣的同学可以自行学习。最后,本项目Github地址:https://github.com/Snailclimb/J2ee-Advanced。

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:结合Spring发送邮件的四种正确姿势,你知道几种?
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00