Подтвердить что ты не робот

Получение System.Net.Mail.MailMessage как MemoryStream в .NET 4.5 beta

Итак, приведенный ниже код использовался для работы в .NET 4, чтобы получить объект System.Net.Mail.MailMessage как MemoryStream, однако с выпуском бета-версии .NET 4.5 возникает исключение среды выполнения.

Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
    ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
    object mailWriter = mailWriterContructor.Invoke(new object[] { stream });
    MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
    sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);

    .....
}

Исключение времени выполнения происходит в sendMethod.Invoke().

4b9b3361

Ответ 1

Удалось выяснить, как это сделать снова в бета-версии .NET 4.5. Частный API-метод Send() в MailMessage изменился на: internal void Send (создатель BaseWriter, bool sendEnvelope, bool allowUnicode)

Пожалуйста, найдите обновленный код ниже.

Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
    ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
    object mailWriter = mailWriterContructor.Invoke(new object[] { stream });
    MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
    sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);

    .....
}

Ответ 2

Это может быть полезно, если вы не хотите идти с неподдерживаемыми хаками и не возражаете против увеличения производительности.

public static class MailMessageExtensions
    {
    public static string  RawMessage(this MailMessage m)
        {
        var smtpClient = new SmtpClient { DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory };

        using (var tempDir = new TemporaryDirectory())
            {
            smtpClient.PickupDirectoryLocation = tempDir.DirectoryPath;
            smtpClient.Send( m );
            var emlFile = Directory.GetFiles( smtpClient.PickupDirectoryLocation ).FirstOrDefault();
            if ( emlFile != null )
                {
                return File.ReadAllText( emlFile );
                }
            else
                return null;
            }
        return null;
        }

    }

class TemporaryDirectory : IDisposable
    {
    public TemporaryDirectory()
        {
        DirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
        Directory.CreateDirectory( DirectoryPath );
        }

    public string DirectoryPath { get; private set; }

    public void Dispose()
        {
        if ( Directory.Exists( DirectoryPath ) )
            Directory.Delete( DirectoryPath, true );
        }
    }

Ответ 3

для проверки использования дополнительного логического значения:

 If _sendMethod.GetParameters.Length = 2 Then
    _sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Object() {_mailWriter, True}, Nothing)
 Else
    _sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Object() {_mailWriter, True, True}, Nothing)
 End If

Ответ 4

Предлагаемое решение с дополнительным TRUE работает красиво.

Я начал получать ошибку при запуске моего проекта в VS2012, хотя я не использую .net 4.5, но 4.0 во всех моих библиотеках.

Ошибка происходит только на компьютере, на котором установлена ​​VS2012, выглядит так: VS2012 ссылается на .net 4.5 во время отладки. Когда вы развертываете и запускаете приложение в клиентах, работающих с .net 4.0, все работает нормально.

Таким образом: если вы запустите 4.0 - не добавляйте дополнительный TRUE, если вы запустите 4.5, добавьте его.

Ответ 5

Мы долго боролись с конверсией почтовых сообщений. В конечном итоге решение было использовать MimeKit.

var memoryStream = new MemoryStream();
var mimeMessage = MimeMessage.CreateFromMailMessage(message);
mimeMessage.WriteTo(memoryStream);

Если вы воспользуетесь описанными выше методами, вы очень близко подойдете, и это сработает в большинстве культур, но в конечном итоге кодировка объекта победит вас.