MemoryStream의 파일을 C #의 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

를 기반으로 마임 유형 당신은 예를 들어 파일 이름에 올바른 확장자를 지정해야"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 2011

5
writer.Disopose()내 솔루션에는 너무 이르지만 다른 모든 것은 훌륭한 예입니다.
— Kazimierz Jawor

7
ms.Position = 0;첨부 파일을 만들기 전에이 있어야한다고 확신 합니다.
— Kenny Evitt 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

3
using ()의 적절한 사용을위한 +1-온라인 예제 및 스 니펫에서 항상 누락 된 것 같습니다 (이 질문에 대한 답변 포함).
— Jay Querido 2014-08-15

2
내 문제 설정이기도 한 @mtbennet 덕분 stream.Position=0입니다.
— Icarus 2014

여기서 MIME 유형 설정은 실제로 무엇을합니까? 이메일 클라이언트 앱을위한 것이 있습니까?
— xr280xr

@ xr280xr-맞습니다. 이 매개 변수는 실제로 필수는 아니지만이를 포함하면 수신자의 이메일 클라이언트가 첨부 파일을 현명하게 처리하는 데 도움이됩니다. docs.microsoft.com/en-us/dotnet/api/…
— 고요한 tarn

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

젠장, 영리 하군. 한 줄의 코드 만 있으면 이미지 파일을 이메일에 첨부 파일로 추가 할 수 있습니다. 좋은 팁!
— Mike Gledhill 2015 년

나는 이것이 실제로 문서화되기를 바랍니다. 이 동작에 대한 테스트 / 검증은 유용하지만 공식 문서에 포함되어 있지 않으면 이것이 항상 해당 될 것이라고 믿기가 어렵습니다. 어쨌든 테스트 해 주셔서 감사합니다.
— Lucas

좋은 노력과 연구 @thymine
— vibs2006

1
참조 출처가 중요하다면 일종의 문서화입니다. mailmessage.dispose 는 attachments.dispose 를 호출 하고, 차례로 각 첨부 파일에 대해 dispose를 호출 하여 mimepart 에서 스트림을 닫습니다 .
— Cee McSharpface

감사합니다. 메일 메시지가 실제로 전송되는 위치와 다른 클래스에서 메시지를 작성하고 있기 때문에 메일 메시지가 그렇게해야하고 필요하다고 생각했습니다.
— xr280xr

20

실제로 .pdf를 추가하려면 메모리 스트림의 위치를 ​​0으로 설정해야합니다.

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

만약 당신이하고있는 모든 것이 문자열을 붙이는 것이라면, 단 두 줄로 할 수 있습니다 :

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 메모리 스트림 사용 :

lauch pdf의 예 및 MVC4 C # 컨트롤러에서 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; 나를 도운 라인입니다. 그것 없이는 내 attcahment가 일부 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.