Приєднайте файл із MemoryStream до MailMessage у C #


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);
Заїн Алі

3
Вам потрібно скористатисяSystem.Net.Mime.MediaTypeNames.Application.Pdf
Waqas Raja

5
writer.Disopose()було занадто рано для мого рішення, але все інше - чудовий приклад.
Казімір Явор

7
Я майже впевнений, що ms.Position = 0;перед створенням вкладеного файлу повинно бути місце .
Кенні Евітт

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
+1 для відповідного використання використання () 's - те, чого завжди не вистачає у прикладах та фрагментах в Інтернеті (включаючи прийняту відповідь на це питання).
Джей Куерідо

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

Чорт, це розумно. Один рядок коду, і ви можете додати файл зображення до електронної пошти як додаток. Чудова порада!
Майк Гледхілл

Я б хотів, щоб це було фактично задокументовано. Ваша перевірка / перевірка такої поведінки корисна, але, не маючи в офіційній документації, важко повірити, що так буде завжди. У будь-якому випадку, дякую за тестування.
Лукас

Хороших зусиль та досліджень @thymine
vibs2006

1
це свого роду документально підтверджено, якщо посилається джерело. mailmessage.dispose call attachments.розподіліть, які по черзі виклики розміщуються на кожному вкладенні, яке, в mimepart, закриває потік .
Cee McSharpface

Дякую. Я думав, що поштове повідомлення повинно це робити і потрібно, тому що я створюю свої повідомлення в інших класах, ніж там, де повідомлення насправді надсилається.
xr280xr

20

Якщо ви насправді хочете додати .pdf, я вважав за потрібне встановити положення потоку пам'яті на Zero.

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

12

Якщо ви лише вкладаєте рядок, ви можете зробити це лише у двох рядках:

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

Мені не вдалося змусити мене працювати, використовуючи наш поштовий сервер із StreamWriter.
Я думаю, може тому, що в StreamWriter вам не вистачає багато інформації про властивості файлів, і, можливо, нашому серверу не сподобалось те, чого бракувало.
За допомогою Attachment.CreateAttachmentFromString () він створив усе, що мені потрібно, і чудово працює!

В іншому випадку я б запропонував взяти файл, який є у пам'яті, та відкрити його за допомогою MemoryStream (байт []) та пропустити StreamWriter разом.


2

Я приземлився на це питання, тому що мені потрібно було долучити файл Excel, який я генерую за допомогою коду і доступний як MemoryStream. Я міг би прикріпити його до поштового повідомлення, але воно було надіслано як файл 64Bytes замість ~ 6KB, як це було передбачено. Отже, рішення, яке працювало для мене, було таким:

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

використовувати ДРУГІ ВІДКРИТІ потоки пам'яті:

приклад для lauch pdf та відправте pdf у 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);
    }

stream.Position=0; це лінія, яка мені допомогла. без цього моєму прихильню було всього 504 байти, встановлених деякими кБ
Абдул Хамед

-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). ОП конкретно заявляє, що не хоче завантажувати з диска. Також це лише код, скопійований із посилання у відповіді Червоного лебедя.
Вальтер Стабош

Потік attachFile також не розміщений
Sameh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.