Click here to Skip to main content
Click here to Skip to main content

Creating In-Memory Mail Attachments

By , 24 Nov 2007
 
Screenshot - InMemoryMailAttachment.gif

Introduction

Recently I wrote a background service which monitors a database and sends emails about the status. Each email has an attached XML file, which is used to automatically process the emails at the receiver's side. I looked for an example on how to create such attachments without first creating files in the file system. There are a lot of examples on how to attach existing files to an email, but none showed how to create attachments in-memory.

For demonstration purposes, I wrote a small windows application which is able to send an email with an attachment. I hope this small example can help some people struggling with the same problem.

Understanding the Code

I put all the code into the click event handler of the "Send" button in the SenderForm class. In real production code, I would have separated the concerns into different classes, especially to be able to test the behavior with unit tests. The code uses the .NET Framework class SmtpClient and MailMessage to send emails. There are already a lot of articles on how to initialize the SmtpClient, how to perform the SMTP authentication and how to create a MailMessage, so I will not cover this part in detail.

// Init the smtp client and set the network credentials
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = hostTextBox.Text;
...
    
// Create MailMessage
MailMessage message = new MailMessage(
    fromTextBox.Text,
    toTextBox.Text,
    subjectTextBox.Text,
    bodyTextBox.Text);

The interesting part is the creation of the attachment. The file content string should be placed inside the attachment. First you have to convert the string into an array of bytes. These bytes must be written into a memory stream. Do not forget to set the position pointer in the stream back to the beginning before you use the stream. You have to define the MIME type and the file name with a ContentType object. Now you can create an Attachment object. Adding this attachment to the email and sending it is easy:

// Create a memory stream
using (MemoryStream memoryStream = new MemoryStream())
{
    byte[] contentAsBytes = Encoding.UTF8.GetBytes(fileContentTextBox.Text);
    memoryStream.Write(contentAsBytes, 0, contentAsBytes.Length);

    // Set the position to the beginning of the stream.
    memoryStream.Seek(0, SeekOrigin.Begin);

    // Create attachment
    ContentType contentType = new ContentType();
    contentType.MediaType = MediaTypeNames.Application.Octet;
    contentType.Name = fileNameTextBox.Text;
    Attachment attachment = new Attachment(memoryStream, contentType);

    // Add the attachment
    message.Attachments.Add(attachment);

    // Send Mail via SmtpClient
    smtpClient.Send(message);
}

Points of Interest

The use of streams and the encoding and decoding of strings is solved very nicely by the creators of the .NET Framework. Nevertheless, someone not concerned with these issues everyday may need some examples to get productive quickly. I hope this article may help a little bit.

History

  • 24th November, 2007: Initial version posted
  • 3rd December, 2007: Disposing the memory stream with a using statement

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sven Grand
Team Leader
Germany Germany
Sven worked as Software Developer, System Architect, Project Manager and Team Leader. He is working for more than 15 years in the software industry.

http://www.svengrand.blogspot.com/

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionEven today a life SavermemberPhoenix2k117-Sep-12 8:35 
Thanks your post just saved me hours of debugging.
 
What I didn't know was setting the stream back to position 0. Thumbs Up | :thumbsup:
QuestionnicememberCIDev19-Apr-12 7:09 
A clearly written and useful article.
Just because the code works, it doesn't mean that it is good code.

QuestionBrilliantmemberMember 475455511-Apr-12 16:37 
I couldn't get the attachment to show greater than a couple of hundred bytes and then I saw your explanation of needing to rewind the memory stream before attaching - that did the trick. Thanks!
GeneralDanke!memberxmanuw5-Oct-09 4:21 
Über den Memorystream war ich auch schon gestolpert und reigeschrieben hab ich auch schon.
 
Bloß dass man noch an den Anfang zurückspringen muss…
 
Da wär ich nie draufgekommen.
 
Danke.
GeneralUse the CreateAttachmentFromString() method to create an attachmentmemberjussieu00724-Feb-09 23:41 
Hi, Sven,
 
I used your code in my project and it works well. Actually we can use the overloaded method "CreateAttachmentFromString" to create an attachment from a string. Hear is the MSDN link for the method:
http://msdn.microsoft.com/en-us/library/system.net.mail.attachment.createattachmentfromstring.aspx[^]
 
The advantage is we don't need to do the conversion and create the memory stream ourselves. For example:
 
public static Attachment CreateAttachmentFromString(
string content,
string name,
Encoding contentEncoding,
string mediaType
)
 
See you... Smile | :)
GeneralRe: Use the CreateAttachmentFromString() method to create an attachmentmemberSven Grand13-Mar-09 11:15 
Hi jussieu007,
thanks for the hint. Thats much easier. Good job!
Sven
GeneralGreat Article...memberJoshua Clark9-May-08 8:28 
Thanks a lot for showing an easy way to build an in-memory file object.
 
Thanks a bunch!
GeneralVery UsefullmemberDhawal Mehta30-Mar-08 23:59 
Thanks Sir,
 
A great and very usefull article and code Smile | :) Rose | [Rose]
GeneralGreat articlememberstylonurus20-Feb-08 8:22 
Sven,
Really nice article which helped me out very quickly. Good job and thanks.
Rick Eis
GeneralNice solution when permissions cant be grantedmemberMember 453350210-Dec-07 5:53 
I wanted to take the time to thank you for this article. I work in an ASP.NET environment where granting write access to the impersonation account may not always be desireable for security and space concerns. This solution allows for sending attachments without the need to grant write access to to file system, and it keeps the servers from getting filled with past files that somebody or some process would need to go back and clean up later. Nice simple solution that may not be immediately apparent. Smile | :)
GeneralDispose!memberSteven Berkovitz26-Nov-07 13:41 
Any class inheriting from System.IO.Stream implements IDisposable so you should ensure to call Dispose() when you are finished with it, or ideally, wrap the MemoryStream in a using statement.
 
ie:
 
using(MemoryStream ms = new MemoryStream()) {
// Send my attachment
} // Automatically dispose
 
-Steven

AnswerRe: Dispose!memberSven Grand27-Nov-07 8:56 
Hi Steven,
 
thanks for the hint. I will update the article and the code accordingly.
 
Sven

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130617.1 | Last Updated 24 Nov 2007
Article Copyright 2007 by Sven Grand
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid