2013-04-05 64 views
9

Iam使用亞馬遜SES SendRawEmail API,因此我需要一個MailMessage作爲一個Memorystream。C#MailMessage流 - 編碼問題

我已經找到了幾個答案,在這裏stackoverflow MailMessage到MemoryStream問題。

解決方案1:使用使用私有方法它會導致電子郵件的部分錯誤編碼的一個: https://stackoverflow.com/a/8826833

解決方案2:沒有編碼問題,使用該解決方案,您發送到拾取目錄,然後再讀回: https://stackoverflow.com/a/14350088

我非常不喜歡這樣一個事實,即我需要寫入臨時文件才能使其正常工作。 有沒有人有任何想法如何純粹的MemoryStream解決方案可以搞砸了一些編碼。

與郵件消息IAM測試是這樣的:

var mailMessage = new MailMessage(); 
mailMessage.Subject = "HEADER WITH SPECIAL ÆØÅ"; 
mailMessage.Body = "TEST"; 

Attachment att = new Attachment(@"C:\AttachmentWithSpecial ÆØÅ.pdf"); 
mailMessage.Attachments.Add(att); 
mailMessage.From = new MailAddress("[email protected]", "NameÆØÅ"); 
mailMessage.To.Add(new MailAddress("[email protected]", "NameÆØÅ")); 

總結:

  • 如果我發送標準SMTP此消息看起來不錯。
  • 如果我是用SendRawEmail它看起來不錯,如果我使用解決方案2
  • 產生的MemoryStream如果我把它用SendRawEmail它具有編碼的問題,如果我使用解決方案1 ​​

產生的MemoryStream送送隨着編碼問題我的意思是「O」顯示爲

enter image description here

+0

爲什麼不使用SendEmail呢? SES允許您撰寫電子郵件,並支持編碼。 – 2013-04-16 18:42:12

+0

正如我所見,它不支持附件。 ? – 2013-04-17 05:14:18

+0

哦,是的,你有沒有嘗試過使用StringWriter?內存流可能會忽略編碼,因爲它使用字節作爲存儲。 – 2013-04-17 07:08:06

回答

1

你嘗試明確指定爲主題/和MailAddress編碼?

我想,當.NET寫郵件到文件夾,並能以某種方式來定義正確的編碼(或可能文件讀取器以某種方式可以找到正確的編碼來轉換數據)。而在內存中,所有內容都是默認編碼,這對您不起作用。

+0

雅我試過,但是.NET我實際上很聰明,在必要時將它們設置爲UTF-8。 在一個郵件地址的構造函數中找到: this.displayNameEncoding = displayNameEncoding ?? Encoding.GetEncoding( 「UTF-8」); 這意味着如果你不定義編碼它將默認爲UTF-8。 在主題和正文的集合中,他們有代碼測試一個字符串是否僅包含ascii,否則它將嘗試猜測編碼是否自己。 所以,如果你做 mail.Subject =「æøå」; 然後檢查mail.SubjectEncoding它將正確地已經是UTF-8 – 2013-04-06 16:33:37

0
message.BodyEncoding = message.SubjectEncoding = message.HeadersEncoding = Encoding.UTF8; 
0

不幸的是MailMessage對象有問題,並且接口很差。

的好處是,.NET 4.5部分與allowUnicode標誌發送固定它()(不幸的發送方法仍然是私有的)

下面是修改「解決方案1」。 它以與「解決方案2」相同的方式編碼主題。 僅限.NET Framework 4.5。

private static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message) 
{ 
    Assembly systemAssembly = typeof(SmtpClient).Assembly; 
    Type mailWriterType = systemAssembly.GetType("System.Net.Mail.MailWriter"); 
    const BindingFlags nonPublicInstance = BindingFlags.Instance | BindingFlags.NonPublic; 
    ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(nonPublicInstance, null, new[] typeof(Stream) }, null); 

    MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", nonPublicInstance); 
    MethodInfo closeMethod = mailWriterType.GetMethod("Close", nonPublicInstance); 
    using (MemoryStream memoryStream = new MemoryStream()) 
    { 
     object mailWriter = mailWriterContructor.Invoke(new object[] { memoryStream }); 
     //AssertHelper.IsTrue(sendMethod.GetParameters().Length > 2, ".NET framework must be 4.5 or higher in order to properly encode email subject."); 
     sendMethod.Invoke(message, nonPublicInstance, null, 
      new[] { mailWriter, true, false }, 
      null); 
     closeMethod.Invoke(mailWriter, nonPublicInstance, null, new object[] { }, null); 
     return memoryStream; 
    } 
}