JavaMail 中的安全连接 SSL/TLS
现在 JavaMail 支持使用 SSL/TLS 建立安全连接访问邮件服务器。为了简化安全访问,提供了两种其中启用 SSL 安全连接的方法:
- 配置连接属性
// 这里以 SMTP 启用 SSL 安全连接为例
props.setProperty("mail.smtp.ssl.enable", "true");
- 使用安全连接协议
// JavaMail 中的非安全连接协议 smtp / pop3 / imap
props.setProperty("mail.transport.protocol", "smtp");
// JavaMail 中的安全连接协议 smtps / pop3s / imaps
props.setProperty("mail.transport.protocol", "smtps");
此外,IMAP 和 SMTP 协议支持使用 **"STARTTLS"** 命令 (参见 RFC 2487 和 RFC 3501) 来切换要由 TLS 保护的连接。在服务器同时支持 SSL 连接和 non-SSL 连接的时候最好使用 STARTTLS 命令。
STARTTLS 支持
STARTTLS 支持在标准的 "IMAP" 和 "SMTP "协议中可用,但必须通过将适当的属性 "mail.imap.starttls.Enable" 或 "mail.smtp.starttls.Enable" 设置为 "true" 来启用。设置时,如果服务器支持 STARTTLS 命令,则在建立连接和发送任何登录信息之前将使用该命令。
// IMAP 协议设置 STARTTLS
props.setProperty("mail.imap.starttls.Enable", "true");
// SMTP 协议设置 STARTTLS
props.setProperty("mail.smtp.starttls.Enable", "true");
安全协议
当使用新的协议名称时,配置属性也必须使用这些协议名称。例如,将属性 "mail.smtps.host" 设置为指定在 SSL 上对 SMTP 使用 "smtps" 协议时要连接到的计算机的主机名。类似地,要在通过 SSL 为 IMAP 使用 "IMAPS" 协议时设置 IMAP 协议超时,请设置属性 "mail.imaps.timeout" 。请参阅用于可用属性列表的不同协议包的包文档,这些属性总是使用表单邮件的属性名称来设置 "mail.."。
Transport.send 方法将使用默认传输协议 "SMTP"。如果要在 SMTP 协议上启用 SSL 安全连接,需要设置属性 "mail.smtp.ssl.enable" 为 "true"。这通常是最简单的方法。
props.setProperty("mail.smtp.ssl.enable", "true");
或者,若要将 Session.getTransport.protocol() 方法返回的默认传输协议更改为基于安全连接 SSL 上的 SMTP,请将属性 "mail.transport.protocol" 设置为 "smtps"。若要更改用于英特网地址的传输 (由 Session.getTransport(Address) 方法返回并由 Transport.send() 方法使用),请使用 Session.setProtocolForAddress() 方法设置相关协议。
// 通过设置属性为安全协议建立安全连接
props.setProperty("mail.transport.protocol", "smtps");
// 通过设置 Session 的协议实现用于因特网地址的安全连接
session.setProtocolForAddress("rfc822", "smtps");
关于其它详细内容可参阅 原文
此处附上一段简易的控制台程序以供参考。
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;
/**
* @author kp
*/
public class Main {
private static final String TRUE_SYMBOL_Y = "y";
private static final String MENU_SEND_OPTION = "1";
private static final String MENU_RECEIVE_OPTION = "2";
private static final String MENU_EXIT_OPTION = "3";
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(inputStreamReader);
while (true) {
try {
System.out.println("\r\n====================== MENU ========================");
System.out.println(" (1)send (2)receive (3)exit");
System.out.println("====================================================");
System.out.print("Input option: ");
String option = reader.readLine();
if (MENU_SEND_OPTION.equalsIgnoreCase(option)) {
send();
} else if (MENU_RECEIVE_OPTION.equalsIgnoreCase(option)) {
receive();
} else if (MENU_EXIT_OPTION.equalsIgnoreCase(option)) {
// 退出
break;
}
System.out.flush();
} catch (Exception e) {
System.out.println("I/O exception");
e.printStackTrace();
}
}
System.out.println("\r\nEND!");
}
private static void send() throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please input smtp host: ");
String host = reader.readLine();
System.out.print("Please input smtp port: ");
String port = reader.readLine();
System.out.print("Please input email address: ");
String email = reader.readLine();
System.out.print("Please input email password: ");
String password = reader.readLine();
System.out.print("Is SSL(y/n): ");
String isSsl = reader.readLine();
String isStartTls = "";
if (!TRUE_SYMBOL_Y.equalsIgnoreCase(isSsl)) {
System.out.print("Is STARTTLS(y/n): ");
isStartTls = reader.readLine();
}
System.out.println("################### Message ########################");
System.out.print("Please input receiver: ");
String receiver = reader.readLine();
System.out.print("Please input subject: ");
String subject = reader.readLine();
System.out.print("Please input content: ");
String content = reader.readLine();
System.out.println("##################### END ##########################");
// 配置连接参数
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.smtp.host", host);
props.setProperty("mail.smtp.port", port);
props.setProperty("mail.smtp.timeout", "20000");
props.setProperty("mail.smtp.connectiontimeout", "20000");
// 此处对于 SSL 和 STARTTLS 的处理不当,有待改正
if (TRUE_SYMBOL_Y.equalsIgnoreCase(isSsl)) {
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.ssl.enable", "true");
} else if (TRUE_SYMBOL_Y.equalsIgnoreCase(isStartTls)) {
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.starttls.enable", "true");
}
try {
// 获取会话
Session session = Session.getInstance(props);
// 构建邮件信息
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(email));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(receiver));
message.setSubject(subject);
// 设置内容
Multipart contentPart = new MimeMultipart();
BodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(content, "text/html;charset=UTF-8");
contentPart.addBodyPart(bodyPart);
message.setContent(contentPart);
// 建立连接并发送
Transport transport = session.getTransport();
transport.connect(email, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
System.out.println("********************** Result **********************");
System.out.println("send success!");
System.out.println("****************************************************");
} catch (Exception e) {
System.out.println("********************** Result **********************");
System.out.println("send fail!");
System.out.println("****************************************************");
e.printStackTrace();
}
}
private static void receive() throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please input imap host: ");
String host=br.readLine();
System.out.print("Please input imap port: ");
String port=br.readLine();
System.out.print("Please input email address: ");
String email =br.readLine();
System.out.print("Please input email password: ");
String password =br.readLine();
System.out.print("Is SSL(y/n): ");
String isSsl = br.readLine();
// 构建基本的配置信息
Properties props = new Properties();
props.setProperty("mail.store.protocol", "imap");
props.setProperty("mail.imap.host", host);
props.setProperty("mail.imap.port", port);
props.setProperty("mail.imap.timeout", "20000");
props.setProperty("mail.imap.connectiontimeout", "20000");
if (TRUE_SYMBOL_Y.equalsIgnoreCase(isSsl)) {
props.setProperty("mail.imap.auth", "true");
props.setProperty("mail.imap.ssl.enable", "true");
}
try {
Session session = Session.getDefaultInstance(props);
Store store = session.getStore();
store.connect(email, password);
Folder folder = store.getFolder("INBOX");
if (folder.isOpen()) {
System.out.println("The folder is opened");
} else {
System.out.println("Open the folder");
folder.open(Folder.READ_ONLY);
}
System.out.println("********************** Result **********************");
System.out.println("receive success!");
System.out.println(folder.getFullName());
System.out.println("total email count: " + folder.getMessageCount());
System.out.println("unread email count: " + folder.getUnreadMessageCount());
System.out.println("deleted email count: " + folder.getDeletedMessageCount());
System.out.println("new email count: " + folder.getNewMessageCount());
System.out.println("****************************************************");
} catch (Exception e) {
System.out.println("********************** Result **********************");
System.out.println("receive fail!");
System.out.println("****************************************************");
e.printStackTrace();
}
}
}

734





