邮件发送的整合与使用


邮件发送的整合与使用

1. 基础协议及邮件配置整合

一、名词概念解释

  • 什么是 POP3、SMTP 和 IMAP?

    简单的说:POP3 和 IMAP 是⽤来从服务器上下载邮件的。SMTP 适⽤于发送或中转信件时找到下⼀个⽬的地。所以我们发送邮件应该使⽤ SMTP 协议。

IMAP 和 POP3 有什么区别?

  • 什么是免费邮箱客户端授权码功能?

    邮箱客户端授权码是为了避免您的邮箱密码被盗后,盗号者通过客户端登录邮箱⽽独特设计的安防功能。可以理解为客户端授权码为邮件发送的⼆次密码。

⼆、 整合邮件发送功能

2.1 引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

2.2 邮箱配置

QQ 系邮箱配置

官方配置说明:参考官方帮助中心

获取客户端授权码:参考官方帮助中心

详细的配置如下:

spring:
  mail:
    host: smtp.qq.com #发送邮件服务器
    username: xx@qq.com #QQ邮箱
    password: xxxxxxxxxxx #客户端授权码
    protocol: smtp #发送邮件协议
    properties.mail.smtp.auth: true
    properties.mail.smtp.port: 465 #端⼝号465或587
    properties.mail.display.sendmail: Javen #可以任意
    properties.mail.display.sendname: Spring Boot Guide Email #可以任意
    properties.mail.smtp.starttls.enable: true
    properties.mail.smtp.starttls.required: true
    properties.mail.smtp.ssl.enable: true
    default-encoding: utf-8

说明:开启 SSL 时使⽤587端⼝时⽆法连接 QQ 邮件服务器

⽹易系(126/163/yeah)邮箱配置

网易邮箱客户端授码:参考官方帮助中心

客户端端口配置说明:参考官方帮助中心

详细的配置如下:

spring:
  mail:
    host: smtp.126.com
    username: xx@126.com
    password: xxxxxxxx
    protocol: smtp
    properties.mail.smtp.auth: true
    properties.mail.smtp.port: 994 #465或者994
    properties.mail.display.sendmail: Javen
    properties.mail.display.sendname: Spring Boot Guide Email
    properties.mail.smtp.starttls.enable: true
    properties.mail.smtp.starttls.required: true
    properties.mail.smtp.ssl.enable: true
    default-encoding: utf-8
    from: xx@126.com

特别说明:

  • 126 邮箱 SMTP 服务器地址:smtp.126.com,端⼝号:465 或者 994
  • 163 邮箱 SMTP 服务器地址:smtp.163.com,端⼝号:465 或者 994
  • yeah 邮箱 SMTP 服务器地址:smtp.yeah.net,端⼝号:465 或者 994

有的邮件服务器接受使⽤客户端授权码发邮件,有的邮件服务器接受使⽤邮箱密码来发送邮件,所以 password 的配置不能⼀概⽽论。客户端授权码不⾏,就试试⽤邮箱密码;邮箱密码不⾏,就试试客户 端授权码。

三、发送简单邮件

这⾥的简单邮件就是指邮件的内容只是普通⽂字的这种邮件。

@Service
public class MailService {
    @Resource
    private JavaMailSender mailSender;
    @Value("${spring.mail.username}")
    private String fromEmail;
    /**
     * 发送⽂本邮件
     */
    public void sendSimpleMail(String to, String subject, String content) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(fromEmail);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
   }
}

sendSimpleMail 的三个参数依次是:邮件的发送⽬标,邮件的标题,邮件的内容.

测试代码:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class MailServiceTest {
    @Resource
    MailService mailService;
    @Test
    public void sendSimpleMail() {
        mailService.sendSimpleMail("16422802@qq.com",
                "普通⽂本邮件",
                "普通⽂本邮件内容测试");
   }
}

测试结果:

测试结果

附录:QQ 邮箱发邮件设置

1.开启 SMTP 服务

图片描述

2.在配置开启 SMTP 之后,会返回给我们⼀个客户端授权码。这个授权码就是上⽂中⽤来发邮件的 password。

图片描述

2. 发送 html 和基于模板的邮件

⼀、发送 html 邮件服务

sendHtmlMail 函数的第⼀个参数是发送⽬标邮箱,第⼆个参数是邮件标题,第三个参数是邮件的正⽂(html)。

  • 上⼀节中发送普通的⽂本⽂件邮件,使⽤的是 SimpleMailMessage
  • 下⽂代码中发送的正⽂是 HTML 的邮件,使⽤的是 MimeMessage
/**
* 发送html邮件
*/
public void sendHtmlMail(String to, String subject, String content) throws MessagingException {
    //注意这⾥使⽤的是MimeMessage
    MimeMessage message = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    helper.setFrom(fromEmail);
    helper.setTo(to);
    helper.setSubject(subject);
    //第⼆个参数是否是html,true表示发送的邮件正⽂是html⽂本
    helper.setText(content, true);
    mailSender.send(message);
}

测试⽤例,我们将 HTML 以字符串拼接的⽅式写在 Java 代码⾥⾯,这样对于开发者⽽⾔不太友好。可以 结合 Java 模板引擎,如 Freemarker 来来发送 HTML 邮件。

@Test
public void sendHtmlMail() throws MessagingException {
  mailService.sendHtmlMail(
    "2470752581@qq.com",
    "一封HTML测试邮件",
    """
    <body>
    <div style="width:600px;height:400px;margin:auto;background:#bdd8f6;color:#fff;text-align:center;">
    <h3>涵的邮件</h3>
    <img src="https://syhan.oss-cn-hangzhou.aliyuncs.com/img/me.png"\040
    style="width:100px;height:100px;">
    <p>
    <a style="text-decoration: none;color: #fff;" href="http://syhan.top" target="_bank">
    <strong>我的博客主页</strong>
    </a>
    </p>
    </div>
    </body>
    """
  );
}

测试结果:

测试结果

⼆、基于 freemarker 模板的邮件

图片描述

基于 freemarker 模板邮件本质上,还是发送 html 邮件,只不过是有⼀个把模板转换成 html 字符串的过程。

  • 先添加 freemarker 依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
  • application.yml 配置 freemarker
spring:
  freemarker:
  cache: false # 缓存配置 开发阶段应该配置为false 因为经常会改
  suffix: .ftl # 模版⽂件后缀名
  charset: UTF-8 # ⽂件编码
  template-loader-path: classpath:/templates/
  • Article 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Article {
    private Long id;
    private String author;
    private String title;
    private String content;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
}
  • 编写模板邮件发送测试代码
@Test
public void sendTemplateMail() throws Exception {
  // 添加动态数据,替换模版里面的占位符
  List<Article> articles = new ArrayList<>();
  articles.add(new Article(1L, "syhan", "今天星期一", "内容一", new Date()));
  articles.add(new Article(2L, "syhan", "今天下雨天", "内容二", new Date()));
  Template template = freeMarkerConfigurer.getConfiguration().getTemplate("freemarker-temp.ftl");
  //将模版文件及数据渲染完成后,转换为html字符串
  Map<String, Object> model = new HashMap<>();
  model.put("articles", articles);
  String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
  // 发送邮件
  mailService.sendHtmlMail("2470752581@qq.com", "这是一封freemarker模版的html测试邮件",templateHtml);
}
  • templates ⽬录新建 freemarker-temp.ftl 模板⽂件
<!DOCTYPE html>
<html lang="en"> <head lang="en">
    <meta charset="UTF-8"/>
    <title>freemarker简单示例</title>
</head> <body> <h1>Hello Freemarker</h1> <table class="">
    <tr>
        <td>作者</td>
        <td>教程名称</td>
        <td>内容</td>
    </tr>
    <#list articles as article>
        <tr>
            <td>${article.author}</td>
            <td>${article.title}</td>
            <td>${article.content}</td>
        </tr>
    </#list>
</table>
</body>
</html>
  • 测试结果:

测试结果

3. 发送带附件和内联附件邮件

⼀、发送带附件的邮件

/**
* 发送带附件的邮件
*/
public void sendAttachmentsMail(String to, String subject, String
content, String filePath) throws MessagingException {
    MimeMessage message = mailSender.createMimeMessage();
    //带附件第⼆个参数true
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    helper.setFrom(fromEmail);
    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);
}

sendAttachmentsMail 的第⼀个参数是发送⽬标邮箱,第⼆个参数是邮件的内容,第三个参数是邮件的附件。

运⾏如下的测试⽤例进⾏测试:

@Test
public void sendAttachmentsMailTest() throws MessagingException {
  String filePath = "/Users/apple/Desktop/me.png";
  mailService.sendAttachmentsMail(
    "2470752581@qq.com",
    "这是一封带附件的邮件--来自syhan",
    "邮件中有附件,请注意查收!",
    filePath);
}

测试结果:

测试结果

⼆、发送内联附件的邮件

所谓的内联附件就是附件⽂件在邮件正⽂内显示,通常是⼀图⽚资源。

图片描述

/**
* 发送正⽂中有静态资源的邮件
*/
public void sendResourceMail(String to, String subject, String content,
String rscPath, String rscId) throws MessagingException {
    MimeMessage message = mailSender.createMimeMessage();
    
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    helper.setFrom(fromEmail);
    helper.setTo(to);
    helper.setSubject(subject);
    helper.setText(content, true);
    //添加内联附件,指定⼀个资源id:rscId
    FileSystemResource res = new FileSystemResource(new File(rscPath));
    helper.addInline(rscId, res);
    
    mailSender.send(message);
}

sendResourceMail ⽅法的参数说明:

  • 参数⼀:发送邮件的⽬标邮箱

  • 参数⼆:⽂件的标题

  • 参数三:邮件的正⽂:html(含图⽚资源 id:rscId)

  • 参数四:图⽚资源⽂件本地磁盘路径 res

  • 参数五:图⽚资源⽂件的资源 Id:rscId

参数三 HTML ⽂本发现正⽂中包含<img src=cid: rscId>,就会根据参数五 helper.addInline(rscId, res);,找 到参数四对应的资源⽂件 res,并渲染到 HTML ⾥⾯。

测试⽤例,执⾏之后看结果

@Test
public void sendResourceMail() throws MessagingException {
  String rscId = "syhan";
  String content = "<html><body>这是有图片的邮件<br/><img src='cid:" + rscId + "'></body></html>";
  String imgPath = "/Users/apple/Desktop/vlog.png";
  mailService.sendResourceMail(
            "2470752581@qq.com",
            "这邮件中包含图片",
            content,
            imgPath,
            rscId);
}

测试结果:

测试结果


文章作者: Syhan
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Syhan !
评论
  目录