C# 在.Net 4.5 beta版中将System.Net.Mail.MailMessage作为MemoryStream获取
因此,下面的代码用于在.NET 4中获得System.NET.Mail.MailMessage对象作为MemoryStream,但是随着.NET 4.5 beta的发布,会出现运行时异常C# 在.Net 4.5 beta版中将System.Net.Mail.MailMessage作为MemoryStream获取,c#,.net-4.5,C#,.net 4.5,因此,下面的代码用于在.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 Memo
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()上发生运行时异常。已设法找出如何在.NET 4.5 beta版中再次运行此功能。MailMessage中的私有API Send()方法已更改为:内部void Send(BaseWriter writer、bool sendEnvelope、bool allowinicode) 请在下面找到更新的代码
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);
.....
}
建议的解决方案加上额外的真值,效果很好 在VS2012中运行项目时,我开始出现错误,尽管我在所有库中使用的不是.net 4.5而是4.0 该错误仅发生在安装了VS2012的计算机上,看起来VS2012在调试时引用了.net 4.5。当您在运行.net 4.0的客户端中部署和运行应用程序时,一切正常
因此:如果您运行4.0-不要添加额外的TRUE,如果您运行4.5,请添加它。如果您不想使用不受支持的hack,也不介意额外的性能打击,这可能是有用的
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 );
}
}
用于检查我是否使用了额外的布尔值:
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
我们与邮件信息转换斗争了很长一段时间。最终的解决办法是使用
如果您使用上述方法,您将非常接近,并且在大多数文化中都可以使用,但最终主题编码将击败您。有什么例外(堆栈跟踪可能会有所帮助)?例外情况是:System.Reflection.TargetParameterCountException:参数计数不匹配。您是否将.NET 4代码与.NET 4.5进行了比较,以查看它们是否丢失了
发送的重载?使用dynamic
可以更简单地处理这一问题。请参阅下面的答案,他们在Send方法中添加了一个额外的布尔参数(AllowInCode)。这就是访问非公共方法所得到的结果:)据我所知,没有其他方法可以获取邮件的MemoryStream。甚至之前的文章都使用私有API方法,甚至第三方供应商的示例也使用这种私有API方法。如果有人知道使用公共API实现这一点的方法,那么分享它会有很大帮助:)嗨,除了closeMethod.Invoke(mailWriter,BindingFlags.Instance | BindingFlags.NonPublic,null,new object[]{},null);。。。有线索吗?ThanksNote,在.NET 5 MailWriterContractor中,上述代码中不能为null。新的构造函数是(Stream,bool)。是的,我也遇到过这个。我们必须设置编译器条件,这样我们才能调试代码并使其在生产环境中工作。这是一个很好的解决方法,并且可能会通过进一步的api版本工作。谢谢我在使用这种技术时发现的唯一问题是Bcc目的地从标头中删除。美好的不过有一件事:如果app.config包含smtp设置,则必须覆盖这些设置。请确保将主机设置为localhost
,凭据设置为null
,并将SSL启用为false
。这是我首选的解决方案。唯一的问题是;既然我们在Windows\TEMP中创建了随机文件夹,那么从长远来看,Windows会“允许”这样做吗?我的意思是,如果很多邮件一直同时发送,程序最终会因此而崩溃吗?
var memoryStream = new MemoryStream();
var mimeMessage = MimeMessage.CreateFromMailMessage(message);
mimeMessage.WriteTo(memoryStream);