SpringBoot从入门到熟悉(八)使用SpringBoot发送邮件--JavaMailSender

本文详细介绍了使用SpringBoot实现邮件发送的方法,包括简单文本邮件、HTML格式邮件、带附件及静态资源的邮件发送,以及如何利用邮件模板和异步发送提升效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发送邮件应该是网站的必备功能之一,什么注册验证,忘记密码或者是给用户发送营销信息。最早期的时候我们会使用JavaMail相关api来写发送邮件的相关代码,后来spring推出了JavaMailSender更加简化了邮件发送的过程,在之后springboot对此进行了封装就有了现在的spring-boot-starter-mail,本文主要通过实例实现一个发送邮件的功能以此来学习JavaMailSender。

一、邮件协议


    我们经常会听到各种各样的邮件协议,比如SMTP、POP3、IMAP,那么这些协议有什么作用,有什么区别?我们先来讨论一下这个问题。

SMTP是一个基于TCP/IP的应用层协议,江湖地位有点类似于HTTP,SMTP服务器默认监听的端口号为25。看到这里,小伙伴们可能会想到既然SMTP协议是基于TCP/IP的应用层协议,那么我是不是也可以通过Socket发送一封邮件呢?回答是肯定的。

生活中我们投递一封邮件要经过如下几个步骤:

  • 1.深圳的小王先将邮件投递到深圳的邮局 
  • 2.深圳的邮局将邮件运送到上海的邮局 
  • 3.上海的小张来邮局取邮件

这是一个缩减版的生活中邮件发送过程。这三个步骤可以分别对应我们的邮件发送过程,假设从aaa@qq.com发送邮件到111@163.com:

  • 1.aaa@qq.com先将邮件投递到腾讯的邮件服务器 
  • 2.腾讯的邮件服务器将我们的邮件投递到网易的邮件服务器 
  • 3.111@163.com登录网易的邮件服务器查看邮件

邮件投递大致就是这个过程,这个过程就涉及到了多个协议,我们来分别看一下。

SMTP协议全称为Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件于SMTP服务器之间,以及SMTP服务器与SMTP服务器之间的通信规则。也就是说aaa@qq.com用户先将邮件投递到腾讯的SMTP服务器这个过程就使用了SMTP协议,然后腾讯的SMTP服务器将邮件投递到网易的SMTP服务器这个过程也依然使用了SMTP协议,SMTP服务器就是用来收邮件。

POP3协议全称为Post Office Protocol,译作邮局协议,它定义了邮件客户端与POP3服务器之间的通信规则,那么该协议在什么场景下会用到呢?当邮件到达网易的SMTP服务器之后,111@163.com用户需要登录服务器查看邮件,这个时候就该协议就用上了:邮件服务商都会为每一个用户提供专门的邮件存储空间,SMTP服务器收到邮件之后,就将邮件保存到相应用户的邮件存储空间中,如果用户要读取邮件,就需要通过邮件服务商的POP3邮件服务器来完成。最后,可能也有小伙伴们听说过IMAP协议,这个协议是对POP3协议的扩展,功能更强,作用类似,这里不再赘述。
 

 二、简单使用

前提:在所使用的邮箱服务web页面开启如下服务

1、gradle jar包配置

  implementation 'org.springframework.boot:spring-boot-starter-mail'

2.在application.properties中添加邮箱配置

pring.mail.host=smtp.163.com //邮箱服务器地址
spring.mail.username=xxx@oo.com //用户名
spring.mail.password=xxyyooo    //密码
spring.mail.default-encoding=UTF-8

mail.fromMail.addr=xxx@oo.com  //以谁来发送邮件,自己在测试时候删掉注释,否则会解析邮件地址错误

3、编写mailService

@Component
public class MailServiceImpl implements MailService {    //MailService是自定义的接口
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JavaMailSender mailSender;

    @Value("${mail.fromMail.addr}")
    private String fromWho;

    public void sendSimpleMail(String to ,String subject , String content){
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(fromWho);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);

        try {
            mailSender.send(message);
            logger.info("简单邮件发送成功");
        } catch (MailException e) {
            logger.error("发送简单邮件时发生异常!", e);
        }
    }
}

4、编写test类进行测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class JavamailApplicationTests {

    @Autowired
    private MailService mailService;
    @Test
    public void testSimpleMail() {
        mailService.sendSimpleMail("接受邮箱@163.com","test simple mail A","Hello, Mail!!!");
    }

}

至此一个简单的文本邮件发送就完成了。

三、升级难度

正常使用的过程中,我们通常在邮件中加入图片或者附件来丰富邮件的内容,下面讲介绍如何使用springboot来发送丰富的邮件。

1.发送html格式邮件

其它都不变在MailService添加sendHtmlMail方法.

  public void sendHtmlMail(String to, String subject, String content) {
        MimeMessage message = mailSender.createMimeMessage();

        try {
            //true表示需要创建一个multipart message
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(fromWho);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);      //whether to apply content type "text/html" for an HTML mail, using default content type ("text/plain") else

            mailSender.send(message);
            logger.info("html邮件发送成功");
        } catch (MessagingException e) {
            logger.error("发送html邮件时发生异常!", e);
        }
    }

在测试类中构建html内容,测试发送

@Test
    public void testHtmlMail() throws Exception {
        String content="<html>\n" +
                "<body>\n" +
                "    <h3>hello world ! 这是一封Html邮件!</h3>\n" +
                "</body>\n" +
                "</html>";
        mailService.sendHtmlMail("接受邮箱@163.com","test Html mail",content);
    }

2.发送带附件的邮件

在MailService添加sendAttachmentsMail方法.

 public void sendAttachmentsMail(String to, String subject, String content, String filePath){
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(fromWho);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);

            FileSystemResource file = new FileSystemResource(new File(filePath));
            String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
            helper.addAttachment(fileName, file);

            mailSender.send(message);
            logger.info("带附件的邮件已经发送。");
        } catch (MessagingException e) {
            logger.error("发送带附件的邮件时发生异常!", e);
        }
    }

添加多个附件可以使用多条 helper.addAttachment(fileName, file)

在测试类中添加测试方法

@Test
    public void sendAttachmentsMail() {
        String filePath="E:\\项目文件\\sample.org";
        mailService.sendAttachmentsMail("接受邮箱@163.com", "主题:带附件的邮件", "有附件,请查收!", filePath);
    }

3.发送带静态资源的邮件

邮件中的静态资源一般就是指图片,在MailService添加sendAttachmentsMail方法.

public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){
        MimeMessage message = mailSender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(fromWho);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);

            FileSystemResource res = new FileSystemResource(new File(rscPath));
            helper.addInline(rscId, res);

            mailSender.send(message);
            logger.info("嵌入静态资源的邮件已经发送。");
        } catch (MessagingException e) {
            logger.error("发送嵌入静态资源的邮件时发生异常!", e);
        }
    }

在测试类中添加测试方法

 

@Test
    public void sendInlineResourceMail() {
        String rscId = "zerah006";      //这个是图片资源id,图片是以html格式写入邮件的
        String content="<html><body>这是有图片的邮件:<img src=\'cid:" + rscId + "\' ></body></html>";
        String imgPath = "E:\\壁纸\\unsplash-Ines Álvarez Fdez.jpg";

        mailService.sendInlineResourceMail("m15500878900@163.com", "主题:这是有图片的邮件", content, imgPath, rscId);
    }

添加多个图片可以使用多条 <img src='cid:" + rscId + "' > 和 helper.addInline(rscId, res) 来实现

四、邮件模板

上面发送邮件的基础服务就这些了,但是如果我们要做成一个邮件系统的话还需要考虑以下几个问题:

我们会经常收到这样的邮件:

尊敬的zerah用户:
                  
              恭喜您注册成为xxx网的用户,,同时感谢您对xxx的关注与支持并欢迎您使用xx的产品与服务。
              ...

其中只有zerah这个用户名在变化,其它邮件内容均不变,如果每次发送邮件都需要手动拼接的话会不够优雅,并且每次模板的修改都需要改动代码的话也很不方便,因此对于这类邮件需求,都建议做成邮件模板来处理。模板的本质很简单,就是在模板中替换变化的参数,转换为html字符串即可,这里以thymeleaf为例来演示。

 

1、pom中导入thymeleaf的包

implementation('org.springframework.boot:spring-boot-starter-thymeleaf')

2、在resorces/templates下创建emailTemplate.html

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>邮件模板测试</title>
</head>
<body>
您好大大,这是验证邮件,请点击下面的链接完成验证,<br/>
<a href="#" th:href="@{ http://www.baidu.com/{id}(id=${id}) }">激活账号</a>
</body>
</html>

3、解析模板并发送

    @Test
    public void sendTemplateMail() {
        //创建邮件正文
        Context context = new Context();                //Context是thymeleaf包的
        context.setVariable("id", "006");       //用户主键id
        String emailContent = templateEngine.process("emailTemplate", context);

        mailService.sendHtmlMail("接收邮箱.com","主题:这是模板邮件",emailContent);
    }

五、发送失败

因为各种原因,总会有邮件发送失败的情况,比如:邮件发送过于频繁、网络异常等。在出现这种情况的时候,我们一般会考虑重新重试发送邮件,会分为以下几个步骤来实现:

  • 1、接收到发送邮件请求,首先记录请求并且入库。
  • 2、调用邮件发送接口发送邮件,并且将发送结果记录入库。
  • 3、启动定时系统扫描时间段内,未发送成功并且重试次数小于3次的邮件,进行再次发送

六、异步发送

很多时候邮件发送并不是我们主业务必须关注的结果,比如通知类、提醒类的业务可以允许延时或者失败。这个时候可以采用异步的方式来发送邮件,加快主交易执行速度,在实际项目中可以采用MQ发送邮件相关参数,监听到消息队列之后启动发送邮件。

 

参考:http://blog.didispace.com/springbootmailsender/

https://blog.youkuaiyun.com/u012702547/article/details/79494474

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值