SMTP 协议邮件发送工具封装
文章目录
- 1. 前言
- 1.1 说明
- 1.2 建议
- 1.3 源码
- 2. 发件人邮箱开通smtp 服务
- 2.1 为什么开通smtp 服务
- 2.2 开启服务的步骤
- 2.3 普通邮箱开启服务图文
- 3. 工具类封装
- 3.1 邮件依赖管理
- 3.2 日志依赖管理
- 3.3 邮件工具类封装
- 4. 工具类测试及效果演示
- 5. 邮件发送API 测试及效果演示
内个, 祝各位七夕快乐 ^ _ ^
1. 前言
1.1 说明
此处为Java 版,封装了邮件发送工具,支持smtp 服务的邮箱,对发件人邮箱要求开通smtp 服务,否则不会发送邮件。
发件邮箱发件过多时,可能会被收件邮箱作为恶意发件人,之后再接收该发件人的邮件会作为垃圾邮件。
1.2 建议
生产环境配置多发件人使用轮询机制发送。
收件人标记发件人不是垃圾邮件。
1.3 源码
https://github.com/niaonao/email
2. 发件人邮箱开通smtp 服务
2.1 为什么开通smtp 服务
点击链接可以看下原理
简单的说,邮件可以通过smtp 协议在各个邮件服务器之间传输。
2.2 开启服务的步骤
- 开启smtp服务;
- 获取授权码/密码;
此授权码用于第三方邮件客户端登录时作为账号密码验证账号登录。
授权码可以重置。
/*** 邮件发送者账户* 邮件发送协议 smtp 账号密码/账号授权码*/private static final String emailSenderAccount = "2171128382@qq.com";private static final String emailSenderAuthCode = "ojaerigbrwgmdjed";
2.3 普通邮箱开启服务图文
(1)腾讯邮箱
图2-1.腾讯邮箱开启SMTP 服务图
图2-2.请求获取授权码图
图2-3.获取授权码图
(2)网易邮箱
图2-4.网易邮箱开启SMTP 服务图
图2-5.网易邮箱设置授权码图
3. 工具类封装
3.1 邮件依赖管理
<!-- 邮件: https://mvnrepository.com/artifact/com.sun.mail/javax.mail -->
<dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version>
</dependency>
3.2 日志依赖管理
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
3.3 邮件工具类封装
package pers.niaonao.email.util;import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import pers.niaonao.email.constant.SystemConstant;import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Properties;/*** @className: SMTPEmailUtil* @description: 邮件工具类** 推荐文章更好理解smtp原理: <<手工体验smtp和pop3协议>> https://www.cnblogs.com/ysocean/p/7653252.html** SMTP 协议发送邮件* (1) 获取会话 Session, 配置环境信息及用户授权验证* (2) 创建邮件 Message, 完善邮件对象消息`主题`附件`日期`发送者接收者抄送者密送者等信息* (3) 发送邮件 Transport, 提供网络传输对象发送邮件** 邮件交互会话 javax.mail.Session: Session 对象保存了邮件系统的配置信息及提供用户验证* 密码验证类 Authenticator, 是抽象类, 可以新建实现类去覆盖原方法, 也可以像下面静态代码块直接使用.* 编写邮件需要 MimeMessage 对象, 该对象是抽象类的 javax.mail.Message 的一个实现类;** @author: niaonao* @date: 2019/7/24**/
@Slf4j
public class SMTPEmailUtil {/*** 邮件发送者账户* 邮件发送协议 smtp 账号密码/账号授权码* 发件人* (邮件发送者从业务上看应支持系统配置, 此处就直接写好了数据; 你可以维护在配置文件,系统参数或数据库)*/private static final String emailSenderAccount = "2171128382@qq.com";private static final String emailSenderAuthCode = "ojaerigbrwgmdjed";private static final String emailSenderName = "哪都通物流有限公司";/*** 环境信息*/private static Properties props = new Properties();static {// 设置用户的认证方式, 邮箱账户, 授权码props.put(SystemConstant.MAIL_SMTP_HOST, getHost(emailSenderAccount));props.setProperty(SystemConstant.MAIL_SMTP_AUTH, String.valueOf(Boolean.TRUE));props.put(SystemConstant.MAIL_SMTP_USER, emailSenderAccount);props.put(SystemConstant.MAIL_SMTP_PASSWORD, emailSenderAuthCode);}/*** @description: 邮箱服务器域名通用转换, 格式支持多数邮件服务器, 部分不支持* @param email* @return: java.lang.String* @author: niaonao* @date: 2019/7/25*/private static String getHost(String email) {return new StringBuffer(SystemConstant.SMTP).append(SystemConstant.SYMBOL_POINT).append(email.split(SystemConstant.SYMBOL_AT)[1]).toString();}/*** @description: 获取共享的 Session* @return: javax.mail.Session* @author: niaonao* @date: 2019/7/25*/private static Session getSession() {return Session.getInstance(props, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(emailSenderAccount, emailSenderAuthCode);}});}/*** @description: 获取非共享的Session, 方法内部使用了 synchronized 关键字* lambda的使用条件是‘a functional interface has exactly one abstract method’* abstract class 使用lambda 的话要改造满足该条件* @return: javax.mail.Session* @author: niaonao* @date: 2019/7/25*/private static Session getDefaultInstance() {return Session.getDefaultInstance(props, new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(emailSenderAccount, emailSenderAuthCode);}});}/*** @description: 默认邮件发送者* 即配置邮箱和密码\授权码的账户* @param* @return: javax.mail.internet.InternetAddress* @author: niaonao* @date: 2019/7/25*/private static InternetAddress getDefaultSender() {try {return new InternetAddress(emailSenderAccount, emailSenderName, SystemConstant.CHARSET_UTF_8);} catch (UnsupportedEncodingException e) {log.error("[邮件工具]: 初始化异常{}", e.getMessage());throw new RuntimeException("获取默认邮件发送人错误!");}}/*** @description: 传输工具* @return: javax.mail.Transport* @author: niaonao* @date: 2019/7/25*/private static Transport getTransport() throws MessagingException {// 设置邮件协议 smtpTransport transport = getSession().getTransport(SystemConstant.SMTP);// 此处 QQ 邮箱, 通过账号和授权码链接transport.connect(getHost(emailSenderAccount), emailSenderAccount, emailSenderAuthCode);return transport;}/*** @description: 收件人转换 Address 对象* @param receiverEmailList* @return: javax.mail.internet.InternetAddress[]* @author: niaonao* @date: 2019/7/25*/private static InternetAddress[] tranAddressByList(List<String> receiverEmailList) {/*List<InternetAddress> internetAddressList = new ArrayList<>();receiverEmailList.forEach(item -> {InternetAddress internetAddress = new InternetAddress();internetAddress.setAddress(item);internetAddressList.add(internetAddress);});InternetAddress[] addresses = internetAddressList.stream().toArray(InternetAddress[]::new);*/if (CollectionUtils.isEmpty(receiverEmailList)) {return null;}InternetAddress[] address = new InternetAddress[receiverEmailList.size()];for (int index = 0; index < receiverEmailList.size(); index++) {InternetAddress internetAddress = new InternetAddress();internetAddress.setAddress(receiverEmailList.get(index));address[index] = internetAddress;}return address;}/*** @description: 发送普通文本* @param subject 邮件主题* @param text 邮件普通文本内容* @param emailReceiverAccount 接收者* @param sendDate 邮件发送时间* @return: void* @author: niaonao* @date: 2019/7/24*/public static void sendEmailByText(String subject, String text, String emailReceiverAccount, Date sendDate) {try {// 邮件对象MimeMessage msg = new MimeMessage(getSession());// 发送人msg.setFrom(getDefaultSender());// 发送方式,接收人msg.setRecipients(Message.RecipientType.TO, emailReceiverAccount);// 消息msg.setSubject(subject);msg.setText(text);if (null != sendDate) {msg.setSentDate(sendDate.before(new Date()) ? new Date() : sendDate);} else {// 邮件默认立即发送msg.setSentDate(new Date());}//发送邮件Transport.send(msg);log.info("[邮件发送]: 邮件已发送!");} catch (MessagingException e) {log.error("[邮件发送]: 普通文本邮件发送异常, {}", e.getMessage());}}/*** @description: 发送普通消息邮件(多收件人)* @param subject 邮件标题* @param text 邮件内容* @param receiverEmailList 接收人* @param sendDate 邮件发送时间* @return: void* @author: niaonao* @date: 2019/7/25*/public static void sendEmailByText(String subject, String text, List<String> receiverEmailList, Date sendDate) {InternetAddress[] addresses = tranAddressByList(receiverEmailList);try {// 邮件对象MimeMessage msg = new MimeMessage(getSession());msg.setFrom(getDefaultSender());msg.setRecipients(Message.RecipientType.TO, addresses);msg.setSubject(subject);msg.setText(text);if (null != sendDate) {msg.setSentDate(sendDate.before(new Date()) ? new Date() : sendDate);}// 开启传输,发送邮件Transport transport = getTransport();transport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));// 关闭链接transport.close();log.info("[邮件发送]: 邮件已发送!");} catch (MessagingException e) {log.error("[邮件发送]: 普通文本邮件发送异常, {}", e.getMessage());}}/*** @description: 发送普通文本消息(指定接收人,抄送人,密送人)* @param subject 邮件主题* @param text 邮件内容* @param receiverEmailList 邮件接收人* @param carbonCopyList 邮件抄送人* @param blindCarbonCopyList 邮件密送人* @param sendDate 邮件发送时间* @return: void* @author: niaonao* @date: 2019/7/25*/public static void sendEmailByText(String subject, String text, List<String> receiverEmailList, List<String> carbonCopyList, List<String> blindCarbonCopyList, Date sendDate) {InternetAddress[] receiverAddresses = tranAddressByList(receiverEmailList);InternetAddress[] carbonCopyAddresses = tranAddressByList(carbonCopyList);InternetAddress[] blindCarbonCopyAddresses = tranAddressByList(blindCarbonCopyList);try {// 邮件对象MimeMessage msg = new MimeMessage(getSession());msg.setFrom(getDefaultSender());// 发送方式,接收人msg.setRecipients(Message.RecipientType.TO, receiverAddresses);msg.setRecipients(Message.RecipientType.CC, carbonCopyAddresses);msg.setRecipients(Message.RecipientType.BCC, blindCarbonCopyAddresses);// 消息msg.setSubject(subject);msg.setText(text);if (null != sendDate) {msg.setSentDate(sendDate.before(new Date()) ? new Date() : sendDate);}// 开启传输,发送邮件Transport transport = getTransport();transport.sendMessage(msg, msg.getAllRecipients());// 关闭链接transport.close();log.info("[邮件发送]: 邮件已发送!");} catch (MessagingException e) {log.error("[邮件发送]: 普通文本邮件发送异常, {}", e.getMessage());}}/*** @description: 发送网页HTML 格式内容* @param subject 邮件标题* @param html 邮件内容, 语法HTML* @param receiverEmailList* @param carbonCopyList* @param blindCarbonCopyList* @param sendDate* @return: void* @author: niaonao* @date: 2019/7/25*/public static void sendEmailByHtml(String subject, String html, List<String> receiverEmailList, List<String> carbonCopyList, List<String> blindCarbonCopyList, Date sendDate) {InternetAddress[] receiverAddresses = tranAddressByList(receiverEmailList);InternetAddress[] carbonCopyAddresses = tranAddressByList(carbonCopyList);InternetAddress[] blindCarbonCopyaddresses = tranAddressByList(blindCarbonCopyList);try {MimeMessage mimeMessage = new MimeMessage(getSession());// 发送方式,接收人mimeMessage.setRecipients(Message.RecipientType.TO, receiverAddresses);mimeMessage.setRecipients(Message.RecipientType.CC, carbonCopyAddresses);mimeMessage.setRecipients(Message.RecipientType.BCC, blindCarbonCopyaddresses);mimeMessage.setFrom(getDefaultSender());mimeMessage.setSubject(subject);mimeMessage.setContent(html, SystemConstant.CHARSET_TYPE_HTML);if (null != sendDate) {mimeMessage.setSentDate(sendDate.before(new Date()) ? new Date() : sendDate);}Transport transport = getTransport();transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());transport.close();log.info("[邮件发送]: HTML 网页邮件已发送!");} catch (MessagingException e) {log.error("[邮件发送]: HTML 网页邮件发送异常, {}", e.getMessage());e.printStackTrace();}}/*** @description: 发送携带附件的邮件* @param subject 邮件标题* @param html 邮件内容, 语法HTML* @param receiverEmailList* @param carbonCopyList* @param blindCarbonCopyList* @param sendDate* @return: void* @author: niaonao* @date: 2019/7/25*/public static void sendEmailByEnclosure(String subject, String html, List<String> fileUrlList, List<String> receiverEmailList, List<String> carbonCopyList, List<String> blindCarbonCopyList, Date sendDate) {InternetAddress[] receiverAddresses = tranAddressByList(receiverEmailList);InternetAddress[] carbonCopyAddresses = tranAddressByList(carbonCopyList);InternetAddress[] blindCarbonCopyaddresses = tranAddressByList(blindCarbonCopyList);try {// html 节点MimeBodyPart contentPart = new MimeBodyPart();contentPart.setContent(html, SystemConstant.CHARSET_TYPE_HTML);// 组合节点MimeMultipart multipart = new MimeMultipart();for (String url:fileUrlList) {// 附件节点MimeBodyPart enclosure = new MimeBodyPart();// 读取文件// 将附件数据添加到"节点"DataHandler dataHandler = new DataHandler(new FileDataSource(url));enclosure.setDataHandler(dataHandler);enclosure.setFileName(MimeUtility.encodeText(dataHandler.getName()));multipart.addBodyPart(enclosure);}multipart.addBodyPart(contentPart);multipart.setSubType(SystemConstant.SUB_TYPE_MIXED);// 邮件对象MimeMessage mimeMessage = new MimeMessage(getSession());mimeMessage.setRecipients(Message.RecipientType.TO, receiverAddresses);mimeMessage.setRecipients(Message.RecipientType.CC, carbonCopyAddresses);mimeMessage.setRecipients(Message.RecipientType.BCC, blindCarbonCopyaddresses);mimeMessage.setFrom(getDefaultSender());mimeMessage.setSubject(subject);mimeMessage.setContent(multipart);if (null != sendDate) {mimeMessage.setSentDate(sendDate.before(new Date()) ? new Date() : sendDate);}Transport transport = getTransport();transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());transport.close();log.info("[邮件发送]: HTML 网页邮件已发送!");} catch (MessagingException e) {log.error("[邮件发送]: HTML 网页邮件发送异常, {}", e.getMessage());e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}}
}
4. 工具类测试及效果演示
在src/test/ 下新建测试类SMTPEmailUtilTest.java
测试发送附件的方法
@Test
public void sendEmailByEnclosure() {List<String> receiverList = Arrays.asList("22221111@163.com");List<String> carbonCopyList = Arrays.asList("22221111@qq.com");String subject = "宝儿姐喊你查阅附件";String content = "<img width=\"300\" height=\"400\" src=\"https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1564045091&di=57335f2e16c0a670b26c72aa9eb61b0c&src=http://imglf5.nosdn.127.net/img/UUZTMkZCa0pWZEE1Ri9yT1Rhc0hmMnUzdU1KellDZTNOOE1WMlE3N01XMCtrdm1HM0pSZVFBPT0.jpg?imageView&thumbnail=500x0&quality=96&stripmeta=0&type=jpg\"/>";// 项目内相对路径String smtpFileUrl = "src\\main\\resources\\static\\smtp.properties";// 本机D盘文件String LocalFileUrl = "D:\\download\\原始数据.csv";List<String> fileDataSourceList = Arrays.asList(smtpFileUrl, LocalFileUrl);SMTPEmailUtil.sendEmailByEnclosure(subject, content, fileDataSourceList, receiverList, carbonCopyList,null,null);
}
测试结果如图所示
图4-1.邮件发送工具类部分方法测试图
图4-2.测试发送邮件成功图
5. 邮件发送API 测试及效果演示
在src/main/java/pers/niaonao/email/web 下新建EmailController.java
测试邮件发送接口
@PostMapping("/sendEmailByEnclosure")
public String sendEmailByEnclosure(@RequestBody EmailRequestVo emailRequest){if (StringUtils.isEmpty(emailRequest.getSubject())){return "请维护邮件主题!";}if (CollectionUtils.isEmpty(emailRequest.getFileUrlList())) {return "请添加附件!";}if (CollectionUtils.isEmpty(emailRequest.getReceiverList())) {return "请维护收件人!";}SMTPEmailUtil.sendEmailByEnclosure(emailRequest.getSubject(), emailRequest.getHtml(), emailRequest.getFileUrlList(), emailRequest.getReceiverList(), emailRequest.getCarbonCopyList(), emailRequest.getBlindCarbonCopyList(), emailRequest.getSendDate());return "发送完成!";
}
使用postman 调用接口发送邮件成功图
图5-1.Postman 测试邮件发送API 图
收件如下
图5-2.Postman 调用接口发送邮件成功图 The End.
SMTP 协议邮件发送工具封装相关推荐
- 发送邮件(支持所有smtp协议邮件发送)
1.所需包: javax.mail.jar maven : <!-- https://mvnrepository.com/artifact/javax.mail/mail --> < ...
- 基于Java的SMTP协议邮件发送模拟系统
目录 1. 原理分析 2. 前端页面 3. 数据库设计 4. 后端数据处理 5. 参考文献 6. 注意事项 1. 原理分析 SMTP协议 SMTP(Simple Mail Transfer Proto ...
- smtp协议——邮件发送
根据自己使用的邮件服务器,完成smtp协议的服务开启 给特定邮箱发送图文并茂的邮件,邮件正文包含的表格如下所示,显示的图片自己确定. 给特定邮箱发送邮件,邮件附件为"实验报告7 smtp协议 ...
- Java 基于mail.jar 和 activation.jar 封装的邮件发送工具类
准备工作 发送邮件需要获得协议和支持! 开启服务 POP3/SMTP 服务 如何开启 POP3/SMTP 服务:https://blog.csdn.net/weixin_44953227/articl ...
- SMTP协议及POP3协议-邮件发送和接收原理(转)
本文转自https://blog.csdn.net/qq_15646957/article/details/52544099 感谢作者 一. 邮件开发涉及到的一些基本概念 1.1.邮件服务器和电子邮箱 ...
- 封装一个邮件发送工具类,一个字,巴适
系列文章目录 文章目录 系列文章目录 前言 一. 介绍 二.二话不说开始干 1.引入库 2. 邮件发送实体(Mail) 3. 邮件发送类型枚举(MailType ) 4.邮件发送抽象类(Abstrac ...
- JAVA 邮件发送工具类
1.封装邮件接收地址MODEL和邮件信息MODEL package com.sicdt.jnzxgzc.common.mail.model;import java.io.Serializable; / ...
- [Java工具] 邮件发送工具
注册邮箱 去163邮箱(或其他邮箱)注册一个邮箱,并开启SMTP授权码. 程序 需要注意的是,由于阿里云服务器不让使用默认的25端口,所以会出现Windows下测试发送邮件成功,Linux服务器下发送 ...
- kali 邮箱攻击_kali下邮件发送工具swaks入坑
Swaks是一个功能强大,灵活,可编写脚本,面向事务的SMTP测试工具, 目前Swaks托管在私有svn存储库中.官方项目页面是 牛刀小试 kali下默认自带,无需安装. 01 测试邮箱的连通性swa ...
最新文章
- 函数计算新功能-----支持C#函数
- Android Bitmap 研究与思考(上篇)
- MVC + AJAX请求失败的问题
- 深拷贝与浅拷贝Object.assign()
- Upload LABS Pass-5
- 打java包需要对应服务器么_java打war包、部署服务器
- php接收表单post数据由于数据字段太多导致丢失的案例
- Win10系统启动Markdown Pad2 报‘Awesomium.Windows.Controls.WebControl’
- SPH(光滑粒子流体动力学)流体模拟实现五:PCISPH
- 2022年最新BIM计费标准,涉及14省市
- UI设计工作流程步骤详解,让你快速了解UI设计!
- 【面经】2018金山WPS前端笔试题 面试题
- hustoj安装16种判题语言
- 2022-11-09:给定怪兽的血量为hp 第i回合如果用刀砍,怪兽在这回合会直接掉血,没有后续效果 第i回合如果用毒,怪兽在这回合不会掉血, 但是之后每回合都会掉血,并且所有中毒的后续效果会叠加 给
- mezzanine-一个功能强大且易于扩展性的Django框架构建的内容管理平台
- 110115-07-6,Ac-LLM-CHOCalpain 抑制剂
- Python数据分析 2.Matplotlib绘图—常用统计图
- 转换cdm为mysql_详解PowerDesigner之CDM、PDM、SQL之间转换
- 【matlab 求极限】limit函数求极限
- 怎么清理IE浏览器缓存