Sunday, January 24, 2016

Amazon Web Services (AWS) Simple Email Services - Lou Person

Amazon Web Services (AWS) Simple Email Services - Lou Person
Sales, IT and Business Professionals such as myself are very conscience when it comes to security.  A security breach can cause irreparable brand damage and financial losses.  It also can kill credibility and trust with users.  One of the easiest and most sinister exploits is around phishing, or email server hijacking.  In the same category is Spam, which at best is really annoying and at worst can be a front door for a virus or malware.  The vast majority of applications today, especially mobile, rely on email in one form or another for one or more of the following use cases: 

  • New account creation confirmation
  • Password reset
  • Notifications, such as receipts, an action the app wants you to take or account changes
  • Marketing or offers
There are a number of ways to send email from an application.  The others I am working with are not as Sales or Business facing as myself, so I didn't get the sense that they were overly motivated to research another solution to increase security, brand protection and minimize financial risk.  So I volunteered to attack the problem for the team.  I did a great deal of research to find a solution which was secure, contained audit controls, provided reporting, is a managed service so it could limit risk and is very cost effective.  I looked at a number of solutions, some I was familiar with, others were new to me.  I'm going to compare SMTP as part of IIS and AWS SES.

The first thing I did to evaluate environments was create a sample application to test sending email.  Here is the code:



<?php 

$action=$_REQUEST['action']; 

if ($action=="")    /* display the contact form */ 
    { 
    ?> 
    <form  action="" method="POST" enctype="multipart/form-data"> 
    <input type="hidden" name="action" value="submit"> 
    Your name:<br> 
    <input name="name" type="text" value="" size="30"/><br> 
    Email to:<br> 
    <input name="emailto" type="text" value="" size="30"/><br> 
Email from:<br> 
    <input name="emailfrom" type="text" value="" size="30"/><br>
    Your message:<br> 
    <textarea name="message" rows="7" cols="30"></textarea><br> 
    <input type="submit" value="Send email"/> 
    </form> 
    <?php 
    }  
else                /* send the submitted data */ 
    { 
    $name=$_REQUEST['name']; 
    $emailto=$_REQUEST['emailto'];
 $emailfrom=$_REQUEST['emailfrom']; 
    $message=$_REQUEST['message']; 
    if (($name=="")||($emailto=="")||($message=="")) 
        { 
        echo "All fields are required, please fill <a href=\"\">the form</a> again."; 
        } 
    else{         
        $from="From: $name<$emailfrom>\r\nReturn-path: $emailfrom"; 
        $subject="Message sent using your contact form"; 
        mail($emailto, $subject, $message, $from); 
        echo "Email sent!"; 
        } 
    }   
?> 

I then setup SMTP within my Windows server instance.  SMTP was a component of IIS through IIS 6.0.  The Web Platform Installer I discussed in an earlier post deploys IIS 8.0.  I am guessing Microsoft stopped shipping an SMTP server by default due to the same issues I am concerned with around security.  I was able to install SMTP as part of IIS 6.0 by enabling it through server management as a new feature.  It took a little bit to get working because I had to add SMTP rules to the Webserver security group and configure the server appropriately for AWS.  I was able to test the setup by using the sample php application above.  I modified the php.ini file to instruct php to use the mail server within the Windows instance as follows:

[mail function]

smtp = localhost

smtp_port = 25

Everything worked great!  Too great in fact!  I was able to send email to ANYONE from ANYONE.  I noticed that emails arriving to my gmail account were flagged as "phising" and test emails to other accounts went immediately to spam.  I had no way to control, monitor or audit what was going on.  In a real world scenario, where this could be used to email hundreds of thousands of people a day, this could be a disaster!  For internal or intranet based applications, it is probably an easy solution, but not for a public facing mobile application.

I then dug into AWS SES.  Referencing here: 
"Building a large-scale email solution is often a complex and costly challenge for a business. You must deal with infrastructure challenges such as email server management, network configuration, and IP address reputation. Additionally, many third-party email solutions require contract and price negotiations, as well as significant up-front costs. Amazon SES eliminates these challenges and enables you to benefit from the years of experience and sophisticated email infrastructure Amazon.com has built to serve its own large-scale customer base."

I had to go through a number of verifications to set it up, which was fine by me.  First, from the SES console, I had to add a txt record to my public DNS through network solutions.  Once this was added, and it had about an hour to propogate out, the SES console indicated that the domain was "verified".  Then, for each email I wanted to use as the "From" email, I had to verify through SES.  I would receive an email with a link from AWS.  Clicking on the link allowed sending from the email address.  Next, in order to send email through SES, I had to generate a username and password to embed in the application code.  The username is 20 characters long and the password 40, mixed randomly with uppercase, lowercase, and symbols.  I was not sure at this point how to test, so I found the following sample application using Visual Studio (it was actually very easy to configure):
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-using-smtp-net.html

I was able to get the code to execute the first try, after changing username, password, smtp host address and port.  But, it would not connect, I received a message that it was sending the email, but nothing was happening, it almost appeared as if it wasn't connecting.  I looked at the security groups and realized I needed to add the standard SMTP port, 25, but also the port used by SES, 587.  I was now able to send the email and the application confirmed it was sent, but it never arrived.

I didn't realized at the time, until I contacted support via chat at 12:30AM Sunday morning, that I could only work in a "sandbox".  Meaning, I could only send email to and from verified email accounts.  I had to go through another security measure and request to have production access granted.  I submitted the form, and by the next morning, I awoke to an email congratulating me for moving out of the sandbox:

"Congratulations! After reviewing your case, we have increased your sending quota to 50,000 messages per day and your maximum send rate to 14 messages per second in AWS Region. Your account has also been moved out of the sandbox, so you no longer need to verify recipient addresses."

There are a number of other security protocols built in.  For example, I have to comply with Amazon's Acceptable Use Policy found here.  If there is a high rate of bounces in a given period, the service is suspended.  I can also view the following statistics in real time, through the SES Console, which has nice charts and graphs of the data points:  Successful Delivery Attempts, Rejected Messages, Bounces and Complaints.  Most importantly, I can "shut things down" immediatley if something goes crazy.  This is worth any nominal charges for the brand protection and financial loss avoidance it provides.

I did have one challenge that took some figuring out.  When I setup SES against the PHP application above, I received authentication errors.  In the php.ini file, I first simply changed the host name to the SES host provided in the console.  Since the C# application I ran in Visual Studio was working, I was sure things were setup correctly so the issue must be at the application level.  It took a little while to realize that the default send command within php was limited because it does not pass username and password through to the smtp server.  Thus, the authentication error.  This wasn't unix, afterall, and there isn't a sendmail service built into Windows.  Oh, wait, why not install sendmail for Windows?  A quick search of "sendmail for Windows" took me to sendmail.org and I was able to download sendmail for Windows.  I had to modify the php.ini file as follows, basically telling php to call out to sendmail:

[mail function]
sendmail_path = c:\sendmail\sendmail.exe
;smtp = localhost
;smtp_port = 25

Then, I had to modify sendmail.ini to include the hostname of the SES server, the port, the SES generated username and password.  

All of these configurations took about 15 minutes once I figured out what the problem was and came up with a solution.

I circled back with the team and simply told them that SMTP outbound email is working and they could only use a verified outbound email.  It really is a black box to the developers, but as a Sales and Business Professional, I have tremendous peace of mind that the application has much less risk and much great security controls, metrics and reporting in place because of SES.

Post by Lou Person

No comments:

Post a Comment