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

发布于 2024-10-22 06:43:58 字数 279 浏览 2 评论 0原文

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

System.Net.Mail.MailMessage.Attachments.Add(
    new System.Net.Mail.Attachment("file name")); 

我不想将文件存储在磁盘中,我想将文件存储在内存中”,并从内存流将其传递给 Attachment< /代码>。

I am writing a program to attach a file to email. Currently I am saving file using FileStream into disk, and then I use

System.Net.Mail.MailMessage.Attachments.Add(
    new System.Net.Mail.Attachment("file name")); 

I do not want to store file in disk, I want to store file in memory and from memory stream pass this to Attachment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

记忆消瘦 2024-10-29 06:43:58

这是示例代码。

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";

// I guess you know how to send email with an attachment
// after sending email
ms.Close();

编辑1

您可以通过System.Net.Mime.MimeTypeNames指定其他文件类型,例如System.Net.Mime.MediaTypeNames.Application.Pdf

基于Mime类型< /strong> 您需要在文件名中指定正确的扩展名,例如 "myFile.pdf"

Here is the sample code.

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";

// I guess you know how to send email with an attachment
// after sending email
ms.Close();

Edit 1

You can specify other file types by System.Net.Mime.MimeTypeNames like System.Net.Mime.MediaTypeNames.Application.Pdf

Based on Mime Type you need to specify correct extension in FileName for instance "myFile.pdf"

别把无礼当个性 2024-10-29 06:43:58

有点晚了 - 但希望对那里的人仍然有用:-

这是一个简化的代码片段,用于将内存中的字符串作为电子邮件附件(在本例中为 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("[email protected]", "[email protected]", "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);
}

StreamWriter 和底层流在消息发送之前不得被释放(以避免ObjectDisposeException:无法访问已关闭的 Stream)。

A bit of a late entry - but hopefully still useful to someone out there:-

Here's a simplified snippet for sending an in-memory string as an email attachment (a CSV file in this particular case).

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("[email protected]", "[email protected]", "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);
}

The StreamWriter and underlying stream must not be disposed until after the message has been sent (to avoid ObjectDisposedException: Cannot access a closed Stream).

懒猫 2024-10-29 06:43:58

由于我在任何地方都找不到对此的确认,因此我测试了处理 MailMessage 和/或 Attachment 对象是否会按照我的预期处理加载到其中的流。

通过以下测试确实可以看出,当 MailMessage 被释放时,所有用于创建附件的流也将被释放。因此,只要您处理 MailMessage,用于创建它的流就不需要再进行其他处理。

MailMessage mail = new MailMessage();
//Create a MemoryStream from a file for this test
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);

//Dispose the mail as you should after sending the email
mail.Dispose();
//--Or you can dispose the attachment itself
//mm.Attachments[0].Dispose();

Console.WriteLine("This will throw a 'Cannot access a closed Stream.' exception: " + ms.Length);

Since I couldn't find confirmation of this anywhere, I tested if disposing of the MailMessage and/or the Attachment object would dispose of the stream loaded into them as I expected would happen.

It does appear with the following test that when the MailMessage is disposed, all streams used to create attachments will also be disposed. So as long as you dispose your MailMessage the streams that went into creating it do not need handling beyond that.

MailMessage mail = new MailMessage();
//Create a MemoryStream from a file for this test
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);

//Dispose the mail as you should after sending the email
mail.Dispose();
//--Or you can dispose the attachment itself
//mm.Attachments[0].Dispose();

Console.WriteLine("This will throw a 'Cannot access a closed Stream.' exception: " + ms.Length);
似狗非友 2024-10-29 06:43:58

如果您确实想添加.pdf,我发现有必要将内存流的位置设置为零。

var memStream = new MemoryStream(yourPdfByteArray);
memStream.Position = 0;
var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
var reportAttachment = new Attachment(memStream, contentType);
reportAttachment.ContentDisposition.FileName = "yourFileName.pdf";
mailMessage.Attachments.Add(reportAttachment);

If you actually want to add a .pdf, I found it necessary to set the position of the memory stream to Zero.

var memStream = new MemoryStream(yourPdfByteArray);
memStream.Position = 0;
var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
var reportAttachment = new Attachment(memStream, contentType);
reportAttachment.ContentDisposition.FileName = "yourFileName.pdf";
mailMessage.Attachments.Add(reportAttachment);
倾`听者〃 2024-10-29 06:43:58

如果您所做的只是附加一个字符串,您只需 2 行即可完成:

mail.Attachments.Add(Attachment.CreateAttachmentFromString("1,2,3", "text/csv");
mail.Attachments.Last().ContentDisposition.FileName = "filename.csv";

我无法使用带有 StreamWriter 的邮件服务器让我的字符串工作。
我想也许是因为使用 StreamWriter 你丢失了很多文件属性信息,也许我们的服务器不喜欢丢失的内容。
使用 Attachment.CreateAttachmentFromString() 它创建了我需要的一切并且工作得很好!

否则,我建议获取内存中的文件并使用 MemoryStream(byte[]) 打开它,并一起跳过 StreamWriter。

If all you're doing is attaching a string, you could do it in just 2 lines:

mail.Attachments.Add(Attachment.CreateAttachmentFromString("1,2,3", "text/csv");
mail.Attachments.Last().ContentDisposition.FileName = "filename.csv";

I wasn't able to get mine to work using our mail server with StreamWriter.
I think maybe because with StreamWriter you're missing a lot of file property information and maybe our server didn't like what was missing.
With Attachment.CreateAttachmentFromString() it created everything I needed and works great!

Otherwise, I'd suggest taking your file that is in memory and opening it using MemoryStream(byte[]), and skipping the StreamWriter all together.

安人多梦 2024-10-29 06:43:58

我之所以提出这个问题,是因为我需要附加一个通过代码生成的 Excel 文件,该文件可作为 MemoryStream 使用。我可以将它附加到邮件消息中,但它是作为 64 字节文件发送的,而不是按其本来的意思是 ~6KB。因此,对我有用的解决方案是:

MailMessage mailMessage = new MailMessage();
Attachment attachment = new Attachment(myMemorySteam, new ContentType(MediaTypeNames.Application.Octet));

attachment.ContentDisposition.FileName = "myFile.xlsx";
attachment.ContentDisposition.Size = attachment.Length;

mailMessage.Attachments.Add(attachment);

设置 attachment.ContentDisposition.Size 的值让我发送具有正确附件大小的邮件。

I landed on this question because I needed to attach an Excel file I generate through code and is available as MemoryStream. I could attach it to the mail message but it was sent as 64Bytes file instead of a ~6KB as it was meant. So, the solution that worked for me was this:

MailMessage mailMessage = new MailMessage();
Attachment attachment = new Attachment(myMemorySteam, new ContentType(MediaTypeNames.Application.Octet));

attachment.ContentDisposition.FileName = "myFile.xlsx";
attachment.ContentDisposition.Size = attachment.Length;

mailMessage.Attachments.Add(attachment);

Setting the value of attachment.ContentDisposition.Size let me send messages with the correct size of attachment.

墨小墨 2024-10-29 06:43:58

使用其他开放内存流:

在 MVC4 C# 控制器中启动 pdf 并发送 pdf 的示例

        public void ToPdf(string uco, int idAudit)
    {
        Response.Clear();
        Response.ContentType = "application/octet-stream";
        Response.AddHeader("content-disposition", "attachment;filename= Document.pdf");
        Response.Buffer = true;
        Response.Clear();

        //get the memorystream pdf
        var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();

        Response.OutputStream.Write(bytes, 0, bytes.Length);
        Response.OutputStream.Flush();

    }


    public ActionResult ToMail(string uco, string filter, int? page, int idAudit, int? full) 
    {
        //get the memorystream pdf
        var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();

        using (var stream = new MemoryStream(bytes))
        using (var mailClient = new SmtpClient("**YOUR SERVER**", 25))
        using (var message = new MailMessage("**SENDER**", "**RECEIVER**", "Just testing", "See attachment..."))
        {

            stream.Position = 0;

            Attachment attach = new Attachment(stream, new System.Net.Mime.ContentType("application/pdf"));
            attach.ContentDisposition.FileName = "test.pdf";

            message.Attachments.Add(attach);

            mailClient.Send(message);
        }

        ViewBag.errMsg = "Documento enviado.";

        return Index(uco, filter, page, idAudit, full);
    }

use OTHER OPEN memorystream:

example for lauch pdf and send pdf in MVC4 C# Controller

        public void ToPdf(string uco, int idAudit)
    {
        Response.Clear();
        Response.ContentType = "application/octet-stream";
        Response.AddHeader("content-disposition", "attachment;filename= Document.pdf");
        Response.Buffer = true;
        Response.Clear();

        //get the memorystream pdf
        var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();

        Response.OutputStream.Write(bytes, 0, bytes.Length);
        Response.OutputStream.Flush();

    }


    public ActionResult ToMail(string uco, string filter, int? page, int idAudit, int? full) 
    {
        //get the memorystream pdf
        var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();

        using (var stream = new MemoryStream(bytes))
        using (var mailClient = new SmtpClient("**YOUR SERVER**", 25))
        using (var message = new MailMessage("**SENDER**", "**RECEIVER**", "Just testing", "See attachment..."))
        {

            stream.Position = 0;

            Attachment attach = new Attachment(stream, new System.Net.Mime.ContentType("application/pdf"));
            attach.ContentDisposition.FileName = "test.pdf";

            message.Attachments.Add(attach);

            mailClient.Send(message);
        }

        ViewBag.errMsg = "Documento enviado.";

        return Index(uco, filter, page, idAudit, full);
    }
夜光 2024-10-29 06:43:58

我假设当您处理 MailMessage 时,内存流也会被处理,正如上面的一位小伙子所提到的。较晚进入,并且存在流太长的内存流异常。当然,我并没有处理我的邮件消息。因此,这可能会有所帮助,我正在发送多文件附件:

    public void SendEmail(EmailDao mail)
    {
        try
        {
            //Send Email:
            var networkCredentials = new NetworkCredential { UserName = _businessSmtpDetails.GetSection("NetworkUsername").Value, Password = _businessSmtpDetails.GetSection("NetworkPassword").Value };
            var smtpServer = new SmtpClient(_businessSmtpDetails.GetSection("SmtpServer").Value);
            smtpServer.Credentials = networkCredentials;

            var mailMessage = new MailMessage();

            mailMessage.From = new MailAddress(_businessSmtpDetails.GetSection("BusinessEmail").Value);
            mailMessage.Body = mail.EmailBody;
            mailMessage.Subject = @"From " + mail.EmailFrom + " " + mail.EmailSubject;
            var fileStream = new FileInfo("/images/attachement");
            MemoryStream memoryStream = null;
            if (mail.Attachment != null)
            {
                memoryStream = new MemoryStream();
                ReadFileAttachment(mail.Attachment, memoryStream);
                memoryStream.Seek(0, SeekOrigin.Begin);
                System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
                var attached = new Attachment(memoryStream, mail.Attachment.FileName, ct.MediaType);
                mailMessage.Attachments.Add(attached);
            }
            if (mail.Attachments != null && mail.Attachments.Length > 0)
            {
                foreach (var attachment in mail.Attachments)
                {
                    memoryStream = new MemoryStream();
                    ReadFileAttachment(attachment, memoryStream);
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
                    var attached = new Attachment(memoryStream, mail.Attachment.FileName, ct.MediaType);
                    mailMessage.Attachments.Add(attached);
                }
            }
            mail.EmailTo += string.Format(";{0}", _businessSmtpDetails.GetSection("BusinessEmail").Value);
            Array.ForEach<string>(mail.EmailTo.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries), (p) =>
            {
                mailMessage.To.Add(p);
            });
            smtpServer.Send(mailMessage);
            memoryStream.Close();
            mailMessage.Dispose();
        }
        catch (Exception e)
        {
            throw e;
        }
    }

    private MemoryStream ReadFileAttachment(IFormFile attacment, MemoryStream memoryStream)
    {
        var bytes = new byte[4096];
        var bytesRead = 0;
        while ((bytesRead = attacment.OpenReadStream().Read(bytes, 0, bytes.Length)) > 0)
        {
            memoryStream.Write(bytes, 0, bytesRead);
            memoryStream.Flush();
        }
        return memoryStream;
    }

I am assuming that when you dispose the MailMessage, the Memory Steams get disposed too, as mentioned above by one of you chaps. A late entry, and was having memory stream exception of stream too long. Of course then I wasn't disposing my mailmessage. So this may help, that I am sending multi-file Attachments:

    public void SendEmail(EmailDao mail)
    {
        try
        {
            //Send Email:
            var networkCredentials = new NetworkCredential { UserName = _businessSmtpDetails.GetSection("NetworkUsername").Value, Password = _businessSmtpDetails.GetSection("NetworkPassword").Value };
            var smtpServer = new SmtpClient(_businessSmtpDetails.GetSection("SmtpServer").Value);
            smtpServer.Credentials = networkCredentials;

            var mailMessage = new MailMessage();

            mailMessage.From = new MailAddress(_businessSmtpDetails.GetSection("BusinessEmail").Value);
            mailMessage.Body = mail.EmailBody;
            mailMessage.Subject = @"From " + mail.EmailFrom + " " + mail.EmailSubject;
            var fileStream = new FileInfo("/images/attachement");
            MemoryStream memoryStream = null;
            if (mail.Attachment != null)
            {
                memoryStream = new MemoryStream();
                ReadFileAttachment(mail.Attachment, memoryStream);
                memoryStream.Seek(0, SeekOrigin.Begin);
                System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
                var attached = new Attachment(memoryStream, mail.Attachment.FileName, ct.MediaType);
                mailMessage.Attachments.Add(attached);
            }
            if (mail.Attachments != null && mail.Attachments.Length > 0)
            {
                foreach (var attachment in mail.Attachments)
                {
                    memoryStream = new MemoryStream();
                    ReadFileAttachment(attachment, memoryStream);
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
                    var attached = new Attachment(memoryStream, mail.Attachment.FileName, ct.MediaType);
                    mailMessage.Attachments.Add(attached);
                }
            }
            mail.EmailTo += string.Format(";{0}", _businessSmtpDetails.GetSection("BusinessEmail").Value);
            Array.ForEach<string>(mail.EmailTo.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries), (p) =>
            {
                mailMessage.To.Add(p);
            });
            smtpServer.Send(mailMessage);
            memoryStream.Close();
            mailMessage.Dispose();
        }
        catch (Exception e)
        {
            throw e;
        }
    }

    private MemoryStream ReadFileAttachment(IFormFile attacment, MemoryStream memoryStream)
    {
        var bytes = new byte[4096];
        var bytesRead = 0;
        while ((bytesRead = attacment.OpenReadStream().Read(bytes, 0, bytes.Length)) > 0)
        {
            memoryStream.Write(bytes, 0, bytesRead);
            memoryStream.Flush();
        }
        return memoryStream;
    }
原来是傀儡 2024-10-29 06:43:58

我认为这段代码会对您有所帮助:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net.Mail;

public partial class _Default : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {

  }

  protected void btnSubmit_Click(object sender, EventArgs e)
  {
    try
    {
      MailAddress SendFrom = new MailAddress(txtFrom.Text);
      MailAddress SendTo = new MailAddress(txtTo.Text);

      MailMessage MyMessage = new MailMessage(SendFrom, SendTo);

      MyMessage.Subject = txtSubject.Text;
      MyMessage.Body = txtBody.Text;

      Attachment attachFile = new Attachment(txtAttachmentPath.Text);
      MyMessage.Attachments.Add(attachFile);

      SmtpClient emailClient = new SmtpClient(txtSMTPServer.Text);
      emailClient.Send(MyMessage);

      litStatus.Text = "Message Sent";
    }
    catch (Exception ex)
    {
      litStatus.Text = ex.ToString();
    }
  }
}

I think this code will help you:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net.Mail;

public partial class _Default : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {

  }

  protected void btnSubmit_Click(object sender, EventArgs e)
  {
    try
    {
      MailAddress SendFrom = new MailAddress(txtFrom.Text);
      MailAddress SendTo = new MailAddress(txtTo.Text);

      MailMessage MyMessage = new MailMessage(SendFrom, SendTo);

      MyMessage.Subject = txtSubject.Text;
      MyMessage.Body = txtBody.Text;

      Attachment attachFile = new Attachment(txtAttachmentPath.Text);
      MyMessage.Attachments.Add(attachFile);

      SmtpClient emailClient = new SmtpClient(txtSMTPServer.Text);
      emailClient.Send(MyMessage);

      litStatus.Text = "Message Sent";
    }
    catch (Exception ex)
    {
      litStatus.Text = ex.ToString();
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文