任何使用它的人都知道,要通过带有附件的Amazon SES C#SDK发送电子邮件,您必须使用SendRawEmail
功能(非常臭)。为此,您可以手动编写MIME邮件代码,或者将System.Net.Mail.MailMessage
对象转换为MemoryStream
。这一切都很好,但我遇到了一个问题。经过多次挖掘,我已经能够找到问题并复制它,它似乎是SMTP点填充的副产品。
问题在于,在某些情况下,当MailMessage
转换为原始MIME消息时,如果消息正文中的句点被包装到原始消息中的行的开头,那么它是 - 塞满(正确的我假设)。但是,它似乎没有在SDK内部或SES方面处理,因为电子邮件通过双倍期间。这可以通过以下示例控制台应用程序代码复制...
static void Main(string[] args)
{
var to = new List<string> { _toAddress };
var subject = "TEST MESSAGE";
var message = $"This is a carefully crafted HTML email message body such that you should see a single period right here ->. However, you'll see <strong>two periods</strong> in the email instead of one period like originally given in the code.";
var body = $"<br />Hello,<br /><br />{message}<br /><br />Sincerely,<br /><br />Your Tester";
var result = SendEmail(to, subject, body, null, isHtml: true);
Console.WriteLine(result ? "Successfully sent message" : "Failed to send message");
if (Debugger.IsAttached)
{
Console.WriteLine("Press any key to continue...");
Console.ReadLine();
}
}
private static bool SendEmail(List<string> to, string subject, string body, List<string> attachmentFilePaths = null, bool isHtml = false)
{
var message = new MailMessage
{
From = new MailAddress(_fromAddress),
Subject = subject,
Body = body,
IsBodyHtml = isHtml
};
foreach (var address in to)
{
message.To.Add(address.Trim());
}
if (attachmentFilePaths?.Any() == true)
{
foreach (var filePath in attachmentFilePaths)
{
message.Attachments.Add(new Attachment(filePath));
}
}
try
{
var creds = new BasicAWSCredentials(_SESAccessKey, _SESSecretKey);
using (var client = new AmazonSimpleEmailServiceClient(creds, RegionEndpoint.USEast1))
{
var request = new SendRawEmailRequest { RawMessage = new RawMessage { Data = ConvertMailMessageToMemoryStream(message) } };
Console.WriteLine($"RawMessage.Data...\r\n\r\n{Encoding.ASCII.GetString(request.RawMessage.Data.ToArray())}");
client.SendRawEmail(request);
return true;
}
}
catch (Exception ex)
{
Console.WriteLine($"AmazonSESHelper.SendEmail => Exception: {ex.Message}");
}
return false;
}
// Have to do this reflection crap in order to send attachments to the SES API
// From http://stackoverflow.com/questions/29532152/create-mime-mail-with-attachment-for-aws-ses-c-sharp/29533336#29533336
private static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message)
{
var stream = new MemoryStream();
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(new object[] { stream });
var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);
closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
return stream;
}
输出的原始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
你可以看到点填充(再次,假设每个SMTP是正确的),但是在发送后它没有完成,因为我收到电子邮件时可以看到......
如果我添加@jstedfast MimeKit(这很棒)我可以使用它,但在我们所有的应用程序中添加了另一个依赖项,这不是我最喜欢的事情。在此之前,我想把它扔出去看看是否有任何我想念的东西。如果没有,那么很高兴看到SES承认这是一个问题并修复它。否则,我必须决定另一个库依赖项或从SES跳转到另一个邮件提供商。
答案 0 :(得分:0)
事实证明,这是AWS方面的一个问题,但它们不会很快(甚至根本不会)解决。我在GitHub回购中发布了一个问题,如下所示:
https://github.com/aws/aws-sdk-net/issues/501
我已经在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;
}
答案 1 :(得分:0)
我遇到了同样的问题,但是能够通过将MailMessage主体编码设置为UTF-8来修复它,然后再作为RawEmail发送
mail.BodyEncoding = System.Text.Encoding.UTF8;
(见System.Net.Mail creating invalid emails and eml files? Inserting extra dots in host names)