2016-03-08 4 views
1

Мы используем OpenPop для получения электронной почты. Я должен прочитать тему сообщения и показать его пользователю. Когда пользователь нажимает на сообщение, я хочу показать содержимое сообщения в заполнителе.
Вот мой код, чтобы показать содержание, но это не очень хорошо работает:Как использовать OpenPop для чтения электронной почты в формате HTML?

plhMessage.Controls.Add(new LiteralControl(Encoding.UTF8.GetString(client.GetMessage(0).RawMessage))); 

возвращает этот текст на голове:

Return-Path: [email protected] 
Received: from adspackages.com (Unknown [185.81.96.156]) by ip-30.afaghhost.com ; Mon, 7 Mar 2016 07:13:06 +0330 
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=adspackages.com; 
    s=default; h=Content-Transfer-Encoding:Content-Type: 
    MIME-Version:Message-ID:Subject:Reply-To:From:To:Date; 
    bh=MBNWLlH5FJIZMrbe+SG0izGjV9d9fR6eupDkfvgklSw=; 
    b=DLYlNuMd7ZAPCpQTQvGCi7yBiX aRhjlqQ8zGLPWcmDDX159frMVPiTh652Os3xwxWZ/iS4BQeOA5cFXdZSwcCxIO9hEaGr7ogZXVM5k blpgoO3htf9GAPJSDOxxVWIjEYgN3+m7UE1N7azmtvUPrrZkl9H8JwCIXLbI0SRpmHQ2ebA7QMgQM /Jl8u+5dLmWo4eYLxFgyTjZwTPPmLKwfSADjET3bb9ZfBTcK/KHsAjfx7Miy7zgP5vSE1n+p .... 

и показать сообщение без фотографий.

Как я могу получить HTML-адрес электронной почты, чтобы показать его в заполнителе? Также, как я могу показать фотографии, содержащиеся в сообщении электронной почты?

+0

Это, вероятно, поможет вам: http://stackoverflow.com/questions/10601913/openpop-net-get-actual-message-text – ManoDestra

+0

Ответ на этот вопрос может быть использован для получения обычного текста или HTML тела сообщений, но если изображения встроены в сообщение, то рендеринг возвращенного html не будет включать изображения (у него будут только сломанные изображения). – jstedfast

ответ

1

Прежде чем начать, я должен отметить, что вы не можете надежно использовать Encoding.UTF8.GetBytes() на client.GetMessage(0).RawMessage, потому что (ошибочно) предполагает, что данные необработанных сообщений находятся в UTF-8, и это не гарантируется. Большинство электронных писем в Западной Европе будут в одном из латинских кодировок, русские электронные письма, как правило, будут в iso-8859-5, windows-1251 или koi8-r. Китайская, японская и корейская электронная почта почти всегда будут в одном из своих языковых кодировок (обычно gbk/big5, iso-2022-jp и euc-kr соответственно).

Теперь, когда это разрешено ... давайте перейдем к вашему основному вопросу.

То, что вы хотите сделать, это довольно откровенно намного проще сделать с помощью MailKit, чем при использовании OpenPOP, поэтому я покажу вам, как сделать это с помощью MailKit вместо:

Чтобы получить сообщение, MailKit работы очень похоже OpenPOP делает:

using System; 

using MailKit.Net.Pop3; 
using MailKit; 
using MimeKit; 

namespace TestClient { 
    class Program 
    { 
     public static void Main (string[] args) 
     { 
      using (var client = new Pop3Client()) { 
       client.Connect ("pop.gmail.com", 995, true); 

       // Note: since we don't have an OAuth2 token, disable 
       // the XOAUTH2 authentication mechanism. 
       client.AuthenticationMechanisms.Remove ("XOAUTH2"); 

       client.Authenticate ("[email protected]", "password"); 

       for (int i = 0; i < client.Count; i++) { 
        var message = client.GetMessage (i); 
        // TODO: render the message 
       } 

       client.Disconnect (true); 
      } 
     } 
    } 
} 

оказывать сообщение, используя MailKit, самый простой способ, чтобы написать свой собственный MimeVisitor так:

/// <summary> 
/// Visits a MimeMessage and generates HTML suitable to be rendered by a browser control. 
/// </summary> 
class HtmlPreviewVisitor : MimeVisitor 
{ 
    List<MultipartRelated> stack = new List<MultipartRelated>(); 
    List<MimeEntity> attachments = new List<MimeEntity>(); 
    string body; 

    /// <summary> 
    /// Creates a new HtmlPreviewVisitor. 
    /// </summary> 
    public HtmlPreviewVisitor() 
    { 
    } 

    /// <summary> 
    /// The list of attachments that were in the MimeMessage. 
    /// </summary> 
    public IList<MimeEntity> Attachments { 
     get { return attachments; } 
    } 

    /// <summary> 
    /// The HTML string that can be set on the BrowserControl. 
    /// </summary> 
    public string HtmlBody { 
     get { return body ?? string.Empty; } 
    } 

    protected override void VisitMultipartAlternative (MultipartAlternative alternative) 
    { 
     // walk the multipart/alternative children backwards from greatest level of faithfulness to the least faithful 
     for (int i = alternative.Count - 1; i >= 0 && body == null; i--) 
      alternative[i].Accept (this); 
    } 

    protected override void VisitMultipartRelated (MultipartRelated related) 
    { 
     var root = related.Root; 

     // push this multipart/related onto our stack 
     stack.Add (related); 

     // visit the root document 
     root.Accept (this); 

     // pop this multipart/related off our stack 
     stack.RemoveAt (stack.Count - 1); 
    } 

    // look up the image based on the img src url within our multipart/related stack 
    bool TryGetImage (string url, out MimePart image) 
    { 
     UriKind kind; 
     int index; 
     Uri uri; 

     if (Uri.IsWellFormedUriString (url, UriKind.Absolute)) 
      kind = UriKind.Absolute; 
     else if (Uri.IsWellFormedUriString (url, UriKind.Relative)) 
      kind = UriKind.Relative; 
     else 
      kind = UriKind.RelativeOrAbsolute; 

     try { 
      uri = new Uri (url, kind); 
     } catch { 
      image = null; 
      return false; 
     } 

     for (int i = stack.Count - 1; i >= 0; i--) { 
      if ((index = stack[i].IndexOf (uri)) == -1) 
       continue; 

      image = stack[i][index] as MimePart; 
      return image != null; 
     } 

     image = null; 

     return false; 
    } 

    // Save the image to our temp directory and return a "data:" url suitable for 
    // the browser control to load. 
    string GetDataImageSrc (MimePart image) 
    { 
     using (var output = new MemoryStream()) { 
      image.ContentObject.DecodeTo (output); 
      return string.Format ("data:{0};base64,{1}", image.ContentType.MimeType, Convert.ToBase64String (output.GetBuffer(), 0, (int) output.Length)); 
     } 
    } 

    // Replaces <img src=...> urls that refer to images embedded within the message with 
    // "data:" urls that the browser control will actually be able to load. 
    void HtmlTagCallback (HtmlTagContext ctx, HtmlWriter htmlWriter) 
    { 
     if (ctx.TagId == HtmlTagId.Image && !ctx.IsEndTag && stack.Count > 0) { 
      ctx.WriteTag (htmlWriter, false); 

      // replace the src attribute with a file:// URL 
      foreach (var attribute in ctx.Attributes) { 
       if (attribute.Id == HtmlAttributeId.Src) { 
        MimePart image; 
        string url; 

        if (!TryGetImage (attribute.Value, out image)) { 
         htmlWriter.WriteAttribute (attribute); 
         continue; 
        } 

        url = GetDataImageSrc (image); 

        htmlWriter.WriteAttributeName (attribute.Name); 
        htmlWriter.WriteAttributeValue (url); 
       } else { 
        htmlWriter.WriteAttribute (attribute); 
       } 
      } 
     } else if (ctx.TagId == HtmlTagId.Body && !ctx.IsEndTag) { 
      ctx.WriteTag (htmlWriter, false); 

      // add and/or replace oncontextmenu="return false;" 
      foreach (var attribute in ctx.Attributes) { 
       if (attribute.Name.ToLowerInvariant() == "oncontextmenu") 
        continue; 

       htmlWriter.WriteAttribute (attribute); 
      } 

      htmlWriter.WriteAttribute ("oncontextmenu", "return false;"); 
     } else { 
      // pass the tag through to the output 
      ctx.WriteTag (htmlWriter, true); 
     } 
    } 

    protected override void VisitTextPart (TextPart entity) 
    { 
     TextConverter converter; 

     if (body != null) { 
      // since we've already found the body, treat this as an attachment 
      attachments.Add (entity); 
      return; 
     } 

     if (entity.IsHtml) { 
      converter = new HtmlToHtml { 
       HtmlTagCallback = HtmlTagCallback 
      }; 
     } else if (entity.IsFlowed) { 
      var flowed = new FlowedToHtml(); 
      string delsp; 

      if (entity.ContentType.Parameters.TryGetValue ("delsp", out delsp)) 
       flowed.DeleteSpace = delsp.ToLowerInvariant() == "yes"; 

      converter = flowed; 
     } else { 
      converter = new TextToHtml(); 
     } 

     body = converter.Convert (entity.Text); 
    } 

    protected override void VisitTnefPart (TnefPart entity) 
    { 
     // extract any attachments in the MS-TNEF part 
     attachments.AddRange (entity.ExtractAttachments()); 
    } 

    protected override void VisitMessagePart (MessagePart entity) 
    { 
     // treat message/rfc822 parts as attachments 
     attachments.Add (entity); 
    } 

    protected override void VisitMimePart (MimePart entity) 
    { 
     // realistically, if we've gotten this far, then we can treat this as an attachment 
     // even if the IsAttachment property is false. 
     attachments.Add (entity); 
    } 
} 

Способ использовать этот HtmlPreviewVisitor будет что-то вроде этого:

void Render (MimeMessage message) 
{ 
    var visitor = new HtmlPreviewVisitor(); 

    message.Accept (visitor); 

    plhMessage.Controls.Add (new LiteralControl (visitor.HtmlBody)); 
} 

Примечание: если HTML в сообщениях вы планируете оказывать все ссылки веб-адреса для своих изображений, вы можете уйти с просто изображая строку message.HtmlBody. Однако решение HtmlPreviewVisitor, , будет работать, даже если изображения встроены в само сообщение.

+0

очень спасибо.и работал. – shahroz

+0

Как сохранить вложение почты? – shahroz

+0

В приведенных выше фрагментах кода 'HtmlPreviewVisitor.Attachments' - список вложений. Есть два типа подклассов MimeEntity, о которых вам нужно беспокоиться: 'MimePart' (наиболее распространенный) и' MessagePart' (который содержит части сообщения/rfc822). Метод 'GetDataImageSrc' выше показывает, как сохранить содержимое вложения (просто используйте 'FileStream' вместо' MemoryStream'). Чтобы сохранить содержимое «MessagePart», просто выполните «messagePart.Message».WriteTo (поток); ' – jstedfast

Смежные вопросы