Pomodoro

I keep hearing about friends using The Pomodoro Technique and I’ve decided I really need to just try it out for myself. I’m not yet sure if it will work for me, but I’ve been hearing positive things about it.

To that end I set myself the task of a small project using it, that is to create a web page with a pomodoro timer with a visible indicator of time left and that makes a noise when the timer expires. The final pomodoro is to write up this blog post.

This task has a mix of things I already know about (putting together a web page with HTML, CSS, JavaScript and jQuery) and things I would have to look up (like how to get a web page to emit a sound at a given point, have it respond to events at timed intervals, and deploy it to the web via Amazon’s AWS).

What I found was that 25 minutes actually goes past very quickly. Secondly, and this is more because it is the Christmas holidays, I still need to discipline myself not to jump to Facebook or Twitter each time my phone beeps or chirrups a notification at me. Similarly, in work I would probably have to discipline myself not to jump to Outlook or Skype when they pop up notifications.

On the whole, it looks like it could be fairly advantageous and I’ll continue to see if it helps productivity.

For the moment, if you do want to have a look at the very simple pomodoro timer that I created, then you can access it here: http://pomodoro.colinmackay.co.uk – I’m also happy to take suggestions on improvements if you think it could be made better.

Sending more than a basic email with Amazon SES

Previously, I wrote about getting started with Amazon’s Simple Email Service, and I included details of how to send a basic email. The SendEmail method is excellent at sending basic emails with HTML or Text bodies. However, it doesn’t handle attachments. For that, you need to use SendRawEmail.

SendRawEmail doesn’t give you much functionality. In fact, you have to do all the work to construct the email yourself. However, it does mean that you can do pretty much what you need with the email.

There are still some limitations. Amazon imposes a 50 recipient limit per email, a maximum 10Mb per email, and you can only add a small number of file types as an attachment. This is, I suspect, in order to reduce the ability for people to use the service to spam and infect other people while permitting most of all legitimate uses for the service.

Building an email

When I said that you have to do all the work to construct the email, I really did mean that. You have to figure out the headers, the way the multi-part MIME is put together the character encoding (because email is always sent using a 7-bit encoding) and so on.

I tried to do this, and it it was most frustrating work. The tiniest thing seemed to put Amazon SES into a sulk.

However, I did find a piece of code that someone else had written to do the heavy work for me. Essentially, what he’s doing is constructing a mail message using the built in System.Net.Mail.MailMessage type in .NET and then using .NET’s own classes to create the raw mail message as a MemoryStream, which is what Amazon SES wants.

I’ve refactored the code in the linked post so that it is slightly more efficient if you are calling it multiple times. It uses reflection, and some of the operations need only be carried out once regardless of the number of times you generate emails, so it removes those bits off to a static initialiser so that they only happen the once.

Here’s my refactored version of the code:

public class BuildRawMailHelper
{
    private const BindingFlags nonPublicInstance =
        BindingFlags.Instance | BindingFlags.NonPublic;

    private static readonly ConstructorInfo _mailWriterContructor;
    private static readonly MethodInfo _sendMethod;
    private static readonly MethodInfo _closeMethod;

    static BuildRawMailHelper()
    {
        Assembly systemAssembly = typeof(SmtpClient).Assembly;
        Type mailWriterType = systemAssembly
            .GetType("System.Net.Mail.MailWriter");

        _mailWriterContructor = mailWriterType
            .GetConstructor(nonPublicInstance, null,
                new[] { typeof(Stream) }, null);

        _sendMethod = typeof(MailMessage).GetMethod("Send",
            nonPublicInstance);

        _closeMethod = mailWriterType.GetMethod("Close",
            nonPublicInstance);
    }

    public static MemoryStream ConvertMailMessageToMemoryStream(
        MailMessage message)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            object mailWriter = _mailWriterContructor.Invoke(
                new object[] {memoryStream});

            _sendMethod.Invoke(message, nonPublicInstance, null,
                                new[] {mailWriter, true}, null);

            _closeMethod.Invoke(mailWriter, nonPublicInstance,
                null, new object[] {}, null);

            return memoryStream;
        }
    }
}

At first glance, the fact that the MemoryStream is disposed of does seem a bit counter-intuitive, however some methods of MemoryStream still function when the stream is closed, such as ToArray().

Incidentally, if you want to see what the raw email looks like you can use a piece of code like this to get the raw email as a string:

MemoryStream memoryStream =
    BuildRawMailHelper.ConvertMailMessageToMemoryStream(mailMessage);
byte[] data = rawMessage.Data.ToArray();
using (StreamReader reader = new StreamReader(new MemoryStream(data)))
{
    string rawMail = reader.ReadToEnd();
    Console.Write(rawEmail);
}

Using SendRawEmail

Because you’re doing all the work, the code that actually interacts with Amazon SES is very simple.

// mailMessage is an instance of a System.Net.Mail.MailMessage
var config = new AmazonSimpleEmailServiceConfig();
var client = new AmazonSimpleEmailServiceClient(config);
SendRawEmailRequest request = new SendRawEmailRequest();
request.RawMessage = new RawMessage();
request.RawMessage.Data = BuildRawMailHelper
    .ConvertMailMessageToMemoryStream(mailMessage);
var response = client.SendRawEmail(request);

And that’s it. You can now send emails with attachments, and anything else you can do with a MailMessage.

Getting started with Amazon SES in .NET

Amazon SES (Simple Email Service) is a cloud based email service for sending bulk or transactional emails. It has a web based API and Amazon also provide a .NET wrapper (The AWS SDK for .NET) to access this (and other Amazon services), so you don’t have to work out how to code the connection yourself.

If you want to get started without installing the SDK, there is a NuGet package available too. (In Visual Studio 2010, go to Project—>Manage NuGet Packages… and the dialog will open. Search for “AWSSDK” to find the package.

But, before we get started creating a little application, you’ll need to set up SES first. Amazon have a Getting Started guide that will walk you through the initial steps. You’ll want to verify a couple of email addresses with the service in order to get going with too.

Verifying an email address with the AWS console

You can verify an email address through the SES tab of the AWS Console. There should be a big friendly button that says “Verify a New Sender” near the top of the page. When you click it you’ll get a new dialog that requests the email address you want to verify.

When you clicked submit, an email will be sent to that address requesting verification. Once the recipient has verified that the address exists (and that they are happy to be a verified sender) then you can start sending email from that address (in development mode, SES only permits recipients that have been verified also)

Setting up your credentials

First of all, you’ll want to store your credentials somewhere. For the purpose of this example, I’ll just put them in the web.config (or app.config) in the appSettings area. It looks like this (replacing the asterisks with your keys):

<appsettings>
  <add value="********************" key="AWSAccessKey" />
  <add value="****************************************" key="AWSSecretKey" />
  <!-- Other app settings go here -->
</appsettings>

You can get your keys by logging in to the Security Credentials page and going to the Access Keys tab in the Access Credentials section.

In your code, the AmazonSimpleEmailServiceConfig class will pick up the settings and apply them for you. There are other ways of setting the security credentails, but that’s beyond the scope of this introduction.

Sending an Email

You can access SES through the SimpleEmailServiceClient, which takes an AmazonSimpleEmailServiceConfig in its constructor. From this point on you can construct the relevant requests, call the appropriate method on the client class and receive a response.

There are two ways of sending an email. You can use the SendEmail method or the SendRawEmail method. The latter gives you much more control with what you can do, but requires much more work to get it to work.

For this example, I’m going to use SendEmail which allows you to send an email to a number of recipients in either text or HTML format. It doesn’t permit attachments, however it is much easier to get going with.

The SendEmailRequest

The SendEmailRequest is an object that contains all the relevant information you need to send an email using the SendEmail method. It consists of a Source (who sent the email), a Destination (which may be made up of up to 50 email addresses), a Message (which is the Subject and Body of the message in Text and/or HTML format), the ReturnPath (where the bounces and errors get sent) and a ReplyTo address (where the user replies get sent to).

var config = new AmazonSimpleEmailServiceConfig();
var client = new AmazonSimpleEmailServiceClient(config);
SendEmailRequest request = new SendEmailRequest();

request.Destination = new Destination();
request.Destination.ToAddresses.Add("recipient@example.com");
request.Destination.CcAddresses.Add("cc@example.com");
request.Destination.BccAddresses.Add("bcc@example.com");

request.Message = new Message();
request.Message.Body = new Body();
request.Message.Body.Html = new Content();
request.Message.Body.Html.Data = "<h1>Hello World!</h1><p>I'm in HTML.</p>";
request.Message.Body.Text = new Content();
request.Message.Body.Text.Data = "Hello World! I'm in Text.";
request.Message.Subject = new Content();
request.Message.Subject.Data = "This is the subject line.";

request.Source = "from@example.com";
request.ReturnPath = "return.path@example.com";
request.ReplyToAddresses.Add("reply.to@example.com");

var response = client.SendEmail(request);

The ToAddresses, CcAddresses, BccAddresses and ReplyToAddresses are each a List<string> collection. Each element representing an address. You don’t have to explicitly create the list object as the API comes with the lists already created (with nothing in them) so you can just add directly to them. However, if you already have an appropriate list from elsewhere then you can assign it to the relevant property.

The SendEmail method can fail for a number of reasons, the most common I’ve found is the MethodRejectedException with the message “Email address is not verfied”. This is because in development you cannot send emails to recipients that have not already verified their email address… and I keep forgetting that.

Follow

Get every new post delivered to your Inbox.

Join 26 other followers