使用C#SDK时,亚马逊SES、附件、点填充的双周期问题

使用C#SDK时,亚马逊SES、附件、点填充的双周期问题,c#,amazon-web-services,amazon-ses,mailmessage,C#,Amazon Web Services,Amazon Ses,Mailmessage,任何使用过它的人都知道,要通过Amazon SES C#SDK发送带有附件的电子邮件,必须使用sendrawmail功能(这非常糟糕)。为此,您要么手工编写MIME消息,要么将System.Net.Mail.MailMessage对象转换为MemoryStream。这一切都很好,但我遇到了一个问题。经过大量挖掘,我已经能够找到问题并复制它,它似乎是SMTP点填充的副产品 问题在于,在某些情况下,当MailMessage转换为原始MIME消息时,如果消息正文中的一个句点被包装到原始消息中一行的开头

任何使用过它的人都知道,要通过Amazon SES C#SDK发送带有附件的电子邮件,必须使用
sendrawmail
功能(这非常糟糕)。为此,您要么手工编写MIME消息,要么将
System.Net.Mail.MailMessage
对象转换为
MemoryStream
。这一切都很好,但我遇到了一个问题。经过大量挖掘,我已经能够找到问题并复制它,它似乎是SMTP点填充的副产品

问题在于,在某些情况下,当
MailMessage
转换为原始MIME消息时,如果消息正文中的一个句点被包装到原始消息中一行的开头,那么它就会被点填充(我正确地假设)。然而,它似乎既不在SDK内部处理,也不在SES方面处理,因为电子邮件是以双句点发送的。这可以通过以下示例控制台应用程序代码进行复制

static void Main(字符串[]args)
{
var to=新列表{{u toAddress};
var subject=“测试消息”;
var message=$“这是一个精心编制的HTML电子邮件正文,您应该在此处看到一个句点->。但是,您将在电子邮件中看到两个句点,而不是代码中最初给出的一个句点。”;
var body=$“
您好,

{message}

真诚地说,

您的测试人员”; var result=sendmail(收件人、主题、正文、null、isHtml:true); Console.WriteLine(结果?“成功发送消息”:“发送消息失败”); if(Debugger.IsAttached) { Console.WriteLine(“按任意键继续…”); Console.ReadLine(); } } 私有静态bool sendmail(列表收件人、字符串主题、字符串正文、列表附件filepath=null、bool isHtml=false) { var message=新邮件消息 { From=新邮件地址(_fromAddress), 主语, 身体, IsBodyHtml=isHtml }; foreach(到中的变量地址) { message.To.Add(address.Trim()); } if(AttachmentFilePath?.Any()==true) { foreach(AttachmentFilePath中的var filePath) { message.Attachments.Add(新附件(文件路径)); } } 尝试 { var creds=新的基本凭证(\u SESAccessKey,\u SESSecretKey); 使用(var client=newamazonsimpleemailserviceclient(creds,RegionEndpoint.USEast1)) { var request=new sendrawmailrequest{RawMessage=new RawMessage{Data=convertmailmessagetomorystream(message)}; Console.WriteLine($“RawMessage.Data…\r\n\r\n{Encoding.ASCII.GetString(request.RawMessage.Data.ToArray())}”); 客户端。发送电子邮件(请求); 返回true; } } 捕获(例外情况除外) { WriteLine($“AmazonSESHelper.sendmail=>异常:{ex.Message}”); } 返回false; } //为了向SESAPI发送附件,我们必须做这个反射垃圾 //从http://stackoverflow.com/questions/29532152/create-mime-mail-with-attachment-for-aws-ses-c-sharp/29533336#29533336 私有静态内存流转换MailMessage到MoryStream(MailMessage消息) { var stream=newmemoryStream(); var assembly=typeof(SmtpClient).assembly; var mailWriterType=assembly.GetType(“System.Net.Mail.MailWriter”); var mailWriterConstructor=mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null,new[]{typeof(Stream)},null); var mailWriter=mailWriterConstructor.Invoke(新对象[]{stream}); var sendMethod=typeof(MailMessage).GetMethod(“发送”,BindingFlags.Instance | BindingFlags.NonPublic); Invoke(message,BindingFlags.Instance | BindingFlags.NonPublic,null,new[]{mailWriter,true,true},null); var closeMethod=mailWriter.GetType().GetMethod(“Close”,BindingFlags.Instance | BindingFlags.NonPublic); 调用(mailWriter,BindingFlags.Instance | BindingFlags.NonPublic,null,新对象[]{},null); 回流; }
输出的原始MIME消息是

X-Sender: noreply@bar.com
X-Receiver: foo@bar.com
MIME-Version: 1.0
From: noreply@bar.com
To: foo@bar.com
Date: 2 Dec 2016 11:45:36 -0500
Subject: TEST MESSAGE
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

<br />Hello,<br /><br />This is a carefully crafted HTML email me=
ssage body such that you should see a single period right here ->=
.. However, you'll see <strong>two periods</strong> in the email i=
nstead of one period like originally given in the code.<br /><br =
/>Sincerely,<br /><br />Your Tester
X-Sender:noreply@bar.com
X接收器:foo@bar.com
MIME版本:1.0
发件人:noreply@bar.com
致:foo@bar.com
日期:2016年12月2日11:45:36-0500
主题:测试消息
内容类型:text/html;字符集=美国ascii码
内容传输编码:引用可打印

您好,

这是一封精心制作的HTML电子邮件= 消息正文,以便您可以在此处看到单个句点->= .. 但是,您将在电子邮件i中看到两个句号= n删除代码中最初给出的一个句点。
真诚地说,

您的测试人员
你可以看到点填充(再次,假设这是正确的每SMTP),但它并没有得到取消后,发送可以看到当我收到电子邮件


如果我加上@jstedfast(这很好),但在我们所有的应用程序中增加了另一个依赖项,我就可以实现这一点,这不是我最喜欢做的事情。在做任何事情之前,我想把它扔到这里,看看我是否遗漏了什么。如果不是这样,SES将承认这是一个问题并解决它将是一件好事。否则,我必须在另一个库依赖项或跳转SES到另一个邮件提供商之间做出决定

事实证明,这是AWS方面的一个问题,但他们不会很快(甚至根本不会)解决。我在GitHub回购协议上发布了一个问题,如下所示:

此后,我在我们的应用程序中添加了MimeKit,以取代通过反射转换为mime。新的
ConvertMailMessageToMemoryStream
是:

private static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message)
{
    var stream = new MemoryStream();
    var mimeMessage = MimeMessage.CreateFromMailMessage(message);
    mimeMessage.Prepare(EncodingConstraint.None);
    mimeMessage.WriteTo(stream);
    return stream;
}

我也遇到了同样的问题,但在作为电子邮件发送之前,通过将MailMessage正文编码设置为UTF-8可以解决这个问题

mail.BodyEncoding = System.Text.Encoding.UTF8;
(见附件)