JavaMail 基於安全連接 SSL/TLS 收發郵件

JavaMail 中的安全連接 SSL/TLS

現在 JavaMail 支持使用 SSL/TLS 建立安全連接訪問郵件服務器。爲了簡化安全訪問,提供了兩種其中啓用 SSL 安全連接的方法:

  1. 配置連接屬性
// 這裏以 SMTP 啓用 SSL 安全連接爲例
props.setProperty("mail.smtp.ssl.enable", "true");
  1. 使用安全連接協議
// 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 SSL(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();
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章