使用 IMAP 從 Gmail 存取電子郵件
1. 概述
Gmail 等網路郵件應用程式會依賴網際網路訊息應用協定 (IMAP) 等協定來擷取和操作來自電子郵件伺服器的電子郵件。
在本教程中,我們將探討如何使用 IMAP 透過 Java 與 Gmail 伺服器互動。此外,我們還將執行閱讀電子郵件、計算未讀電子郵件數量、在資料夾之間移動電子郵件、將電子郵件標記為已讀以及刪除電子郵件等操作。此外,我們還將了解如何設定 Google 應用程式專用密碼進行身份驗證。
2.IMAP是什麼?
IMAP 是一種可協助電子郵件用戶端擷取儲存在遠端伺服器上的電子郵件以進行進一步操作的技術。與郵局協定 (POP3) 將電子郵件下載到用戶端並將其從電子郵件伺服器中刪除不同, IMAP 將電子郵件保留在伺服器上並允許多個用戶端存取相同電子郵件伺服器。
此外,IMAP 在從遠端伺服器存取電子郵件時保持開放連線。它允許跨多個設備/機器更好地同步。
對於未加密連接,IMAP 預設在連接埠 143 上運行;對於 SSL/TLS 加密連接,IMAP 在連接埠 993 上運行。當連線被加密時,它被稱為 IMAPS。
大多數網路郵件服務(包括 Gmail)都提供對 IMAP 和 POP3 的支援。
3. 項目設定
首先,讓我們將jarkarta.mail-api依賴項新增至pom.xml :
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>2.1.3</version>
</dependency>
此依賴項提供了一些類別來建立與電子郵件伺服器的連接並執行不同形式的操作,例如開啟電子郵件、刪除電子郵件以及在不同資料夾之間移動電子郵件。
要連接到 Gmail 伺服器,我們需要建立一個應用程式密碼。讓我們導覽至Google 帳戶設定頁面並選擇側邊欄的安全性選項。然後,讓我們啟用 2 因素身份驗證 (2FA)(如果尚未啟動)。
接下來,讓我們在搜尋欄中搜尋“ app password ”,並為我們的應用程式建立一個新的應用程式專用密碼。
4. 連接到 Gmail
現在我們有了用於身份驗證的應用程式密碼,讓我們建立一個方法來建立與 Gmail 伺服器的連接:
static Store establishConnection() throws MessagingException {
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
Session session = Session.getDefaultInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.googlemail.com", "GMAIL", "APP PASSWORD");
return store;
}
在上面的程式碼中,我們建立一個傳回Store物件的連接方法。我們建立一個Properties物件來設定郵件會話的設定參數。此外,我們也指定Store物件的驗證憑證,以成功建立與我們的電子郵件的連線。
5. 基本操作
透過 IMAP 成功連接到 Gmail 伺服器後,我們可以執行基本操作,例如閱讀電子郵件、列出所有電子郵件、在資料夾之間移動電子郵件、刪除電子郵件、將電子郵件標記為已讀等等。
5.1.計算郵件總數和未讀郵件數
讓我們列出inbox和Spam資料夾中所有電子郵件和未讀電子郵件的總數:
static void emailCount(Store store) throws MessagingException {
Folder inbox = store.getFolder("inbox");
Folder spam = store.getFolder("[Gmail]/Spam");
inbox.open(Folder.READ_ONLY);
LOGGER.info("No of Messages : " + inbox.getMessageCount());
LOGGER.info("No of Unread Messages : " + inbox.getUnreadMessageCount());
LOGGER.info("No of Messages in spam : " + spam.getMessageCount());
LOGGER.info("No of Unread Messages in spam : " + spam.getUnreadMessageCount());
inbox.close(true);
}
上面的方法接受Store物件作為參數來建立與電子郵件伺服器的連線。此外,我們也定義了一個Folder物件來指示inbox和Spam資料夾。然後,我們對資料夾物件呼叫getMessageCount()和getUnreadMessageCount()以取得總電子郵件數和未讀電子郵件數。
「 [Gmail]”前綴表示 Gmail 層次結構中的特殊資料夾,必須用於特定於 Gmail 的資料夾。除了Spam資料夾之外,其他特定於 Gmail 的資料夾包括[Gmail]/All Mail 、 [Gmail]/Bin和[Gmail]/Draft 。
我們可以指定任何資料夾來取得其電子郵件計數。但是,如果該資料夾不存在,則會引發錯誤。
5.2.閱讀電子郵件
此外,讓我們閱讀inbox資料夾中的第一封電子郵件:
static void readEmails(Store store) throws MessagingException, IOException {
Folder inbox = store.getFolder("inbox");
inbox.open(Folder.READ_ONLY);
Message[] messages = inbox.getMessages();
if (messages.length > 0) {
Message message = messages[0];
LOGGER.info("Subject: " + message.getSubject());
LOGGER.info("From: " + Arrays.toString(message.getFrom()));
LOGGER.info("Text: " + message.getContent());
}
inbox.close(true);
}
在上面的程式碼中,我們會擷取inbox資料夾中的所有電子郵件並將它們儲存在Message類型的陣列中。然後,我們將電子郵件的主題、寄件者地址和內容記錄到控制台。
最後,操作成功後我們關閉收件匣資料夾。
5.3.搜尋電子郵件
此外,我們可以透過建立SearchTerm實例並將其傳遞給search()方法來執行搜尋操作:
static void searchEmails(Store store, String from) throws MessagingException {
Folder inbox = store.getFolder("inbox");
inbox.open(Folder.READ_ONLY);
SearchTerm senderTerm = new FromStringTerm(from);
Message[] messages = inbox.search(senderTerm);
Message[] getFirstFiveEmails = Arrays.copyOfRange(messages, 0, 5);
for (Message message : getFirstFiveEmails) {
LOGGER.info("Subject: " + message.getSubject());
LOGGER.info("From: " + Arrays.toString(message.getFrom()));
}
inbox.close(true);
}
在這裡,我們建立一個接受Store物件和搜尋條件作為參數的方法。然後,我們打開inbox並呼叫它的search()方法。在呼叫Folder物件的search()方法之前,我們將搜尋查詢傳遞給SearchTerm物件。
值得注意的是,搜尋將僅限於指定的資料夾。
5.4.跨資料夾移動電子郵件
此外,我們可以在不同的資料夾之間移動電子郵件。如果指定的資料夾不可用,則會建立一個新資料夾:
static void moveToFolder(Store store, Message message, String folderName) throws MessagingException {
Folder destinationFolder = store.getFolder(folderName);
if (!destinationFolder.exists()) {
destinationFolder.create(Folder.HOLDS_MESSAGES);
}
Message[] messagesToMove = new Message[] { message };
message.getFolder().copyMessages(messagesToMove, destinationFolder);
message.setFlag(Flags.Flag.DELETED, true);
}
在這裡,我們指定目標資料夾並在目前電子郵件資料夾上呼叫copyMessages()方法。 copyMessages()方法接受messagesToMove和destinationFolder作為參數。將電子郵件複製到新資料夾後,我們將其從原始資料夾中刪除。
5.5.將未讀電子郵件標記為已讀
此外,我們可以將指定資料夾中的未讀電子郵件標記為已讀:
static void markLatestUnreadAsRead(Store store) throws MessagingException {
Folder inbox = store.getFolder("inbox");
inbox.open(Folder.READ_WRITE);
Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
if (messages.length > 0) {
Message latestUnreadMessage = messages[messages.length - 1];
latestUnreadMessage.setFlag(Flags.Flag.SEEN, true);
}
inbox.close(true);
}
打開收件匣資料夾後,我們啟用讀寫權限,因為將電子郵件標記為已讀會改變其狀態。然後,我們搜尋收件匣並列出所有未讀電子郵件。最後,我們將最新的未讀電子郵件標記為已讀。
5.6.刪除電子郵件
雖然我們可以將電子郵件移至Trash資料夾,但我們也可以在連線仍處於開啟狀態時刪除電子郵件:
static void deleteEmail(Store store) throws MessagingException {
Folder inbox = store.getFolder("inbox");
inbox.open(Folder.READ_WRITE);
Message[] messages = inbox.getMessages();
if (messages.length >= 7) {
Message seventhLatestMessage = messages[messages.length - 7];
seventhLatestMessage.setFlag(Flags.Flag.DELETED, true);
LOGGER.info("Delete the seventh message: " + seventhLatestMessage.getSubject());
} else {
LOGGER.info("There are less than seven messages in the inbox.");
}
inbox.close(true);
}
在上面的程式碼中,在取得收件匣中的所有電子郵件後,我們選擇陣列中的第七封電子郵件並對其呼叫setFlag()方法。此操作將電子郵件標記為刪除。
六、結論
在本文中,我們介紹了在 Java 中使用 IMAP 的基礎知識,重點是 Gmail 整合。此外,我們還探索了基本的電子郵件操作,例如閱讀電子郵件、在資料夾之間移動電子郵件、刪除電子郵件以及將未讀電子郵件標記為已讀。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。