Joindre un fichier de MemoryStream à un MailMessage en C#

J'écris un programme pour joindre un fichier à un e-mail. Actuellement, j'enregistre le fichier en utilisant FileStream dans le disque, puis j'utilise

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

Je ne veux pas stocker de fichier sur le disque, je veux stocker le fichier en mémoire et à partir du flux de mémoire, passez ceci à Attachment.

88
demandé sur wonea 2011-03-17 10:45:49

8 réponses

Voici l'exemple de 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();

Modifier 1

Vous pouvez spécifier d'autres types de fichiers par System. Net. Mime. MimeTypeNames comme System.Net.Mime.MediaTypeNames.Application.Pdf

Basé sur type Mime vous devez spécifier l'extension correcte dans le nom de fichier par exemple "myFile.pdf"

84
répondu Waqas Raja 2018-07-04 12:26:06

Un peu de retard mais j'espère toujours utile à quelqu'un là-bas:-

Voici un extrait simplifié pour envoyer une chaîne en mémoire en pièce jointe (un fichier CSV dans ce cas particulier).

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

Le StreamWriter et le flux sous-jacent ne doivent pas être éliminés avant l'envoi du message (pour éviter ObjectDisposedException: Cannot access a closed Stream).

86
répondu tranquil tarn 2014-07-30 10:04:32

Comme je n'ai trouvé aucune confirmation de cela, j'ai testé si la disposition du MailMessage et / ou de l'objet Attachment éliminerait le flux chargé en eux comme je m'y attendais.

Il apparaît avec le test suivant que lorsque le MailMessage est éliminé, tous les flux utilisés pour créer des pièces jointes seront également éliminés. Donc, tant que vous disposez de votre MailMessage, les flux qui ont été créés n'ont pas besoin de traitement au-delà de cela.

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);
23
répondu Thymine 2011-10-18 22:11:40

Si vous voulez réellement ajouter un .pdf, je l'ai trouvé également nécessaire de définir la position du flux de mémoire à Zéro.

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);
15
répondu Jason Dimmick 2017-04-18 14:24:53

Si tout ce que vous faites est d'attacher une chaîne, vous pouvez le faire en seulement 2 lignes:

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

Je n'ai pas pu faire fonctionner le mien en utilisant notre serveur de messagerie avec StreamWriter.
Je pense peut-être parce qu'avec StreamWriter, il vous manque beaucoup d'informations sur les propriétés du fichier et peut-être que notre serveur n'a pas aimé ce qui manquait.
Avec Pièce Jointe.CreateAttachmentFromString () il a créé tout ce dont j'avais besoin et fonctionne très bien!

Sinon, je suggère de prendre votre fichier en mémoire et l'ouvrir en utilisant MemoryStream (byte []), et sauter le StreamWriter tous ensemble.

12
répondu MikeTeeVee 2013-10-25 05:01:52

J'ai atterri sur cette question parce que j'avais besoin de joindre un fichier Excel que je génère via le code et qui est disponible en tant que MemoryStream. Je pourrais l'attacher au message électronique mais il a été envoyé en tant que Fichier 64Bytes au lieu d'un ~6KB comme cela était signifié. Donc, la solution qui a fonctionné pour moi était la suivante:

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

Définir la valeur de attachment.ContentDisposition.Size permettez-moi d'envoyer des messages avec la taille correcte de la pièce jointe.

2
répondu ilForna 2016-06-14 07:50:13

Utiliser un autre flux de mémoire ouvert:

Exemple pour lauch pdf et envoyer pdf dans 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);
    }
1
répondu Ángel Ibáñez 2017-09-28 12:15:22

Je pense que ce code vous aidera:

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();
    }
  }
}
-5
répondu r12 2013-01-24 03:54:30