0. 引言
邮件发送是我们日常开发中比较常见的功能,常用于预警信息提醒、统计数据定期发送等需求。一般该方法会由前人封装好,实际开发时只需要调用即可,但具体怎么实现的,如何从零实现邮件发送,这是我们要掌握的。
上一次我们讲解了基于javax.mail实现邮件发送,今天我们接着讲解基于org.apache.commons.mail
的实现方式
1. 环境准备
1.1 开发环境
以下演示均基于各组件当前最新的稳定版本实现,jdk基于1.8版本
1.2 开启邮箱协议与授权
其次我们需要了解的是,程序要发送邮件,是需要一个邮箱账号的, 并且其账号需要开启SMTP邮件协议以及邮件授权码,并不是密码。
以下我们以QQ邮箱为例,示范其开启过程,其他邮箱大同小异。
1、登陆邮箱,点击设置
,进入账户
,下拉页面
2、找到POP3/IMAP/SMTP
服务设置。这里我们可以开启POP3/SMTP
或者IMAP/SMTP
服务,两者的区别
3、点击开启
后,会要求你发送短信验证
4、发送后,点击我已发送
,然后会给你一个授权码,将该码保存下来,这就是我们需要的授权码。
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 org.apache.commons.mail实现
2.1.1 思路
1、commons
包中提供了Email
抽象类,该类下实现了HtmlEmail
,ImageHtmlEmail
,MultiPartEmail
,SimpleEmail
其继承关系如图所示:
-
SimpleEmail
用于简单邮件发送 -
MultiPartEmail
用于附件邮件发送 -
HtmlEmail
用于HTML正文,附件邮件发送 -
ImageHtmlEmail
用于HTML图片正文,附件邮件发送
2、这里因为我们要实现HTML正文以及附件发送,因此我们创建HtmlEmail
对象,且设置各种参数属性。
3、调用email.send()
方法发送邮件
2.1.2 实操
1、引入依赖
<!-- 邮件依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.5</version>
</dependency>
<!-- @ConfigurationProperties依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2、我们将配置项提取到配置文件application.yml
中
email:
smtp:
host: smtp.qq.com
email: xxx@qq.com
name: 邮件提醒系统
password: xxx
port: 25
3、创建配置类,关联配置项
@Data
@Component
@ConfigurationProperties(value = "email.smtp")
public class SmtpProperties {
/**
* smtp服务地址
*/
private String host;
/**
* 发件人邮箱
*/
private String email;
/**
* 发件人昵称
*/
private String name;
/**
* 邮箱授权码
*/
private String password;
/**
* 邮箱服务端口
*/
private Integer port=25;
}
4、创建工具类,实现发送功能
/**
* @author benjamin_5
* @Description
* @date 2022/10/3
*/
@AllArgsConstructor
@Component
public class EmailCommonsUtil {
private static final Log logger = LogFactory.getLog(EmailCommonsUtil.class);
private final SmtpProperties emailProperties;
/**
* 邮件发送
* @param subject 邮件主题
* @param content 邮件内容
* @param contentIsHtml 内容是否为html格式
* @param toMail 收件人邮箱
* @param ccMail 抄送人邮箱
* @param bccMail 秘密抄送人邮箱
* @param fileList 附件
*/
public void sendEmail(String subject, String content,boolean contentIsHtml,
String[] toMail, String[] ccMail, String[] bccMail, File[] fileList)
throws EmailException, UnsupportedEncodingException {
HtmlEmail email = new HtmlEmail();
// smtp服务地址
email.setHostName(emailProperties.getHost());
// 邮件验证
email.setAuthentication(emailProperties.getEmail(),emailProperties.getPassword());
// smtp端口
email.setSmtpPort(emailProperties.getPort());
email.setCharset("utf-8");
// 发件人邮箱地址及昵称
email.setFrom(emailProperties.getEmail(),emailProperties.getName());
// 收件人邮箱
email.addTo(toMail);
if(!ObjectUtils.isEmpty(ccMail)){
// 抄送人邮箱
email.addCc(ccMail);
}
if(!ObjectUtils.isEmpty(bccMail)){
// 秘密抄送人邮箱
email.addBcc(bccMail);
}
// 主题
email.setSubject(subject);
if(contentIsHtml){
email.setHtmlMsg(content);
}else{
email.setMsg(content);
}
// 设置附件
if(!ObjectUtils.isEmpty(fileList)){
for (File file : fileList) {
EmailAttachment emailAttachment = new EmailAttachment();
emailAttachment.setName(MimeUtility.encodeText(file.getName()));
emailAttachment.setPath(file.getPath());
email.attach(emailAttachment);
}
}
// 发送邮件
email.send();
logger.info("邮件发送完成");
}
}
5、调用测试,我们创建一个接口来模拟测试
@RestController
@AllArgsConstructor
public class EmailController {
private final EmailCommonsUtil emailCommonsUtil;
@GetMapping("sendCommonEmail")
public void sendCommonEmail(){
String subject = "这是一个测试标题";
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>";
String[] toMail = new String[]{"wuhanxue5@sina.com"};
String[] ccMail = new String[]{"wuhanxue5@163.com"};
File file = new File("/Users/wuhanxue/Downloads/canal mysql到es数据同步.png");
try {
emailCommonsUtil.sendEmail(subject,html,true,toMail,ccMail,null,new File[]{file});
} catch (EmailException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
4、浏览器访问该接口http://localhost:8080/sendCommonEmail
邮件接收成功,附件和HTML正文也显示正常
查看抄送邮箱,接收正常
2.1.4 常见报错
1、535 Login Fail. Please enter your authorization code to login
解决:
邮箱验证设置的账号密码错误,使用如下代码设置,注意参数值正确性
email.setAuthentication(发件人邮箱地址,邮箱授权码);
2、MessagingException: Got bad greeting from SMTP host: smtp.qq.com, port: 465, response: [EOF]
解决:
commons.mail发送邮件时,QQ邮箱使用默认端口25即可
源码地址
以上演示的源码可以在如下地址中下载
git源码地址
关注专栏,了解后续内容
- 基于spring-boot-starter-mail实现邮件发送