Adjunte un archivo de MemoryStream a un MailMessage en C #

Estoy escribiendo un progtwig para adjuntar un archivo al correo electrónico. Actualmente estoy guardando archivos usando FileStream en el disco, y luego uso

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

No quiero almacenar el archivo en el disco, quiero almacenar el archivo en la memoria y desde la secuencia de la memoria, pasar esto a Attachment .

Aquí está el código de ejemplo.

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

Editar 1

Puede especificar otros tipos de archivos por System.Net.Mime.MimeTypeNames como System.Net.Mime.MediaTypeNames.Application.Pdf

Según el tipo de Mime , debe especificar la extensión correcta en FileName, por ejemplo, "myFile.pdf"

Una entrada algo tardía, pero afortunadamente sigue siendo útil para alguien:

Aquí hay un fragmento simplificado para enviar una cadena en la memoria como un archivo adjunto de correo electrónico (un archivo CSV en este caso particular).

 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,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); } 

El StreamWriter y la secuencia subyacente no deben eliminarse hasta que se haya enviado el mensaje (para evitar ObjectDisposedException: Cannot access a closed Stream ).

Como no pude encontrar la confirmación de esto en ninguna parte, probé si deshacerme de MailMessage y / o del objeto Attachment eliminaría la secuencia cargada en ellos como esperaba.

Parece que con la siguiente prueba, cuando se elimina el MailMessage, también se eliminarán todas las secuencias utilizadas para crear archivos adjuntos. Por lo tanto, siempre que disponga de MailMessage, las secuencias que se utilizaron para crearlo no necesitan más tratamiento.

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

Si realmente desea agregar un .pdf, también me pareció necesario establecer la posición de la secuencia de memoria en cero.

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

Si todo lo que estás haciendo es conectar una cadena, puedes hacerlo en solo 2 líneas:

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

No pude hacer funcionar el mío usando nuestro servidor de correo con StreamWriter.
Creo que tal vez porque con StreamWriter te falta mucha información sobre la propiedad del archivo y tal vez a nuestro servidor no le gustó lo que faltaba.
Con Attachment.CreateAttachmentFromString () creó todo lo que necesitaba y ¡funciona muy bien!

De lo contrario, te sugiero que tomes el archivo que está en la memoria y lo abras usando MemoryStream (byte []) y omitiendo todo el StreamWriter.

Llegué a esta pregunta porque necesitaba adjuntar un archivo Excel que genero a través del código y está disponible como MemoryStream . Podría adjuntarlo al mensaje de correo, pero se envió como un archivo 64Bytes en lugar de un ~ 6KB como se suponía. Entonces, la solución que funcionó para mí fue esta:

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

Establecer el valor de attachment.ContentDisposition.Size me permite enviar mensajes con el tamaño correcto de archivo adjunto.

use OTHER OPEN memorystream:

ejemplo para lauch pdf y enviar pdf en 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); } 

Creo que este código te ayudará a:

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