C#でMemoryStreamからMailMessageにファイルを添付する


113

メールにファイルを添付するプログラムを書いています。現在FileStream、ファイルをディスクに保存しています。

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

ファイルをディスクに保存したくありません。ファイルをメモリに保存し、メモリストリームからこれをに渡しAttachmentます。

回答:


104

これがサンプルコードです。

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タイプに基づいて、たとえばFileNameに正しい拡張子を指定する必要があります"myFile.pdf"


私はPDFを使用しています。このタイプをSystem.Net.Mime.ContentTypeに渡す方法ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
Zain Ali

3
使用する必要がありますSystem.Net.Mime.MediaTypeNames.Application.Pdf
Waqas Raja

5
writer.Disopose()私のソリューションには早すぎましたが、他のすべては素晴らしい例です。
Kazimierz Jawor 2015

7
ms.Position = 0;添付ファイルを作成する前にがあるはずです。
ケニーエビット2017年

94

少し遅れたエントリ-うまくいけば、そこにいる誰かにとってまだ役に立つでしょう:-

これは、メモリ内の文字列を電子メールの添付ファイル(この場合は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)に破棄しないでください。


30
初心者にとって、私にとって重要なのはstream.position = 0;
mtbennettを2013

3
using()を適切に使用するための+1-オンラインでの例やスニペット(この質問に対する受け入れられた回答を含む)から常に欠落しているように見えるもの。
Jay Querido 2014

2
@mtbennetのおかげで、これも私の問題設定stream.Position=0でした。
イカルス

ここでMIMEタイプを設定すると、実際にはどうなりますか?電子メールクライアントアプリに何かありますか?
xr280xr

@ xr280xr-正解。このパラメーターは実際には必須ではありませんが、これを含めると、受信者の電子メールクライアントが添付ファイルを適切に処理するのに役立ちます。 docs.microsoft.com/en-us/dotnet/api/...
静かな沼を

28

これの確認がどこにも見つからなかったため、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);

くそー、それは賢いです。1行のコードで、メールに画像ファイルを添付ファイルとして追加できます。すばらしいヒントです。
Mike Gledhill、2015年

これが実際に文書化されたことを願っています。この動作のテスト/検証は役立ちますが、公式のドキュメントに記載されていないと、常にそうであるとは信じられません。とにかく、テストしてくれてありがとう。
Lucas

グッドエフォートアンドリサーチ@ thymine
vibs2006

1
参照ソースが重要であれば、それは一種の文書化されています。mailmessage.disposeattachments.disposeを呼び出し、次に添付ファイルごとにdisposeを呼び出し、mimepartでストリームを閉じます
Cee McSharpface 2018

ありがとうございました。実際にメッセージが送信される場所とは異なるクラスでメッセージを作成しているので、メールメッセージはそれを行うべきであり、それを必要とすると考えていました。
xr280xr

20

実際に.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);

PDFの送信に何時間も費やして、これは魅力のように機能しました!
dijam 2016年

12

あなたがしているすべてが文字列を付けることであるなら、あなたはたった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

この質問にたどり着いたのは、コードで生成したExcelファイルをとして添付する必要があったためですMemoryStream。メールメッセージに添付することはできましたが、意図されていた〜6KBではなく64Bytesファイルとして送信されました。だから、私のために働いた解決策はこれでした:

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すると、正しいサイズの添付ファイルでメッセージを送信できます。


2

OTHER OPENメモリストリームを使用します。

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

stream.Position=0; 私を助けたラインです。それがなければ、私の添付ファイルはいくつかのkBの504バイトだけでした
Abdul Hameed

-6

このコードはあなたに役立つと思います:

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
-1この回答は、Attachment(string fileName)コンストラクターを使用してディスクから添付ファイルをロードします。OPはディスクからロードしたくないと明確に述べています。また、これはRed Swanの回答のリンクからコピーして貼り付けたコードです。
Walter Stabosz 2013

attachFileストリームが同様に配置されていない
Sameh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.