Vai al contenuto principaleVai al footer
aws
|
24 maggio 17

Come inviare email da un sito statico usando AWS Lambda e SES

I siti statici sono più sicuri, sono più veloci e richiedono meno manutenzione. Ma cosa succede quando vogliamo implementare un mailer personalizzato invece di usarne uno prefabbricato?

La soluzione più veloce e facile si chiama AWS Lambda + SES (Simple Email Service).

Come dice la documentazione ufficiale:

AWS Lambda consente di eseguire codice senza dover effettuare il provisioning né gestire server. AWS Lambda esegue il codice solo quando necessario e scala automaticamente, da poche richieste al giorno fino a migliaia al secondo.

Lambda esegue il codice (e le sue dipendenze) scritto nelle Functions; Possiamo scrivere direttamente le funzioni dentro le Lambda tramite la console AWS oppure usare un servizio che ci lasci usare il nostro editor preferito e le carichi per noi. Serverless fa esattamente ciò di cui abbiamo bisogno.

Ok, fine delle presentazioni, vediamo ora come funziona.

Setup di Serverless

Prima di tutto, assicuriamoci di installare Serverless npm install serverless -g, e creiamo il nostro progetto:

serverless create --template aws-nodejs --path email_sender

Il nostro progetto è ora pronto e abbiamo bisogno di fornire delle credenziali per l'accesso a AWS IAM per far si che Serverless abbia il permesso di uploadare.

Le nostre credenziali andranno dentro ~/.aws/credentials:

[default]
aws_access_key_id=**************
aws_secret_access_key=***************

In questo caso serverless prenderà ovviamente le credenziali di default, ma se volessimo creare un nuovo profilo potremmo specificare quale utilizzare scrivendo export AWS\_PROFILE="profileName" && export AWS\_REGION=eu-west-1 da dentro il progetto Serverless.

Una volta aperto il progetto possiamo vedere che sono presenti 3 file: il .gitignore, handler.js e serverless.yml

Serverless.yml determina la struttura del nostro progetto:

service: email-sender

provider:
  name: aws
  runtime: nodejs4.3

functions:
  send:
    handler: handler.send
    events:
      - http:
          path: submissions
          method: post
          response:
            headers:
              Content-Type: "text/json"
          cors:
            origins:
              - '*'

In questo file possiamo anche gestire le nostre dipendenze e specificare quali pacchetti o plugin verranno caricati su Lambda:

package:
  exclude:
    - node_modules/**
  include:
    - node_modules/serverless-offline/**

plugins:
  - serverless-offline

Nota: serverless-offline è un plugin essenziale che permette di utilizzare il servizio che stiamo scrivendo facendo richieste verso localhost, senza dover caricare tutte le volte la funzione Lambda per provarla. Installiamo serverless-offline con npm install serverless-offline -g.

Il file handler.js è dove andremo a scrivere il codice che vorremo eseguire. Dal file serverless.yml, invece, dichiariamo quali metodi verranno eseguiti quando chiamiamo determinate funzioni. Nel nostro caso, in handler.js il nostro metodo si chiamerà ‘send’:

'use strict';
var https = require("https");
var http = require("http");
var AWS = require('aws-sdk');

module.exports.send = (event, context, callback) => {};

Siamo ora pronti per deployare la nostra funzione.

Deploy su AWS Lambda

serverless deploy carica la funzione su AWS Lambda e ci ritorna gli endpoint ai quali puntare per chiamare il metodo che abbiamo appena scritto.

endpoints:

  POST - https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/submissions

functions:

  email-sender-dev-send: arn:aws:lambda:us-east-1:32xxxxxx:function:email-sender-dev-send

Aggiungere SES

L'ultima cosa che abbiamo bisogno di impostare è il nostro servizio di email.

var ses = new AWS.SES();
ses.sendEmail(params, function(err) {
    callback(null, {
      statusCode: 200,
      headers: {
        "Access-Control-Allow-Origin": "*"
      },
      body: JSON.stringify({ status: "success" })
    });
  })

Inviare la nostra prima email

Adesso il nostro handler.js sarà pronto per inviare la nostra prima mail:

'use strict';
var https = require("https");
var http = require("http");
var AWS = require('aws-sdk');
var ses = new AWS.SES();

module.exports.send = (event, context, callback) => {
  const data = JSON.parse(event.body);

  const params = {
    Destination: {
      ToAddresses: [ "receiver@example.com" ],
    },
    Message: {
      Subject: {
        Data: data.subject,
        Charset: 'UTF-8'
      },
      Body: {
        Text: {
          Data: data.text,
          Charset: "UTF-8"
        }
      }
    },
    Source: "sender@example.com"
  };

  ses.sendEmail(params, function(err) {
    callback(null, {
      statusCode: 200,
      headers: { "Access-Control-Allow-Origin": "*" },
      body: JSON.stringify({ status: "success" })
    });
  })
};

Facciamo una richiesta curl POST al nostro endpoint e riceviamo la nostra email!

curl -H "Content-Type: application/json" -X POST -d '{subject: "test email", text: "this is a test email"}' https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/submissions

PS: Se si sta utilizzando la versione sandbox di SES dobbiamo verificare entrambe le email, sia quella del mittente che del ricevente, come esplicitamente scritto nella documentazione: