Converting Strings to Streams
Sending simple email works fine, and I'm guessing that if you have ever sent email, you figured this all out. But what if, as I mentioned earlier, you want to create the attachment "on the fly?" That is, you don't want to attach a text fileinstead, you want to take the contents of a string, and attach the contents as a text file without ever saving the file on disk? No problem, you can do that. The trick lies in the overloaded versions of the constructor for the Attachment class. The class provides six overloaded versions. Three versions accept a string (plus possibly other information), where the string represents the name of a file. The other three versions allow you to supply a stream insteadthe only trick then is to get the contents of the string into a stream. This task isn't as easy as you might think, however.
You can't simply convert text from a string into a streamyou must work around the conversion. You can create a new MemoryStream instance, passing to the stream's constructor the bytes you retrieve from the string itself. Of course, you can't simply retrieve the bytes from the stringyou must use an encoder to do this, and the System.Text class provides several different encoders that can do the work for you. You can use the UTF32Encoding class to do the work for you, using the default encoder (see the documentation for this class for more information on all its behaviors). The
GetBytes method of an encoder instance retrieves all the bytes in a specified string, like this:
[Visual Basic]
Dim stream As New MemoryStream( _
UTF32Encoding.Default.GetBytes(data))
[C#]
MemoryStream stream = new MemoryStream(
UTF32Encoding.Default.GetBytes(data));
To make it easier for my friend, I created a helper procedure, which creates the stream from the string he supplies, and then adds the attachment to the mail message (this procedure assumes you have added
using/Imports statements for the System.IO and System.Text namespaces):
[Visual Basic]
Private Sub AddAttachmentFromStream( _
ByVal message As MailMessage, _
ByVal data As String, _
ByVal attachmentName As String)
Dim stream As New MemoryStream( _
UTF32Encoding.Default.GetBytes(data))
' Rewind the stream.
stream.Position = 0
' Create a new attachment, and
' add the attachment to the supplied
' message.
Dim att As New Attachment( _
stream, attachmentName)
message.Attachments.Add(att)
End Sub
[C#]
private void AddAttachmentFromStream(
MailMessage message,
String data,
String attachmentName)
{
MemoryStream stream =
new MemoryStream(
UTF32Encoding.Default.
GetBytes(data));
// Rewind the stream.
stream.Position = 0;
// Create a new attachment, and
// add the attachment to the supplied
// message.
Attachment att = new Attachment(
stream, attachmentName);
message.Attachments.Add(att);
}
Given this procedure, my friend wrote a test procedure like this, to try out the
AddAttachmentFromStream method (with all the confidential information changed, of course):
[Visual Basic]
Dim sw As New StringWriter
' Write your data into the buffer:
sw.WriteLine("This is some text")
sw.WriteLine( _
"Personalized for a recipient.")
Dim msg As New MailMessage( _
"someone@somewhere.com", _
"someone@elsewhere.com", _
"Attachments on the fly", _
"Check out the attachment!")
AddAttachmentFromStream(msg, _
sw.ToString, "Attachment.txt")
Dim client As _
New SmtpClient("MySMTPServer")
client.UseDefaultCredentials = True
client.Send(msg)
[C#]
StringWriter sw = new StringWriter();
MailMessage msg =
new MailMessage(
"someone@somewhere.com",
"someone@elsewhere.com",
"Attachments on the fly",
"Check out the attachment");
// Write your data into the buffer:
sw.WriteLine("This is some text");
sw.WriteLine(
"Personalized for a recipient.");
SmtpClient client =
new SmtpClient("MySMTPServer");
client.UseDefaultCredentials = true;
client.Send(msg);
To test it out, add the
AddAttachmentFromStream method to a project, add the sample code (and modify the email addresses and the SMTP server name), and give it a try. You should easily be able to generate an attachment in memory, without ever saving a text file to disk.
This isn't brain surgeryit's hardly even tricky. But it's never obvious how to convert from a string in memory into a stream, and many methods require you to supply a stream (or a file name). In those cases, if you have a string and need a stream instead, remember the technique shown here; it doesn't apply only to email attachments. Finally, repeat after me: "I won't use this power for the forces of evil." Don't start your own spamming serviceI wouldn't want to be responsible for that! (And if you find a solution to the PowerPoint challenge, please let me know!)