Call AES SES sendEmail from a Alexa skill

185 Views Asked by At

I have been trying for weeks now to figure out how to invoke a call to sendEmail from an Alexa-hosted node.js skill. It is a very simple skill where the user makes a selection. when the selection is made I want to send a email to myself with contents of the selection. I have been trying to call sendEmail from my index.js, which contains the logic for my skill. I created a IAM role with the proper .json file as indicated on AWS, and was able to run a basic node file from the aws command line interface that sends me a email. What kind of steps will I have to take to get my Alexa skill to send the email? Can I just invoke the lambda function that is already working from my Alexa skill?

I have been trying to put the code below, and code similar to it without nodemailer doing the basic ses send email. I started with the aws ses webpage. I cannot find a single tutorial that actually walks you through step by step of calling this ses send email function in a Alexa skill and I would be so grateful to be pointed in the right direction. '''

const Alexa = require('ask-sdk-core');

const AWS = require("aws-sdk");

let nodemailer = require("nodemailer");
let aws = require("@aws-sdk/client-ses");

// configure AWS SDK
process.env.AWS_ACCESS_KEY_ID = "xxxx";
process.env.AWS_SECRET_ACCESS_KEY = "xxxx";
const ses = new aws.SES({
  apiVersion: "2010-12-01",
  region: "us-east-1",
});

// create Nodemailer SES transporter
let transporter = nodemailer.createTransport({
  SES: { ses, aws },
});

// send some mail
transporter.sendMail(
  {
    from: "[email protected]",
    to: "[email protected]",
    subject: "Message",
    text: "I hope this message gets sent!",
    ses: {
      // optional extra arguments for SendRawEmail
      Tags: [
        {
          Name: "tag_name",
          Value: "tag_value",
        },
      ],
    },
  },
  (err, info) => {
    console.log(info.envelope);
    console.log(info.messageId);
  }
);

'''

edit: thanks for the responses already guys! The only notable error I am getting is there is a problem with the requested skills response. So my Alexa skill is amazon hosted. Do I have to change this to use SES,sendEmail()? In my lambda page on amazon I have a file in a folder called sendEmail() but that gives me a error about the line AWS = require(etc.. in the debugger with the output "errorMessage": "2021-03-14T00:33:00.315Z e19e74c6-4c00-47dc-9872-77c0a602541a Task timed out after 3.00 seconds" the code I have in the lambda function titled sendEmail is actually the below code. the line sendEmail() also gives there is a problem with the requested skills response from the Alexa. I do not see my Alexa skill in my lambda functions. Do I have to add it in? Sorry, I really am a noob for AWS programming. Thank you!

`AWS = require('aws-sdk');
// Set the region 
AWS.config.update({region: 'us-east-1'});
// Create sendEmail params 
var params = {
  Destination: { /* required */
    ToAddresses: [
      '[email protected]',
      /* more items */
    ]
  },
  Message: { /* required */
    Body: { /* required */
      Html: {
       Charset: "UTF-8",
       Data: "HTML_FORMAT_BODY"
      },
      Text: {
       Charset: "UTF-8",
       Data: "TEXT_FORMAT_BODY"
      }
     },
     Subject: {
      Charset: 'UTF-8',
      Data: 'Test email'
     }
    },
  Source: '[email protected]', /* required */
  ReplyToAddresses: [
     '[email protected]',
    /* more items */
  ],
};
// Create the promise and SES service object
var sendPromise = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(params).promise();
// Handle promise's fulfilled/rejected states
sendPromise.then(
  function(data) {
    console.log(data.MessageId);
  }).catch(
    function(err) {
    console.error(err, err.stack);
  });`
3

There are 3 best solutions below

0
On BEST ANSWER
const AWS = require( 'aws-sdk' );

var SES = new AWS.SES( { apiVersion: '2010-12-01', region: 'us-east-1' } );

//when we are sending our email
//we have to return a promise
//this is because the sendEmail funx
//from SES
//is an ASYNCHRONOUS CALL to the simple email server
//we have to wait for this call to complete before RET


//this is the vital line that resolves my issue
if  (typeof Promise === 'undefined' ) {
    
  AWS.config.setPromisesDependency( require( 'bluebird' ) );
  
}


sendEmail("SOME TEXT");

function sendEmail ( text,event, context, callback ){
var link = "";



var params = {
    Destination: {
        ToAddresses: [ "[email protected]" ]
    },
    Message: {
        Body: {
            Text: { Data: link
            }
        },

        Subject: { Data: " text + " has arrived!" }
    },
    Source: "[email protected]"
};

return SES.sendEmail( params ).promise();
}

         
0
On

Where are you defining process.env? If you're running in Alexa Hosted, you'll get environment variables for the Alexa-owned IAM role which will have no access to SES.

Have you tried hardcoding the key and secret from your personal AWS account? If that solves it, look at adding the dotenv package in your package.json, and follow its documentation to set the values in a .env file you can add to your .gitignore.

0
On

I believe this part of the documentation is what you're looking for. after you put your custom skill on Lambda function you need to send the content of the body to your email:

const querystring = require('querystring');
let post_data = null;
exports.handler = function (event, context) {
post_data = querystring.stringify(event.body);
}

// your emailing code here

Check this repo too