Configuring Amazon SNS To Publish Email Notification To SES via SQS Programmatically

Amazon Web Services is a broad set of services that together form a reliable, scalable, and inexpensive computing platform in the cloud. These services are used from the world’s largest enterprises to the hottest startups so as to power up their wide variety of workloads from web and mobile applications, data warehousing, storage service, and many others.

In this article, I will share how to configure Amazons SNS (Simple Notification Service ) service to publish email notification to SES (Simple Email Service) vis SQS(Simple Queue Service) programmatically in .NET.And for a short introduction into these services.

  • SNS
    SNS is a fully managed push notification service that lets you send individual messages or to fan-out messages to large numbers of recipients. Amazon SNS makes it simple and cost effective to send push notifications to mobile device users, email recipients or even send messages to other distributed services.

    (Ref: http://docs.aws.amazon.com/sns/latest/dg/welcome.html)

  • SQS
    SQS refers to a message queuing service for reliably communicating among distributed software components and microservices - at any scale

    (Ref: http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/Welcome.html)

  • SES
    Amazon Simple Email Service (Amazon SES) is a cost-effective email service built on the reliable and scalable infrastructure that Amazon.com developed to serve its own customer base.

    (Ref: http://docs.aws.amazon.com/ses/latest/DeveloperGuide/Welcome.html)
Although SNS is a notification service, it can’t deliver email notifications without the end user confirming the subscription or without the confirmation token that is sent to the end user. The entire point of the confirmation step is to stop using SNS as a spamming method. If the application developer was allowed to confirm the subscriptions without the endpoint tokens, then he could confirm anyone’s email address.
One possible solution is to use the queue service (SQS) and then deliver emails from those notifications using SES. i.e
  1. SNS sends the message to SQS
  2. Another application component polls the queue, retrieves the message
  3. From the message an email is composed and use SES service to deliver emails.
So, first of all, to get started you need have AWS tootlkit installed for visual studio (https://aws.amazon.com/visualstudio/)

You also need to have an AWS subscription which is free for 12months with usage per month terms & conditions but I think the free usage is more than enough for personal website

Prerequisites
  • Visual Studio
  • Amazon SDK for .NET Installed
  • Valid Amazon AWS Account
The following steps will explain how to configure Amazon SNS to publish email notification to SES via SQS programmatically
  • Open Visual Studio.

    visual studio

  • Select Files >> New Project.

    visual studio
Go to AWS Sample Projects and select AWS Console Project for this demo (Make sure that you have AWS SDK for .NET installed).

visual studio

VS will then ask for your Amazon credentials (Username, Access key, Secret access key which you get when you sign up for AWS account) if you have already added the information (ViewàAWS Explorer) you can select the same from account profile, else you can add that.

Replace the default code in console project.

Namespaces required

In short SNS-SQS-SES.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Configuration;  
  4. using System.IO;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using Newtonsoft.Json;  
  8. using Amazon.SimpleNotificationService;  
  9. using Amazon.SimpleNotificationService.Model;  
  10. using Amazon.SQS;  
  11. using Amazon.SQS.Model;  
  12. using Amazon.SimpleEmail;  
  13. using Amazon.SimpleEmail.Model;  
  14. using Newtonsoft.Json.Linq;  

In main function, write the following code.

Creating topic for Amazon SNS.

  1. string awsArn, queueUrl;  
  2.   
  3. AmazonSimpleNotificationServiceClient sns = new AmazonSimpleNotificationServiceClient();  
  4. var response = sns.ListTopics();  
  5.   
  6. awsArn = sns.CreateTopic("vsStudio").TopicArn;   

 Creating an Amazon SQS.

  1. AmazonSQSClient sqsClient = new AmazonSQSClient();  
  2. var createQueueRequest = new CreateQueueRequest  
  3. {  
  4.     QueueName = "testQueue",  
  5.     Attributes = new Dictionary<string, string>  
  6.     {  
  7.         { "VisibilityTimeout","20"}  
  8.     }  
  9.   
  10. };   

To get queue attributes 

  1. queueUrl = sqsClient.CreateQueue(createQueueRequest).QueueUrl;  
  2.   
  3.   
  4. var request = new GetQueueAttributesRequest  
  5. {  
  6.     QueueUrl = queueUrl,  
  7.     AttributeNames = new List<string>() { "All" }  
  8. };  
  9. GetQueueAttributesResponse Sqsresponse = sqsClient.GetQueueAttributes(request);  
  10. string queueArn = Sqsresponse.QueueARN;   

Subscribe SQS to SNS queue 

  1. sns.Subscribe(  
  2.                     awsArn,              //topic arn  
  3.                       "sqs",               //protocol  
  4.                    queueArn            //sqs queue arn  
  5.                                   );   

After subscribing SQS queue to SNS topic, you should set the policy for the SQS queue so that it is allowed to receive messages published to an SNS topic.

  1.            var attrs = new Dictionary<string, string>();  
  2.   attrs.Add(QueueAttributeName.Policy,  
  3.       "{\"Version\": " + "\"2012-10-17\"," +  
  4. "\"Id\":" + "\"arn:aws:sqs:us-west-2:632861646958:testQueue/SQSDefaultPolicy\"," +  
  5.   
  6. "\"Statement\":" + " [ {\"Sid\":" + "\"Sid1494310941284\"," +  
  7.    "\"Effect\":" + "\"Allow\"," +  
  8.    "\"Principal\":" + "\"*\"," +  
  9.   "\"Action\":" + "\"SQS:SendMessage\"," +  
  10.     "\"Resource\":" + "\"arn:aws:sqs:us-west-2:632861646958:testQueue\"," +  
  11.   "\"Condition\":" +  
  12.     "{\"StringEquals\":" +  
  13.          "{\"aws:SourceArn\":" + "\"arn:aws:sns:us-west-2:632861646958:vsStudio\"}} }]}");  
  14.   var rqst = new SetQueueAttributesRequest  
  15.   {  
  16.       Attributes = attrs,  
  17.       QueueUrl = queueUrl  
  18.   
  19.   };  
  20.   SetQueueAttributesResponse policyresponse = sqsClient.SetQueueAttributes(rqst);   

Publish message to a topic.

  1. string msg = "My text published to sns topic with sqs endpoint";  
  2. PublishRequest publishrqst = new PublishRequest(awsArn, msg);  
  3. PublishResponse publishresponse = sns.Publish(publishrqst);   

Receive message from an SQS.

  1. ReceiveMessageRequest receivemsg = new ReceiveMessageRequest();  
  2. receivemsg.QueueUrl = queueUrl;  
  3. ReceiveMessageResponse receivemsgresponse = sqsClient.ReceiveMessage(receivemsg);  
  4. int Count = receivemsgresponse.Messages.Count;   

Delete the messages that are read 

  1. DeleteMessageRequest deleteMessageRequest = new DeleteMessageRequest();  
  2. deleteMessageRequest.QueueUrl = queueUrl;         
  3.   
  4. foreach (var message in receivemsgresponse.Messages)  
  5. {  
  6.     SentMail(message.Body); //Function to sent email   
  7.     deleteMessageRequest.ReceiptHandle = message.ReceiptHandle;  
  8.     DeleteMessageResponse sqsDelteresponse =sqsClient.DeleteMessage(deleteMessageRequest); //delete messages   

Function to sent mail.

  1. public static void SentMail(string sqsMsg)  //message from sqs as parameter  
  2. {  
  3.    var obj = JObject.Parse(sqsMsg);  
  4.     string msgBody = (string)obj.SelectToken("Message");  
  5.     Destination destination = new Destination();  
  6.     destination.ToAddresses = (new List<string>() { "rinku.kurian@ccstechnologies.in" }); //This should be a verified address if u are in sandbox mode amazon provides only sandbox mode for testing purpose you can ask for and upgrade later   

If you want to list all verified email address rather than providing one manually 

  1. AmazonSimpleEmailServiceClient sesclient = new AmazonSimpleEmailServiceClient();  
  2.   ListVerifiedEmailAddressesRequest addrsrqst = new ListVerifiedEmailAddressesRequest();  
  3.   ListVerifiedEmailAddressesResponse adrsrsp = sesclient.ListVerifiedEmailAddresses(addrsrqst);   

Attach a body and subject and sent email using SES client.

  1. string body = "Test email Sent from amazon Ses :" + msgBody;  
  2. String subject = "Subject For Testing Only :";  
  3. Body bdy = new Body();  
  4. bdy.Html = new Amazon.SimpleEmail.Model.Content(body);  
  5. Amazon.SimpleEmail.Model.Content title = new Amazon.SimpleEmail.Model.Content(subject);  
  6. Amazon.SimpleEmail.Model.Message msg = new Amazon.SimpleEmail.Model.Message(title, bdy);  
  7. try  
  8. {  
  9.     SendEmailRequest sndrqst = new SendEmailRequest("john.antony@ccstechnologies.in", destination, msg);  
  10.     SendEmailResponse sndrsp = sesclient.SendEmail(sndrqst);  
  11.       
  12. }  
  13. catch(Exception ex)  
  14. {   
  15.  }   

Note

Amazon doesn’t grant unlimited SES usage to new users instead they are placed in Amazon sandbox mode. In sandbox, the users have full access to all Amazon SES sending methods, however, the From address and To addresses must be verified once and there is a limit of 200messages per 24 hour period.

To remove the restriction on recipient addresses and increase your sending limits, you can opt out from sandbox mode to do this --  follow the step in below mentioned link

http://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html

You can also add SQS queue permissions at AWS console at SQS section, navigate to

SQS-Permissions-Add Permission

For more information regarding queue policies, go to http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-creating-custom-policies.html