AWS SES failing with "Recipient count exceeds 50." on individual recipient emails - amazon-web-services

We are looping on 160 email addresses in AWS Lambda and calling SES' send_raw_email() API call with one address per call. After 50 loops we get the error "Recipient count exceeds 50." but there is only one recipient per call. The other information in the emails, other than "To:", are the same between calls. We do this to keep recipients from seeing the addresses of other recipients.
Are the emails being batched at SES? (How are we even hitting this limit?)
How can we get past this error?
Adding code:
for item in recipients['Items']:
RECIPIENT = item['email']['S']
msg['To'] = RECIPIENT
try:
#Provide the contents of the email.
response = ses.send_raw_email(
Source=SENDER,
Destinations=[
RECIPIENT
],
RawMessage={
'Data':msg.as_string(),
}
)
# Display an error if something goes wrong.
except ClientError as e:
print("failed to send email: ",e.response['Error']['Message'])
return {
'statusCode': 400,
'body': json.dumps(e.response['Error']['Message'])
}
else:
print("Email sent! Message ID:"),
print(response['MessageId'])

The issue was that the library operates by adding to the "To" list when assigning, not replacing. So a "del msg['To']" was needed.
for item in recipients['Items']:
RECIPIENT = item['email']['S']
del msg['To']
msg['To'] = RECIPIENT
...

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

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.

Sending tokens out on coinpayments success payment using Web3py

I'm writing Django app and want to send out tokens using Web3 once Coinpayments sends me callback about successfull payment. The problem is that Coinpayments sends multiple callbacks at once and just in one case tokens are sending, other callbacks get replacement transaction underpriced error. I've already tried to use solutions like add +1 to nonce or remove this parameter, but that doesn't help me because transactions are still building with the same nonce. How can that be fixed or what am I doing wrong?
class CoinpaymentsIPNPaymentView(BaseCoinpaymentsIPNView):
def post(self, request, order_id, *args, **kwargs):
status = int(request.POST.get('status'))
order = Order.objects.get(id=order_id)
order.status = request.POST.get("status_text")
if not status >= 100:
order.save()
return JsonResponse({"status": status})
amount = Decimal(request.POST.get('amount1'))
record = Record.objects.create(
user=order.user,
type='i',
amount=amount,
)
order.record = record
order.save()
gold_record = GoldRecord.objects.get(from_record=record)
contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=ABI_JSON)
transaction = contract.functions.transfer(order.user.wallet.address, int(gold_record.amount * 10 ** 18)).buildTransaction({
'chainId': 1,
'gas': 70000,
'nonce': w3.eth.getTransactionCount(WALLET_ADDRESS) # address where all tokens are stored
})
signed_tx = w3.eth.account.signTransaction(transaction, WALLET_PRIVATE_KEY) # signing with wallet's above private key
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(tx_hash.hex())
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
return JsonResponse({"status": status})
P.S. I've already asked it on Ethereum StackExchange, but nobody answered or commented it: https://ethereum.stackexchange.com/questions/80961/sending-tokens-out-on-coinpayments-success-payment-using-web3py
Ok, let the web know answer and solution that I found out by myself
Each transaction should have unique nonce, so I noticed that if I do a loop for sending transactions and set nonce as w3.eth.getTransactionCount(WALLET_ADDRESS) + index then it sends all transactions without any errors. So I removed instant coins sending (even removed waitForTransactionReceipt to speed up it), and made management command where I process all payouts and if it was sent successfully I assign its tx_hash and run it every 10 minutes with Heroku Scheduler

boto3 - aws sns - specify Sender ID

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