Java-Mail 实现电子邮件发送
前言
我们日常维护系统的过程当中,会遇到一些系统上的异常需要管理员或者软件工程师去手动修复的情况,但是一般来说我们设计的系统是一个不会说话的孩子疼他是不会向我们表达的。一般这种情况我们就需要有一个系统的监听系统,可以想象成一个月嫂来负责观察系统有什么要的问题,去把这些问题记录下来,有急需要解决的问题我们就需要去通知孩子的父母及时的去满足孩子的一些要求。当我们需要去通知系统管理员的时候,如果使用 MQ 或者是 IM 这些工具的话就会显得太大动干戈了,而且有一些软件是没有配套 app 的,为此特意开发一个维护的 app 是不必要的,又承受不了这么一个频繁调度但是又没有直接收益的一个功能去调短信的 api,其实这个时候就可以去发送邮件来通知管理员或者软件工程师,并且可以记录下实际用户以及复现方式等等信息。
同时邮件功能也是非常有必要去掌握的,在小网站的创业初期可以通过邮件绑定用户的方式来实现用户的账号安全设置,这样做几乎是零成本的。今天就想跟大家介绍一下一个开源而且好用的一个 Java 语言的 Email 工具包,使用的是 SMTP 协议,实例中使用的是网易163邮箱做演示,正常使用只要支持 SMTP 的邮箱网站都是可以的,像 QQ,outlook等等。
打开 SMTP 协议开关
如下图指示,我们就可以打开 SMTP 协议支持,一般会需要一个安全认证。一般的邮箱网站在打开功能的时候都会提供一个授权码,这个授权码普遍用作来代替密码访问邮箱网站,再通过邮箱网站代理发送邮件到收件人处,这个授权码我们需要记录下来的,在程序中我们会使用到。如果没有这个授权码说明这个网站就是需要使用密码来验证,我们就使用密码验证就行了。
pom 引入 jar 包
演示的时候就只是发送一个邮件就可以了,所以就只需要引入工具包本身就可以,它是跟 spring boot 解耦的这也是我非常喜欢它的原因,它可以独立运行在一个相对独立的程序里面,不用说做一个小功能也需要引入一个 spring boot 来使用,非常方便。大家可以通过百度搜索 mvn repository 来搜索这个工具包就可以获取到最新的一个版本。
<dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency>
实体类
先写一个实体类对邮件进行封装,里面封装这封邮件的大部分信息,收件人账号,收件人姓名,主题,内容等信息。
public class EmailPojo { // 收件人账号 private String toEmail; // 收件人姓名 private String toName; // 主题 private String object; // 内容 private String context; ... 省略 Geter、Seter方法 }
发送邮件的业务逻辑
接下来需要创建会话实现跟邮箱服务器的通信,还有设置发件人的信息,这是一个大量重复的工作,我们大可以把它封装到一个业务处理类中处理这块业务,不必每次发送邮件都手写一遍。
public class EmailService { // 发件人的 邮箱 和 密码(替换为自己的邮箱和密码) private static String emailAccount = "这里填自己的账号"; private static String emailPassword = "这里填自己的密码(授权码)"; // SMTP 服务器地址 // 网易 163 SMTP服务器: smtp.163.com private static String myEmailSMTPHost = "smtp.163.com"; // 发送一个简单的邮件 public void sendSimpleEmail(EmailPojo email) throws Exception { // 1. 创建参数配置 java.util.Properties props = new java.util.Properties(); props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议(JavaMail规范要求) props.setProperty("mail.smtp.host", emailSMTPHost); // 发件人的邮箱的 SMTP 服务器地址 props.setProperty("mail.smtp.auth", "true"); // 需要请求认证 // 2. 根据配置创建会话对象, 用于和邮件服务器交互 javax.mail.Session session = javax.mail.Session.getInstance(props); session.setDebug(true); // 设置为debug模式, 可以查看详细的发送 log // 3. 创建一封邮件 javax.mail.internet.MimeMessage message = new javax.mail.internet.MimeMessage(session); message.setFrom(new InternetAddress(emailAccount, "这里填发件人姓名", "UTF-8")); // From: 发件人 message.setRecipient(MimeMessage.RecipientType.TO, new javax.mail.internet.InternetAddress(email.getToEmail(), email.getToName(), "UTF-8")); // To: 收件人(可以增加多个收件人、抄送、密送) message.setSubject(email.getObject(), "UTF-8"); // Subject: 邮件主题 message.setContent(email.getContext(), "text/html;charset=UTF-8"); // Content: 邮件正文(可以使用html标签) message.setSentDate(new java.util.Date()); // 设置发件时间 message.saveChanges(); // 保存设置 // 4. 根据 Session 获取邮件传输对象 javax.mail.Transport transport = session.getTransport(); transport.connect(emailAccount, emailPassword); // 配置发件人用户名密码 transport.sendMessage(message, message.getAllRecipients()); // 发送邮件, 发到所有的收件地址 // saveEmail(message); // 保存邮件, 暂时注释,有需要可以重写 saveEamil 方法把邮件信息优雅的存放起来留档 transport.close(); // 14. 关闭连接, 由于是演示所以比较随意, 生产环境最好使用 try{} finally {} 的方式保证 transport 的安全释放, 虽然它没有显式的异常抛出 } // 保存邮件 public void saveEmail(javax.mail.Message message) { // 8. 将该邮件保存到本地 java.io.OutputStream out = null; try { out = new java.io.FileOutputStream("myEmail.eml"); message.writeTo(out); } finally { try { if(out != null) out.close(); } catch (java.io.IOException e) { e.printStackTrace(); } } } }
调用
public class EmailApplication { public static void main(String[] args) { EmailPojo emailPojo = new EmailPojo(); emailPojo.setToEmail("这里填收件人邮箱"); emailPojo.setToName("帅锅"); emailPojo.setObject("你真帅"); emailPojo.setContext("真的很帅"); EmailService email = new EmailService(); try { email.sendSimpleEmail(emailPojo); } catch (Exception e) { e.printStackTrace(); } } }
log
日志信息一切都正常,也成功的收取到了这封邮件
DEBUG: setDebug: JavaMail version 1.4.7 DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "smtp.163.com", port 25, isSSL false 220 163.com Anti-spam GT for Coremail System (163com[20141201]) DEBUG SMTP: connected to host "smtp.163.com", port: 25 EHLO 192.168.0.103 250-mail 250-PIPELINING 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrXmT4AUCa0xDrUUUUj 250-STARTTLS 250 8BITMIME DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN" DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN" DEBUG SMTP: Found extension "coremail", arg "1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrXmT4AUCa0xDrUUUUj" DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM DEBUG SMTP: AUTH LOGIN command trace suppressed DEBUG SMTP: AUTH LOGIN succeeded DEBUG SMTP: use8bit false MAIL FROM:<######_xiaohu@163.com> 250 Mail OK RCPT TO:<########@qq.com> 250 Mail OK DEBUG SMTP: Verified Addresses DEBUG SMTP: =?UTF-8?B?6IOh6YeR5by6?= <########@qq.com> DATA 354 End data with <CR><LF>.<CR><LF> Date: Tue, 18 May 2021 22:33:30 +0800 (CST) From: =?UTF-8?B?6IOh6YeR5by6?= <#######_xiaohu@163.com> To: =?UTF-8?B?6IOh6YeR5by6?= <#######@qq.com> Message-ID: <20132171.0.1621348410147.JavaMail.xiaohu@DESKTOP-1TNHVJM> Subject: =?UTF-8?B?5L2g55yf5biF?= MIME-Version: 1.0 Content-Type: text/html;charset=UTF-8 Content-Transfer-Encoding: base64 55yf55qE5b6I5biF . 250 Mail OK queued as smtp11,D8CowACHhaI70KNgaKzkBA--.37721S2 1621348414 QUIT 221 Bye
总结
整个工具包使用起来还是挺简单挺好上手的,到时候如果嫌弃日志太多了,可以设置屏蔽掉 debug 或者屏蔽这个类包的日志信息。最重要的是它可以跟 spring boot 分隔开来,在没有 spring boot 的场景下可以整合进去,没有 spring boot 的场景它也可以独立运行。非常感谢大家耐心的阅读和批评指教,有兴趣的话可以关注我的微信公众号,我会持续在这上面输出技术类型的文章,祝大家生活愉快,身体健康。
![](https://img2020.cnblogs.com/blog/1184562/202105/1184562-20210519004316554-1870600476.png)
有兴趣的话可以扫码或搜索 "边缘技术" 关注我的微信公众号,非常感谢大家。