资讯专栏INFORMATION COLUMN

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

doodlewind / 2307人阅读

摘要:我拿网易邮箱账号举例子,那么我们如何才能让你的邮箱账号可以利用第三方发送邮件这里的第三方就是我们即将编写的程序。

一 前言 测试所使用的环境

测试使用的环境是企业主流的SSM 框架即 SpringMVC+Spring+Mybatis。为了节省时间,我直接使用的是我上次的“SSM项目中整合Echarts开发”该项目已经搭建完成的SSM环境。

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

发送text格式的邮件

发送HTML格式的邮件

基于FreeMarker模板引擎发送邮件

基于Velocity模板引擎发送邮件

如何获取以及运行我的Demo

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

你可以选择直接下载或者直接在DOS窗口运行:git clone https://github.com/Snailclimb/J2ee-Advanced.git命令,这样项目就被拷贝到你的电脑了。

然后选择导入Maven项目即可(不懂Maven的可以自行百度学习).

二 准备工作

既然要发送邮件,那么你首先要提供一个能在第三方软件上发送邮件功能的账号。在这里,我选择的网易邮箱账号。

我拿网易邮箱账号举例子,那么我们如何才能让你的邮箱账号可以利用第三方发送邮件(这里的第三方就是我们即将编写的程序)。

大家应该清楚:客户端和后台交互数据的时候用到了Http协议,那么相应的,邮箱传输也有自己的一套协议,如SMTP,POP3,IMAP。

开启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包,如下图所示:

        
            javax.mail
            mail
            1.4.7
        
相关配置文件

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

pom.xml

需要用到的jar包。

        
        
              org.springframework
              spring-context-support
              5.0.0.RELEASE
        
        
        
            javax.mail
            mail
            1.4.7
        
        
        
            org.freemarker
            freemarker
            2.3.23
        
        
        
            org.apache.velocity
            velocity
            1.7
        
        
            org.apache.velocity
            velocity-tools
            2.0
        
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



    
    

    
    
        
        
        
        
        
            
                ${mail.smtp.auth}
                ${mail.smtp.timeout}
            
        
    
    
    
        
        
        
            
                UTF-8
            
        
    


    
    
        
        
    

三 开始编写工具类

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

所有用到的类如下图所示:

发送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 map = new HashMap();
            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模板,返回的格式如下图所示:




测试



你好Snailclimb

其实就是HTML,然后我们就可以像前面发送HTML格式邮件的方式发送这端消息了。

email.ftl




测试



你好${user}

效果:

不知道为啥,腾讯每次把我使用模板引擎发的邮件直接放到垃圾箱。大家如果遇到接收不到邮件,但是又没报错的情况,可以看看是不是到了自己邮箱的垃圾箱。

基于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 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




    
    
 

今天的日期是:${date}

效果:

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(
                "

大傻子大傻子大傻子,你好!!!


" + "点击打开我的Github!
", "发送给我家大傻子的~", "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”你可能看到想要的东西哦!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76677.html

相关文章

  • Spring Boot 2.x(四):整合Mybatis四种方式

    摘要:前言目前的大环境下,使用作为持久层框架还是占了绝大多数的,下面我们来说一下使用的几种姿势。测试测试的程序与之前的一致,我们直接访问,可以看到成功的结果姿势三使用的姿势和可以与上面两种方式进行结合,。。。接口的实现是通过。然后我们将的改为。 前言 目前的大环境下,使用Mybatis作为持久层框架还是占了绝大多数的,下面我们来说一下使用Mybatis的几种姿势。 姿势一:零配置注解开发 第...

    felix0913 评论0 收藏0
  • @ConfigurationProperties 注解使用姿势,这一篇就够了

    摘要:在项目中,为满足以上要求,我们将大量的参数配置在或文件中,通过注解,我们可以方便的获取这些参数值使用配置模块假设我们正在搭建一个发送邮件的模块。这使得在不影响其他模块的情况下重构一个模块中的属性变得容易。 在编写项目代码时,我们要求更灵活的配置,更好的模块化整合。在 Spring Boot 项目中,为满足以上要求,我们将大量的参数配置在 application.properties 或...

    SolomonXie 评论0 收藏0
  • @ConfigurationProperties 注解使用姿势,这一篇就够了

    摘要:在项目中,为满足以上要求,我们将大量的参数配置在或文件中,通过注解,我们可以方便的获取这些参数值使用配置模块假设我们正在搭建一个发送邮件的模块。这使得在不影响其他模块的情况下重构一个模块中的属性变得容易。 在编写项目代码时,我们要求更灵活的配置,更好的模块化整合。在 Spring Boot 项目中,为满足以上要求,我们将大量的参数配置在 application.properties 或...

    KoreyLee 评论0 收藏0
  • Java开发 大厂面试整理

    摘要:用户态不能干扰内核态所以指令就有两种特权指令和非特权指令不同的状态对应不同的指令。非特权指令所有程序均可直接使用。用户态常态目态执行非特权指令。 这是我今年从三月份开始,主要的大厂面试经过,有些企业面试的还没来得及整理,可能有些没有带答案就发出来了,还请各位先思考如果是你怎么回答面试官?这篇文章会持续更新,请各位持续关注,希望对你有所帮助! 面试清单 平安产险 飞猪 上汽大通 浩鲸科...

    Scorpion 评论0 收藏0
  • Spring Boot 邮件发送的 5 种姿势

    摘要:也就是说用户先将邮件投递到腾讯的服务器这个过程就使用了协议,然后腾讯的服务器将邮件投递到网易的服务器这个过程也依然使用了协议,服务器就是用来收邮件。 邮件发送其实是一个非常常见的需求,用户注册,找回密码等地方,都会用到,使用 JavaSE 代码发送邮件,步骤还是挺繁琐的,Spring Boot 中对于邮件发送,提供了相关的自动化配置类,使得邮件发送变得非常容易,本文我们就来一探究竟!看...

    W4n9Hu1 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<