web-dev-qa-db-fra.com

Joindre un fichier de MemoryStream à un MailMessage en C #

Je suis en train d'écrire un programme pour joindre un fichier à un email. Actuellement, j’enregistre le fichier avec FileStream sur le disque, puis j’utilise

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

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

104
Zain Ali

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

Edit 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 NomFichier, par exemple "myFile.pdf"

94
Waqas Raja

Une entrée tardive - mais j'espère toujours utile à quelqu'un: -

Voici un extrait simplifié pour envoyer une chaîne en mémoire sous forme de pièce jointe à un e-mail (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("[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);
}

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

91
tranquil tarn

N'ayant trouvé aucune confirmation de cela nulle part, j'ai vérifié si l'élimination de l'objet MailMessage et/ou de l'objet Pièce jointe éliminerait le flux chargé comme prévu.

Le test suivant semble indiquer que lorsque MailMessage est supprimé, tous les flux utilisés pour créer des pièces jointes le seront également. Donc, tant que vous disposez de votre MailMessage, les flux entrés dans sa création n'ont pas besoin d'être traités plus tard.

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

Si vous souhaitez réellement ajouter un fichier .pdf, j’ai jugé nécessaire de définir la position du flux de mémoire sur 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);
17
Jason Dimmick

Si vous ne faites qu'attacher une chaîne, vous pouvez le faire en 2 lignes seulement:

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

Je n'ai pas réussi à faire fonctionner le mien à l'aide de notre serveur de messagerie avec StreamWriter.
Je pense que peut-être parce qu'avec StreamWriter, il manque beaucoup d’informations sur les propriétés des fichiers et que notre serveur n’a peut-être pas aimé ce qui manquait.
Avec Attachment.CreateAttachmentFromString (), il a créé tout ce dont j'avais besoin et fonctionne très bien!

Sinon, je vous suggèrerais de prendre votre fichier en mémoire et de l'ouvrir à l'aide de MemoryStream (byte []), puis de sauter le StreamWriter en même temps.

12
MikeTeeVee

utilisez le programme de mémorisation AUTREMENT OUVERT:

exemple pour lancer un pdf et envoyer un pdf dans un contrôleur MVC 4 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
Ángel Ibáñez

J'ai atterri sur cette question car j'avais besoin de joindre un fichier Excel généré par le code et disponible sous la forme MemoryStream. Je pouvais le joindre au message électronique, mais il a été envoyé sous forme de fichier de 64 Ko au lieu de ~ 6 Ko comme prévu. 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 laissez-moi envoyer des messages avec la taille correcte de la pièce jointe.

2
ilForna