Прикрепите файл из MemoryStream к MailMessage в C # - PullRequest
104 голосов
/ 17 марта 2011

Я пишу программу для прикрепления файла к электронной почте. В настоящее время я сохраняю файл, используя FileStream на диск, а затем я использую

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

Я не хочу хранить файл на диске, я хочу сохранить файл в памяти и передать из потока памяти в Attachment.

Ответы [ 8 ]

94 голосов
/ 17 марта 2011

Вот пример кода.

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 Type необходимо указать правильное расширение в FileName, например "myFile.pdf"

91 голосов
/ 12 февраля 2013

Немного поздняя запись - но, надеюсь, все еще полезно для кого-то там: -

Вот упрощенный фрагмент для отправки строки в памяти в виде вложения электронной почты (файл 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@example.com", "you@example.com", "Just testing", "See attachment..."))
{
    writer.WriteLine("Comma,Seperated,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 и базовый поток не следует утилизировать до тех пор, пока сообщение не будет отправлено (во избежание ObjectDisposedException: Cannot access a closed Stream).

24 голосов
/ 19 октября 2011

Поскольку я нигде не мог найти подтверждения этому, я проверил, будет ли удаление объекта 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);
17 голосов
/ 21 октября 2015

Если вы действительно хотите добавить .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);
12 голосов
/ 25 октября 2013

Если все, что вы делаете, это присоединяете строку, вы можете сделать это всего за 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вместе.

2 голосов
/ 28 сентября 2017

использовать ДРУГОЙ ОТКРЫТЫЙ поток памяти:

пример для lauch pdf и отправки pdf в MVC4 C # Контроллер

        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);
    }
2 голосов
/ 14 июня 2016

Я попал на этот вопрос, потому что мне нужно было прикрепить файл Excel, который я генерирую с помощью кода, и доступен как MemoryStream.Я мог прикрепить его к почтовому сообщению, но оно было отправлено в виде файла размером 64 байта вместо ~ 6 КБ, как это и предполагалось.Итак, решение, которое работало для меня, было следующим:

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 позволяет мне отправлять сообщения с правильным размером вложения.

0 голосов
/ 17 марта 2011

Я думаю, этот код поможет вам:

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();
    }
  }
}
...