MailKit записывает HtmlBody в базу данных в виде строки - PullRequest
0 голосов
/ 01 ноября 2018

Модель

 public class Mail
{
    public int Id { get; set; }
    public string Tema { get; set; }
    public string Note { get; set; }
    public string Date { get; set; }
    public string Email { get; set; }
}

Клиент IMAP

using (var client = new ImapClient())
        {
            var Emails = _context.Settings.FirstOrDefault();
            client.ServerCertificateValidationCallback = (s, c, h, e) => true;
            client.Connect(Emails.Imap,Convert.ToInt32(Emails.ImapPort), true);
            client.Authenticate(Emails.Login, Emails.Password);
            client.Inbox.Open(FolderAccess.ReadOnly);

            var inbox = client.Inbox;
            var messages = inbox.Fetch(0, -1, MessageSummaryItems.All | MessageSummaryItems.Full | MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure);
            if (messages.Where(c => c.Flags.Value.HasFlag(MessageFlags.Seen) != true).Count() > 0)
            {

                foreach (var message in messages.Where(c => c.Flags.Value.HasFlag(MessageFlags.Seen) != true))
                {
                    var mime = inbox.GetBodyPart(message.UniqueId, message.HtmlBody);
                    Mail mail = new Mail();
                    mail.Date = DateTime.Now;
                    mail.Note = Convert.ToString(mime);
                    mail.Tema = message.Envelope.Subject.ToString();
                    mail.Email = Convert.ToString(message.Date);
                    _context.Add(mail);
                    await _context.SaveChangesAsync();
                    break;
                }
            }
            client.Disconnect(true);
        }

в результате я получаю нечитаемую строку в примечании

   Content-Type: text/html; charset="utf-8"
 Content-Transfer-Encoding: base64

 PGh0bWw+PGhlYWQ+PG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50
 PSJ0ZXh0L2h0bWw7Ij48dGl0bGU+0JzQldCU0JjQkNCb0J7Qk9CY0K88L3RpdGxlPjxz
 dHlsZT4uYmR7Zm9udDogMTI1JS8xMTUlIGFyaWFsLCBzYW5zLXNlcmlmOyBjb2xvcjog
 IzAwM0U1MDsgbWFyZ2luLXRvcDogMTJweH0gcHtmb250OiAxMDAlIGFyaWFsLCBzYW5z
 LXNlcmlmOyBjb2xvcjogIzAwM0U1MDsgbWFyZ2luLXRvcDogMTJweH0gdGR7Zm9udDog
 ODAlLzExNSUgYXJpYWwsIHNhbnMtc2VyaWY7IGNvbG9yOiAjMDAzRTUwOyBtYXJnaW4t
 dG9wOiAxMnB4fSB0ZC5oZHJ7Zm9udDogYm9sZCAxMXB4LzE0cHggYXJpYWwsIHNhbnMt
 c2VyaWY7IGNvbG9yOiAjMWIxYjU2OyBtYXJnaW4tdG9wOiAxMnB4OyBsaW5lLWhlaWdo
 dDoxNXB4O30gLnNlYXJjaF9obHtjb2xvcjogI2ZmZmZmZjtiYWNrZ3JvdW5kLWNvbG9y
 OiAjMDAzODQ4O308L3N0eWxlPjwvaGVhZD48Ym9keSBiZ2NvbG9yPSNGRkZGRkY+PHRh
 ......

после «Content-Transfer-Encoding: base64» мы видим html-файл в bass64. Есть ли способ, MileKit будет записывать только данные самого файла.

1 Ответ

0 голосов
/ 01 ноября 2018

Вы, по сути, вызываете MimePart.ToString() ... и, насколько MimeKit знает, вы хотите MIME в виде строки.

Но это не то, что вы на самом деле хотите.

То, что вы хотите, это фактический текстовый контент.

Вот что вам нужно сделать в цикле:

var html = (TextPart) inbox.GetBodyPart (message.UniqueId, message.HtmlBody);
Mail mail = new Mail();
mail.Date = DateTime.Now;
mail.Note = html.Text;
...

A TextPart - это подкласс MimePart, который представляет text/* MIME-части (включая text/html) и имеет несколько удобных API, которые можно использовать для получения (или установки) текстового содержимого MimePart в виде строки вместо того, чтобы иметь дело с потоками - в первую очередь это свойство .Text.

Это должно ответить на ваш вопрос, но я еще не закончил, потому что ваш код может использовать еще несколько изменений.

Вместо того, чтобы просить MailKit Fetch() метаданные для каждого отдельного сообщения в вашем почтовом ящике, почему бы не запросить только то, что вам нужно?

Поскольку вам явно не безразличны уже просмотренные сообщения, вы можете воспользоваться функциональностью ПОИСКА IMAP, например:

var uids = inbox.Search (SearchQuery.NotSeen);
if (uids.Count > 0)
{
    var messages = inbox.Fetch (uids, MessageSummaryItems.UniqueId | MessageSummaryItems.Envelope | MessageSummaryItems.Flags | MessageSummaryItems.BodyStructure);
    foreach (var message in messages.Where (c => !c.Flags.Value.HasFlag (MessageFlags.Seen))
    {
        // ...
    }
}

Примечание. Вам по-прежнему необходимо использовать фильтр Where(), поскольку возможно изменение флагов сообщений (другим клиентом) между Search() и Fetch(). Я также изменил MessageSummaryItems на только поля, которые вы фактически используете.

Вы также можете избавиться от своего оператора if (messages.Where(c => c.Flags.Value.HasFlag(MessageFlags.Seen) != true).Count() > 0), поскольку он является избыточным и требует полного прохода для возвращаемых данных, когда в следующий раз вы все равно будете зацикливать данные.

А поскольку вы break; вышли из цикла, как только вы нашли самое первое сообщение, которое еще не было замечено, почему бы не сделать это вместо этого?

var message = messages.FirstOrDefault (x => !x.Flags.Value.HasFlag (MessageFlags.Seen));
if (message != null)
{
    var html = (TextPart) inbox.GetBodyPart(message.UniqueId, message.HtmlBody);
    Mail mail = new Mail();
    mail.Date = DateTime.Now;
    mail.Note = html.Text;
    mail.Tema = message.Envelope.Subject;
    mail.Email = Convert.ToString(message.Envelope.Date);
    _context.Add(mail);
    await _context.SaveChangesAsync();
}

Конечный результат:

using (var client = new ImapClient())
{
    var Emails = _context.Settings.FirstOrDefault();
    client.ServerCertificateValidationCallback = (s, c, h, e) => true;
    client.Connect(Emails.Imap,Convert.ToInt32(Emails.ImapPort), true);
    client.Authenticate(Emails.Login, Emails.Password);
    client.Inbox.Open(FolderAccess.ReadOnly);

    var inbox = client.Inbox;
    var uids = inbox.Search (SearchQuery.NotSeen);
    if (uids.Count > 0)
    {
        var messages = inbox.Fetch (uids, MessageSummaryItems.UniqueId | MessageSummaryItems.Envelope | MessageSummaryItems.Flags | MessageSummaryItems.BodyStructure);
        var message = messages.FirstOrDefault (x => !x.Flags.Value.HasFlag (MessageFlags.Seen));
        if (message != null)
        {
            var html = (TextPart) inbox.GetBodyPart(message.UniqueId, message.HtmlBody);
            Mail mail = new Mail();
            mail.Date = DateTime.Now;
            mail.Note = html.Text;
            mail.Tema = message.Envelope.Subject;
            mail.Email = Convert.ToString(message.Envelope.Date);
            _context.Add(mail);
            await _context.SaveChangesAsync();
        }
    }

    client.Disconnect(true);
}

Последнее изменение, которое вам нужно внести в приведенный выше код, - это то, что делать, если в сообщении нет тела HTML. Что, если сообщение имеет только тело text/plain? Или что, если он вообще не содержит каких-либо text/* частей?

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

...