在C#中,将MemoryStream中的文件附加到MailMessage中。

5 浏览
0 Comments

在C#中,将MemoryStream中的文件附加到MailMessage中。

我正在编写一个程序来将文件附加到电子邮件。目前我正在使用FileStream将文件保存到磁盘上,然后使用

System.Net.Mail.MailMessage.Attachments.Add(
new System.Net.Mail.Attachment("文件名"));

将其添加为附件。

我不想将文件存储在磁盘上,而是想将文件存储在内存中,并通过内存流将其传递给Attachment

0
0 Comments

问题的原因是在将一个内存流作为附件添加到邮件消息中时,需要确保在消息发送之前不要释放StreamWriter和底层流。另外,需要将流的位置设置为0,以便从写入的开头开始读取。此外,设置MIME类型可以帮助接收方的邮件客户端正确处理附件。

解决方法是在发送邮件消息之前不要释放StreamWriter和底层流,以避免"ObjectDisposedException: Cannot access a closed Stream"异常。另外,需要将流的位置设置为0,以便从写入的开头开始读取。可以使用stream.Position = 0;来实现。此外,可以设置附件的MIME类型,以便接收方的邮件客户端正确处理附件。

以下是一个简化的示例代码,用于将内存中的字符串作为电子邮件附件发送(在这个特定的示例中是一个CSV文件):

using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))    // using UTF-8 encoding by default
using (var mailClient = new SmtpClient("localhost", 25))
using (var message = new MailMessage("me.com", "you.com", "Just testing", "See attachment..."))
{
    writer.WriteLine("Comma,Separated,Values,...");
    writer.Flush();
    stream.Position = 0;     // read from the start of what was written
    message.Attachments.Add(new Attachment(stream, "filename.csv", "text/csv"));
    mailClient.Send(message);
}

以上是对问题的原因和解决方法的整理和总结。通过确保正确使用using语句块、设置流的位置以及设置附件的MIME类型,可以成功地将内存流作为附件添加到邮件消息中。

0
0 Comments

问题原因:

在这段代码中,作者想要确认当MailMessage对象或Attachment对象被释放时,它们是否会同时释放内部的MemoryStream流。通过对MailMessage对象进行Dispose操作后,发现与之相关联的流也被释放了。因此,只要正确地释放MailMessage对象,创建附件时使用的流就不需要额外处理。

解决方法:

为了证实这一行为,作者进行了一个简单的测试。测试中,首先创建了一个MemoryStream对象,然后将其作为附件添加到MailMessage对象中。通过判断ContentStream属性与原始的MemoryStream对象是否相同,可以确定流是否被正确地传递给了附件。接着,通过调用Dispose方法释放MailMessage对象,并尝试访问原始的MemoryStream对象,发现会抛出"Cannot access a closed Stream."的异常。这表明在正确地释放MailMessage对象后,相关的流也被正确地释放了。

文章内容如下:

在使用C#中的MailMessage时,如何将一个内存流(MemoryStream)的文件作为附件添加到邮件中呢?经过实验,发现当MailMessage对象被Dispose时,附件中使用的内存流也会被释放。只要正确地释放MailMessage对象,创建附件时使用的流就不需要额外处理。
下面是一个简单的测试代码示例:
MailMessage mail = new MailMessage();
//从文件创建一个内存流(MemoryStream)用于测试
MemoryStream ms = new MemoryStream(File.ReadAllBytes(@"C:\temp\test.gif"));
mail.Attachments.Add(new System.Net.Mail.Attachment(ms, "test.gif"));
if (mail.Attachments[0].ContentStream == ms) Console.WriteLine("Streams are referencing the same resource");
Console.WriteLine("Stream length: " + mail.Attachments[0].ContentStream.Length);
//在发送邮件后,按照规范释放MailMessage对象
mail.Dispose();
//--或者你也可以直接释放附件本身
//mm.Attachments[0].Dispose();
Console.WriteLine("This will throw a 'Cannot access a closed Stream.' exception: " + ms.Length);
通过这个简单的测试,我们可以得出结论:当MailMessage对象被Dispose时,与之相关联的流也会被正确地释放。因此,我们可以放心地在使用MailMessage对象后,直接释放该对象而不需要额外处理相关的流。
希望这个行为能够被官方文档所记录。虽然作者进行了测试并验证了这种行为,但如果没有官方文档的支持,很难相信这种行为会一直存在。不管怎样,感谢作者进行了测试。
在C#中,将内存流作为附件添加到MailMessage对象中的方法非常简单。只需要将内存流作为Attachment对象的参数,然后将该Attachment对象添加到MailMessage对象的Attachments集合中即可。在正确地使用MailMessage对象后,只需要释放该对象即可,不需要额外处理相关的流。这种行为可能没有被官方文档记录,但通过测试可以确认其有效性。

0
0 Comments

问题的原因是在将MemoryStream附加到MailMessage时需要确保MemoryStream的位置为0,以便正确读取文件内容。在给MemoryStream创建附件之前,需要添加代码ms.Position = 0;来将位置重置为0。

解决方法是在创建MailAttachment之前,添加ms.Position = 0;代码来重置MemoryStream的位置。

以下是完整的代码示例:

System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.StreamWriter writer = new System.IO.StreamWriter(ms);
writer.Write("Hello its my sample file");
writer.Flush();
writer.Dispose();
ms.Position = 0;
System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
attach.ContentDisposition.FileName = "myFile.txt";
// 发送带附件的邮件
// 发送邮件后
ms.Close();

在编辑1中,提到了可以使用System.Net.Mime.MimeTypeNames来指定其他文件类型,例如System.Net.Mime.MediaTypeNames.Application.Pdf。根据Mime类型,需要在FileName中指定正确的扩展名,例如"myFile.pdf"。在System.Net.Mime.ContentType的参数中,需要使用System.Net.Mime.MediaTypeNames.Application.Pdf来传递PDF文件类型。

在编辑2中,提到了在解决方案中writer.Dispose()的位置不正确,需要将其放到其他位置。除此之外,其他部分都是一个很好的示例。

最后,还提到了在创建附件之前,应该有ms.Position = 0;的代码来确保MemoryStream的位置为0。

0