Работа с сообщениями с IMAP‑сервера

Список MIME‑идентификаторов сообщений с сервера

ImapMessageInfo предоставляет MIME MessageId для идентификации сообщения без извлечения полного сообщения. Ниже показан фрагмент кода, демонстрирующий, как вывести MIME‑messageId.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
ImapClient client = new ImapClient();
client.setHost("domain.com");
client.setUsername("username");
client.setPassword("password");

try {
    ImapMessageInfoCollection messageInfoCol = client.listMessages("Inbox");
    for (ImapMessageInfo info : messageInfoCol) {
        // Display MIME Message ID
        System.out.println("Message Id = " + info.getMessageId());
    }
} catch (java.lang.RuntimeException ex) {
    System.out.println(ex.getMessage());
}

Вывод сообщений с сервера

Aspose.Email предоставляет перегруженный вариант с 2 параметрами для listMessages() для получения заданного количества сообщений по запросу. Ниже показан фрагмент кода, демонстрирующий, как вывести сообщения.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
// Create an imapclient with host, user and password
ImapClient client = new ImapClient("localhost", "user", "password");

// Select the inbox folder and Get the message info collection
ImapQueryBuilder builder = new ImapQueryBuilder();
MailQuery query = builder
        .or(builder.or(builder.or(builder.or(builder.getSubject().contains(" (1) "), builder.getSubject().contains(" (2) ")), builder.getSubject().contains(" (3) ")),
                builder.getSubject().contains(" (4) ")), builder.getSubject().contains(" (5) "));
ImapMessageInfoCollection messageInfoCol4 = client.listMessages(query, 4);
System.out.println((messageInfoCol4.size() == 4) ? "Success" : "Failure");

Рекурсивный вывод сообщений с сервера

Протокол IMAP поддерживает рекурсивный список сообщений из папки почтового ящика. Это также помогает перечислять сообщения из подпапок. Ниже показан фрагмент кода, демонстрирующий рекурсивный вывод сообщений.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
// Create an imapclient with host, user and password
ImapClient client = new ImapClient();
client.setHost("domain.com");
client.setUsername("username");
client.setPassword("password");
client.selectFolder("InBox");
ImapMessageInfoCollection msgsColl = client.listMessages(true);
System.out.println("Total Messages: " + msgsColl.size());

Получение сообщений с MultiConnection

ImapClient предоставляет UseMultiConnection Свойство, которое может использоваться для создания нескольких соединений при тяжёлых операциях. Вы также можете задать количество соединений, используемых в режиме мультисоединения, используя ImapClient.ConnectionsQuantity. Ниже показан фрагмент кода, демонстрирующий использование режима множественных соединений для перечисления сообщений и сравнивающий его производительность с режимом одиночного соединения.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
ImapClient imapClient = new ImapClient();
imapClient.setHost("<HOST>");
imapClient.setPort(993);
imapClient.setUsername("<USERNAME>");
imapClient.setPassword("<PASSWORD>");
imapClient.setSupportedEncryption(EncryptionProtocols.Tls);
imapClient.setSecurityOptions(SecurityOptions.SSLImplicit);

imapClient.selectFolder("Inbox");
imapClient.setConnectionsQuantity(5);
imapClient.setUseMultiConnection(MultiConnectionMode.Enable);
long multiConnectionModeStartTime = System.currentTimeMillis();
ImapMessageInfoCollection messageInfoCol1 = imapClient.listMessages(true);
long multiConnectionModeTimeSpan = System.currentTimeMillis() - multiConnectionModeStartTime;

imapClient.setUseMultiConnection(MultiConnectionMode.Disable);
long singleConnectionModeStartTime = System.currentTimeMillis();
ImapMessageInfoCollection messageInfoCol2 = imapClient.listMessages(true);
long singleConnectionModeTimeSpan = System.currentTimeMillis() - singleConnectionModeStartTime;

double performanceRelation = singleConnectionModeTimeSpan / multiConnectionModeTimeSpan;
System.out.println("Performance Relation: " + performanceRelation);

Получить сообщения в обратном порядке

Aspose.Email предоставляет ImapClient.listMessagesByPage метод, который перечисляет сообщения с поддержкой постраничного вывода. Некоторые перегрузки ImapClient.listMessagesByPage принимать PageSettings в качестве параметра. PageSettings предоставляет AscendingSorting свойство, которое при установке в false возвращает письма в обратном (убывающем) порядке.

Следующий пример кода демонстрирует использование AscendingSorting свойство PageSettings класс для изменения порядка писем.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
ImapClient imapClient = new ImapClient();
imapClient.setHost("<HOST>");
imapClient.setPort(993);
imapClient.setUsername("<USERNAME>");
imapClient.setPassword("<PASSWORD>");
imapClient.setSupportedEncryption(EncryptionProtocols.Tls);
imapClient.setSecurityOptions(SecurityOptions.SSLImplicit);

PageSettings pageSettings = new PageSettings();
pageSettings.setAscendingSorting(false);
ImapPageInfo pageInfo = imapClient.listMessagesByPage(5, pageSettings);
ImapMessageInfoCollection messages = pageInfo.getItems();

for (ImapMessageInfo message : messages) {
    System.out.println(message.getSubject() + " -> " + message.getDate().toString());
}

Получить сообщения с сервера и сохранить на диск

Этот ImapClient класс может получать сообщения с IMAP‑сервера и сохранять их в формате EML на локальный диск. Для сохранения сообщений на диск требуется выполнить следующие шаги:

  1. Создать экземпляр ImapClient класс.
  2. Укажите имя хоста, порт, имя пользователя и пароль в ImapClient конструктор.
  3. Выберите папку, используя selectFolder() метод.
  4. Вызвать listMessages метод, чтобы получить ImapMessageInfoCollection объекта.
  5. Итерируйтесь по ImapMessageInfoCollection коллекцию, вызовите saveMessage() метод и указать путь вывода и имя файла.

Ниже показан фрагмент кода, демонстрирующий, как получить сообщения электронной почты с сервера и сохранить их.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
// Select the inbox folder and Get the message info collection
client.selectFolder(ImapFolderInfo.IN_BOX);
ImapMessageInfoCollection list = client.listMessages();

// Download each message
for (int i = 0; i < list.size(); i++) {
    // Save the EML file locally
    client.saveMessage(list.get_Item(i).getUniqueId(), dataDir + list.get_Item(i).getUniqueId() + ".eml");
}

Сохранение сообщений в формате MSG

В приведённом выше примере, письма сохраняются в формате EML. Чтобы сохранить письма в формате MSG, ImapClient.fetchMessage() необходимо вызвать метод. Он возвращает сообщение в экземпляре MailMessage класс. The MailMessage.save() затем можно вызвать метод для сохранения сообщения в формате MSG. Ниже приведён фрагмент кода, показывающий, как сохранять сообщения в формате MSG.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
// The path to the file directory.
String dataDir = "data/";

// Create an imapclient with host, user and password
ImapClient client = new ImapClient("localhost", "user", "password");

// Select the inbox folder and Get the message info collection
client.selectFolder(ImapFolderInfo.IN_BOX);
ImapMessageInfoCollection list = client.listMessages();

// Download each message
for (int i = 0; i < list.size(); i++) {
    // Save the message in MSG format
    MailMessage message = client.fetchMessage(list.get_Item(i).getUniqueId());
    message.save(dataDir + list.get_Item(i).getUniqueId() + "_out.msg", SaveOptions.getDefaultMsgUnicode());
}

Групповое получение сообщений

ImapClient предоставляет fetchMessages метод, который принимает итерируемый набор номеров последовательности или уникальных ID и возвращает список MailMessage. Следующий фрагмент кода демонстрирует использование fetchMessages метод для получения сообщений по номерам последовательности и уникальному идентификатору.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
ImapClient imapClient = new ImapClient();
imapClient.setHost("<HOST>");
imapClient.setPort(993);
imapClient.setUsername("<USERNAME>");
imapClient.setPassword("<PASSWORD>");
imapClient.setSupportedEncryption(EncryptionProtocols.Tls);
imapClient.setSecurityOptions(SecurityOptions.SSLImplicit);

ImapMessageInfoCollection messageInfoCol = imapClient.listMessages();
System.out.println("ListMessages Count: " + messageInfoCol.size());

List<Integer> sequenceNumberAr = new ArrayList<Integer>();
List<String> uniqueIdAr = new ArrayList<String>();
for (ImapMessageInfo mi : messageInfoCol) {
    sequenceNumberAr.add(mi.getSequenceNumber());
    uniqueIdAr.add(mi.getUniqueId());
}

for (MailMessage m : imapClient.fetchMessagesBySequences(sequenceNumberAr)) {
    System.out.println("FetchMessages-sequenceNumberAr : " + m.getSubject());
}

for (MailMessage m : imapClient.fetchMessagesByUids(uniqueIdAr)) {
    System.out.println("FetchMessages-uniqueIdAr : " + m.getSubject());
}

Группировка писем/Организация писем в беседы

Aspose.Email позволяет группировать все пересылки, ответы и ответы всем, связанные с одной беседой, в иерархическом порядке. По сути, протокол IMAP может поддерживать возможность THREAD, определённую в RFC‑5256. Кроме того, существует другое расширение IMAP, предоставляемое Gmail и описанное как X‑GM‑EXT‑1.

Следующие возможности группировки писем доступны для использования:

  • getMessageThreads метод — получает цепочки сообщений по ImapClient.
  • boolean getGmExt1Supported - Получает информацию о поддержке расширения Gmail X-GM-EXT-1.
  • boolean getThreadSupported - Получает информацию о том, поддерживается ли расширение THREAD.
  • String[] getThreadAlgorithms - Получает поддерживаемые алгоритмы THREAD.

Ниже приведены примеры кода, демонстрирующие использование этих возможностей для получения цепочек писем из Gmail:

  ImapClient client = new ImapClient("imap.gmail.com", 993, "username", "password", SecurityOptions.SSLImplicit);

try {

    client.selectFolder(ImapFolderInfo.IN_BOX);

   // get a list of messages that we'll group by conversation

   ImapMessageInfoCollection messages = client.listMessages();

   // make sure the IMAP server supports X-GM-EXT-1 extension

   if (client.getGmExt1Supported()) {

       // gets unique conversationId for our example

       Set<String> conversationIds = new HashSet<String>();

       for (ImapMessageInfo messageInfo : messages) {

           if (messageInfo.getConversationId() != null)

                conversationIds.add(messageInfo.getConversationId());

       }

       for (String conversationId : conversationIds) {

           // create the necessary search conditions for a thread

           XGMThreadSearchConditions conditions = new XGMThreadSearchConditions();

            conditions.setConversationId(conversationId);

            conditions.setUseUId(true);

           // get results

           List<MessageThreadResult> conversation = client.getMessageThreads(conditions);

           // print the email conversation in hierarchically manner

           printConversaton("", conversation, messages);

            System.out.println("--------------------");

       }

   }

} finally {

    client.dispose();

}

/**

 * <p>

 * Prints the email conversation in hierarchically manner

 * </p>

 */

public static void printConversaton(String indent, Iterable<MessageThreadResult> conversation,

    Iterable<ImapMessageInfo> messages) {

   for (MessageThreadResult thread : conversation) {

       for (ImapMessageInfo messageInfo : messages) {

           if (thread.getUniqueId().equals(messageInfo.getUniqueId())) {

                System.out.println(indent + " (" + thread.getUniqueId() + ") " + messageInfo.getSubject());

               break;

           }

       }

       if (thread.getChildMessages().size() != 0) {

            printConversaton(indent += "-", thread.getChildMessages(), messages);

       }

   }

}

Код слегка меняется, если IMAP‑сервер поддерживает возможность THREAD:

Проверьте, поддерживает ли IMAP‑сервер расширение THREAD:

 if (client.getThreadSupported())

Создайте подходящие условия поиска для ветки:

 ThreadSearchConditions conditions = new ThreadSearchConditions();

conditions.setAlgorithm(client.getThreadAlgorithms()[0]);

conditions.setUseUId(true);

Список сообщений с поддержкой постраничного вывода

В сценариях, когда почтовый сервер содержит большое количество сообщений в ящике, часто требуется перечислять или получать сообщения с поддержкой постраничного вывода. API Aspose.Email ImapClient позволяет получать сообщения с сервера с поддержкой постраничного вывода.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
// This example shows the paging support of ImapClient for listing messages from the server
// Available in Aspose.Email for Java and onwards
final ImapClient client = new ImapClient("host.domain.com", 993, "username", "password");
try {
    try {
        int messagesNum = 12;
        int itemsPerPage = 5;
        MailMessage message = null;
        // Create some test messages and append these to server's inbox
        for (int i = 0; i < messagesNum; i++) {
            message = new MailMessage("from@domain.com", "to@domain.com", "EMAILNET-35157 - " + UUID.randomUUID(),
                    "EMAILNET-35157 Move paging parameters to separate class");
            client.appendMessage(ImapFolderInfo.IN_BOX, message);
        }

        // List messages from inbox
        client.selectFolder(ImapFolderInfo.IN_BOX);
        ImapMessageInfoCollection totalMessageInfoCol = client.listMessages();
        // Verify the number of messages added
        System.out.println(totalMessageInfoCol.size());

        ////////////////// RETREIVE THE MESSAGES USING PAGING SUPPORT////////////////////////////////////

        List<ImapPageInfo> pages = new ArrayList<ImapPageInfo>();
        PageSettings pageSettings = new PageSettings();
        ImapPageInfo pageInfo = client.listMessagesByPage(itemsPerPage, 0, pageSettings);
        System.out.println(pageInfo.getTotalCount());
        pages.add(pageInfo);
        while (!pageInfo.getLastPage()) {
            pageInfo = client.listMessagesByPage(itemsPerPage, pageInfo.getNextPage().getPageOffset(), pageSettings);
            pages.add(pageInfo);
        }
        int retrievedItems = 0;

        // foreach to while statements conversion
        for (ImapPageInfo folderCol : pages) {
            retrievedItems += folderCol.getItems().size();
        }
        System.out.println(retrievedItems);
    } finally {
    }
} finally {
    if (client != null)
        client.dispose();
}

Получение папок и чтение сообщений рекурсивно

В этой статье большинство ImapClient Эти возможности используются для создания приложения, которое рекурсивно перечисляет все папки и подпапки с IMAP‑сервера. Оно также сохраняет сообщения в каждой папке и подпапке в формате MSG на локальном диске. На диске папки и сообщения создаются и сохраняются в той же иерархической структуре, что и на IMAP‑сервере. Ниже приведён фрагмент кода, показывающий, как получить сообщения и информацию о подпапках рекурсивно.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
public static void run() throws Exception {
    // Create an instance of the ImapClient class
    ImapClient client = new ImapClient();

    // Specify host, username, password, Port and SecurityOptions for your client
    client.setHost("imap.gmail.com");
    client.setUsername("your.username@gmail.com");
    client.setPassword("your.password");
    client.setPort(993);
    client.setSecurityOptions(SecurityOptions.Auto);
    try {
        // The root folder (which will be created on disk) consists of host and username
        String rootFolder = client.getHost() + "-" + client.getUsername();

        // Create the root folder and List all the folders from IMAP server
        new File(rootFolder).mkdirs();
        ImapFolderInfoCollection folderInfoCollection = client.listFolders();
        for (ImapFolderInfo folderInfo : folderInfoCollection) {
            // Call the recursive method to read messages and get sub-folders
            listMessagesInFolder(folderInfo, rootFolder, client);
        }
        // Disconnect to the remote IMAP server
        client.dispose();
    } catch (java.lang.RuntimeException ex) {
        System.out.println(ex);
    }

    System.out.println("Downloaded messages recursively from IMAP server.");
}

/// Recursive method to get messages from folders and sub-folders
private static void listMessagesInFolder(ImapFolderInfo folderInfo, String rootFolder, ImapClient client) {
    // Create the folder in disk (same name as on IMAP server)
    String currentFolder = "data/";
    new File(currentFolder).mkdirs();

    // Read the messages from the current folder, if it is selectable
    if (folderInfo.getSelectable()) {
        // Send status command to get folder info
        ImapFolderInfo folderInfoStatus = client.getFolderInfo(folderInfo.getName());
        System.out.println(folderInfoStatus.getName() + " folder selected. New messages: " + folderInfoStatus.getNewMessageCount() + ", Total messages: "
                + folderInfoStatus.getTotalMessageCount());

        // Select the current folder and List messages
        client.selectFolder(folderInfo.getName());
        ImapMessageInfoCollection msgInfoColl = client.listMessages();
        System.out.println("Listing messages....");
        for (ImapMessageInfo msgInfo : msgInfoColl) {
            // Get subject and other properties of the message
            System.out.println("Subject: " + msgInfo.getSubject());
            System.out.println("Read: " + msgInfo.isRead() + ", Recent: " + msgInfo.getRecent() + ", Answered: " + msgInfo.getAnswered());

            // Get rid of characters like ? and :, which should not be included in a file name and Save the message in MSG format
            String fileName = msgInfo.getSubject().replace(":", " ").replace("?", " ");
            MailMessage msg = client.fetchMessage(msgInfo.getSequenceNumber());
            msg.save(currentFolder + "\\" + fileName + "-" + msgInfo.getSequenceNumber() + ".msg", SaveOptions.getDefaultMsgUnicode());
        }
        System.out.println("============================\n");
    } else {
        System.out.println(folderInfo.getName() + " is not selectable.");
    }

    try {
        // If this folder has sub-folders, call this method recursively to get messages
        ImapFolderInfoCollection folderInfoCollection = client.listFolders(folderInfo.getName());
        for (ImapFolderInfo subfolderInfo : folderInfoCollection) {
            listMessagesInFolder(subfolderInfo, rootFolder, client);
        }
    } catch (java.lang.RuntimeException e) {
    }
}

Получить UID сообщения или порядковый номер

Публичный API Aspose.Email предоставляет следующие возможности для получения информации об идентификации сообщения, такой как UID или порядковый номер, которые могут потребоваться при обработке сообщений, полученных с сервера:

MailboxInfo класс — представляет информацию идентификации сообщения в почтовом ящике.

  • getSequenceNumber() метод — получает порядковый номер сообщения.
  • getUniqueId() метод — получает уникальный идентификатор сообщения.

MailMessage класс — представляет электронное сообщение и позволяет получать свойства сообщения, например тему, тело, отправителя и адреса получателей и т.д.

  • getItemId метод — представляет идентификационную информацию о сообщении в почтовом ящике.

Следующий пример кода демонстрирует, как получить и отобразить детали сообщений из папки "INBOX" на IMAP‑сервере с использованием ImapClient класс:

try (ImapClient client = new ImapClient(imapHost, port, emailAddress, password, securityOption)) {
    ImapMessageInfoCollection msgs = client.listMessages("INBOX");
    List<Integer> seqIds = new ArrayList<>();
    for (ImapMessageInfo msg : msgs) {
        seqIds.add(msg.getSequenceNumber());
    }
    Iterable<MailMessage> msgsViaFetch = client.fetchMessagesBySequences(seqIds);
    for (MailMessage thisMsg : msgsViaFetch) {
        System.out.println("Message ID: " + thisMsg.getItemId().getUniqueId()
                + " SequenceNumber: " + thisMsg.getItemId().getSequenceNumber()
                + " Subject: " + thisMsg.getSubject());
    }
}

Получение дополнительных параметров как сводной информации

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
final ImapClient client = new ImapClient("host.domain.com", "username", "password");
try {
    MailMessage message = new MailMessage("from@domain.com", "to@doman.com", "EMAILNET-38466 - " + UUID.randomUUID().toString(),
            "EMAILNET-38466 Add extra parameters for UID FETCH command");

    // append the message to the server
    String uid = client.appendMessage(message);

    // wait for the message to be appended
    Thread.sleep(5000);

    // Define properties to be fetched from server along with the message
    List<String> messageExtraFields = Arrays.asList("X-GM-MSGID", "X-GM-THRID");

    // retreive the message summary information using it's UID
    ImapMessageInfo messageInfoUID = client.listMessage(uid, messageExtraFields);

    // retreive the message summary information using it's sequence number
    ImapMessageInfo messageInfoSeqNum = client.listMessage(1, messageExtraFields);

    // List messages in general from the server based on the defined properties
    ImapMessageInfoCollection messageInfoCol = client.listMessages(messageExtraFields);

    ImapMessageInfo messageInfoFromList = messageInfoCol.get_Item(0);

    // verify that the parameters are fetched in the summary information
    for (String paramName : messageExtraFields) {
        System.out.println(messageInfoFromList.getExtraParameters().containsKey(paramName));
        System.out.println(messageInfoUID.getExtraParameters().containsKey(paramName));
        System.out.println(messageInfoSeqNum.getExtraParameters().containsKey(paramName));
    }
} finally {
    if (client != null)
        client.dispose();
}

Получение информации заголовка List-Unsubscribe

Заголовок List-Unsubscribe содержит URL для отписки от почтовых рассылок, например рекламных, новостных и т.д. Чтобы получить заголовок List-Unsubscribe, используйте listUnsubscribe свойство ImapMessageInfo класс. В следующем примере показано использование listUnsubscribe свойство для получения заголовка List-Unsubscribe.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-Java
ImapClient imapClient = new ImapClient();
imapClient.setHost("<HOST>");
imapClient.setPort(993);
imapClient.setUsername("<USERNAME>");
imapClient.setPassword("<PASSWORD>");
imapClient.setSupportedEncryption(EncryptionProtocols.Tls);
imapClient.setSecurityOptions(SecurityOptions.SSLImplicit);

ImapMessageInfoCollection messageInfoCol = imapClient.listMessages();
for (ImapMessageInfo imapMessageInfo : messageInfoCol) {
    System.out.println("ListUnsubscribe Header: " + imapMessageInfo.getListUnsubscribe());
}