DEV Community

Cover image for Build a bulk email and sms app with Vue and AWS SES, AWS SNS OR Twilio Part 2
Kevin Odongo
Kevin Odongo

Posted on

Build a bulk email and sms app with Vue and AWS SES, AWS SNS OR Twilio Part 2

In this part, we are going to focus on AWS SNS and AWS SES.

To integrate with AWS Simple Email Service we need to install AWS SDK and carry out some simple steps. You also need an AWS Account. To register for an AWS account click here https://portal.aws.amazon.com/billing/signup#/start

Start with installing AWS SDK in you bulk-email-ses-app

// I will be using javascript SDK
yarn add aws-sdk
Enter fullscreen mode Exit fullscreen mode

Next, we need to get credentials from AWS IAM. Always avoid using credentials for a user with an administrative role. You can create a user and add a policy with AWS SES access and AWS SNS access.

Alt Text

Alt text of image

Once done create a .env file in your application and add your credentials.

VUE_APP_MY_REGION = us-east-1 // region
VUE_APP_SECRET_ACCESS_KEY = // secret access key
VUE_APP_ACCESS_KEY_ID = // access key id
VUE_APP_SNS_ARN = // access arn
Enter fullscreen mode Exit fullscreen mode

You need to reboot your app so the .env file can be loaded.

Next, add a script.js file to your application.

Script.js

var AWS = require("aws-sdk");
AWS.config.update({
  region: process.env.VUE_APP_MY_REGION,
  secretAccessKey: process.env.VUE_APP_SECRET_ACCESS_KEY,
  accessKeyId: process.env.VUE_APP_ACCESS_KEY_ID
});
Enter fullscreen mode Exit fullscreen mode

Next, let's configure SNS and SES then we complete the integration. I will also discuss briefly the pricing of AWS SES and AWS SNS. This will give us a good comparison at the end.

AWS SES

This will allow us to send bulk emails.
For AWS SES you need a valid domain name to be able to work with AWS Simple Email Service. Here is an article I wrote about WorkMail and how to add a domain.
https://dev.to/kevin_odongo35/how-to-start-with-aws-workmail-gn7

If you followed the above the domain will automatically appear in your dashboard when you click domain

Alt Text

In case you haven't no problem just click the domain button and click verify your domain. Thereafter verify two email addresses that you want to test your application with.

At first, you will be working in a sandbox meaning you will only be able to send emails that you have verified. It's very simple to come out of the sandbox and, your daily limit increased. Once you are out of the sandbox you will be able to send emails to unverified emails.

When you call Amazon SES from an application hosted in Amazon EC2, you can send 62,000 messages per month at no charge. This Free Usage Tier benefit does not expire.
$0.10 for every 1,000 emails you send.

On average it will cost $0.10 - $0.12

AWS SNS

This will allow us to send bulk SMS
With SNS you need to add two things a Topic and a Subscription. You will be sending your SMS to the topic.

Alt Text

Once you have created a topic you need to add subscriptions with the numbers you want to send SMS to. You can add the numbers through the console but we will add them in our app.

Standard topic requests include publishes, topic owner operations, and subscription owner operations
First, 1 million Amazon SNS requests per month are free, $0.50 per 1 million requests thereafter

We now have the following and can update our .env file with AWS SNS ARN. Let's update our Script.js with all the functions.

Script.js

/**
 * EMAIL SCRIPT
 * - Send bulk email
 * - Send bulk sms
 * ================================
 */
// Import AWS SDK
var AWS = require("aws-sdk");
AWS.config.update({
  region: process.env.VUE_APP_MY_REGION,
  secretAccessKey: process.env.VUE_APP_SECRET_ACCESS_KEY,
  accessKeyId: process.env.VUE_APP_ACCESS_KEY_ID
});

// send bulk normal email
export const sendbulkemail = async item => {
  // send normal email
  var receipient = item.addresses;
  var title = item.title ? item.title : "";
  var content = item.content ? item.content : "";
  var subject = item.subject ? item.subject : "";
  var ses = new AWS.SES();
  var params = {
    Destination: {
      ToAddresses: receipient
    },
    Message: {
      Body: {
        Html: {
          Charset: "UTF-8",
          Data: `<div style="font-weight: 700; margin-bottom: 10px;">${title}</div><div>${content}</div> <a class="ulink" href="http://docs.aws.amazon.com/ses/latest/DeveloperGuide" target="_blank">Amazon SES Developer Guide</a>.`
        },
        Text: {
          Charset: "UTF-8",
          Data: `${content}`
        }
      },
      Subject: {
        Charset: "UTF-8",
        Data: `${subject}`
      }
    },
    Source: "crudavid36@gmail.com"
  };
  ses.sendEmail(params).promise();
};

// send bulk raw email
export const sendbulkRawemail = async item => {
  // 1. Email Content
  var ses = new AWS.SES();
  var sender = "crudavid36@gmail.com";
  var receipient = item.addresses;
  var title = item.title ? item.title : "";
  var content = item.content ? item.content : "";
  var subject = item.subject ? item.subject : "";
  var filename = JSON.stringify(item.attachment);
  var attachment = item.base64;
  // 1b. Email Raw Data
  // eslint-disable-next-line no-useless-escape
  var message = `From:${sender}\nTo:${receipient}\nSubject:${subject}\nContent-type: Multipart/Mixed; boundary=\"NextPart\"\n\n--NextPart\nContent-Type: text/html\n\n<html><body><div style="font-weight: bold; text-transform: uppercase; margin-bottom: 10px;">${title}</div><div>${content}</div><div style="margin-top: 2rem;"><span style="color: #AD1457">WORK</span><span style="color: #023e7d">BOOK</span></div><div style="color: grey; font-size: 10px;">Copyright © 2021 Jogevk Group Limited, All rights reserved.</div></body></html>\n\n--NextPart\nContent-Type: text/plain; name=${filename}\nContent-Description: ${item.attachment}\nContent-Disposition: attachment;filename=${filename}\nContent-Transfer-Encoding: base64\n\n${attachment}\n\n--NextPart--`;
  // 2a. Params (Email Object)
  // eslint-disable-next-line
  var params = {
    RawMessage: {
      Data: message
    },
    Destinations: receipient,
    Source: "crudavid36@gmail.com"
  };
  // send email
  ses.sendRawEmail(params).promise();
};

// sns to send email
export const sendbulksms = async item => {
  // subscribe the new numbers
  await subscribenewusers(item.addresses)
  var params = {
    Message:
      "TITLE:" +
      "\n" +
      item.title +
      "\n\n" +
      "SUBJECT:" +
      " \n" +
      item.subject +
      "\n\n" +
      "CONTENT:" +
      "\n" +
      item.contact +
      "\n",
    // subscription ARN
    TopicArn: process.env.VUE_APP_SNS_ARN
  };
  new AWS.SNS({ apiVersion: "2010-03-31" }).publish(params).promise();
};

// subscribe users in your aws sns Topic
export const subscribenewusers = async item => {
  item.forEach(e => {
    var params = {
      Protocol: "sms" /* required */,
      TopicArn: process.env.VUE_APP_SNS_ARN /* required */,
      Endpoint: `${e}`,
      ReturnSubscriptionArn: true || false
    };
    new AWS.SNS({ apiVersion: "2010-03-31" }).subscribe(params).promise()
  });
};

// =========================================

// sort email addresses
export const sortsenderemail = item => {
  // this will hold our final items
  let array = [];
  // get the email and phone numbers and sort them
  const response = item.split(",");
  // loop through the response and check the validity of each email
  response.forEach(e => {
    let item = checkvalidityofemail(e);
    if (item === true) {
      // if email is valid send to array
      array.push(e.trim());
    }
  });
  // end
  // return array
  return array;
};

// sort phone numbers
export const sortsenderphone = item => {
  // this will hold our final items
  let array = [];
  // get the email and phone numbers and sort them
  const response = item.split(",");
  // loop through the response and check the validity of each email
  response.forEach(e => {
    let item = checkvalidityofphone(e);
    if (item === true) {
      // if email is valid send to array
      array.push(e.trim());
    }
  });
  // end
  // return array
  return array;
};

// This function checks the format of an email
// Those that wont pass will be eliminated
const checkvalidityofemail = item => {
  // eslint-disable-next-line no-useless-escape
  let pattern = /(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
  return pattern.test(item);
};

// This function checks the format of a phone number
// Those that wont pass will be elimited
const checkvalidityofphone = item => {
  // eslint-disable-next-line prettier/prettier
  let pattern = /^\+[1-9]\d{1,14}$/g;
  return pattern.test(item);
};
// ==================================

Enter fullscreen mode Exit fullscreen mode

In case you have downloaded the application from Github let me explain how the components are connected.

bulk.module.js

This will be our store in the Vuex. The function saveandeditbulk will call most of the functions in the script.js. We will be using local storage to handle for us which transaction is being carried out thereafter the correct function is called.

Bulk.vue

This will handle the creation of a campaign. There will be three option's handle bulk email, handle bulk SMS, or handle bulk email with an attachment.

View.vue

This component will handle the preview and sending the campaign.

This will be a complete guide on how to build and integrate a bulk email application using Vue and AWS SES and AWS SNS.

Let's handle the final part of integrating with Twilio

Discussion (0)