How to verify message is delivered or not in AWS SNS? - node.js

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/

Related

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.

How to fix error subscribing to a SNS topic with node js and http endpoint

I want to use a http endpoint to subscribe to a topic so I can display any messages on a webapp, I am trying to subscribe to a topic but get an error InvalidParameter: Invalid parameter: TopicArn and I'm not sure why? I think my topicarn is in the correct format,
The relevant code:
// configure AWS
AWS.config.update({
'region': 'eu-west-2', // is this the region of my topic ?
'accessKeyId': 'keyid',
'secretAccessKey': 'secretkey'
});
const sns = new AWS.SNS();
sns.subscribe({
'TopicArn': 'arn:aws:sns:eu-west-x:xxxxxxx:my_topic',
'Protocol': 'http',
'Endpoint': 'http://localhost/:3000'
}, function (err, result) {
if (err !== null) {
console.log(util.inspect(err));
return;
}
console.log(util.inspect(result));
});
According to this issue and this issue in github it looks like it's due to the region of AWS instance mismatching the region of the topic.
If you use the AWS instance in other areas and wish to keep the global region as is, you could do this to make the sns instance in the correct region:
const sns = new AWS.SNS({ region: 'eu-west-x' });

Send SMS with Amazon SNS in node js : Invalid parameter: PhoneNumber Reason: +XXXX is not valid to publish

Here is my code for sending SMS to a particular number with AWS sms service.
var AWS = require('aws-sdk');
AWS.config.update({
accessKeyId: '{ID}',
secretAccessKey: '{KEY}',
region: 'us-east-2'
});
var sns = new AWS.SNS();
var params = {
Message: 'this is a test message',
MessageStructure: 'text',
PhoneNumber: '+XXXXXXXX'
};
sns.publish(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
But i got the following error in console
'InvalidParameter: Invalid parameter: PhoneNumber Reason: +XXXXXX is
not valid to publish
Please try with setting the region to "us-east-1". It worked for me before.
var sns = new AWS.SNS({ "region": "us-east-1" });
It is a bit misleading to ask everyone to change the region to us-east-1.
All the supported region are listed in the following link: https://docs.aws.amazon.com/sns/latest/dg/sms_supported-countries.html
P.S. I am new user, I can't add comments or edit anyone posts to include the supported list.
SNS currently supports SMS only in the form of E.164 formats, please make sure you are using the same format.
Check it out here: https://en.wikipedia.org/wiki/E.164
Additionally, you are using SNS sms service in us-east-2, which does not support SMS delivery as of yet. Checkout the SMS enabled regions: http://docs.aws.amazon.com/sns/latest/dg/sms_supported-countries.html
change your region us-east-2 to us-east-1 it worked for me
var sns = new aws.SNS({
"accessKeyId": functions.config().aws.key,
"secretAccessKey": functions.config().aws.secret,
"region": "us-east-1",
});

Getting delivery status of AWS SMS

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' }

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