简体   繁体   中英

How do I add an attachment to an email using System.Net.Mail?

I have an excel document represented as a byte[] and I'm wanting to send it as an attachment in an email.

I'm having a bit of trouble constructing the attachment.

I can create an Attachment which has the following constructors:

(Stream contentStream, ContentType contentType)
(Stream contentStream, string name)
(Stream contentStream, string name, string mediaType)

My idea at the moment is to create a MemoryStream from the byte[] and pass it to the method which creates the attachment.

Unfortunately I can't see a way to obtain the intended filename and content type from the MemoryStream and I also can't see how to supply the correct content type. There are options for plain text, Pdf, Rtf etc but none that I can see that immediately jump out at me as the one I should use for an Excel document.

The closest I can find is MediaTypeNames.Application.Octet which states:

The Octet member designates that the attachment contains generic binary data.

However, even if this is the one to use, unless it can be passed as a property of the Stream then my method for sending emails will only be able to send a byte[] as an Excel document...

Is there perhaps some other sort of Stream I could use? Or will I have to create my own type of Stream that has the details I need.

Surely someone out there has done this thing before and surely Microsoft would have thought this through to this level....

Any help would be much appreciated.

Update: Please don't vote for any answers that use the constructors that take the filename as a string. I'm really needing help using the ones that take a Stream...I want to avoid having to write the file to disk, email it, and then immediately delete it. Since there is a method that allows me to do that I'd like to use that one if at all possible.

Solution Update

Conrad managed to find what I was looking for! Thanks heaps man!

I'll just document the suggested solution just in case something happens to the content at the supplied link.

Credit for this solution goes to www.systemnetmail.com

static void AttachmentFromStream()
{

//create the mail message
MailMessage mail = new MailMessage();

//set the addresses
mail.From = new MailAddress("me@mycompany.com");
mail.To.Add("you@yourcompany.com");

//set the content
mail.Subject = "This is an email";
mail.Body = "this content is in the body";

//Get some binary data
byte[] data = GetData();

//save the data to a memory stream
MemoryStream ms = new MemoryStream(data);

//create the attachment from a stream. Be sure to name the data 
//with a file and 
//media type that is respective of the data
mail.Attachments.Add( new Attachment( ms, "example.txt", "text/plain" ));

SmtpClient smtp = new SmtpClient("127.0.0.1");
smtp.Send(mail);
}

In my case, it just means I'll have to change my method to take the filename and fileformat as strings. I'll try using the Octet one...but failing that I'll just pass in the official MIME type.

All things considered, this is a pretty obvious solution...but I do appreciate the help in solving it...and the good thing is this solution will be documented for future programmers who have the same problem.

Thanks again everyone for you help!

The attachment constructor does indeed have a constructor that does what you need. I'm assuming you're using the System.Net.MailMessage class from .NET Framework 2. If so read this link for some sample code of what you need

Since the link from the accepted answer is gone, here it is from the Wayback Machine

TL;DR: mail.Attachments.Add(new Attachment(contentStream, "yourfilename.txt", "text/plain"));

Full:

static void AttachmentFromStream()
{

    //create the mail message
    MailMessage mail = new MailMessage();

    //set the addresses
    mail.From = new MailAddress("me@mycompany.com");
    mail.To.Add("you@yourcompany.com");

    //set the content
    mail.Subject = "This is an email";
    mail.Body = "this content is in the body";

    //Get some binary data
    byte[] data = GetData();

    //save the data to a memory stream
    MemoryStream ms = new MemoryStream(data);

    //create the attachment from a stream. Be sure to name the data with a file and 
    //media type that is respective of the data
    mail.Attachments.Add(new Attachment(ms, "example.txt", "text/plain"));

    //send the message
    SmtpClient smtp = new SmtpClient("127.0.0.1");
    smtp.Send(mail);
}
static byte[] GetData()
{
    //this method just returns some binary data.
    //it could come from anywhere, such as Sql Server
    string s = "this is some text";
    byte[] data = Encoding.ASCII.GetBytes(s);
    return data;
}

Got this answer from Microsoft docs:

public static void CreateMessageWithAttachment(string server)
{
    // Specify the file to be attached and sent.
    // This example assumes that a file named Data.xls exists in the
    // current working directory.
    string file = "data.xls";
    // Create a message and set up the recipients.
    MailMessage message = new MailMessage(
        "jane@contoso.com",
        "ben@contoso.com",
        "Quarterly data report.",
        "See the attached spreadsheet.");

    // Create  the file attachment for this email message.
    Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
    // Add time stamp information for the file.
    ContentDisposition disposition = data.ContentDisposition;
    disposition.CreationDate = System.IO.File.GetCreationTime(file);
    disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
    disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
    // Add the file attachment to this email message.
    message.Attachments.Add(data);

    //Send the message.
    SmtpClient client = new SmtpClient(server);
    // Add credentials if the SMTP server requires them.
    client.Credentials = CredentialCache.DefaultNetworkCredentials;

    try
    {
        client.Send(message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception caught in CreateMessageWithAttachment(): {0}",
            ex.ToString());
    }
    // Display the values in the ContentDisposition for the attachment.
    ContentDisposition cd = data.ContentDisposition;
    Console.WriteLine("Content disposition");
    Console.WriteLine(cd.ToString());
    Console.WriteLine("File {0}", cd.FileName);
    Console.WriteLine("Size {0}", cd.Size);
    Console.WriteLine("Creation {0}", cd.CreationDate);
    Console.WriteLine("Modification {0}", cd.ModificationDate);
    Console.WriteLine("Read {0}", cd.ReadDate);
    Console.WriteLine("Inline {0}", cd.Inline);
    Console.WriteLine("Parameters: {0}", cd.Parameters.Count);
    foreach (DictionaryEntry d in cd.Parameters)
    {
        Console.WriteLine("{0} = {1}", d.Key, d.Value);
    }
    data.Dispose();
}

--------------- I guess im wrong, this is if you have a file you want to attach ---------------

it looks like there is an example of sending mail with an attachment here:

http://www.aspnettutorials.com/tutorials/email/email-attach-aspnet2-csharp.aspx

I hope this is what you're looking for.

The name parameter in the Attachment constructor is the name that will be displayed for the attachment in the recipient's email.

Thus you can freely choose the name parameter (extension .xls preferred), and set the mediaType parameter to "application/vnd.ms-excel", which is the defined MIME type for excel files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM