MailKit: как загрузить все вложения локально из MimeMessage

Я просмотрел другие примеры в Интернете, но я не могу понять, как загрузить и сохранить ВСЕ вложения из объекта MimeMessage. Я заглянул в WriteTo (), но не смог заставить его работать. Также интересно, будут ли вложения сохраняться в соответствии с исходным именем файла, и введите его в электронное письмо. Вот что у меня есть на данный момент:

using (var client = new ImapClient())
{
    client.Connect(Constant.GoogleImapHost, Constant.ImapPort, SecureSocketOptions.SslOnConnect);
    client.AuthenticationMechanisms.Remove(Constant.GoogleOAuth);
    client.Authenticate(Constant.GoogleUserName, Constant.GenericPassword);

    if (client.IsConnected == true)
    {
        FolderAccess inboxAccess = client.Inbox.Open(FolderAccess.ReadWrite);
        IMailFolder inboxFolder = client.GetFolder(Constant.InboxFolder);
        IList<UniqueId> uids = client.Inbox.Search(SearchQuery.All);

        if (inboxFolder != null & inboxFolder.Unread > 0)
        {
            foreach (UniqueId msgId in uids)
            {
                MimeMessage message = inboxFolder.GetMessage(msgId);

                foreach (MimeEntity attachment in message.Attachments)
                {
                    //need to save all the attachments locally
                }
            }
        }
    }
}

person Community    schedule 10.04.2017    source источник
comment
Вам нужно будет выполнить некоторую дезинфекцию имен файлов. Проверяйте на подделки, удаляйте плохие символы ...   -  person Max    schedule 10.04.2017


Ответы (1)


Все это объясняется в FAQ раздела «Как мне сохранить вложения? " раздел.

Вот исправленная версия кода, который вы разместили в своем вопросе:

using (var client = new ImapClient ()) {
    client.Connect (Constant.GoogleImapHost, Constant.ImapPort, SecureSocketOptions.SslOnConnect);
    client.AuthenticationMechanisms.Remove (Constant.GoogleOAuth);
    client.Authenticate (Constant.GoogleUserName, Constant.GenericPassword);

    client.Inbox.Open (FolderAccess.ReadWrite);
    IList<UniqueId> uids = client.Inbox.Search (SearchQuery.All);

    foreach (UniqueId uid in uids) {
        MimeMessage message = client.Inbox.GetMessage (uid);

        foreach (MimeEntity attachment in message.Attachments) {
            var fileName = attachment.ContentDisposition?.FileName ?? attachment.ContentType.Name;

            using (var stream = File.Create (fileName)) {
                if (attachment is MessagePart) {
                    var rfc822 = (MessagePart) attachment;

                    rfc822.Message.WriteTo (stream);
                } else {
                    var part = (MimePart) attachment;

                    part.Content.DecodeTo (stream);
                }
            }
        }
    }
}

Несколько примечаний:

  1. Нет необходимости проверять client.IsConnected после аутентификации. Если бы он не был подключен, это вызвало бы исключение в методе Authenticate(). Если бы это не удалось, это вызвало бы исключение и в методе Connect(). Нет необходимости проверять состояние IsConnected, если вы буквально только что вызвали Connect() на две строки вверх.
  2. Зачем вы проверяете inboxFolder.Unread, если даже нигде не пользуетесь? Если вы просто хотите загрузить непрочитанные сообщения, измените свой поиск на SearchQuery.NotSeen, что даст вам только UID сообщений, которые не были прочитаны.
  3. Я удалил вашу IMailFolder inboxFolder = client.GetFolder(Constant.InboxFolder); логику, потому что она вам не нужна. Если вы собираетесь выполнять ПОИСК с использованием client.Inbox, не перебирайте результаты с другим объектом папки.
person jstedfast    schedule 10.04.2017
comment
Это не будет работать для TnefPart (winmail.dat). ссылка: github.com/jstedfast/MimeKit/issues/234 - person MichaelD; 07.10.2018
comment
Конечно, будет. Приведенный выше код отлично сохранит вложение winmail.dat. Этот отчет об ошибке не имеет ничего общего с сохранением вложения winmail.dat. - person jstedfast; 07.10.2018
comment
Просто укажите другим читателям, которые хотят обрабатывать вложения электронной почты, что они также должны обрабатывать структуру tnef winmail.dat. Если вы не знаете об этом, вы можете удалить winmail.dat, пока в нем могут находиться важные файлы. Кстати, спасибо за отличную библиотеку! - person MichaelD; 07.10.2018
comment
Просто хотел прокомментировать и сказать спасибо, все равно спасибо все это время. Ваши библиотеки и упорный труд просто великолепны! Хотел бы я дать вам больше голосов и спасибо! - person Piotr Kula; 02.07.2020