首页 > 编程语言 >springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】

时间:2023-02-06 22:05:38浏览次数:99  
标签:java springboot smtp 发送 源码 new mail 邮件 String


0. 引言

邮件发送是我们日常开发中比较常见的功能,常用于预警信息提醒、统计数据定期发送等需求。一般该方法会由前人封装好,实际开发时只需要调用即可,但具体怎么实现的,如何从零实现邮件发送,这是我们要掌握的。

所以今天我们就整理一下java实现邮件发送的三种方式,供大家参考。

  • 基于javax.mail实现
  • 基于org.apache.commons.mail实现
  • 基于spring-boot-starter-mail实现

1. 环境准备

1.1 开发环境

以下演示均基于各组件当前最新的稳定版本实现,jdk基于1.8版本

commons-email 1.5
javax.mail 1.4.7
spring-boot-starter-mail 跟随springboot版本,文中演示的是2.3.7.RELEASE

1.2 开启邮箱协议与授权

其次我们需要了解的是,程序要发送邮件,是需要一个邮箱账号的, 并且其账号需要开启SMTP邮件协议以及邮件授权码,并不是密码。

以下我们以QQ邮箱为例,示范其开启过程,其他邮箱大同小异。

1、登陆邮箱,点击​​设置​​​,进入​​账户​​,下拉页面

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_开发语言

2、找到​​POP3/IMAP/SMTP​​​服务设置。这里我们可以开启​​POP3/SMTP​​​或者​​IMAP/SMTP​​服务,两者的区别

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_spring boot_02

3、点击​​开启​​后,会要求你发送短信验证

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_spring boot_03

4、发送后,点击​​我已发送​​,然后会给你一个授权码,将该码保存下来,这就是我们需要的授权码。

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_邮件发送_04

5、其次我们需要获取到邮件服务器的smtp地址,比如我们这里用的是qq邮箱,其地址就是​​smtp.qq.com​​。对应类型邮箱的smtp地址直接百度即可。

1.3 常见的邮箱服务及端口

服务商

smtp服务地址

smtp服务端口

pop3服务地址

pop3服务端口

新浪 sina.com

smtp.sina.com.cn

25

pop3.sina.com.cn

110

搜狐 sohu.com

smtp.sohu.com

25

pop3.sohu.com

110

163 163.com

smtp.163.com

25

pop3.163.com

110

QQ qq.com

smtp.qq.com

25

pop3.qq.com

110

foxmail foxmail.com

smtp.foxmail.com

25

pop3.foxmail.com

110

QQ企业邮箱 exmail.qq.com

smtp.exmail.qq.com

995

pop3.exmail.qq.com

587/465

2. 实现

2.1 javax.mail实现

2.1.1 思路

利用javax.mail实现邮件发送功能主要分成一下几步:

1、创建配置项变量​​Properties​​对象,用于声明smtp相关配置

2、重写一个​​Authenticator​​,用于声明发件人邮箱地址和授权码

3、基于上述两步创建的对象,创建一个​​Session​

4、利用session创建一个​​MimeMessage​​​对象,再利用MimeMessage创建一个​​MimeMessageHelper​​对象,该对象用于设置收件人、发件人、抄送、秘密抄送、主题、内容、附件、发送时间等属性

5、利用​​Transport.send​​方法发送邮件

在清楚了实现流程后,我们直接上代码演示

2.1.2 实操

1、引入依赖

<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>

2、创建工具类,实现发送功能

/**
* @author benjamin_5
* @Description
* @date 2022/10/3
*/
public class EmailJavaxUtil {

private static final Logger logger = LoggerFactory.getLogger(EmailJavaxUtil.class);

// 发件人smtp邮箱服务地址
private static final String senderSmtpHost = "smtp.qq.com";
// 发件人邮箱地址
private static final String senderEmail = "[email protected]";
// smtp邮箱授权码
private static final String senderPassword = "xxx";
// 端口
private static final String senderSmtpPort = "465";

private static void sendEmail(String subject, String content,boolean contentIsHtml, String fromMailPersonalName,
String toMail, String ccMail, String bccMail, List<String> fileNames)
throws GeneralSecurityException, UnsupportedEncodingException, MessagingException {

// 设置参数
Properties properties = System.getProperties();
// smtp服务地址
properties.put("mail.smtp.host",senderSmtpHost);
// smtp服务端口
properties.put("mail.smtp.port", senderSmtpPort);
// 开启验证
properties.put("mail.smtp.auth","true");
// 开启TLS加密
properties.put("mail.smtp.starttls.enable","true");
// 是否启用socketFactory,默认为true
properties.put("mail.smtp.socketFactory.fallback", "true");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
// 建立会话,利用内部类将邮箱授权给jvm
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(senderEmail, senderPassword);
}
});
// 设置为true可以在控制台打印发送过程,生产环境关闭
session.setDebug(true);
// 创建邮件对象
MimeMessage message = new MimeMessage(session);
// 通过MimeMessageHelper设置正文和附件,否则会导致两者显示不全
MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");
//设置收件人,to为收件人,cc为抄送,bcc为密送
if (StringUtils.isEmpty(toMail)) {
logger.error("邮件收件人为空");
return;
}
//设置发件人
helper.setFrom(new InternetAddress(senderEmail, fromMailPersonalName));
helper.setTo(InternetAddress.parse(toMail, false));
if (!StringUtils.isEmpty(ccMail)) {
helper.setCc(InternetAddress.parse(ccMail, false));
}
if (!StringUtils.isEmpty(bccMail)) {
helper.setBcc(InternetAddress.parse(bccMail, false));
}
// 设置邮件主题
helper.setSubject(subject);
//设置邮件正文内容
helper.setText(content,contentIsHtml);
//设置发送的日期
helper.setSentDate(new Date());
// 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
if(!CollectionUtils.isEmpty(fileNames)){
for (String fileName : fileNames) {
FileDataSource fileDataSource = new FileDataSource(fileName);
helper.addAttachment(fileDataSource.getName(),fileDataSource);
}
}
//调用Transport的send方法去发送邮件
Transport.send(message);

}

}

3、调用测试

public static void main(String[] args) throws MessagingException, GeneralSecurityException, UnsupportedEncodingException {
String fileName = "/Library/project/study/java/mail_send_demo/src/main/resources/供应商接口参数.xlsx";
sendEmail("测试邮件1","这是一封测试邮件",false,"55555","[email protected]",null,null, Collections.singletonList(fileName));
}

4、可以看到邮件正常接收到了

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_spring boot_05

2.1.3 补充内容

1、需要注意的是如果采用如下的方式设置附件和正文的话,会导致两者有一个不显示。如下,附件设置在后就会覆盖设置的正文内容,正文内容在后就会覆盖附件内容。

//设置邮件正文内容
message.setText(content);
if(!CollectionUtils.isEmpty(fileNames)){
// 附件上传组件
Multipart multipart =new MimeMultipart("mixed");
for (String fileName : fileNames) {
MimeBodyPart bodyPart = new MimeBodyPart();
FileDataSource fileDataSource = new FileDataSource(fileName);
bodyPart.setDataHandler(new DataHandler(fileDataSource));
// 解决附件中文名乱码
bodyPart.setFileName(MimeUtility.encodeText(fileDataSource.getName(), "utf-8", null));
// 添加附件
multipart.addBodyPart(bodyPart);
}
// 附件的设置语句必须放在设置正文内容之后,否则会导致附件设置为空
message.setContent(multipart);
}

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_html_06

解决的办法就是使用​​MimeMessageHelper​​类来实现,如上述演示所示。

2、附件上传有多种方式,除了上述演示的使用​​FileDataSource​​形式添加附件外,还有文件、输入流的方式来添加,可以结合需求多样开发。

  • ​addAttachment(String attachmentFilename, DataSource dataSource)​
  • ​addAttachment(String attachmentFilename, File file)​
  • ​addAttachment(String attachmentFilename, InputStreamSource inputStreamSource)​
  • ​addAttachment(String attachmentFilename, InputStreamSource inputStreamSource, String contentType)​

同时看源码会发现,除了​​addAttachment​​​方法外,​​addInline​​方法也能添加附件。生产开发复制粘贴上述的工具类完全足够,但是要想进一步理解,深入掌握组件,更需要大家去阅读源码,了解api方法的多样性。

2.1.3 邮件正文为html格式

有时我们需要自定义我们邮件正文的样式,也就需要发送html格式的邮件正文。那么这又怎么实现呢?

其实眼尖的同学会发现,我上述提供的工具类中已经提供了一个​​contentIsHtml​​参数,用来标识内容是否为html

其实现利用了​​MimeMessageHelper​​​提供的setText方法的第二参数,通过调用​​setHtmlTextToMimePart​​​或​​setPlainTextToMimePart​​来实现html正文的解析

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_java_07

话不多说,我们来测试一下

public static void main(String[] args) throws MessagingException, GeneralSecurityException, UnsupportedEncodingException {
String fileName = "/Library/project/study/java/mail_send_demo/src/main/resources/供应商接口参数.xlsx";
String html = "<h1>统计数据如下所示:</h1>" +
"<table border=\"1\">\n" +
" <tr>\n" +
" <th>月度销售额</th>\n" +
" <th>年度销售额</th>\n" +
" </tr>\n" +
" <tr>\n" +
" <td>10000</td>\n" +
" <td>2000000</td>\n" +
" </tr>\n" +
"</table>";
sendEmail("统计数据",html,true,"55555","[email protected]",null,null, Collections.singletonList(fileName));
}

邮件正常接收并且html样式显示正常

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】_开发语言_08

源码地址

以上演示的源码可以在如下地址中下载

​git源码地址​

关注专栏,了解后续内容

  • 基于org.apache.commons.mail实现邮件发送
  • 基于spring-boot-starter-mail实现邮件发送


标签:java,springboot,smtp,发送,源码,new,mail,邮件,String
From: https://blog.51cto.com/u_15952602/6037768

相关文章

  • springboot:java实现邮件及附件发送、HTML正文的三种方式(三)【附带源码】
    0.引言邮件发送是我们日常开发中比较常见的功能,常用于预警信息提醒、统计数据定期发送等需求。一般该方法会由前人封装好,实际开发时只需要调用即可,但具体怎么实现的,如何从......
  • javaScript - 预解析
    代码实例:console.log(data1)//undefinedvardata1=12;fn1();//executefunctionfn1functionfn1(){console.log("executefunctionfn1")}fn2();//fn2is......
  • javaScript - 函数,函数的定义与函数的特性,函数的内置对象
    1.函数的定义//方式1无参无返回值函数functionclose(){}//方式2有参有返回值函数functionset(id,name){returnid+name;}//方式3匿名函数varcallback=......
  • Java数组
    通常,数组是具有连续内存位置的类似类型的元素的集合。Java数组是一个包含类似数据类型的元素的对象。它是一个数据结构,我们存储类似的元素。只能在java数组中存储固定的......
  • Error:java: Compilation failed: internal java compiler error 解决办法
    错误现象使用Idea导入新项目或升级idea或新建项目时会出现以下异常信息:Error:java:Compilationfailed:internaljavacompilererror错误原因导致这个错误的原因主要......
  • Java包装类
    java中的包装类提供了将原始数据类型转换为对象,以及将对象转换为原始数据类型的机制。自J2SE5.0以来,自动装箱和取消装箱功能将原始对象和对象自动转换为原始数据类型。......
  • Java按值调用和引用调用
    在java中只有通过值调用,而不是通过引用调用。如果要调用一个传递值的方法,则称为按值调用。在被调用方法中完成的更改,在调用方法的外部不受影响。在java中通过值调用的......
  • Java Object类
    默认情况下,Object类是java中所有类的父类。换句话说,它是java的顶级类。如果想引用你不知道的类型的对象,使用Object类是没有错的。请注意,父类引用变量可以引用子类对象,称......
  • javaScript - 数组的创建方式,数组的属性,数组的常用方法,数组的全部方法
    1.数组的创建方式//方式1vararray=newArray();array[0]="levi"//方式2vararray=newArray("png","jpg");//方式3vararray=["levi","mikasa"] 2.数组的属......
  • Java开发手册 黄山版(2022) 下载
    链接:https://wwxz.lanzouw.com/iPx1S0ms0cdg密码:9v7d......