×
Community Blog Using Alibaba Cloud DirectMail with Web Application

Using Alibaba Cloud DirectMail with Web Application

In this article, we will see how we can use the DirectMail service within a web application by leveraging the SDK's provided.

By Sai Sarath Chandra, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

In previous articles, we learned about the features of DirectMail and saw a complete step-by-step guide on setting up Alibaba Cloud DirectMail service. In this particular article, we will see how we can use the DirectMail service within a web application by leveraging the SDK's provided.

We will create a web application running on a NodeJS as the server. We will also see a brief about the pugJS template engine. We will be using SMTP for sending the emails in the web application.

These are the frameworks/technologies used in the web application:

  1. HTML5
  2. CSS3
  3. MaterializeCSS
  4. ExpressJS
  5. NodeJS

Material Design is created by Google. Material Design is a guideline for developing great user interfaces and creating the best user experience. Inspired by Material Design, MaterializeCSS is a top independent framework that helps us in adopting Material Design.

ExpressJS is a web application framework that helps us in developing web applications and NodeJS very easily. Express JS never overwrite existing node JS functionalities this feature makes Express JS get compared to other frameworks. We shortly see in detail how easy it is to develop applications with Express JS particularly web application and API's.

NodeJS is built based on Chrome JavaScript runtime. NodeJS helps in running the applications on the server side in a very lightweight fashion. Node JS is actively improving. It is an asynchronous event-driven JavaScript runtime and is designed to build scalable network applications.

Creating the Web Application

About the App

We are going to create a simple login, password reset, and registration flow. Whenever an event (login, forgot password, registration) occurs, we trigger an email from the DirectMail service to inform the user that the event has occurred.

We are going to create the whole application in two steps:

  1. Creating the web application and the API's
  2. Integrating the web application with the DirectMail service

Setting Up DirectMail

Before we go further, you should make sure the Alibaba Cloud DirectMail service is properly set up and working with one sender Email ID under a Domain.

The whole code is available in GitHub, find the link below: https://github.com/saichandu415/AC-Direct-Mail-Demo

We will be referring to this code during this article. You can start exploring the code by cloning/downloading the repository.

Before we start we need to know some basic principles of pugJS, which is a template engine (helps creating the html pages quickly and easily).

Similar to how html pages bearing .html extension, these pages/files with pugjs ends with .pug

Extends Layout

If you have a file named 'layout.pug' which bears some html code, and if we want to reuse the same code across pages you can place 'extends layout'. This will replace this statement with the content in the 'layout.pug'. This is one of the features of pugjs that will help us to reuse the code.

Block Content

This is some placeholder within the template. Suppose you extend another layout file, which simply consists of the "block content" statement, you can not only extend the ode but also replace the statement with other content in the runtime. This greatly increases the reusability and makes the code more dynamic.

Pug Markdown to HTML Translation

Let's look at the similarities and differences of pug markdown by comparing a few examples with HTML.

div.col.s6.offset-s3 translates to <div class="col s6 offset-s3"></div>

div.#signin.row.tabContent translates to <div id="signin" class="row tabContent"></div>

div.row
      div.col.s6.offset-s3
        div.card 

translates to

<div class= "row">
    <div class="col s6 offset-s3">
        <div class="card">….</div>
    </div>
</div>

Note: You need to make sure they are properly indented to currently follow the expected nesting of div/elements.

input#password(type='password') translates to <input id="password" type="password">

This is all you need to know for now to get started with pugjs. There is lot more to learn and you can find it in their official page.

Project Directory Structure

Let's see the project directory structure first.

1

/bin

This folder has all the logic related start the server on port number 3000 and also handling the errors if the port is already in use. It consists one file named 'www'. Copy paste the below code in the file. All methods are self-explanatory, but the key method if you want to change the port:

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

The changes in the above two lines is required to change the port. One more thing to notice here is we used the 'http' module to create the server. If you want to use 'https', then you need to require the https module and bootstrap the SSL Certificates.

/node_modules

This folder consists of all the dependencies downloaded by running the command "npm install".

/package.json

This file contains all the information related to the dependency & their versions.

{
  "name": "AC-Direct-Mail-Demo",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "morgan": "~1.9.0",
    "nodemailer": "^4.6.7",
    "pug": "2.0.0-beta11"
  }
}

You can also update this file by running the npm install <package-name> --save command. This installs the latest and update the same in the package.json

/routes

We can relate that routes folder contains the backend logic on the server required for manipulating the html page using nodejs modules. It is good practice to have a separate js files for every html page in the front end.

index.js

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

We import the dependency for the express and create an express router object to register the router. Then we register the get functionality to the express router on the base path '/'. This means that this particular index.html will be loaded when the application is invoked on http://localhost:3000/. And then we will export the method on the router.

If you see the line res.render('index', { title: 'Express' });, this provides us an ability to send the information to the html page to render the information even though we are not using that in this specific scenario. This also make sure it searches for the index.pug file within the applications 'views' folder and then translates to the valid html and send back to the client/user.

/public

This folder consists of the client-side scripts required for the functionalities, images used in the application & stylesheets required.

Images

This contains all the images required for the applications

Stylesheets

This contains all the CSS/SCSS file required for the application. Although SCSS needs to be converted to CSS before rendering the page to client from server.

Javascripts

This contains all the script files required to while rendering the html page at the client side for execution.

/views

Contains the pugjs template files for the translations. If we are not using the pugjs, we should have the .html files in the same folder.

layout.pug

This file consists of the basic layout related code, which is repeatable across pages

doctype html
html
  head
    style
      include ../public/stylesheets/style.css
    title= 'Alibaba Cloud | Direct Mail Demo'
    link(rel="stylesheet", href="https://fonts.googleapis.com/icon?family=Material+Icons")
    link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/css/materialize.min.css")
script(src='https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-rc.2/js/materialize.min.js', type="text/javascript")

Block Content

The key thing to notice here is that pug allows us to keep HTML along with the pugjs markdown, which helps developers at times to include plain html code if they feel any limitation with pugjs.

This file in particular contains all the header information of the html, and a placeholder to insert the body related information. As said we will be using the materialize.css, imported the CDN version of the files and we will also be needing the materialize.js files for some of the components to work as expected along with the Material Icons.

error.pug

This is the fallback error page in case of any issues.

index.pug

This file consists of the complete logic for the whole web application, I have took the advantage of the 'tabs' functionality, which helps me to create both login and registration flows on a single page.

2

Let's see the code for this page:

extends layout

block content
  body
    .container
      h1 Alibaba Cloud DirectMail Demo
    div.row
      div.col.s6.offset-s3
        div.card
          div.card-tabs
            ul.tabs.tabs-fixed-width
              li.tab.col.s6
                a(href='#signin') 
                  strong Sign In
              li.tab.col.s6
                a(href='#signup') 
                  strong Sign Up
          div.card.content.grey.lighten-4
          #signin.row.tabContent
            form.col.s12
              .row
                .col.s12.input-field.inline
                  input#email_inline.validate(type='email')
                  label(for='email_inline') Email
                  span.helper-text(
                  data-error='Please provide valid email'
                  data-success='Valid Email'
                )
                .col.s12.input-field.inline
                  input#password(type='password')
                  label(for='password') Password
            .row
              button.col.s4.offset-s1.btn.waves-effect.waves-light(
                type=button
                onclick='login()'
              ) Login
                i.material-icons.right send
              button.col.s4.offset-s2.waves-effect.waves-teal.btn-flat(
                type=button
                onclick='forgotPassword()'
              ) Forgot Password
                i.material-icons.right help_outline
          #signup.row.tabContent
            form.col.s12
              .row
                .col.s6.input-field.inline
                  input#first_name(type='text')
                  label(for='first_name') First Name
                .col.s6.input-field.inline
                  input#last_name(type='text')
                  label(for='last_name') Last Name
                .col.s12.input-field.inline
                  input#phnNumber(type='number')
                  label(for='phnNumber') Phone Number
                .col.s12.input-field.inline
                  input#email_reg(type='email')
                  label(for='email_reg') Email
                .col.s12.input-field.inline
                  input#password(type='password')
                  label(for='password') Password
                button.col.s12.btn.waves-effect.waves-light(
                  type=button
                  onclick='register()'
                ) Register Me !!

  script
    include ../public/javascripts/utilities.js

There are couple of things to note here:

extends layout

As mentioned earlier, we are using the base layout file and reusing the common code.

div.card

This contains the tabs in the card layout.

div.card.content.grey.lighten-4

This division contains the content for each tab.

include ../public/javascripts/utilities.js

This will include the utilities script when the html pages are rendered.

app.js

This is the complete logic for the server-side app.

var nodemailer = require('nodemailer');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
app.use('/', indexRouter);
app.use('/users', usersRouter);

We will create the router objects and bootstrap with the application object (app).

var transporter = nodemailer.createTransport({
  "host": "smtpdm-ap-southeast-2.aliyun.com",
  "port": 25,
  "secureConnection": false, // use SSL
  "auth": {
    "user": 'admin@mail.actestdomain.xyz', // user name
    "pass": 'AdMIN12345'
  }
});

We will create the transporter object with all the information required.

app.post('/sendMail', function (req, res, next) {
  var reqBody = req.body;
  var mailOptions = {
    from: 'admin@mail.actestdomain.xyz', // sender address mailfrom must be same with the user.
    to: reqBody.email_inline, // list of receivers
    cc: '', // copy for receivers
    bcc: '', // secret copy for receivers
    subject: reqBody.subject, // Subject line
    text: '', // plaintext body
    html: reqBody.body // html body
  };
    transporter.sendMail(mailOptions, function(error, info){
      if(error){
          return console.log(error);
      }
      console.log('Message sent: ' + info.response);
      res.send('');
  });
});

app.post will create a /sendMail which receives an object and create mailOptions object which contains all the information required for the mail.

transporter.sendMail will use the mailOptions to send the mail send the response if the mail send is success.

You can see all the detailed code at the below GitHub repository for detailed instructions
https://github.com/saichandu415/AC-Direct-Mail-Demo

3

You are welcome to improve the project by raising the GitHub issues or pull requests.

0 0 0
Share on

Alibaba Clouder

2,605 posts | 747 followers

You may also like

Comments