• 使用JavaMailSender进行邮件发送


    以前发送邮件可能大家需要使用javax下的mail包,自己创建session,mimemessage这种;其实spring帮我们集成了一下,让发邮件变的更简单、可靠。

    1.引入对应依赖

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-mailartifactId>
    4. dependency>

    2.具体使用

    首先spring 的依赖常规使用方式就是配置加注入,邮件模块也不例外。先来看看配置

    1. spring:
    2. mail:
    3. host: 10.110.xxx.xxx #邮件服务器地址
    4. port: 25 #邮件服务器端口
    5. protocol: smtp #使用的协议
    6. default-encoding: UTF-8 #默认编码
    7. username: user #这个是通过邮件服务器认证的用户名和密码,不一定是邮箱,看服务器的要求
    8. password: password
    9. properties: #properties中的属性都是比较灵活可配置的,其实是javax.mail.Session中对应的配置项,可以参考对应文档
    10. mail.smtp.auth: true #如果邮件服务器需要实名需要认证开启此选项
    11. mail.from: 100010@qq.com #统一设置发件人邮箱

    然后放具体代码,后面一点一点分析

    邮件实体类

    1. import lombok.*;
    2. import org.springframework.core.io.InputStreamSource;
    3. import javax.activation.DataSource;
    4. import javax.mail.internet.InternetAddress;
    5. import java.io.File;
    6. import java.util.Date;
    7. import java.util.HashMap;
    8. import java.util.List;
    9. import java.util.Map;
    10. /**
    11. * @author
    12. * @Description
    13. * @create 2022-07-12 14:23
    14. */
    15. @Data
    16. @NoArgsConstructor
    17. @AllArgsConstructor
    18. public class MailInfo {
    19. /**
    20. * 邮件标题
    21. */
    22. private String subject;
    23. /**
    24. * 邮件正文
    25. */
    26. private String content;
    27. /**
    28. * 发件时间,默认当前时间
    29. */
    30. private Date sentDate;
    31. /**
    32. * 收件人
    33. */
    34. private List recipients;
    35. /**
    36. * 抄送人
    37. */
    38. private List ccs;
    39. /**
    40. * 密件抄送人
    41. */
    42. private List bccs;
    43. /**
    44. * 是否为邮件组
    45. */
    46. private Boolean isGroup;
    47. /**
    48. * 文件形式附件
    49. */
    50. @Setter(AccessLevel.NONE)
    51. private Mapbyte[]> attachments = new HashMap<>();
    52. public void addAttachment(String fileName, byte[] file){ attachments.put(fileName, file); }
    53. }

    service层实现

    1. import lombok.extern.slf4j.Slf4j;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.core.io.ByteArrayResource;
    4. import org.springframework.core.io.InputStreamSource;
    5. import org.springframework.mail.javamail.JavaMailSender;
    6. import org.springframework.mail.javamail.MimeMessageHelper;
    7. import org.springframework.stereotype.Service;
    8. import org.springframework.transaction.annotation.Transactional;
    9. import org.springframework.util.StringUtils;
    10. import org.springframework.web.bind.annotation.PostMapping;
    11. import org.springframework.web.bind.annotation.RequestMapping;
    12. import com.cicc.op.mail.api.MailService;
    13. import javax.activation.DataSource;
    14. import javax.mail.MessagingException;
    15. import javax.mail.internet.AddressException;
    16. import javax.mail.internet.InternetAddress;
    17. import javax.mail.internet.MimeMessage;
    18. import javax.mail.util.ByteArrayDataSource;
    19. import java.io.ByteArrayInputStream;
    20. import java.io.File;
    21. import java.nio.charset.StandardCharsets;
    22. import java.time.LocalDate;
    23. import java.time.LocalDateTime;
    24. import java.util.ArrayList;
    25. import java.util.List;
    26. /**
    27. * @author
    28. * @Description
    29. * @create 2022-07-26 15:39
    30. */
    31. @Slf4j
    32. @Service
    33. public class MailController {
    34. @Autowired
    35. private JavaMailSender javaMailSender;
    36. @Override
    37. public MailResponse sendMail(MailInfo mailInfo) {
    38. Long id = recordLog(mailInfo);
    39. log.info("----------开始邮件发送------------");
    40. checkValue(mailInfo, id);
    41. //html加附件邮件发送
    42. try {
    43. MimeMessage message = javaMailSender.createMimeMessage();
    44. MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
    45. if(mailInfo.getIsGroup() != null && mailInfo.getIsGroup()){
    46. List internetAddressList = new ArrayList<>();
    47. mailInfo.getRecipients().forEach(to ->{
    48. try {
    49. internetAddressList.add(new InternetAddress(to, true));
    50. } catch (AddressException e) {
    51. log.error("邮件发送失败,地址信息有误", e);
    52. throw new CommonMailException("邮件发送失败,地址信息有误", id, e);
    53. }
    54. });
    55. mimeMessageHelper.setTo(internetAddressList.toArray(new InternetAddress[internetAddressList.size()]));
    56. }else {
    57. mimeMessageHelper.setTo(mailInfo.getRecipients().toArray(new String[mailInfo.getRecipients().size()]));
    58. }
    59. mimeMessageHelper.setSubject(mailInfo.getSubject());
    60. mimeMessageHelper.setText(mailInfo.getContent(), true);
    61. if (mailInfo.getAttachments() != null && !mailInfo.getAttachments().isEmpty()) {
    62. for (String fileName : mailInfo.getAttachments().keySet()) {
    63. byte[] file = mailInfo.getAttachments().get(fileName);
    64. if(file != null){
    65. mimeMessageHelper.addAttachment(fileName, new ByteArrayResource(file));
    66. } else {
    67. throw new CommonMailException("不支持的附件类型", id);
    68. }
    69. }
    70. }
    71. if (mailInfo.getSentDate() != null) {
    72. mimeMessageHelper.setSentDate(mailInfo.getSentDate());
    73. }
    74. if (mailInfo.getCcs() != null && !mailInfo.getCcs().isEmpty()) {
    75. for (String cc : mailInfo.getCcs()) {
    76. mimeMessageHelper.setCc(cc);
    77. }
    78. }
    79. if (mailInfo.getBccs() != null && !mailInfo.getBccs().isEmpty()) {
    80. for (String bcc : mailInfo.getBccs()) {
    81. mimeMessageHelper.setBcc(bcc);
    82. }
    83. }
    84. javaMailSender.send(message);
    85. } catch (MessagingException e) {
    86. log.error("邮件发送失败", e);
    87. throw new CommonMailException("邮件发送失败", id, e);
    88. }
    89. return new MailResponse(true, "发送成功");
    90. }
    91. private void checkValue(MailInfo mailInfo, Long id) {
    92. if (!StringUtils.hasText(mailInfo.getSubject())) {
    93. throw new CommonMailException("邮件标题不能为空", id);
    94. } else if (!StringUtils.hasText(mailInfo.getContent())) {
    95. throw new CommonMailException("邮件内容不能为空", id);
    96. } else if (mailInfo.getRecipients().isEmpty()) {
    97. throw new CommonMailException("收件人不能为空", id);
    98. }
    99. }
    100. }

    3.深入了解

    首先是JavaMailSender,只要配置好spring.mail相关,就可以直接注入此Bean。

    1. package org.springframework.mail.javamail;
    2. import java.io.InputStream;
    3. import javax.mail.internet.MimeMessage;
    4. import org.springframework.mail.MailException;
    5. import org.springframework.mail.MailSender;
    6. public interface JavaMailSender extends MailSender {
    7. MimeMessage createMimeMessage();
    8. MimeMessage createMimeMessage(InputStream contentStream) throws MailException;
    9. void send(MimeMessage mimeMessage) throws MailException;
    10. void send(MimeMessage... mimeMessages) throws MailException;
    11. void send(MimeMessagePreparator mimeMessagePreparator) throws MailException;
    12. void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException;
    13. }

    根据接口来看,一共两个环节,创建MimeMessage对象(里面是邮件相关属性),然后send发送。

    具体的实现类JavaMailSenderImpl截取

    1. public synchronized Session getSession() {
    2. if (this.session == null) {
    3. this.session = Session.getInstance(this.javaMailProperties);
    4. }
    5. return this.session;
    6. }
    7. public MimeMessage createMimeMessage() {
    8. return new SmartMimeMessage(this.getSession(), this.getDefaultEncoding(), this.getDefaultFileTypeMap());
    9. }
    10. public MimeMessage createMimeMessage(InputStream contentStream) throws MailException {
    11. try {
    12. return new MimeMessage(this.getSession(), contentStream);
    13. } catch (Exception var3) {
    14. throw new MailParseException("Could not parse raw MIME content", var3);
    15. }
    16. }

    getSession方法可以看出,spring是对javax实现的邮件发送进行了一层封装,还是用的session,之前的properties配置也是在这里给到session,然后通过session创建MimeMessage。直接操作MimeMessage写入也可以,但是一个是不太方便,一个是不能发送附件,所以借助MimeMessageHelper来实现。

    1. public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart) throws MessagingException {
    2. this(mimeMessage, multipart, (String)null);
    3. }
    4. public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, @Nullable String encoding) throws MessagingException {
    5. this(mimeMessage, multipart ? 3 : 0, encoding);
    6. }
    7. public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode) throws MessagingException {
    8. this(mimeMessage, multipartMode, (String)null);
    9. }
    10. public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode, @Nullable String encoding) throws MessagingException {
    11. this.encodeFilenames = false;
    12. this.validateAddresses = false;
    13. this.mimeMessage = mimeMessage;
    14. this.createMimeMultiparts(mimeMessage, multipartMode);
    15. this.encoding = encoding != null ? encoding : this.getDefaultEncoding(mimeMessage);
    16. this.fileTypeMap = this.getDefaultFileTypeMap(mimeMessage);
    17. }

    使用MimeMessageHelper的时候注意三个点,

    1. 一个是multipart字段,如果要进行附件传输的话,这个要设置为true,还有就是如果配置文件中没有设置默认字符集,然后发送邮件出现乱码情况,可以在encoding设置编码。

    2. 还有一个是setText方法,如果需要发送的邮件正文不是简单的文本格式,而是使用了模板或者有图片表格等内容,需要在setText方法设置strict属性为true

    3. 邮件的附件如果需要http请求进行传输,但是又不方便使用Multipartfile类型,可以使用byte数组发送,如果是JSON需要注意序列化时编码问题;直接使用form-data也可以。

  • 相关阅读:
    git常用操作
    CleanMyMac X4.14.1最新版本下载
    Hadoop原理与技术——hdfs命令行基本操作
    计算机网络性能指标——时延,时延带宽积,RTT和利用率
    在CentOS操作系统上使用yum安装/使用/卸载Docker容器引擎
    unity webgl怎么获取当前页面网址
    【设计模式】使用建造者模式组装对象并加入自定义校验
    java--07 面向对象
    Hive的独立安装
    如果可以,带项目真的别只靠经验了
  • 原文地址:https://blog.csdn.net/yiyuzz/article/details/126399355