使用 JavaMail 发送邮件
虽然现在的交流办公软件层出不穷,但是邮件的一些优势是即时通信软件无法取代的。邮件可以作为一个很好的凭证并且可以存档。在传输文件和大型复杂的场景下,大多数人还是会选择邮件。所以,在我们开发网站的时候肯定也要应用邮件服务。
JavaMail是Sun发布的用来提供给开发者处理电子邮件相关的编程接口。其中用于处理电子邮件的核心类是: Session, Message, Address, Authenticator, Transport, Store, Folder等。Session定义了一个基本的邮件会话,它需要从 Properties 中读取类似于邮件服务器,用户名和密码等信息。另外,很好的实现了 JavaMail API 的框架有 James、Spring Mail。
一、邮件协议
在使用 Java 实现发送邮件之前,我们应该先弄清有关邮件的各种协议和每种协议包含的属性,一般的情况下我们使用SMTP协议发送邮件,POP3协议接收邮件:
协议 | 作用 | 端口 |
---|---|---|
SMTP | 用于将邮件发送到服务器的协议 | 25 |
SMTPS | 使用SSL协议加密的SMTP协议 | 465 |
POP3 | 将服务器上的邮件下载到客户端上并可以删除服务器上的邮件 | 110 |
POP3S | 使用SSL协议加密的POP3协议 | 995 |
IMAP | 从服务器读取邮件的协议,不能删除服务器上的邮件 | 143 |
IMAPS | 使用SSL协议加密的IMAP协议 | 993 |
二、邮件的发送与接收
邮件的服务流程可由下图所示:
发送邮件时,发件人会发消息给邮件服务器中的 SMTP service 。这时有两种情况:如果邮件的收信人也是处于同一个域,比如,从 QQ 的邮箱发送给 QQ 的邮箱,SMTP service 只需要保存在自己服务器即可。如果邮件收信人是不同的域,比如,QQ 邮箱发送给 163 邮箱,QQ 的 SMTP service 需要找到 163 的 SMTP service 并使用 SMTP 协议发送。然后,163 服务器中的 SMTP service 收到邮件后保存在存储空间中,此时收信人可使用 POP3 service 下载邮件。
三、SMTP中的常用头属性
在搭建后端或者一些服务的时候,会以发送邮件为主。所以本文主要介绍关于使用 SMTP 协议发送邮件的实现。有关于 SMTP 协议更多的具体内容,可以参见官方标准文件 RFC 5321
一封邮件主要由邮件头和邮件体组成.邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域。有点类似于我们经常使用的HTTP头。
域 | 含义 | 示例 |
---|---|---|
Received | 邮件的路由信息,由链路中的路由添加 | - |
From | 发件人地址 | From: xxx <xxx@xx.com> |
To | 收件人地址 | To: xxx@xx.com |
CC | 抄送地址 | CC: xxx@xx.com |
BCC | 密送地址 | BCC: xxx@xx.com |
Return-Path | 邮件无法发送的回退地址 | Return-Path: <xxx@xx.com> |
Date | 发件的日期和时间 | Date: Mon, 11 Nov 2020 11:11:11 +0800 (CST) |
MIME-Version | MIME版本 | MIME-Version: 1.0 |
Boundary | 标识分割内容与信息的字符串 | Boundary: "xxxxxxxxxxx" |
Subject | 邮件主题,用 Base64 编码 | Subject: TWljcm9uIFN0dWRpbw== |
Content-Type | 内容的类型 | Content-Type: text/html;charset=UTF-8 |
X-* | 非标准的、自定义的域以 X- 开头 | X-Priority: 1 |
三、JavaMail 代码实现
Maven Repository: javax.mail » javax.mail-api » 1.6.2
包 :
- javax.mail.jar ( 依赖 activation.jar )
- activation.jar
类:
- java.util.Properties
- javax.mail.Session
- javax.mail.Transport
- javax.mail.internet.InternetAddress
- javax.mail.internet.MimeMessage
/*
** MimeMessage.RecipientType.TO 接收人
** MimeMessage.RecipientType.CC 抄送人
** MimeMessage.RecipientType.BCC 密送人
*/
try {
Properties prop = new Properties();//创建Java配置对象
prop.setProperty("mail.transport.protocol", "smtp");//传输协议
prop.setProperty("mail.smtp.host", "smtp.xxx.com");//邮箱服务器地址
prop.setProperty("mail.smtp.auth","true");//是否需要身份验证
prop.setProperty("mail.debug", "true");//是否显示日志信息
prop.setProperty("mail.smtp.port", "25");//发送邮件端口号
Session session = Session.getDefaultInstance(prop);//使用配置对象获取会话对象
MimeMessage msg = new MimeMessage(session);//获取消息对象
msg.setSentDate(new java.util.Date());//设置发件日期
msg.setFrom(new InternetAddress("xxx@xx.com","xxx"));//设置发件地址
msg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("xxx@xx.com"));//设置接收地址
msg.addHeader("X-Company", "Produced By Micron Studio");//自定义头信息
msg.setSubject("xxxxxxxx");//邮件主题 ( 即邮件标题 )
msg.setContent("<html></html>","text/html");//邮件内容以及 Content-Type
Transport trans = session.getTransport("smtp");//获取传输对象
trans.connect("smtp.xxx.com","xxx@xx.com", "**********");//使用账户密码连接邮件服务器
trans.sendMessage(msg, msg.getAllRecipients());//发送消息
trans.close();//关闭对象
} catch (Exception e) {
//异常处理
}
四、使用 SSL 协议加密 SMTP 报文 (SMTPS)
类:
- com.sun.mail.util.MailSSLSocketFactory
创建以下对象
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
为 Properties 添加以下属性
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
prop.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
prop.setProperty("mail.smtp.socketFactory.fallback", "false");
prop.setProperty("mail.smtp.ssl.enable", "true");
更改发送的端口号
prop.setProperty("mail.smtp.port", "465");