boto3 - aws sns - specify Sender ID - amazon-web-services

The following code works to send a message but when it arrives, it displays the text 'VERIFY' for a sender id. How do I specific a sender ID? I think it's done with the message attributes but I cannot figure out the syntax.
session = boto3.session.Session(profile_name='Credentials',region_name='us-east-1')
theMessage='Now is the time for all good people to come to the aid of their party'
senderID='Godzilla'
snsclient = session.client('sns')
response = snsclient.publish(PhoneNumber='+84932575571', Message=theMessage)
pp = pprint.PrettyPrinter(indent=4)
print(pp.pprint(response))

Add a third parameter MessageAttributes to the publish method.
snsclient.publish(PhoneNumber='+84932575571', Message=theMessage,MessageAttributes={
'AWS.SNS.SMS.SenderID': {
'DataType': 'String',
'StringValue': 'Godzilla'
}})
The sender id is not supported in many countries. see AWS SNS SMS SenderId Supported Countries

Related

AWS Lambda, SNS and Python - "Missing final '#domain'"

I am trying to send SNS messages for old AWS access keys, but am getting the below error:
Response
null
Function Logs
START RequestId: a266bda6-2d17-4c24-a6d3-a0a05180025b Version: $LATEST
[ERROR] 2021-03-17T15:48:33.592Z a266bda6-2d17-4c24-a6d3-a0a05180025b Missing final '#domain'
I have tried Googling a bit, and the IAM user accounts are NOT email addresses - just people's first names. The SNS subscriber is already setup, so I'm not sure why it would care to know a user's email address.
Any ideas?
Python Script below:
import boto3, json, time, datetime, sys, re
iam_client = boto3.client('iam')
sns_client = boto3.client('sns')
users = iam_client.list_users()
user_list = []
for key in users['Users']:
user_list = key['UserName']
accesskeys = iam_client.list_access_keys(UserName=key['UserName'])
for items in user_list.split('\n'):
for key in accesskeys['AccessKeyMetadata']:
accesskeydate = accesskeys['AccessKeyMetadata'][0]['CreateDate']
accesskeydate = accesskeydate.strftime("%Y-%m-%d %H:%M:%S")
currentdate = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
accesskeyd = time.mktime(datetime.datetime.strptime(accesskeydate, "%Y-%m-%d %H:%M:%S").timetuple())
currentd = time.mktime(datetime.datetime.strptime(currentdate, "%Y-%m-%d %H:%M:%S").timetuple())
active_days = (currentd - accesskeyd)/60/60/24
message = (key['UserName'],int(round(active_days))),
message = re.sub(r'[^a-zA-Z0-9 ]', "", str(message))
message = re.sub(r' ', ' is ', str(message))
if active_days >= 1:
sns_client.publish(
TopicArn='<redacted SNS topic>',
Subject='User with Old Access Key Detected',
Message="The access key for " + str(message) + " days old. This user access key should be replaced ASAP.",
if active_days >= 1:
sns_client.publish(
TopicArn='<redacted SNS topic>',
Subject='User with Old Access Key Detected',
For Publishing the message you don't need Subject. You can send message as described as here
SNS Publish API Call
Subject
Optional parameter to be used as the "Subject" line when the message is delivered to email endpoints. This field will also be included, if present, in the standard JSON messages delivered to other endpoints.
To publish a message to a topic, we simply call the publish() function, passing the topic’s ARN, the desired message, and optionally a subject (it will only be used in email messages).
aws examples for sns operations using boto3

AWS SNS OTP emails

I am working on sending OTP messages for user login leveraging Amazon SNS. I am able to send Text message as suggesting here. For the email notification as well I would like to use a similar approach. But looks like for email notifications, a topic has to be created in SNS and a subscriber has to be created for each email id registered in the application.
Is it not possible to send email to mail-id dynamically as done for text messages without creating topics and subscribers? If not please suggest a way to set email id dynamically based on the user logged in.
Code for Text Messaging:
public static void main(String[] args) {
AmazonSNSClient snsClient = new AmazonSNSClient();
String message = "My SMS message";
String phoneNumber = "+1XXX5550100";
Map<String, MessageAttributeValue> smsAttributes =
new HashMap<String, MessageAttributeValue>();
//<set SMS attributes>
sendSMSMessage(snsClient, message, phoneNumber, smsAttributes);
}
public static void sendSMSMessage(AmazonSNSClient snsClient, String message,
String phoneNumber, Map<String, MessageAttributeValue> smsAttributes) {
PublishResult result = snsClient.publish(new PublishRequest()
.withMessage(message)
.withPhoneNumber(phoneNumber)
.withMessageAttributes(smsAttributes));
System.out.println(result); // Prints the message ID.
}
Correct.
Amazon SNS normally uses a Public/Subscribe model for messages.
The one exception is the ability to send an SMS message to a specific recipient.
If you wish to send an email to a single recipient, you will need to use your own SMTP server, or use Amazon Simple Email Service (Amazon SES).

SNS publish to topic with phone number is not working

I have boto3 code that creates a topic and creates a subscription to that topic and publishes the message to the topic.
The code was working fine. I tried to add a US number to the mix of Indian phone number subscribed group and everything went south. I don't get any errors all the responses are successful but I don't receive any messages.
Then I tried with normal console publish a message, even the console publish is not working.
TO cross-verify it the issue was with the region I tried publishing in us-east-1 and all worked fine.
Here is my code:
def lambda_handler(event, context):
sns = boto3.client("sns")
number = ['+91xxxxxxxx','+1xxxxxxxxxxxx','+91xxxxxxxxxx']
response = sns.create_topic(
Name='loadeo-demo',
Attributes={
}
)
arn = response['TopicArn']
print ("arn: " + arn)
for phno in number:
response = sns.subscribe(
TopicArn=arn,
Protocol='sms',
Endpoint=phno,
Attributes={
},
ReturnSubscriptionArn=False
)
# print(response)
response = sns.list_subscriptions_by_topic(
TopicArn=arn
)
print (response)
response = sns.publish(
topicArn=arn,
Message="A Load of your interest has been placed.\n" + "Please visit the web for more details.\n" + "Thank you",
)

Email not being sent / No errors AWS/SES

I have an AWS Lambda function:
sendEmail.js
const AWS = require('aws-sdk');
const ses = new AWS.SES();
function sendEmail(subject, message, senderEmail) {
const params = {
Destination: {
ToAddresses: [
process.env.VERIFIED_EMAIL
]
},
Message: {
Body: {
Text: {
Data: message,
Charset: 'UTF-8'
}
},
Subject: {
Data: subject,
Charset: 'UTF-8'
}
},
Source: process.env.VERIFIED_EMAIL,
ReplyToAddresses: [senderEmail]
}
return ses.sendEmail(params).promise();
}
module.exports = sendEmail;
Called from
index.js
const sendEmail = require('./sendEmail');
exports.handler = async (event, context) => {
return sendEmail(event.subject, event.message, event.email).then((response) => { context.done(null, 'Email sent')});
};
I have the env. variable VERIFIED_EMAIL set to a personal e-mail that is verified by AWS/SES.
My test case:
{
"email": "redacted#outlook.com",
"subject": "desc",
"message": "Hello!"
}
Which passes and returns "Email sent" but I don't actually receive an e-mail. I've also deployed the API-GATEWAY and I can call the API w/ Postman and I receive the same "Email sent" message but no e-mail is actually sent.
I don't think it should be an issue with being in sandbox mode because the email I am sending it from is verified.
PS:
When Looking at the SES management console it says that the emails are being sent (they take up part of the 200 daily quota) and then that none of them were bounced or rejected but simply deliveries.
A few things you should check with your SES before diving deeper.
In sandbox mode both "source email address" and "destination email address" have to be verified. Instead a mail won't be delivered.
In case you verify Email Domain so appropriate dns and DKIM records have to be added in your domain. Plus additional whitelist clearance is assumed if you use corporate domains.
Your IAM AWS user should be permitted to execute SES api calls. Check your policies and roles. Check Secret Key and Secret Id you use.
There might be problems when you use inappropriate email types and email sending endpoints (eg you try to send "SingleTemplatedMessage" via "BulkTemplatedMessage" endpoint)
Check all this things first.
Then you might try something else. In my project we use AWS SDK based on java to interact between BE and SES. It provides logs containing message statuses (if a message was sent successfully, rejected, its id and other errors if they occurred)
Additionally to keep track on every single message you send you can set up SES-SNS to exchange with notifications. It's described in the following article
https://sysgears.com/articles/how-to-track-email-status-with-amazon-ses-and-amazon-sns/
Other problems might occur in your mail client (spam filters etc)
Follow the check list to troubleshoot SES email sending:
Check the SMTP credential is ok or not using code shared by AWS
Same credential using in multiple application/IP may not work
Use minimum mail configuration, if you do not know setting value remove it, do not leave it with NULL.
Set, $config['charset'] = 'UTF-8'; // // 'UTF-8', 'ISO-8859-15'
Set, $config['newline'] = "\r\n"; // "\r\n" or "\n" or "\r"
Additional Check
Make sure trying to send email to the same domain if SES account is Sandbox
Check all outbound with mail TCP port is open
If using NATgateway Check both inbound and outbound with mail TCP port is open in open for the mail sending instance in it.

AppFabric Topic Subscription

I am trying to assemble a simple AppFabric Topic whereby messages are sent and received using the SessionId. The code does not abort, but brokeredMessage is always null. Here is the code:
// BTW, the topic already exists
var messagingFactory = MessagingFactory.Create(uri, credentials);
var topicClient = messagingFactory.CreateTopicClient(topicName);
var sender = topicClient.CreateSender();
var message = BrokeredMessage.CreateMessage("Top of the day!");
message.SessionId = "1";
sender.Send(message);
var subscription = topic.AddSubscription("1", new SubscriptionDescription { RequiresSession = true});
var mikeSubscriptionClient = messagingFactory.CreateSubscriptionClient(subscription);
var receiver = mikeSubscriptionClient.AcceptSessionReceiver("1");
BrokeredMessage brokeredMessage;
receiver.TryReceive(TimeSpan.FromMinutes(1), out brokeredMessage); // brokeredMessage always null
You have two problems in your code:
You create a subscription AFTER you send the message. You need to create a subscription before sending, because a subscription tells the topic to, in a sense, copy, the message to several different "buckets".
You are using TryReceive but are not checking for its result. It returns true, if a message was received, and false if not (e.g. Timeout has occured).
I am writing my sample application and will post it on our blog today. I will post the link here as well. But until then, move the subscription logic to before sending the message, and the receiver after it and you will start seeing results.
Update:
As promised, here is the link to my blog post on getting started with AppFabric Queues, Topics, Subscriptions.