AWS - SNS - how to set sender on a per call basis? - node.js

How to set a sender while sending sms from AWS SNS service?
Checking the docs for SNS about sending SMS
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/sns-examples-sending-sms.html#sending-sms-getattributes
And also here
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish-property
With these docs combined I can send a sms but the sender remains unset. Why?
var AWS = require('aws-sdk');
AWS.config.update({ region: 'eu-west-1' });
var params = {
Message: 'TEXT_MESSAGE',
PhoneNumber: '+44123456780',
MessageAttributes: {
'SenderID': {
DataType: "String",
StringValue: "Company1",
}
}
};
var publishTextPromise = new AWS.SNS().publish(params).promise();
publishTextPromise.then(
function (data) {
console.log("MessageID is " + data.MessageId);
}).catch(
function (err) {
console.error(err, err.stack);
});
I can send a sms except I cannot see a way to set a sender.
How do I set a sender for each message?

I added following section under params for Node.js code and sender id works
MessageAttributes:{
"AWS.SNS.SMS.SenderID" : {
DataType: "String",
StringValue: "abc"
}
},
Note that senderId works for countries/regions as defined in AWS documentation:
https://docs.aws.amazon.com/sns/latest/dg/sns-supported-regions-countries.html#sms-support-note-1

Related

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

Send transactional text messages from Elastic Beanstalk app using SNS - Node.js

I am trying to send text messages from my Elastic Beanstalk server application, but I keep getting {"Error":{"message":null,"code":404,... }. I followed the code in the documentation, but I still can't get it to work.
I followed this YouTube tutorial and I am able to send messages from my local development environment, but can't seem to be able to replicate this for my server app. In that tutorial the presenter creates an IAM group and an IAM user and the keys are saved in an .env folder, which I imagine is what makes things work.
I have also granted my Elastic Beanstalk EC2 instances full access to SNS using IAM.
Can someone please explain to me how I can replicate this in my server app? Or how can I send transactional text messages from a node.js/express server?
This is my code:
//we have to use us-east-1 because sending texts is not allowed in us-east-2
AWS.config.update({region: 'us-east-1'});
var params = {
Message: "This is a test",
PhoneNumber: '+' + "phoneNumberGoesHere",
MessageAttributes: {
'AWS.SNS.SMS.SenderID': {
'DataType': 'String',
'StringValue': "app name goes here"
}
}
};
var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31'}).publish(params).promise();
publishTextPromise.then(
function (data) {
console.log("Message sent successfully...... ", JSON.stringify({ MessageID: data.MessageId }))
}).catch(
function (err) {
console.log("Error sending Text Message...... ", JSON.stringify({ Error: err }))
});
All I had to do was add the right endpoint and region to this line, now it works perfectly!
var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31', endpoint: 'http://sns.us-east-1.amazonaws.com', region: 'us-east-1' }).publish(params).promise();
and as #Raman Damodar Shahdadpuri mentioned, I needed to remove the .SenderID portion. This is the final code:
var params = {
Message: "This is a test of text messaging",
PhoneNumber: '+' + 'phone number goes here',
MessageAttributes: {
'AWS.SNS.SMS.SMSType': {
'DataType': 'String',
'StringValue': "Transactional"
}
}
};
var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31', endpoint: 'http://sns.us-east-1.amazonaws.com', region: 'us-east-1' }).publish(params).promise();
publishTextPromise.then(
function (data) {
res.end(JSON.stringify({ MessageID: data.MessageId }));
}).catch(
function (err) {
res.end(JSON.stringify({ Error: err }));
});

Where are AWS SQS message built-in message attributes documented?

I'm sending messages to AWS SQS with the Node.js SDK. I cannot find the documentation that lists the various built-in attributes that can be specified in a message. The example in the documentation specifies an attribute called "DelaySeconds", but I don't see where that is documented anywhere??
Presumably that instructs the SDK to wait n seconds before sending the message? I'm trying to get the full list of Attributes I'm allowed to specify in a message. Note: I'm not referring to the MessageAttributes where I can specify my own message attributes, I'm referring to attributes that AWS looks at, such as MessageBody, QueueURL, DelaySeconds, etc.
Here is link to documentation I'm looking at:
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/sqs-examples-send-receive-messages.html
Full Example code here:
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'REGION'});
// Create an SQS service object
var sqs = new AWS.SQS({apiVersion: '2012-11-05'});
var params = {
DelaySeconds: 10, <--- where is this documented?
MessageAttributes: {
"Title": {
DataType: "String",
StringValue: "The Whistler"
},
"Author": {
DataType: "String",
StringValue: "John Grisham"
},
"WeeksOn": {
DataType: "Number",
StringValue: "6"
}
},
MessageBody: "Information about current NY Times fiction bestseller for week of 12/11/2016.",
// MessageDeduplicationId: "TheWhistler", // Required for FIFO queues
// MessageId: "Group1", // Required for FIFO queues
QueueUrl: "SQS_QUEUE_URL"
};
sqs.sendMessage(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.MessageId);
}
});
I found documentation here, was linked from page, just didnt see it.
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SQS.html#sendMessage-property

How to fix sending emails with AWS SES and Lambda?

I'm setting up a simple NodeJS Lambda function on AWS to send emails.
The code below is working when I run it locally. I have received all the credentials from AWS, verified both sender and recipient emails and granted all permissions to SES for my Lamba
const aws = require("aws-sdk");
const config = require('../config')
aws.config.update({
accessKeyId: config.mailUser,
secretAccessKey: config.mailPassword,
region:'us-east-1'
});
const ses = new aws.SES({apiVersion: '2010-12-01'});
const sendEmail = async (mailOptions) => {
const {
from,
to,
subject,
html
} = mailOptions
console.log('foo')
ses.sendEmail({
Source: from,
Destination: {
ToAddresses: [to]
},
Message: {
Subject: {
Data: subject,
Charset: 'UTF-8'
},
Body: {
Html: {
Data: html,
Charset: 'UTF-8'
}
}
}
},
(err, data) => {
console.log('baz')
if (err) {
console.error(err);
} else {
console.log('Email sent:');
console.log(data);
}
});
};
console.log('bar')
module.exports = {
sendEmail
};
It seems that ses.sendEmail() never fires when the function is deployed - I get foo and bar in the CloudWatch logs but never baz. Again, everything is running smoothly if run locally.
What is it that I am missing?
https://www.reddit.com/r/aws/comments/bf2iss/lambda_function_not_able_to_send_email_using_ses/elb8vzr/
Here is a very good explanation - apparently you need to wrap your ses.sendMail call in a promise for it to work with AWS Lambda.
All credit goes to https://www.reddit.com/user/jsdfkljdsafdsu980p/ and https://www.reddit.com/user/Enoxice/

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