Проблема с двойной точкой в ​​Amazon SES, вложениями, расстановкой точек при использовании C# SDK

Как известно любому, кто работал с ним, чтобы отправить электронное письмо через SDK Amazon SES C# с вложением, вы должны использовать функцию 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: [email protected]
X-Receiver: [email protected]
MIME-Version: 1.0
From: [email protected]
To: [email protected]
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 на другого почтового провайдера.


person robertmiles3    schedule 02.12.2016    source источник


Ответы (2)



Я столкнулся с той же проблемой, но смог исправить ее, установив кодировку тела MailMessage в UTF-8 перед отправкой как RawEmail.

mail.BodyEncoding = System.Text.Encoding.UTF8;

(См. System. Net.Mail создает недействительные электронные письма и eml-файлы? Добавляет лишние точки в имена хостов)

person Benedict    schedule 12.04.2017