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

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
वकास राजा

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

संदेश भेजे जाने (बचने के लिए ObjectDisposedException: Cannot access a closed Stream) के बाद स्ट्रीम स्ट्रीमर और अंतर्निहित स्ट्रीम का निपटान नहीं किया जाना चाहिए ।


30
किसी भी नवागंतुक के लिए, मेरे लिए कुंजीstream.position = 0;
mtbennett

3
+1 () के उपयोग के उचित उपयोग के लिए - ऐसा कुछ जो हमेशा उदाहरणों और स्निपेट्स से ऑनलाइन गायब लगता है (इस प्रश्न के स्वीकृत उत्तर सहित)।
जे क्वेरिडो

2
@Mtbennet के लिए धन्यवाद, जो मेरी समस्या भी थी - सेटिंग stream.Position=0
इकारस

MIME टाइप सेट करने से वास्तव में यहाँ क्या होता है? ई-मेल क्लाइंट ऐप के लिए कुछ?
xr280xr

@ xr280xr - सही है। यह पैरामीटर वास्तव में आवश्यक नहीं है, लेकिन इसमें प्राप्तकर्ता के ईमेल क्लाइंट को अनुलग्नक को समझदारी से संभालने में मदद करनी चाहिए। docs.microsoft.com/en-us/dotnet/api/…
शांत

28

चूँकि मुझे कहीं भी इसकी पुष्टि नहीं मिली, इसलिए मैंने परीक्षण किया कि यदि MailMessage और / या अटैचमेंट ऑब्जेक्ट का निपटारा किया जाता है, तो मैं उनसे भरी हुई धारा को हटा दूंगा जैसा कि मुझे लगता है कि होगा।

यह निम्नलिखित परीक्षण के साथ प्रकट होता है कि जब 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 कॉल अटैचमेंट।बस जो कॉल में प्रत्येक अटैचमेंट पर डिस्पोज करता है, जो माइमपार्ट में स्ट्रीम को बंद कर देता है
Cee McSharpface

धन्यवाद। मैं सोच रहा था कि मेल संदेश को ऐसा करना चाहिए और इसकी आवश्यकता है क्योंकि मैं अपने संदेश अलग-अलग कक्षाओं में बना रहा हूं, जहां संदेश वास्तव में भेजा गया है।
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);

एक पीडीएफ भेजने पर घंटे बिताए यह एक आकर्षण की तरह काम किया!
दिजम

12

यदि आप एक स्ट्रिंग संलग्न कर रहे हैं, तो आप इसे केवल 2 लाइनों में कर सकते हैं:

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

मैं स्ट्रीमवेयर के साथ हमारे मेल सर्वर का उपयोग कर काम करने में सक्षम नहीं था।
मुझे लगता है कि शायद क्योंकि StreamWriter के साथ आप बहुत सारी फ़ाइल संपत्ति की जानकारी याद कर रहे हैं और शायद हमारे सर्वर को यह पसंद नहीं था कि क्या गायब था।
Attachment.CreateAttachmentFromString () के साथ इसने मेरी ज़रूरत की हर चीज़ बनाई और बढ़िया काम किया!

अन्यथा, मैं सुझाव दूंगा कि आपकी फ़ाइल को मेमोरी में रखें और इसे मेमोरीस्ट्रीम (बाइट []) का उपयोग करके खोलें, और स्ट्रीमविटर को एक साथ छोड़ दें।


2

मैं इस प्रश्न पर उतरा क्योंकि मुझे एक एक्सेल फ़ाइल जो मुझे कोड के माध्यम से उत्पन्न करनी थी, संलग्न करने की आवश्यकता थी और जो उपलब्ध है 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

अन्य खुले मेमोरीस्ट्रीम का उपयोग करें:

उदाहरण के लिए lauch pdf और MVC4 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);
    }

stream.Position=0; वह रेखा है जिसने मेरी मदद की। इसके बिना मेरा ध्यान सिर्फ 504 बाइट्स का था जो कुछ kBs का था
अब्दुल हमीद

-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 यह जवाब अटैचमेंट (स्ट्रिंग फ़ाइलनाम) कंस्ट्रक्टर का उपयोग करके डिस्क से लगाव को लोड करता है। ओपी विशेष रूप से बताता है कि वह डिस्क से लोड नहीं करना चाहता है। इसके अलावा, यह लाल स्वान के जवाब में लिंक से केवल कॉपी-पेस्ट किया गया है।
वाल्टर स्टबोसज़

attachFile धारा के रूप में अच्छी तरह से निपटारा नहीं किया गया है
Sameh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.