AWS

Come aggiornare il listino del proprio ecommerce via email sfruttando AWS SES

Lettura 9 minuti

Introduzione

La soluzione che vi presentiamo nasce da un’esigenza specifica di un nostro cliente: consentire ai responsabili acquisti di aggiornare i listini del negozio online in modo facile, senza obbligarli ad utilizzare un nuovo strumento.

Poiché i responsabili acquisti sono abituati a produrre i listini in un foglio di calcolo e a scambiarseli come allegati via email, si è deciso di mantenere questa modalità operativa.

Il sistema implementato riceve le email con il foglio di calcolo allegato, verifica che non ci siano errori e aggiorna i prezzi del negozio online utilizzando le relative API. Infine, risponde al mittente segnalando eventuali criticità o indicando che il file è stato preso in carico correttamente.

Per realizzare il sistema descritto abbiamo sfruttato alcuni servizi di AWS, precisamente:

Per orchestrare i servizi abbiamo utilizzato il framework AWS Serverless Application Model (SAM).

In realtà, la soluzione realmente implementata prevede che le modifiche ai prezzi possano essere pianificate nel futuro, quindi gestisce una coda di aggiornamenti sfruttando ulteriori servizi di AWS.

Per semplificare, nell’articolo forniamo una descrizione passo passo di come implementare la versione senza code di aggiornamento e senza i dettagli relativi all’integrazione con il negozio online.

Configurazione

SES Verified identity

Per abilitare la ricezione delle email su SES è necessario verificare la proprietà del dominio che si vuole utilizzare. Per fare questo la procedura più veloce consiste nel creare una nuova identità verificata dalla console web di SES navigando in Configuration > Verified identities:

Amazon SES - Create Verified Identity

Al termine delle creazione verrà richiesto di pubblicare alcuni record CNAME nel DNS del proprio dominio, ad esempio con nome xxxxxxxxxx._domainkey.mydomain.com e valore xxxxxxx.dkim.amazonses.com.

Questo tipo di verifica, chiamata DomainKeys Identified Mail (DKIM), è necessaria sia per la verifica del dominio da parte di SES sia come metodo di autenticazione per le email utilizzato per verificare la provenienza di un’email apponendo una firma digitale e prevenendo così lo spoofing.

Una volta pubblicati i record DNS necessari, l’identità verificata passerà in stato “Verified”.

MX DNS record

Quando viene inviata una email, viene effettuata una chiamata al DNS di tipo MX per chiedere quale sia il server preposto alla ricezione.

Per poter delegare la ricezione delle email del dominio scelto è necessario quindi pubblicare un ulteriore record alla configurazione DNS, ad esempio con nome mydomain.com e come valore 10 inbound-smtp.{region}.amazonaws.com (da sostituire con la regione di AWS utilizzata). Questo valore indica che se si vuole consegnare una email al destinatario example@mydomain.com il client di posta dovrà collegarsi a inbound-smtp.{region}.amazonaws.com per poterla depositare.

Il valore 10 indica la priorità. Se sono impostati più valori, vengono presi in ordine crescente passando da un server al successivo nel caso si verifichino problemi durante la consegna della email. Nel nostro esempio, come da documentazione di AWS, basta inserire un solo valore; sarà AWS a garantire l’affidabilità dell’endpoint di ricezione.

SES Sandbox

Quando viene creato un nuovo account AWS l’invio delle email è abilitato solo per le identità verificate. Ad esempio, verificando mydomain.com sarà possibile inviare email solamente a indirizzi @mydomain.com. Se l’account è ancora in sandbox si nota dal banner in alto appena si atterra nella console SES:

Amazon SES - Account Dashboard

Per poter inviare email verso qualsiasi indirizzo è necessario aprire un ticket al supporto di AWS, tramite procedura guidata, descrivendo in modo dettagliato il proprio caso d’uso:

Amazon SES - Request production access

È possibile convivere con questa limitazione durante i test creando un’identità verificata tramite il metodo email:

Amazon SES - Create Identity

Una volta creata l’identità verificata, sarà necessario cliccare sul link ricevuto via email da SES (no-reply-aws@amazon.com). Questo metodo di validazione è consigliato ai soli fini di test, non essendo un metodo di verifica abbastanza robusto per inviare e/o ricevere email.

Implementazione

AWS Component Architecture

Ricezione ed elaborazione email

Durante l’invio dell’email, il client della posta interrogherà il DNS per sapere su quale server depositare la email con una richiesta di tipo MX [1]. Nel nostro caso il dominio è gestito con Amazon Route 53, il quale risponderà con il record MX configurato in precedenza indicando inbound-smtp.{region}.amazonaws.com come server di posta incaricato della ricezione.

L’email viene quindi inviata a SES [2] il quale, tramite una regola di ricezione (Receipt Rule) basata sull’indirizzo del destinatario, eseguirà alcune azioni predefinite [3].

Il contenuto dell’email viene depositato da SES su un bucket S3 [4] e successivamente viene eseguita una funzione Lambda [5]. La funzione Lambda scarica il contenuto della email dal bucket S3 ed elabora il contenuto, estraendo eventuali allegati. Gli allegati vengono poi caricati, separatamente, sullo stesso bucket S3, per facilitare le integrazioni.

Al termine dell’elaborazione della email, la Lambda invia un evento ad un bus EventBridge [6] con tutte le informazioni relative a mittente, destinatario, oggetto, contenuto (testo oppure HTML) ed eventuali allegati.

Ricevere ed elaborare l’evento

EventBridge supporta un gran numero di integrazioni con altri servizi di AWS, nel nostro caso prendiamo come esempio una funzione Lambda che sarà invocata al momento della ricezione di un’email [7]. Per fare questo usando SAM si dichiara un evento di tipo EventBridgeRule usando New Email Received come filtro per il campo detail-type dell’evento.

 EmailReceiveFunction:
   Type: AWS::Serverless::Function
   Properties:
     FunctionName: !Ref AWS::StackName
     Handler: index.handler
     Events:
       EmailReceive:
         Type: EventBridgeRule
         Properties:
           EventBusName: !Ref EventBusName
           Pattern:
             detail-type:
               - "New Email Received"

La funzione Lambda dichiarata effettuerà gli opportuni controlli su oggetto, contenuto, mittente e/o destinatario. Nel caso siano presenti allegati, la funzione Lambda scaricherà l’allegato dal bucket S3 e ne elaborerà il contenuto.

/**
* Lambda handler
* @param {object} event
*/
exports.handler = async (event) => {
 const { subject, from, to, attachments } = event.detail
 // [..]
}

Utilizzando le API di SES è possibile inviare una mail di risposta con il risultato dell’elaborazione e i dettagli di eventuali errori.

const SES = require('aws-sdk/clients/ses')
const ses = new SES()
 
const { subject, from, to, attachments } = event.detail
 
// elaborate incoming data
 
await ses.sendEmail({
  Source: to.filter(email => email.endsWith('@mydomain.it')).shift(),
  Destination: {
    ToAddresses: from
  },
  Message: {
    Subject: {
      Data: 'Re: ' + subject
    },
    Body: {
      Text: {
        Data: 'Here the email body response'
      }
    }
  }
}).promise()

Deploy

Parte della soluzione riguardante la ricezione e parsing delle email è descritta tramite SAM, in modo da poterla riutilizzare velocemente in un altro progetto con esigenze simili.

Installazione rapida

Per eseguire il deploy tramite il link di installazione

  • Eseguire il login alla console WEB di AWS
  • Cliccare sul link di deploy dal repository GitHub bitbull-serverless/ses-email-receiver. Utilizzare il link relativo alla regione in cui si vuole creare lo stack.
  • Compilare il form che si presenta inserendo il nome ed i parametri dello stack

CloudFormation - Create stack

Deploy SAM template

Per eseguire il deploy della soluzione tramite SAM

  • Installare SAM CLI
  • Clonare il repository GitHub bitbull-serverless/ses-email-receiver
  • Eseguire la build del codice tramite il comando sam build nella root del progetto. È consigliato l’utilizzo del parametro --use-container così da utilizzare un container Docker come ambiente di esecuzione.
  • Lanciare il deploy dello stack con sam deploy indicando il profilo da utilizzare ed i parametri necessari. Usando il parametro --guided verranno richiesti i parametri in maniera interattiva salvando poi le configurazioni nel file samconfig.toml.

Al termine del deploy, verranno mostrati gli output del template con le informazioni necessarie per collegare il resto del processo, personalizzando il comportamento alla ricezione della email:

  • EventLogs: CloudWatch Log dove gli eventi vengono salvati in formato di testo
  • EmailBucket: Nome del Bucket S3 dove le email ed i loro allegati vengono salvati alla ricezione
  • ReceiptRuleSet: Nome del set di regole SES
  • EventBus: Nome del EventBridge bus dove verrà inviato l’evento alla ricezione della email

Passaggi manuali

È necessario attivare manualmente il set di regole creato dallo stack dalla console web di SES navigando in Configuration > Email receiving:

Amazon SES - Email receiving

Selezionare il set di regole con lo stesso nome dello stack ed utilizzare il bottone Set as active per attivare la ricezione delle email.

Conclusioni

Abbiamo illustrato una soluzione che rappresenta soltanto uno dei molteplici casi d’uso in cui l’invio di una email può essere utilizzato all’interno di un processo aziendale, sfruttando la sinergia dei servizi AWS.

Per concludere, vediamo brevemente altri possibili casi d’uso interessanti, senza addentrarci nei dettagli di implementazione.

Sistema Ticketing

In questo caso d’uso, l’utente invia una email con eventuali allegati per aprire una richiesta di assistenza su un ticket system. È molto probabile che un ticket system moderno offra già la possibilità di aprire richieste tramite email ma non è detto che permetta la flessibilità che si può raggiungere con un processo personalizzato.

Lo schema dei componenti e delle relative interazioni è quello già visto per la soluzione descritta nell’articolo; l’unica differenza riguarda il fatto che la funzione Lambda che riceve l’evento da EventBridge si collegherà al sistema di Ticketing per l’inserimento della richiesta di assistenza e risponderà all’utente con il numero di richiesta assegnato, utilizzabile come riferimento futuro.

Sistema Prenotazione

In questo secondo caso d’uso, l’utente invia una richiesta di prenotazione o preventivo, con data, numero di persone ed i propri dati anagrafici.

La funzione Lambda che viene invocata alla ricezione della email controlla ed elabora il contenuto per estrarre le informazioni necessarie alla creazione di una prenotazione.

La funzione si occupa anche di validare la richiesta e di rispondere all’utente nel caso manchino dati necessari. Se invece la richiesta è andata a buon fine, la funzione restituirà all’utente il numero di prenotazione con il riepilogo delle informazioni e le eventuali istruzioni di pagamento, se richiesto.

Sistema Ordini Fornitori

In questo terzo caso d’uso, l’utente scarica un modello di foglio di calcolo dal sito del fornitore; nel foglio è presente l’elenco dei prodotti ordinabili e la colonna dove poter specificare la quantità da acquistare.

L’utente compila il file e lo invia via email. La funzione Lambda collegata a SES valida l’email e se non sono presenti errori invia un evento ad un bus EventBridge che a sua volta invia il contenuto dell’evento ad una coda SQS di tipo FIFO.

Una funzione Lambda viene invocata per processare i messaggi in coda, uno alla volta rispettando l’ordine di ricezione, scaricando il file allegato dal bucket S3 per elaborarne il contenuto e creare un richiesta d’ordine sul sistema utilizzato dal fornitore.

Al termine del processo viene inviata un’email di risposta al cliente con un numero di preordine nell’intestazione, l’elenco dei prodotti ordinabili e il totale nel contenuto. In calce si può prevedere un riepilogo degli eventuali prodotti non ordinabili in quanto non disponibili e una previsione della data di spedizione in caso di conferma d’ordine entro un certo tempo.

Si potrebbe ipotizzare di implementare un ulteriore processo che consenta di confermare l’ordine semplicemente rispondendo alla email.

Crediti: Foto di Sigmund da Unsplash

Articolo scritto da

☝ Ti piace quello che facciamo? Unisciti a noi!