Java學習101:接受Email

發送Email的過程我們在上一節已經講過了,客戶端總是通過SMTP協議把郵件發送給MTA。

接收Email則相反,因爲郵件最終到達收件人的MDA服務器,所以,接收郵件是收件人用自己的客戶端把郵件從MDA服務器上抓取到本地的過程。

接收郵件使用最廣泛的協議是POP3:Post Office Protocol version 3,它也是一個建立在TCP連接之上的協議。POP3服務器的標準端口是110,如果整個會話需要加密,那麼使用加密端口995。

另一種接收郵件的協議是IMAP:Internet Mail Access Protocol,它使用標準端口143和加密端口993。IMAP和POP3的主要區別是,IMAP協議在本地的所有操作都會自動同步到服務器上,並且,IMAP可以允許用戶在郵件服務器的收件箱中創建文件夾。

JavaMail也提供了IMAP協議的支持。因爲POP3和IMAP的使用方式非常類似,因此我們只介紹POP3的用法。

使用POP3收取Email時,我們無需關心POP3協議底層,因爲JavaMail提供了高層接口。首先需要連接到Store對象:

// 準備登錄信息:
String host = "pop3.example.com";
int port = 995;
String username = "[email protected]";
String password = "password";

Properties props = new Properties();
props.setProperty("mail.store.protocol", "pop3"); // 協議名稱
props.setProperty("mail.pop3.host", host);// POP3主機名
props.setProperty("mail.pop3.port", String.valueOf(port)); // 端口號
// 啓動SSL:
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", String.valueOf(port));

// 連接到Store:
URLName url = new URLName("pop3", host, post, "", username, password);
Session session = Session.getInstance(props, null);
session.setDebug(true); // 顯示調試信息
Store store = new POP3SSLStore(session, url);
store.connect();

一個Store對象表示整個郵箱的存儲,要收取郵件,我們需要通過Store訪問指定的Folder(文件夾),通常是INBOX表示收件箱:

// 獲取收件箱:
Folder folder = store.getFolder("INBOX");
// 以讀寫方式打開:
folder.open(Folder.READ_WRITE);
// 打印郵件總數/新郵件數量/未讀數量/已刪除數量:
System.out.println("Total messages: " + folder.getMessageCount());
System.out.println("New messages: " + folder.getNewMessageCount());
System.out.println("Unread messages: " + folder.getUnreadMessageCount());
System.out.println("Deleted messages: " + folder.getDeletedMessageCount());
// 獲取每一封郵件:
Message[] messages = folder.getMessages();
for (Message message : messages) {
    // 打印每一封郵件:
    printMessage((MimeMessage) message);
}

當我們獲取到一個Message對象時,可以強制轉型爲MimeMessage,然後打印出郵件主題、發件人、收件人等信息:

void printMessage(MimeMessage msg) throws IOException, MessagingException {
    // 郵件主題:
    System.out.println("Subject: " + MimeUtility.decodeText(msg.getSubject()));
    // 發件人:
    Address[] froms = msg.getFrom();
    InternetAddress address = (InternetAddress) froms[0];
    String personal = address.getPersonal();
    String from = personal == null ? address.getAddress() : (MimeUtility.decodeText(personal) + " <" + address.getAddress() + ">");
    System.out.println("From: " + from);
    // 繼續打印收件人:
    ...
}

比較麻煩的是獲取郵件的正文。一個MimeMessage對象也是一個Part對象,它可能只包含一個文本,也可能是一個Multipart對象,即由幾個Part構成,因此,需要遞歸地解析出完整的正文:

String getBody(Part part) throws MessagingException, IOException {
    if (part.isMimeType("text/*")) {
        // Part是文本:
        return part.getContent().toString();
    }
    if (part.isMimeType("multipart/*")) {
        // Part是一個Multipart對象:
        Multipart multipart = (Multipart) part.getContent();
        // 循環解析每個子Part:
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String body = getBody(bodyPart);
            if (!body.isEmpty()) {
                return body;
            }
        }
    }
    return "";
}

最後記得關閉Folder和Store:

folder.close(true); // 傳入true表示刪除操作會同步到服務器上(即刪除服務器收件箱的郵件)
store.close();

小結
使用Java接收Email時,可以用POP3協議或IMAP協議。

使用POP3協議時,需要用Maven引入JavaMail依賴,並確定POP3服務器的域名/端口/是否使用SSL等,然後,調用相關API接收Email。

設置debug模式可以查看通信詳細內容,便於排查錯誤。

謝謝觀看

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章