In my last post, I promised to look at SendRawEmail next. I got busy on other projects so this has taken longer than I originally anticipated it would.

Converting MailMessage into a MemoryStream

public static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message)
{
	Assembly assembly = typeof(SmtpClient).Assembly;

	Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");

	MemoryStream fileStream = new MemoryStream();

	ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);

	object mailWriter = mailWriterContructor.Invoke(new object[] { fileStream });

	MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);

	sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);

	MethodInfo closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);

	closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);

	return fileStream;
}

When we create a request for the SES service, we need to give it a MemoryStream object that contains our mail message. I created a MailMessage object for this, but in order to give this to SES I had to convert it to a MemoryStream. I found the guts of the method above online, and slightly modified it for my own use. I’m not going to talk about it, but you can find it here.

SendRawEmail

public static Boolean SendRawEmail(String from, String to, String Subject, String text = null, String html = null, String replyTo = null, String returnPath = null)
{
	AlternateView plainView = AlternateView.CreateAlternateViewFromString(text, Encoding.UTF8, "text/plain");
	AlternateView htmlView = AlternateView.CreateAlternateViewFromString(html, Encoding.UTF8, "text/html");

	MailMessage mailMessage = new MailMessage();
	mailMessage.From = new MailAddress(from);

	List<String> toAddresses = to.Replace(", ", ",").Split(',').ToList();
	foreach (String toAddress in toAddresses)
	{
		mailMessage.To.Add(new MailAddress(toAddress));
	}

	//foreach (String ccAddress in ccAddresses)
	//{
	//    mailMessage.CC.Add(new MailAddress(ccAddress));
	//}

	//foreach (String bccAddress in bccAddresses)
	//{
	//    mailMessage.Bcc.Add(new MailAddress(bccAddress));
	//}

	mailMessage.Subject = Subject;
	mailMessage.SubjectEncoding = Encoding.UTF8;

	if (replyTo != null)
	{
		mailMessage.ReplyTo = new MailAddress(replyTo);
	}

	if (text != null)
	{
		mailMessage.AlternateViews.Add(plainView);
	}

	if (html != null)
	{
		mailMessage.AlternateViews.Add(htmlView);
	}

	RawMessage rawMessage = new RawMessage();

	using (MemoryStream memoryStream = ConvertMailMessageToMemoryStream(mailMessage))
	{
		rawMessage.WithData(memoryStream);
	}

	SendRawEmailRequest request = new SendRawEmailRequest();
	request.WithRawMessage(rawMessage);

	request.WithDestinations(toAddresses);
	request.WithSource(from);

	AmazonSimpleEmailService ses = AWSClientFactory.CreateAmazonSimpleEmailServiceClient(AppConfig["AWSAccessKey"], AppConfig["AWSSecretKey"]);

	try
	{
		SendRawEmailResponse response = ses.SendRawEmail(request);

		SendRawEmailResult result = response.SendRawEmailResult;

		Console.WriteLine("Email sent.");
		Console.WriteLine(String.Format("Message ID: {0}", result.MessageId));

		return true;
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);

		return false;
	}
}

The above method uses the .NET MailMessage class to create my email message.

Lines 3/4 create our alternative email messages so the email should be visible in whatever mail app is used to retrieve the emails.

Lines 9-13 add the TO addresses to the mail message. Again, I pass in the emails as a string separated by a semi-colon and convert this to a list. The mail message wants each address added as a MailAddress object so a foreach loop steps through the list and adds each address correctly.

Lines 15-23 do the same for CC and BCC address if you wanted to use them. I haven’t in my example, but include the code commented out for you. You’ll also need to add them so you can pass them in when calling the method (Line 1).

Line 25/26 sets the Subject and its encoding and then lines 28-41 add the Reply To address and our alternative views we created earlier (if the String isn’t null).

Line 43 creates our RawMessage object and then lines 45-48 call our method above to convert the MailMessage into a MemoryStream.

We create our request on line 50 and give it our RawMessage on line 51. We also give it our TO addresses and our FROM address on lines 53/54.

We connect to SES on line 56 and then get the response from giving SES our request on lines 60-62 and output to the console the Message ID and a confimation message on lines 64/65.

Other than converting the MailMessage to a MemoryStream this is pretty straight forward. I’ll do my best to help anyone having issues via the comments…

Neil

Smile

About these ads