添加为 smtp 的 MailAttachment 后,无法正确呈现 Exchange 电子邮件附件

Unable to render the Exchange Email attachment properly after adding as MailAttachment for smtp

提问人:Carls Jr. 提问时间:7/27/2023 最后编辑:Carls Jr. 更新时间:7/27/2023 访问量:34

问:

我需要将 EmailMessage 转换为 MailMessage 以发送 smtp 邮件。虽然如果附件是 .docx、.txt、.jpg 等文件,它会正确显示。我面临的问题是,每当电子邮件消息包含电子邮件附件(.msg)时,附件就会变成字符串/流(Image2)。我添加了附件对象(Image3)属性的屏幕截图。

问题:我需要在代码中添加什么以确保附件与来自 Microsoft Exchange 电子邮件的原始附件完全相似,例如预期结果 Image1?

Image1:发送 smtp 后附件的外观。 Before the attachment was sent via smtp

图2:smtp邮件发送后的附件结果。 Email Attachment in binaries

图3:附件属性截图 Attachment Properties

我的代码如下:

MailMessage message = new MailMessage();
EmailMessage msg = new EmailMessage(service); //service is Microsoft.Exchange.WebServices.Data
MemoryStream ms = new MemoryStream();
            
PropertySet propSet = new PropertySet(BasePropertySet.FirstClassProperties,ItemSchema.Attachments, EmailMessageSchema.NormalizedBody, EmailMessageSchema.TextBody);
propSet.RequestedBodyType = BodyType.HTML;
propSet.BlockExternalImages = false;
msg = EmailMessage.Bind(service, emailId, propSet);

foreach (Microsoft.Exchange.WebServices.Data.Attachment attachment in msg.Attachments){  
    if (attachment is FileAttachment)
    {
        // Attachments such as .txt, .docx, .xlsx
        // This code block for FileAttachment is totally working fine.
        FileAttachment fileAttachment = attachment as FileAttachment;
        if (fileAttachment != null)
        {
            fileAttachment.Load();
            ms = new MemoryStream(fileAttachment.Content);
            attachmentName = fileAttachment.Name;
            System.Net.Mail.Attachment att = new System.Net.Mail.Attachment(ms, attachmentName);
            message.Attachments.Add(att);
        }
    }
    else if (attachment is ItemAttachment)
    {
        //This is where the EmailMessage attachment gets converted to MailMessage attachment
        //Attachment is .msg
        //The result here becomes random strings
        ItemAttachment itemAttachment = attachment as ItemAttachment;
        if (itemAttachment != null)
        {
             itemAttachment.Load(new PropertySet(ItemSchema.MimeContent));
             byte[] itemContent = itemAttachment.Item.MimeContent.Content.ToArray();
             ms = new MemoryStream(itemContent);
             attachmentName = itemAttachment.Name;
             System.Net.Mail.Attachment att = new System.Net.Mail.Attachment(ms, attachmentName, attachment.ContentType);
             message.Attachments.Add(att);
        }
    }
}

//Send the MailMessage using SMTP
using (SmtpClient client = new SmtpClient())
{
    client.Host = config.smtp_AmazonAWSHost;
    client.Port = config.portSMTP;
    client.UseDefaultCredentials = false;
    client.Credentials = new NetworkCredential(config.smtp_Username, config.smtp_Password);
    client.EnableSsl = true;
    client.Send(message);
}
ExchangeWebServices 电子邮件附件 SMTPCLIENT 内存流 邮件消息

评论


答:

1赞 Heslacher 7/27/2023 #1

由于 ContentType 表示邮件(附件)采用 internet-message-format,这是邮件服务器通常发送和接收电子邮件的格式,因此您需要将附件名称从 .msg 更改为 .eml。 Outlook 可以轻松打开文件。message/rfc822eml

另请参阅:saving-an-email-to-a-msg-file-using-ews-managed-api

评论

0赞 Carls Jr. 7/27/2023
我试过了。这是行不通的。相同的结果
0赞 Heslacher 7/27/2023
本案包含哪些内容?attachment.ContentType
0赞 Carls Jr. 7/27/2023
我添加了附件的屏幕截图。ContentType 请参考 Image3。
0赞 Heslacher 7/27/2023
不太确定,但是您能否将附件的扩展更改为一个结尾并重试。.eml
0赞 Carls Jr. 7/27/2023 #2

我设法解决了这个问题。我在这里添加更新的代码,以便它可以帮助任何人。我尝试了@Heslacher的建议。

ItemAttachment itemAttachment = attachment as ItemAttachment;
if (itemAttachment != null)
{
   itemAttachment.Load(new PropertySet(ItemSchema.MimeContent));
   // Store it inside a memorystream
   byte[] itemContent = itemAttachment.Item.MimeContent.Content.ToArray();
   ms = new MemoryStream(itemContent);
   attachmentName = itemAttachment.Name;
 
   if (attachment.ContentType.ToString().ToLower().Equals("message/rfc822"))
   {
      //renaming the extension to make the email readable
      //Compatibility: .eml files are supported by many email clients and applications, 
      //making them a more portable and interoperable choice for 
      //sharing email messages across different platforms.
      attachmentName = $"{itemAttachment.Name}.eml";
   }
   System.Net.Mail.Attachment att = new System.Net.Mail.Attachment(ms, attachmentName);
   ContentDisposition disposition = att.ContentDisposition;
   disposition.Inline = true;
   att.ContentType.CharSet = "UTF-8";
   message.Attachments.Add(att);
}