前言
最近公司用一个发送邮件的需求,虽说通过java
发送邮件本身也不是很复杂,但是本着学习积累的宗旨,我还是想做一个简单的总结,一个是方便自己后期遇到相同需求的时候查阅,另一个也是希望我的实践过程可以为各位正在做相关需求的小伙伴提供一点点帮助和借鉴。
java发送邮件
邮件服务的常见协议及区别
IMAP
关于IMAP
的解释,我这里就直接引用百度百科解释了:
IMAP(Internet Message Access Protocol)以前称作交互邮件访问协议(Interactive Mail Access Protocol),是一个应用层协议。IMAP是斯坦福大学在1986年开发的一种邮件获取协议。它的主要作用是邮件客户端可以通过这种协议从邮件服务器上获取邮件的信息,下载邮件等。当前的权威定义是RFC3501。IMAP协议运行在TCP/IP协议之上,使用的端口是143。它与
POP3
协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作。
各位小伙伴需要注意的是,IMAP
协议是针对接收邮件的(邮件获取协议),也就是客户端协议,通过它我们只能接收和管理邮件,但并不能发送邮件。另外还需要注意的是:
它与POP3
协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作
POP3
这里的pop3
协议也是一种邮件客户端通信协议,所以也是不可以发送邮件的:
POP3,全名为“Post Office Protocol - Version 3”,即“邮局协议版本3”。是TCP/IP协议族中的一员,由RFC1939 定义。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。提供了SSL加密的POP3协议被称为POP3S。
POP 协议支持“离线”邮件处理。其具体过程是:邮件发送到服务器上,电子邮件客户端调用邮件客户机程序以连接服务器,并下载所有未阅读的电子邮件。这种离线访问模式是一种存储转发服务,将邮件从邮件服务器端送到个人终端机器上,一般是PC机或 MAC。一旦邮件发送到 PC 机或MAC上,邮件服务器上的邮件将会被删除。但POP3邮件服务器大都可以“只下载邮件,服务器端并不删除”,也就是改进的POP3协议。
SMTP
SMTP
协议主要就是用来发送邮件的,因为如果只是通过IMAP
或者POP3
协议的话,我们只能被动地接收邮件,而不能发送邮件,所以我们在邮箱服务商的配置文档中看到POP3
和IMAP
的配置通常是和SMTp
成对出现的,因为只有配置了SMTP
服务,才能确保我们的客户端可以发出邮件。
SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于系统之间的邮件信息传递,并提供有关来信的通知。SMTP独立于特定的传输子系统,且只需要可靠有序的数据流信道支持,SMTP的重要特性之一是其能跨越网络传输邮件,即“SMTP邮件中继”。使用SMTP,可实现相同网络处理进程之间的邮件传输,也可通过中继器或网关实现某处理进程与其他网络之间的邮件传输。
比如163
邮箱:
再比如qq
邮箱:
这里需要补充说明的是,SMTP
的端口号是25
和465
,但是考虑到安全性,很多服务云服务商是不允许使用非SSL
的端口的,也就是25
端口,我在实际测试的时候,发现阿里云就不允许通过25
端口发送邮件,所以通常我们用更安全的SSL
端口就可以了,基本上大部分的邮件服务商都支持这个端口,比如QQ
、163
、阿里企业邮箱。
Exchange
Exchange Server 是微软公司的一套电子邮件服务组件,是个消息与协作系统。 简单而言,Exchange server可以被用来构架应用于企业、学校的邮件系统。Exchange是收费邮箱,但是国内微软并不直接出售Exchange邮箱,而是将Exchange、Lync、Sharepoint三款产品包装成Office365出售。Exchange server还是一个协作平台。在此基础上可以开发工作流,知识管理系统,Web系统或者是其他消息系统。
邮件地址校验
端口、服务器校验
这里我自己写了一个telnet
方法,用于检测服务器和端口是否联通,同时设置了超时时间
public static boolean telnet(String host, Integer port, Integer timeout) {
try {
Socket socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(host, port);
socket.connect(socketAddress, timeout);
if (socket.isConnected()) {
return Boolean.TRUE;
}
} catch (IOException e) {
logger.warning("telnet error" + e);
}
return false;
}
发送测试邮件
端口和服务器校验通过之后,还需要通过发送测试邮件的方式来测试用户名和邮箱账号是否正确,这里自己写了一个发送邮件的方法,需要用到javax.mail
的mail
包,本次示例用的版本是1.4
,在实际测试中发现,相同的代码,用不同的版本可能会报错。
/**
* 发送邮件的方法
*
* @param host :邮件服务器地址
* @param account :账户(发送方)
* @param password :账户密码(发送方)
* @param port :邮箱服务器端口(发送方)
* @param toUser :收件人
* @param title :标题
* @param content :内容
*/
public static void sendMail(String host, String account, String password, String port, String toUser, String title, String content) throws Exception {
Properties props = System.getProperties();
props.setProperty("mail.host", host);
props.setProperty("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "false");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", port);
// 发送邮件超时时间
props.put("mail.smtp.writetimeout", 1000);
// 连接超时时间
props.put("mail.smtp.connectiontimeout", 1000);
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(account, password);
}
});
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(account));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toUser));
msg.setContent(content, "text/html;charset=utf-8");
msg.setSubject(title);
msg.setSentDate(new Date());
Transport.send(msg);
}
这里比较繁琐的就是邮箱服务器的配置了:
-
mail.host
:这个不用说,就是邮件服务的服务器地址(域名或者IP
) -
mail.smtp.port
:这个就是邮件服务器的端口,通常是465
(SSL
),当然你也可以用非SSL
的端口,但是你需要移除mail.smtp.socketFactory.class
的相关配置,否则会报错(不过这里还是推荐大家使用SSL
协议,毕竟比较安全): -
mail.smtp.auth
:smtp
验证,这个配置项是必须的,且值必须是true
,否则会报错: -
mail.smtp.starttls.enable
:设置TLS
是否启用,如果是SSL
通信协议,该设置项必须未设置或者值为flase
,否则也会报错: -
mail.smtp.socketFactory.class
:设置socket
工厂,SSL
通信的话,必须设置为javax.net.ssl.SSLSocketFactory
,否则会报错: -
mail.smtp.socketFactory.port
:设置socket
的端口,实际测试中发现该配置参数可以省略
java发送邮件
其实在上面发送测试邮件那里,我们已经展示了发送邮件的方式,这里我们直接调用那个方法即可。在开始发送邮件之前,我们先来看下如何获取方法的参数,也就是邮件服务器的相关配置信息,这里我们以163
邮箱为例,其他邮箱大同小异。
首先登录到163
邮箱网页端,点击顶部的设置菜单,选择POP3/SMTP/IMAP
那个选项
开启IMAP/SMTP
或者POP3/SMTP
服务中的任意一个,因为我们主要是为了实现发送邮件的需求,所以只要我们开启了SMTP
服务即可。
前面我们说了,POP3
或者IMAP
协议都是接收邮件的协议,发送邮件的协议是SMTP
,所以开启其中一个,SMTP
协议都会开启。
开通时要求用邮箱绑定的手机号发送一行验证码,然后系统会生成一个授权码,这个授权码就是我们后面发送邮件的密码,因为只展示一次,所以务必保存下。
然后根据我们前面说的SMTP
的服务器和端口,既可以实现邮件发送功能,这里我主要是用于测试邮箱配置是否正确,所以我直接给自己发的邮件:
发送成功后,我们可以在接收方邮箱中看到该邮件:
至此,我们发送邮件的需求就实现了。
结语
就整个需求的实现来说,其实代码层面还是比较简单的,真正的难点是邮件服务器配置的相关内容,由于前期对邮件服务的相关协议和配置不了解,所以踩了很多坑,当然也正是有了这样一个踩坑的过程,也才让我对邮件服务配置有了一个更全面的了解和认识。好了,今天的内容就先到这里,感兴趣的小伙伴可以自己动手实践下。