因此,下面的代码曾经在.NET 4中用于将System.Net.Mail.MailMessage对象作为MemoryStream获取,但是随着.NET 4.5 beta的发布,发生了运行时异常。
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()上发生运行时异常。
答案 0 :(得分:30)
管理如何在.NET 4.5 beta中重新使用它。 MailMessage中的私有API Send()方法已更改为:internal void Send(BaseWriter writer,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);
.....
}
答案 1 :(得分:12)
如果您不想使用不受支持的黑客并且不介意额外的性能影响,这可能是有用的。
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 );
}
}
答案 2 :(得分:9)
用于检查我是否使用了额外的布尔值:
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
答案 3 :(得分:0)
带有额外TRUE的建议解决方案非常有效。
我在VS2012中运行项目时遇到错误,即使我在所有库中都没有使用.net 4.5但是4.0。
错误只发生在安装了VS2012的机器上,看起来VS2012在调试时会引用.net 4.5。在运行.net 4.0的客户端中部署和运行应用程序时,一切正常。
因此:如果你运行4.0 - 不要添加额外的TRUE,如果你运行4.5添加它。
答案 4 :(得分:0)
我们与邮件转换进行了长期的战斗。最终,解决方案是使用MimeKit。
var memoryStream = new MemoryStream();
var mimeMessage = MimeMessage.CreateFromMailMessage(message);
mimeMessage.WriteTo(memoryStream);
如果您使用上述方法,您将会非常接近,并且在大多数文化中都可以使用,但是最终主题编码会打败您。