The Adoption Program Insights series describes experiences of Microsoft Services consultants involved in the Windows Azure Technical Adoption Program assisting customers deploy solutions on the Windows Azure platform. This post is by Norman Sequeira, Patrick Butler Monterde and Tom Hollander.
This is the second part of a two-part series describing options for sending emails from Windows Azure applications. In Part 1 we described a pattern that uses a custom on-premise Email Forwarder Service to send mails on behalf of a Windows Azure application. In this post we describe how to use your email server's web services APIs to accept messages directly from a Windows Azure application.
Pattern 2: Using Email Server's Web Services APIs
This pattern leverages the web services capability of Exchange Server 2007 or Exchange Server 2010 to send email out directly from the Windows Azure platform. This approach could also be used other email servers that provide web service interfaces, however this post only describes the implementation for Microsoft Exchange Server.
Since both web and worker roles can make outbound connections to Internet resources via HTTP or HTTPS, it is possible for the web/worker roles to communicate with the web services hosted on Exchange Server. Both Exchange Server 2007 and Exchange Server 2010 support EWS (Exchange Web Services) as an interface for automation. Exchange Web Services offers rich feature set which supports most common mail automation related scenarios like sending email, adding attachments, checking a user's mailbox, configuring delegate access etc. For a full list of features supported by EWS, please check out this MSDN article.
If your organisation has opted to use Exchange Online instead of an on-premise email server, the same EWS based approach can be used from Windows Azure without any code changes since both Exchange Online Standard and Exchange Online Dedicated offer EWS support. Exchange Online is a part of the Microsoft Business Productivity Online Suite (BPOS) which is a set of messaging and collaboration solutions offered by Microsoft.
The following diagram shows how a Windows Azure application could leverage EWS to send emails on its behalf:
The EWS Managed API provides strongly typed .NET interfaces for interacting with the Exchange Web Services. Once the Exchange Web Services Managed API is installed, your first step is to add a reference to the Microsoft.Exchange.WebServices.dll in your existing Windows Azure project in Visual Studio:
Using the EWS Managed API against a Test Server
Test servers are deployed with self-signed certificates, which are not trusted by the Microsoft .NET Framework. If you use the EWS Managed API against a test server, you might receive the following error:
To resolve this issue, you can write code to disable certificate validation in test scenarios. You should use #if DEBUG or similar techniques to ensure this code is not used for production scenarios!
// Hook up the cert callback.
// Validate the certificate and return true or false as appropriate.
// Note that it not a good practice to always return true because not
// all certificates should be trusted.
Creating an Instance of the ExchangeService Object
Next it's time to connect to the server by creating and configuring an ExchangeService instance. Note the use of Autodiscover to determine the service's URL based on an e-mail address:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
//Retrieve the credential settings from the Azure configuration
string userName = RoleEnvironment.GetConfigurationSettingValue("EWSUserName");
string password = RoleEnvironment.GetConfigurationSettingValue("EWSPassword");
string domain = RoleEnvironment.GetConfigurationSettingValue("EWSDomain");
service.Credentials = new WebCredentials(userName, password, domain);
// In case the EWS URL is not known, then the EWS URL can also be derived automatically by the EWS Managed API
// using the email address of a mailbox hosted on the Exchange server
string emailAddress = RoleEnvironment.GetConfigurationSettingValue("emailAddress");
Once an instance of the ExchangeService object has been created and initialized, it can be used for sending/receiving mails.
EmailMessage message = new EmailMessage(service);
message.From = new EmailAddress("firstname.lastname@example.org");
message.Subject = "Sending mail from Windows Azure";
message.Body = new MessageBody(BodyType.HTML, "This is the body of the mail sent out from Windows Azure environment");
//code for sending attachments.
//The AddFileAttachment method takes in a 'display name' and 'byte array' as parameters
//The following property 'ContentId' is used in case the attachment needs to be referenced from the body of the mail
message.Attachments.ContentId = "Attachment1";
// The following method sends the mail and also saves a copy in the 'Sent Items' folder
It is important to understand the architectural implications for any solution. Some of the considerations for the Email Server Web Service APIs approach include:
- Cost: Outbound data flow from Windows Azure to EWS will incur the additional cost to the overall solution. The overall cost impact will vary based on the email volume and bandwidth usage in individual solution, that must be studied carefully before the implementation of this pattern.
- Performance: Large email attachments may pose some performance impact since these needs to be serialized and downloaded to the Exchange Servers by using EWS (on-premise or online). This must also be considered carefully.
Even though Windows Azure does not include its own native SMTP server, there are several options for building applications that send emails. If you have an on-premise email server, you can use Windows Azure storage to send messages to a custom Email Forwarder Service which then forwards them onto your email server. If your email server exposes a web services API, you can use this to communicate directly instead of using a custom service. And if you have direct access to a SMTP server (including a commercial service) you can configure your Windows Azure app to use that.
One final comment - no matter which of these approaches you use, keep in mind that if your application needs to send out a very large number of emails (for example, for user registrations) you may run into problems if your email server is configured to limit email volume or if the recipients' servers are likely to reject messages as spam. In this case you will need to choose or configure your email server carefully to ensure your messages make it to their final destination.