Send SNS notification to all Users that subscribed the topic from Lambda - node.js

I have created an E-Commerce IOS app with backend in nodejs (AWS Lambda). When a user signedIn/LoggedIn, the app subscribes a SNS Topic which I have created to send notifications and stores the push token and device ARN in DB.
Now I want to send push notification to all users who have subscribed that SNS Topic, when we added a new item to the store.
Currently, to send notification I am fetching all users from DB and loop through the users to get their push token and send notification to users one by one, which is very costly process, and the API took too much time.
Now I want to do is to hit the SNS topic from Lambda and pass the body of notification to that topic and that SNS topic will send notification to all users who have subscribed the Topic.
I have searched it but can't find any solution.
The code I have done to send notification is
await Promise.all(targetArns.map(async (item, index) => {
const publishNotificationParams = {
"TargetArn": item,
"Message": JSON.stringify({
"default": JSON.stringify({
"category" : title,
"alert" : {
"title" : title,
"body" : 'New product is launced',
"data" : product
},
"badge" : 1,
"sound" : "chime.aiff"
}),
"APNS_SANDBOX": JSON.stringify(params),
"APNS": JSON.stringify(params)
}),
"MessageStructure": "json"
};
var publishTextPromise = sns.publish(publishNotificationParams).promise();
publishTextPromise.then(
function(data) {
console.log(`Message ${publishNotificationParams.Message} sent to the topic ${publishNotificationParams.TargetArn}`);
}).catch(
function(err) {
console.error(err, err.stack);
});
}));
But for this I have to fetch every user from DB get their endpoint ARN and then send notification by iteration.
I want to call SNS topic pass the body of notification and SNS will send notification to every user that has subscribed that SNS topic.
I am doing this because I want to save the cost to fetch every users from DB and then send notification

This is how you could achieve that flow. I think you already have some parts of this implemented.
Create a topic that will be used to fan out the notification to all of your users: https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html
Create platform application(s) for the different platforms your app is used on: https://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformApplication.html
When a user signs up for your app, create a platform endpoint for the application corresponding to the user's platform: https://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformEndpoint.html
3.1. If you want to be able to target this user directly, also store this ARN somewhere for direct publishes (as you are doing now).
Now also create a subscription for the topic created in step 1 to the endpoint ARN: https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html
Publish to the topic created during step 1: https://docs.aws.amazon.com/sns/latest/api/API_Publish.html
SNS will automatically fan out the message to all subscribers (all of your users), so each of them will receive a notification without you iterating over each user.

Related

AWS SNS or SES for password reset

guys! I have a task to create AWS lambda endpoint for resetting user's password. I have to send a new password to user's email. I have read a lot about SNS and SES and currently have no idea what service is better for my purpose. Will be glad to hear from you advice!
Here is my lambda code
const requestData = AdminResetPasswordDto.from(event.body);
const errors = await AdminResetPasswordDto.validate(requestData);
if (errors) {
return new BadRequestError({ message: "errors.invalid-request-params", errors })
}
const repo = new UsersRepo();
const entity = await repo.getOneByEmail(requestData.email);
if (!entity) {
return new BadRequestError({ message: 'errors.user-not-exists' })
}
// const newPass = generatePassword();
// sending newPass to user via SNS
// use SNS or SES ???
// https://docs.aws.amazon.com/sns/latest/dg/sns-email-notifications.html
const user = UserDto.fromEntity(entity);
const result = await repo.updateUserPassword(user.userId, user.userRole, newPass);
if (!result) {
return new BadRequestError({ message: 'errors.password-not-updated' })
}
return new ResponseSuccessNoBody();
SES is meant for sending high-volume e-mail efficiently and securely. Once you have verified that you are the owner of an e-mail address, you can send e-mails through SES to any other e-mail address without the recipient's consent. SES takes care of the engineering required to ensure the delivery of their e-mails.
SNS is meant as a channel publisher/subscriber service. In order to receive e-mails from SNS, the end-user must first subscribe and approve that subscription through e-mail before amazon delivers e-mails from the subscribed channel to that end-user. End-users can subscribe via e-mail, SMS, webhooks, and other means up to the user independent of the publisher.
On a practical level, we use SES to send our users e-mails about their content and we use SNS to send our developers notifications (via SMS and e-mail) when servers go down or have issues.
In short,
SNS
email messages
SMS
push notifications to mobile device
messages between services/apps
Clients have to subscribe, to receive above notifications
SES
email messages
No subscriptions required
SNS is used for “technical” notifications; delivery as e-mail is possible, but rather limited. First, you need to create dedicated subscriptions and provide the destination mail address at this point. Second, you can’t really “design” your messages, it will just be a blob of text. You should go with SES for messages where the recipient is determined at runtime and you want to have control over the message layout.

Slack webhook not sending personal message

I am trying to send personal message to particular user using webhook. I created webhook so i am getting personal message. But I am not able to send personal message to others personal chat. I don't want to use bot.
slack.setWebhook("Webhook");
slack.webhook({
channel: "D01KMUZ4E4S",
username: "webhookbot",
text: "This is posted to #general and comes from a bot named webhookbot."
}, function(err, response) {
console.log(response);
});
Slack Webhook URLs are tied to a particular channel, individual message, or group message. You need to create a new webhook in your workspace for each user you would like to send messages to.

Google Cloud Platform pub/sub - messages aren't being being delivered to subscriber

I am setting up push notifications for gmail based on the guide provided by google (https://developers.google.com/gmail/api/guides/push). I want to have my node app register a client with .watch(), and then receive emails at a specified endpoint, as described in the documentation.
I have created the pub/sub topic, added gmail as a publisher, added a subscriber, and called watch() in my node app. watch() returns the appropriate { historyId: xxxx, expiration: yyyy } object which, according to google's documentation, means the call succeeded.
handler for receiving email notification on backend:
export const receiveGmailEmail: RequestHandler = async (req, res) => {
log('Received update from google!');
log(JSON.stringify(req.body, null, 2));
return res.status(200);
}
Registering:
const watchRes = await gmailClient.watch();
log('====> Watch Response <=====');
log(JSON.stringify(watchRes, null, 2));
Server log that shows it is registering properly:
====> Watch Response <=====
{
"historyId": "6560",
"expiration": "1562025255689"
}
I never receive messages at the receive endpoint on my node app. According to the server logs, I never actually receive any request when a message is published. The problem appears to be that my messages are undelivered. I have confirmed through the Stackdriver monitor that the pub/sub topic is publishing messages when I send an email to the email address, but if I view the details of the subscription in Stackdriver, it shows an increasing number of undelivered messages.
Any thoughts on why messages in a subscription are sitting around undelivered?
It turns out this wasn't a Google pub/sub issue. Amazon Cloudfront blocks POST requests by default, so I had to edit the caching behavior to enable POST requests. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesAllowedHTTPMethods

find publisher id when subscriber subscribe to topic in mqtt

I am using mqtt in my nodejs backed application where there is communication with iot devices and where i am able to publish and subscribe to different topic.every thing is working well i can publish and subscribe to different topic.
I am able to send client id or the publisher id who publish topic in message part which is a repeated task for every publisher.
Is there any way we can know who is publisher while subscribing to topic.
my mqtt client code at nodejs is
var mqtt = require('mqtt')
var url = "http://127.0.0.1:1883";
var client = mqtt.connect(url);
client.on('connect', () => {
console.log('Mqtt client connected to broker');
client.subscribe('status/open');
client.subscribe('status/close');
client.subscribe('sendMsg');
})
client.on('message', (topic, message) => {
console.log('new topic received at controller', topic);
console.log('new messge received at controller', message.toString());
///is there any way to determine who is publishere here
});
No.
This goes against one of the core principals of pub/sub messaging, which is that a publisher shouldn't care who is subscribed to a given topic and a subscriber shouldn't care where the data is coming from, it just subscribes to a topic.
If you want to make it clear you have 2 options.
Use a topic structure that encodes the publisher in the topic and the subscriber uses wildcard topics to receive data from all publishers.
Encode the publisher information into the message payload.

Send Extra payloads params in SNS notification register and get back same params when notification receives

I am implementing AWS SNS with AWS SES.
I am registering notification that calls my http endpoint handler and i am receiving perfect notification object. But along with notification identity i want to send my extra payloads that can be received when registered endpoints called. I am doing it in nodeJS
here is the snippet of registering notification
var params = {
Identity: 'myemail#mydomain.com', /* required */
NotificationType: 'Bounce', //["Delivery","Bounce","Complaint"], /* required */
SnsTopic: 'arn:aws-arnstring'
};
ses.setIdentityNotificationTopic(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
is there anyway to send extra params like Identity and NotificationType ?
thanks in advance
There does not appear to b a mechanism for adding metadata, however... the notification should contain source inside the mail object, which looks like it would be the sending email address.
Arguably, there's no need for additional metadata, because there's also the messageId provided with the notifications. This is the same identifier you got back when you submitted the message.
If you saved the metadata locally (or even in simpledb, dynamodb, rds, or even S3) under that ID when the message was submitted, you'd be able to look it up again. If you don't save something with each message you send, then you don't have a way to "close the loop" and track the fact that you've received a notification of bounce, complaint, or delivery of each message to each recipient from SES.
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html
It isn't currently possible to send extra parameters along with the notification. You should submit this feature request to the Amazon SES team, either via the Amazon SES forums or through AWS Developer Support.

Resources