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.
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = hostTextBox.Text;
...
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:
using (MemoryStream memoryStream = new MemoryStream())
{
byte[] contentAsBytes = Encoding.UTF8.GetBytes(fileContentTextBox.Text);
memoryStream.Write(contentAsBytes, 0, contentAsBytes.Length);
memoryStream.Seek(0, SeekOrigin.Begin);
ContentType contentType = new ContentType();
contentType.MediaType = MediaTypeNames.Application.Octet;
contentType.Name = fileNameTextBox.Text;
Attachment attachment = new Attachment(memoryStream, contentType);
message.Attachments.Add(attachment);
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