PHP for ASP.NET developers (part 4 – Object Orientation)

Continuing on my series of getting to know PHP for ASP.NET developers, I’m going to concentrate on the object oriented parts of the language.

Class Diagram

In order to creating a class is very similar to C#, for example:

class Animal {
    //put your code here
}

To create a derived class you “extend” the base class.

class Mammal extends Animal {
    //put your code here
}

There is a bit of a clash of nomenclature here, but in PHP “properties” are what C# calls “fields”. Don’t confuse PHP properties with C# properties, they are not the same thing.

To create a PHP property, all you need to do is indicate the accessibility of the property and name the property. In PHP you don’t need to declare a type as you would in C#. The accessors are public, protected and private which are similar to C#.

class Dog extends Mammal{
    protected $name;
}

You can also set default values for properties. They must be compile time constants or literal values. For example:

class Dog extends Mammal{
    private $name = "Rover";
}

To create methods (or rather “functions”) on a class you can declare them in a similar way to C#, you indicated the accessibility (although in PHP they are public by default). For example:

public function speak() {
    echo ("Woof!");
}

You can create an instance of the class in a similar way to C#, to use the methods you replace the dot in C# with a -> in PHP. For example:

$dog = new Dog();
$dog->speak();

Each class has a default constructor, to create your own constructor create a function called __construct with the desired parameters. For example:

class Mammal extends Animal {
    protected $mother;
    protected $father;

    public function __construct($mother, $father)
    {
        $this->mother = $mother;
        $this->father = $father;
    }

    public function displayParents()
    {
        echo ("Mother=".$this->mother."; Father=".$this->father);
    }
}

In derived classes you have to call the base constructor explicitly. It won’t be called otherwise. You can do this like so:

class Cat extends Mammal {
    public function __construct($mother, $father)
    {
        parent::__construct($mother, $father);
    }

PHP also supports abstract classes and methods (functions). For example, in the examples I’m using here, you probably would not want to instantiate the Animal class. Let’s also say that we want to create an abstract function (one that we fill in the details of in a derived class). Simply add the keyword “abstract” to the method signature just like in C#. For example:

abstract class Animal {
    public abstract function Vocalise();
}

abstract class Mammal extends Animal {
}

class Dog extends Mammal{

    public function Vocalise() {
        echo ("Woof!");
    }
}

PHP for ASP.NET developers (part 3)

Now that the basics have been covered in the previous two posts, I’ll continue with some thing a bit more useful… writing some logic.

Conditional Statements

In PHP the conditional operators are pretty much the same as in C#, however there are some subtle differences.

== and != use type coercion. That means that if the type on the left side is not the same as the type on the right side then PHP will coerce them so that they can be compared. For example:

$a = 1;
$b = 1.0;

if ($a == $b)
    echo 'a and b are equal.';
else
    echo 'a and b are not equal.';

It even works if one of them is a string representation of the number one.


To get the functionality you’d expect in C# you need to use === and !==.

There is also an additional not equals operator similar to == that consists of a left and right cheveron: <>

Be careful of accidentally using a single equal sign for comparison. In C# the compiler will issue an error if it doesn’t evaluate to a Boolean. However, in PHP everything can be evaluated as a Boolean (see the section on Booleans in my previous post).

You can join comparisons together with && or || just like in C#, however, PHP also supports the use of and or or.

if statements also support an elseif clause in PHP.

if ($a < 123)
{
    // Do stuff
}
elseif ($a == 123)
{
    // Do other stuff
}
else
{
    // Do different stuff
}

Unlike C#, switch statements allow one case clause to drop in to the next, so it does not require a break at the end of each case block. The break on the last case or default is not necessary either.

switch($a)
{
    case 1:
        // Do some stuff
        break;
    case 2:
        // Do stuff
    case 3:
        // Do stuff (and continue case 2 if necessary)
        break;
    default:
        // Do stuff for all other cases
        break;
}

Loops

PHP, like C#, has a number of loop statements depending on what you want to do.

for loops, while, and dowhile work exactly the same way. So I won’t discuss them further.

Just like C#, you can break out of a loop, and continue to the next iteration of the loop.

PHP for ASP.NET Developers (part 2)

In my previous post on PHP for ASP.NET Developers, I introduced the basics of how to set up a PHP environment and started showing the differences between PHP’s way of doing things from an ASP.NET developer’s perspective. In this post, I’m continuing with those differences.

Comments

Comments in PHP are very similar to C#. You can use /* to open a comment block and */ to close it later, and you can use the // format to comment to the end of a line.

PHP also allows the use of a hash symbol, #, to indicate that the remainder of the line is a comment.

Types

Booleans

In .NET a Boolean is a specific type and you had to get the type you are using into the Boolean to use it as such. In PHP things are a little more flexible. A Boolean can be true or false, as you might expect. But there are special cases with other types. For example, a string can be treaded as a Boolean (in an if statement, for example). If the string is empty or contains just “0” (zero) then it is treated a false. Any other value is true. Numbers have a similar effect. Zeros are treated as false and others are treated as true. null is also treated as false.

 

Dates

There are two ways to get the current date. The first is with a call to time() which returns a Unix timestamp (an integer representing the number of seconds between 00:00:00 on 1/1/1970 and the date in question). The other way is to use date() with just a format string which returns the current date formatted as specified. You can also call date and pass a timestamp and have it convert the timestamp in to the specified format. For example:

$nowTimestamp = time();
echo "<p>The time now is ".$nowTimestamp."</p>";

$nowDate = date('d/M/Y H:i:s');
echo "<p>The time now is ".$nowDate."</p>";

You can find the details of the formatting specifiers at php.net.

If you want to convert a specific date into a timestamp then you can use the function strtotime() to perform the conversion. It is quite powerful in ways that I didn’t expect, you can set the string to values such as “next Tuesday” and “yesterday”. However, the parsing of specific dates can be tricky. If you are using the American format which puts the month first you separate the components with a slash, if you are going for the European sequence which puts the day firsr then the month, you must use a dash as a separator.

For example:

$weddingTimestamp = strtotime('13-4-2012');
echo "<p>My wedding is ".$weddingTimestamp."</p>";

$weddingDate = date('d/M/Y', $weddingTimestamp);
echo "<p>My wedding is ".$weddingDate."</p>";

There is a DateTime class also available which can be used.

$now = new DateTime();
echo "<p>Today is ".$now->format('d-M-Y')."</p>";

Collections (arrays, lists, dictionaries, etc.)

PHP allows you to create an array simply by referencing the first item.

$myArray[0] = "Hello";
$myArray[1] = "World!";
echo $myArray[0].' '.$myArray[1];

And if you don’t want to have to keep a count and just keep appending on the end, you can do this:

$cities[] = 'Edinburgh';
$cities[] = 'Glasgow';
$cities[] = 'Aberdeen';
$cities[] = 'Dundee';
$cities[] = 'Inverness';
$cities[] = "Stirling";

Or, in an even more compact manner, like this:

$cities = array('Edinburgh', 'Glasgow', 'Aberdeen',
    'Dundee', 'Inverness', 'Stirling');

However, there is much more flexibility here. You can define the contents of a Dictionary like collection in the same way. Like this:

$capitals['Scotland'] = 'Edinburgh';
$capitals['England'] = 'London';
$capitals['Wales'] = 'Cardiff';
echo 'Scotland's capital is '.$capitals['Scotland'];

Like regular arrays, there is a compact way of expressing this too.

$capitals = array('Scotland' => 'Edinburgh',
    'England' => 'London', 'Wales' => 'Cardiff');

You can also use the formatting options that defining a string with double quotes permits in order to put the value of an array element into a string. Like this:

$capitals = array('Scotland' => 'Edinburgh',
    'England' => 'London', 'Wales' => 'Cardiff');
echo "The capital of Wales is {$capitals['Wales']}";

Finally, to remove an item from the array you can use the unset

unset($capitals['England']);

However, be aware that the indexes don’t move up if you remove an element, so for example, the following will fail:

$stuff = array('Zero','One', 'Two', 'Three', 'Four');
unset($stuff[1]);
echo 'Element 1 = '.$stuff[1];

PHP for ASP.NET Developers (part 1)

For some reason that I can’t even explain to myself, I decided it would be a good idea to learn PHP. It is apparently used on roughly 60% of web sites, so it is certainly popular.

Quick Start – Install XAMPP

To get going quickly I downloaded XAMPP, which is an installation that contains all the bits I’d likely want to use to get started with. It contains apache, php and mysql in one handy package that is easier to install than trying to get the bits going separately. It also hopefully reduces the frustration of getting going which can be terribly off putting for someone new to a technology.

If you have IIS running already on your machine, I’d turn it off if you are installing XAMPP (at least during the installation and configuration phase) as the two technologies will request use of port 80 (HTTP). If you do want to run both at the same time, you are going to have to ensure that they use different ports.

if you have IIS running when XAMPP installs, then it won’t start Apache, and the use interface control panel that it provides doesn’t seem to keep up with the running state effectively so if you turn off IIS then ask it to start Apache it appears not to do so (although it does also put little warning messages up saying that if you are running 64bit to disregard the previous warning…. and I am running 64bit) yet it will serve pages.

Anyway, I didn’t install XAMPP to prepare production ready code, I installed it to learn, so I’m going to ignore some of these little foibles. Over the course of time I expect to become familiar enough with Apache, PHP, and MySQL that I’ll understand how to install them properly so that it can be used in a production setting.

Choosing an IDE

There are many IDEs to choose from, or you can go with notepad if you like. I’d rather not be stuck with notepad so I installed NetBeans 7. I don’t think it is necessarily the best, but it is a good starter. If you want a quick comparison then you can find a PHP IDE comparison chart on smashingmagazine.com.

Some basic differences between PHP and ASP.NET

Code Render Blocks

In ASP.NET you can open code render blocks using <% and close them with %> In PHP you can start with <?php and end with ?>. Some implementations also allow a shorter version of the opening tag which is <?

 

Statements

PHP statements are case insensitive, although variable names are not. For example, the following two lines are equal:

echo "<p>Hello World!</p>";
Echo "<p>Hello World!</p>";

 

Variables

In PHP all variables start with a $ sign. While statements in PHP are case insensitive, variables are not. Also, you don’t have to declare a variable with a specific type, you can just assign directly to it. You can also assign a value of a different type to the variable from the one it started out with.

However, if you do attempt to use a variable that is unassigned then you may end up with a message like this on your page:

Notice:  Undefined variable: name in C:devindex.php on line 11

If you have a variable that you no longer want, you can explicitly unset it, which means the variable will cease to exist. To unset a variable use:

unset($variable);

You can, of course, also set the variable to null. In this case the variable will still exist, it just won’t have a value.

You can check to see if a variable is set (exists and is not null) using isset($myVariable). If the variable has never been assigned, or is null, then it will return false.

 

Strings

Strings can span lines (in C#, you have to prefix the string with an @ to allow this). For example:

echo "<p>Hello World!</p>";
echo "<p>Hello
   World!</p>";

Will produce output that looks like this

<p>Hello World!</p><p>Hello
   World!</p>

Strings are handled differently if you enclose them in single or double quotes. If you enclose a string in single quotes it is treated as a literal string. If you enclose a string in double quotes, then you can embed variable any they’ll be parsed into the string…. so you can treat is like a simple form of string formatting.

If you want to put something in a string that looks like a variable name then you have to escape the initial $ sign at the front. For example:

$name = "Colin";
$message = "$name is a variable";
echo "<p>The first char is not a $ but a ",$message[0],"</p>";
echo "<p>",$message,"</p>";

If you have an exceptionally long string PHP has a neat little trick to allow you to specify a string of, I guess, limitless length. It is called a “heredoc”. How you use it is that you put in three left pointing chevrons followed by a string that denotes the end of the heredoc. That terminator string is something that will never appear in the heredoc and therefore will be safe to use as a terminator. For example:

$myString = <<<ThisIsMyTerminator
I can put as much as I want in this space
using any formatting I want, so long as I never
put in the termination sequence I specified at
the start until I am ready to terminate the
string. Like this
ThisIsMyTerminator;

Remember that you have include the semi-colon, just because the heredoc allows you to suspend all the other PHP parsing rules doesn’t mean the statement can live without its semi-colon at the end.

 

Variable variables – Or pointers to variables

PHP has a concept of Variable variables… Which is a variable that contains the name of another variable. It is a bit like a pointer to the actual variable you want to use. So, you can do this:

$myVar = "name";
$$myVar = "Colin";
echo "<p>$myVar is ",$myVar,"</p>";
echo "<p>$$myVar is ",$$myVar,"</p>";

Note that to dereference the “pointer” you use a double $ sign in front of the variable name that points to the actual value.

The result of the above is:

$myVar is name
$$myVar is Colin

If you want to get the value being pointed formatted into a string, you need to put the pointer name in braces, like this:

$myVar = "name";
$$myVar = "Colin";
echo "<p>$myVar is $myVar</p>";
echo "<p>$$myVar is ${$myVar}</p>";

 

Constants

To declare a constant in PHP there is a define statement. For example:

define(“copyright”, 2012);

Unlike variables you don’t need the $ sign in front when using the constant, however, you can’t put the constant in to strings like you can with variables.

define("year", 2012);
define("holder", "Colin Angus Mackay");
echo "<p>Copyright &copy; ",year, " ", holder, ". All Rights Reserved.</p>";

Tip-of-the-day: Columns in CSS

The CSS Multi-column layout module is a Candidate Recommendation that allows CSS to specify various aspects of column layout for page flow. It has some implementations in Chrome and FireFox but it does not work in IE yet. (I’ve not tested it on other browsers). Because of this you have to specify the Webkit and Mozilla extensions in the CSS. e.g.

div.example
{
  column-width: 300px;
  -moz-column-width: 300px;
  -webkit-column-width: 300px;
}

To show you what it can do, I’ve created some small simple examples using a list of cities, a poem and some prose. (The links open in new windows. You are encouraged to look at the page source too)

Without Columns With Columns

Checking for NULL using Entity Framework

Here is a curious gotcha using the Entity Framework: If you are filtering on a value that may be null then you may not be getting back the results you expect.

For example, if you do something like this:

var result = context.GarmentsTryOns
    .Where(gto => gto.WeddingId == weddingId
                  && gto.PersonId == personId);

And personId is null then you won’t get any results back. This is because under the hood the query is structured like this:

…WHERE WeddingId = @p0 AND PersonId = @p1

That’s all great when @p1 has a value, but when it is null SQL Sever says nothing matches. In SQL Server, NULL is not a value, it is the absence of a value, it does not equal to anything (including itself) e.g. Try this:

SELECT CASE WHEN NULL = NULL THEN 1 ELSE 0 END

That returns 0!

Anyway, if you want to test NULL-ability, you need the IS operator, e.g.

SELECT CASE WHEN NULL IS NULL THEN 1 ELSE 0 END

That returns 1, which is what you’d expect.

Now, for whatever reason, EF is not clever enough to realise that in the above example, personId is (perfectly validly) null in some cases and switch from using = to IS as needed. So, what we need is a little jiggery-pokery to get this to work. EF can tell if you hard code the null, so you can do this in advance to set things up:

Expression<Func<GarmentTryOns, bool>> personExpression;
if (personId == null)
    personExpression = gto => gto.PersonId == null;
else
    personExpression = gto => gto.PersonId == personId;

This can then be injected as a Where filter onto the query and it EF will interpret it correctly. Like this:

var result = context.GarmentTryOns
                      .Where(gto => gto.WeddingId == weddingId)
                      .Where(personExpression);

The SQL that EF produces now correctly uses PersonId IS NULL when appropriate.

Handling bounces on Amazon SES

If you send to an email that does not exist, Amazon SES will perform some handling of the bounce before passing the details on to you.

When you send email through Amazon SES you may notice that the email arrives with a Return Path that looks something like this: 00000331b8b1d648-b8302192-701f-124d-a1d5-d268912677de-135246@email-bounces.amazonses.com

As it happens, the large delimited hex number before the @ sign is the same value that you got back from the SendEmail or SendRawMail response. (If you’re unfamiliar with sending an email see previous posts on SendEmail and SendRawEmail.)

// client is a AmazonSimpleEmailServiceClient
// request is a SendEmailRequest
SendEmailResponse response = client.SendEmail(request);
string messageId = response.SendEmailResult.MessageId;

When the email bounces, it will go first to Amazon SES where they will note which email bounced. Then the email will be forwarded on to you and you will receive the bounced email. (Be aware, tho’, that the email may end up in your spam folder – they did for me). Exactly where the bounce email will go depends on the API call you are using and the fields that you have populated in the outgoing email. The rules are detailed on the Bounce and Complaints notifications page of the Amazon SES Developer’s Guide.

If you look in the headers of this email you’ll see that Message Id again in various parts of the header. e.g.

X-Original-To: 00000331b8b1d648-b8302192-701f-124d-a1d5-d268912677de-135246@email-bounces.amazonses.com
Delivered-To: 00000331b8b1d648-b8302192-701f-124d-a1d5-d268912677de-135246@email-bounces.amazonses.com
Message-Id: <00000331b8b1d648-b8302192-701f-124d-a1d5-d268912677de-135246@email.amazonses.com>

How you process these bounces on your side is up to you. Amazon do not, yet (I’m hopeful they will and it has been requested a lot) provide an automated way of using the API for querying which emails are bouncing, are complained about or are rejected.

At present the best detail you are going to get on bounced emails is in the aggregate data provided through the GetSendStatistics API call or via the graphs on the AWS Console.

What happens if I send more email to an address that bounced?

If you continue to send emails to an address that bounces you will get a MessageRejectedException when you call SendEmail or SendRawEmail with the message “Address blacklisted.”

Conclusion on bounce handling

At present bounce handling using Amazon SES isn’t great (but it’s certainly no better than using a plain old SMTP service) however Amazon do appear to be interested in providing better support for handling bounces and the like. It may very well be better supported in the future.

Verifying Senders with Amazon SES

I’ve already written a couple of pieces about Amazon Simple Email Service (SES) on sending Email and sending emails with attachments.

Why do you have to verify senders?

It is important to note that while in development mode you have to verify all recipients and senders, in production mode you still have to verify the senders (this is, presumably, an anti-spam measure to ensure the high quality of email).

If you attempt to send an email from an email address that is not registered you will get a MessageRejectedException when you call SendEmail or SendRawEmail with the message “Email address is not verified”.

Listing and verifying senders

You can add and view senders in via AWS Console which is fine if all you need is to add the odd sender now and again. However, if your application is going to send on behalf of a number of people then you need a way to automate this.

The AWS API contains three methods that help with managing verified email addresses. You can VerifyEmailAddress, DeleteVerifiedEmailAddress and ListVerifiedEmailAddresses.

To Verify an email address

Here is the code to verify an email address

var config = new AmazonSimpleEmailServiceConfig();
var client = new AmazonSimpleEmailServiceClient(config);
VerifyEmailAddressRequest request = new VerifyEmailAddressRequest();
request.EmailAddress = "joe.bloggs@example.com";
var response = client.VerifyEmailAddress(request);

The an email will be sent to the email address listed

from        no-reply-aws@amazonaws.com via email-bounces.amazonses.com
to:         joe.bloggs@example.com
date:       13 November 2011 15:08
subject:    Amazon SES Address Verification Request
mailed-by:  email-bounces.amazonses.com

Dear Amazon SES customer:

We have received a request to authorize an email address for use with Amazon
SES.  To confirm that you are authorized to use this email address, please go
to the following URL:

https://email-verification.us-east-1.amazonaws.com/...........

Your request will not be processed unless you confirm the address using this
URL.

To learn more about sending email from Amazon SES, please refer to the Amazon
SES Developer Guide.

Sincerely, Amazon Web Services

Once you’ve clicked the link you’ll get a page with a message like this:

Congratulations!

You have successfully verified an email address with Amazon Simple Email Service. You can now begin sending email from this address.

If you are a new Amazon SES user and have not yet received production access to Amazon SES, then you can only send email to addresses that you have previously verified. To view your list of verified email addresses, go to the AWS Management Console or refer to the Amazon SES Developer Guide.

If you have already been approved for production access, then you can send email to any address.

Thank you for using Amazon SES.

Once this message has been displayed the email addresses will be displayed in the SES Console and you will be able to send email from this email address (in development mode it also means you will be able to send email to the address)

Listing the verified email addresses

In order to check the email addresses that have passed through the verification process you can use the method ListVerifiedEmailAddresses.

var config = new AmazonSimpleEmailServiceConfig();
var client = new AmazonSimpleEmailServiceClien(config);
var request = new ListVerifiedEmailAddressesRequest();
var response = client.ListVerifiedEmailAddresses(request);
var result = response.ListVerifiedEmailAddressesResult;
List<string> addresses = result.VerifiedEmailAddresses;

The addresses that have been successfully verified will be listed in the addresses list.

If the email goes out (from VerifyEmailAddress or from the AWS Console), and it the address is not yet verified then it won’t appear in the list.

Removing a verified email address

If you no longer need to send from an email address you can use the DeleteVerifiedEmailAddress method.

var config = new AmazonSimpleEmailServiceConfig();
var client = new AmazonSimpleEmailServiceClient(config);
var request = new DeleteVerifiedEmailAddressRequest();
request.EmailAddress = viewModel.NewEmailAddress;
var response = client.DeleteVerifiedEmailAddress(request);

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.