Getting delivery status of AWS SMS - node.js

I'm sending sms from AWS through the node SDK. SMS are going out well and I'm trying to get delivery informations. Apparently it's not that easy and one has to setup SNS to send logs to Cloudwatch and to parse CloudWatch to get the delivery information looking up the MessageId: https://stackoverflow.com/a/40327061/2054629
If I send sms through SNS web interface, logs I see logs in cloudwatch, but not when I send them through the node SDK. I could not get information on how to setup things before sending them from node.
Ideally, I want to achieve something like:
const sendSMS = async (message, number) => {
// send the SMS
// wait to get delivery info
// resolve with delivery info, or reject if failed
}
Currently I have:
import AWS from 'aws-sdk';
AWS.config.update({
accessKeyId: accessKey,
secretAccessKey: secretKey,
region: 'us-east-1',
});
const sns = new AWS.SNS();
const sendSMS = async (message, number) => {
return await new Promise((resolve, reject) => {
sns.publish({
Message: message,
MessageStructure: 'string',
PhoneNumber: number,
}, (err, res) => {
if (err) { return reject(err); }
resolve(res);
});
});
}
which only send a SMS request to AWS and resolves with something like
{
ResponseMetadata: { RequestId: '7e0999a3-xxxx-xxxx-xxxx-xxxxxxxxxxxx' },
MessageId: 'f7f21871-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
}
I'm not sure if one has to setup an SNS application to be able to get logs or not, and I'd rather not to keep things simple.

You might have already done this but to configure cloudwatch logs for SMS deliveries, you have to configure SMS preferences. For that you need to create an IAM role to allow cloudwatch logs access. It is very simple to do it through AWS console. The steps are given at http://docs.aws.amazon.com/sns/latest/dg/sms_preferences.html
You can even control what percentage of successful deliveries + failed SMSs are logged if you want. Once this is done, you should start seeing cloudwatch logs whichever way you sent the SMS.
I wanted to add this as a comment but I don't have enough rep. I'll delete this answer if it doesn't work.

Your code seems to work just fine with nodejs v6 by changing the import statement (lack of ES5/6 support). After enabling logging to cloudwatch, every SMS (both through the Web interface and this code) creates a log steam in CloudWatch logs. I think you should reinstall the AWS SDK or avoid using ES5/6 to make the SDK work correctly.
For the second question, if the message wasn't delivered, you would get an error:
(err, res) => {
if (err) { return reject(err); }
resolve(res);
});
if the message was successfully sent, you get a response like:
{ ResponseMetadata: { RequestId: 'e31feda6-669c-5b13-XXX-bc25b07877b5' },
MessageId: '53555115-6acb-5684-XXXX-0096bc2f6a22' }

Related

AWS-SNS publish() method not sending any messages to phone number

I have used aws-sdk in node express to send the verification code to the phone number I referred this docs to implement it. here I get the response but do not get any messages on the phone.
const AWS = require("aws-sdk");
AWS.config.update({
region: "region",
accessKeyId: "ACCESS_KEY",
secretAccessKey: "SECRET_KEY",
});
router.post("/", async (req, res) => {
let phone_no = "+91876214****";
let random = Math.floor(100000 + Math.random() * 900000);
const YOUR_MESSAGE = `Your verification code is ${random}`;
let params = {
Message: YOUR_MESSAGE,
PhoneNumber: phone_no,
MessageAttributes: {
"AWS.SNS.SMS.SMSType": {
DataType: "String",
StringValue: "Transactional",
},
};
let publishTextPromise = new AWS.SNS({ apiVersion: "2010-03-31" })
.publish(params)
.promise();
publishTextPromise
.then(function (data) {
return res.json({ id: data.MessageId, otp: random });
})
.catch(function (err) {
return res.send(err.stack);
});
});
is anything I'm doing wrong, new to this aws-sns concept.
here i logged the publishTextPromise i get response as Promise { <pending> }
If you get Success result from api but message is not received. You need to check SNS logs.
On SNS console, you can see Text messaging (SMS) under Mobile section. If you don't enable status logging, firstly edit preferences on Delivery status logs section then on new page create an IAM Role (SNSSuccessFeedback) with Success sample rate 100%.
You can find error on cloudwatch.
Potential problem. You account is in the SMS sandbox in the region which you used.
If you see any message like ☝️, You can add your phone number on sandbox destination phone number.
Then sandbox will send you a verify code, when you put it on AWS console. Then you will be able to receive messages from SNS.

Subscribing SNS topic with HTTP End point in NodeJS

The question is not regarding subscribing to SNS Topic via HTTP endpoint. I was successfully able to configure and also confirm the subscription. Also, I am able to receive messages at the endpoint.
The requirement is to have another subscriber of the topic in nodejs backend app. I tweaked the code in this article for setting up the application, however couldn't manage to do so.
const AWS = require('aws-sdk');
const credentials = new AWS.SharedIniFileCredentials({ profile: '<profile-name>' });
const sns = new AWS.SNS({ credentials: credentials, region: 'eu-central-1' });
let params = {
Protocol: 'HTTP',
TopicArn: 'arn:aws:sns:eu-central-1:TOPIC:NAME',
Endpoint: 'http://mockbin.org/bin/bin-id'
};
sns.subscribe(params, (err, data) => {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
The response is
{
ResponseMetadata: { RequestId: '0af83f58-c562-592f-b493-65fef627ac28' },
SubscriptionArn: 'pending confirmation'
}
However, in the console, i see this endpoint as confirmed
Can someone suggest here.

Nodejs - AWS SNS publish is called, but message is not being sent

I'm trying to publish a SNS message to a single user.
The message is working when I manually press the "Publish Endpoint" button in the AWS console, but I'm trying to send it programmatically using the SNS nodejs SDK.
I have made sure to create a single IAM role giving full access permissions to SNS.
I have made sure to configure it:
const AWS = require("aws-sdk");
AWS.config.update({
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
});
I first create a platform endpoint using sns.createPlatformEndpoint(endPointParams) and it works fine so my IAM role is not an issue.
Using the result from that call, I use the data to create publishParams to make a call right after creating the endpoint:
let payload = {
user : "Hihih test",
shopping_list : "shopping_item"
};
let endPointParams = {
PlatformApplicationArn: process.env.REACT_APP_SNS_ARN,
Token: req.body.device_token
}
const createEndPoint = sns.createPlatformEndpoint(endPointParams).promise();
createEndPoint.then(data => {
console.log(data.EndpointArn);
console.log(JSON.stringify(payload));
let publishParams = {
Message: JSON.stringify(payload),
MessageStructure: 'json',
TargetArn: data.EndpointArn
};
sns.publish(publishParams, (err, result1) =>{
console.log("Success");
});
return;
}).then(result => {
res.status(200).send("Success sending invite to user.");
}).catch(err => {
console.log(err);
res.status(500).send("Something went wrong sending the invite.");
});
});
The console.log("Success"); inside sns.publish() is being fired, but on the client side, the app does not receive a message. I have also tried multiple times to manually call "Publish Message" in the console and it works fine.
So what could my issue be? I think it's something wrong with my code.
When using SNS with GCM you need to structure your JSON payload with the keys GCM and default or it will throw an err.
var payload = {
default: 'Hello World',
GCM: {
notification: {
title: 'Hello World',
body: 'Notification Body'
// other configs can be put here
}
}
};

How to verify message is delivered or not in AWS SNS?

Here is my lambda function. only return message-id and request-id. but how to verify the message is delivered or not?
const AWS = require('aws-sdk');
AWS.config.update({
accessKeyId: 'xxxx',
secretAccessKey: 'xxxx',
region: 'xxxx'
});
const mobile = 'xxxxxxx';
const sns = new AWS.SNS();
const confirmUpload = (callback) => {
sns.publish({
Message: 'Test From Admin side',
Subject: 'Admin',
MessageStructure: 'string',
PhoneNumber: mobile
}, (err, result) => {
if (err) callback(false, err);
else callback(true, result);
});
};
exports.handler = (event,context, callback) => {
confirmUpload((st, data) =>{
if(st){
let record = {
"data": JSON.stringify(data),
"event": event,
"context": context
};
callback(null, (record));
} else{
callback(data, "not send");
}
});
};
And here is the response when running the lambda function
"{\"ResponseMetadata\":{\"RequestId\":\"e8a07b26-d793-58e1-a529-2d7ac17aca9x\"},\"MessageId\":\"b8ecbcac-9f83-5bca-a9eb-eaf0896a69b\"}",
If you enable the delivery status feature on your topics you can use the message ID field in order to track the delivery status of the messages you have published.
After you configure the message delivery status attributes, log
entries will be sent to CloudWatch Logs for messages sent to a topic
subscribed to an Amazon SNS endpoint. Logging message delivery status
helps provide better operational insight, such as the following:
Knowing whether a message was delivered to the Amazon SNS endpoint.
Identifying the response sent from the Amazon SNS endpoint to Amazon SNS.
Determining the message dwell time (the time between the publish timestamp and just before handing off to an Amazon SNS endpoint).
Configuring Delivery Status Logging Using the AWS Management Console
You can look into this article to look for delivery status using message ID
using-the-delivery-status-feature-of-amazon-sns
Btw I will not suggest to check in the same lambda but to configure cloud watch logs and filter failure topic only. Here will be flow
Enable delivery status logs for the topic
Configure filter on Cloud watch for the failed topic
Trigger lambda when delivery status if failed
Process the failed SNS topic in lambda.
You may also like SLA for SNS by AWS.
You can enable SNS dead-letter queues to catch messages that can’t be delivered to subscribers:
https://aws.amazon.com/blogs/compute/designing-durable-serverless-apps-with-dlqs-for-amazon-sns-amazon-sqs-aws-lambda/

How to send SMS using Amazon SNS from a AWS lambda function

Amazon SNS provides a facility to send SMS globally.
I want to send SMS from a Lambda function were we provide the mobile number and text message and use SNS to deliver that message but I didn't find a helpful documentation or example code for NodeJS or java.
Can any one suggest a solution?
Code:
var params = {
Message: 'Hi this is message from AWS_SNS', /* required */
MessageAttributes: {
someKey: {
DataType: 'String' ,
StringValue: 'String'
},
},
MessageStructure: 'String',
PhoneNumber: '+91MyNUMBER',
Subject: 'MYSubject',
//TargetArn: 'arn:aws:sns:us-west-2:798298080689:SMS',
//TopicArn: 'arn:aws:sqs:us-west-2:798298080689:SendSMS'
};
sns.publish(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
};
So, you need to write Lambda function which is invoked somehow, let's say via HTTP request so you'll also need to setup API Gateway to route connections to your Lambda function.
Next, your Lambda function will push that data to "SNS Topic" while SMS Subscription will "poll" for any new data in this "Topic". As soon as any data gets into this topic, it will be consumed by subscription and SMS will be sent.
Few days ago I wrote a post about SNS & Lambda which might help you. Flow you wanted to achieve is pretty similar to one described in this article.
https://medium.com/#rafalwilinski/use-aws-lambda-sns-and-node-js-to-automatically-deploy-your-static-site-from-github-to-s3-9e0987a073ec#.3x6wbrz91
Documentation pages that might help:
Pushing to SNS: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish-property
Subscribing to SNS:
http://docs.aws.amazon.com/sns/latest/dg/SubscribeTopic.html
Please try with setting the region explicitly to "us-east-1". I managed to send SMS to India by explicitly setting this region. I also tried with "ap-south-1", but was not successful.
Based on latest AWS SNS > SMS documenration, When you don't have any topicArn and you need to send a text message directly to a phone number, you need to send following params:
const AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-1'});
const sns = new AWS.SNS();
const publish = (phone, text, subject) => {
// Create publish parameters
var params = {
Message: text,
Subject: subject,
PhoneNumber: phone,
MessageAttributes: {
'AWS.SNS.SMS.SMSType' : {
DataType : 'String',
StringValue: 'Transactional'
},
},
};
console.log('------------- text message param before sending------------');
console.log(params);
console.log('----------------------------------------------------');
// Create promise and SNS service object
var publishTextPromise = sns.publish(params).promise();
// Handle promise's fulfilled/rejected states
publishTextPromise.then(
function(data) {
console.log("MessageID is " + data.MessageId);
}).catch(
function(err) {
console.error(err, err.stack);
});
}
exports.publish = publish;
Here's what I did
Create a new Lambda function Author from scratch with your Runtime of choice. (I went to latest, Node.js 12.x)
For execution role, choose Create a new role from AWS policy templates.
Type in your Role name and because you want to send SMS to any mobile number, you must set Resource to *.
Type this as your IAM Role Template.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sns:Publish"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Use this code snippet
const AWS = require('aws-sdk');
const SNS = new AWS.SNS();
exports.handler = async (event) => {
let params = {
PhoneNumber: '+123xxxxxxx',
Message: 'You are receiving this from AWS Lambda'
};
return new Promise((resolve, reject) => {
SNS.publish(params, function(err, data) {
if(err) {
reject(err);
}
else {
resolve(data);
}
})
})
}
That's all. Click Deploy then Test and you should receive an SMS.
Here is a link to a tutorial for building an Alexa skill that connects with AWS SNS to send a text message.
It works fine if can make sure you have the right access to publish to SNS.
const smsParams = ()=>({
Message: getUpdateMessage(order),
PhoneNumber: `+91${order.contactNo}`,
MessageAttributes: {
'AWS.SNS.SMS.SMSType' : {
DataType : 'String',
StringValue: 'Transactional'
},
},
})
Permissions to my lambda:
- Effect: 'Allow'
Action:
- "sns:Publish"
Resource:
- '*'
Note that you have to allow all the resources to send SMS using PhoneNumber
Here is a link to all the supported SNS regions

Resources