AWS verifying SES identity from the wrong region - amazon-web-services

I am trying to send an email from an AWS lambda function. However, I get this error
INFO MessageRejected: Email address is not verified. The following identities failed the check in region US-EAST-1: testemail#gmail.com, support#mydomain.com
Both identities are verified in ap-southeast-2 and the lambda function is in the same region. If I am running the function from ap-southeast-2 and all my email configurations, including SMTP point to ap-southeast-2, why is the verification happening in us-east-1
Below is my code
const SES = new AWS.SES({ region: "us-east-1" });
const sendEmail = async (event) => {
const params = getNotificationParams(event);
console.log(params);
if (!params || params.error) {
return Responses._400({
message: params.error,
});
}
try {
await SES.sendTemplatedEmail(params).promise();
return Responses._200();
} catch (err) {
console.log(err);
return Responses._500({ message: "Error sending email" });
}
};
module.exports = {
handler: sendEmail,
};

The mistake was that I specified the wrong region (us-east-1) during SES initialization. Here is the fixed code with ap-southeast-2
const SES = new AWS.SES({ region: "ap-southeast-2" });
const sendEmail = async (event) => {
const params = getNotificationParams(event);
console.log(params);
if (!params || params.error) {
return Responses._400({
message: params.error,
});
}
try {
await SES.sendTemplatedEmail(params).promise();
return Responses._200();
} catch (err) {
console.log(err);
return Responses._500({ message: "Error sending email" });
}
};
module.exports = {
handler: sendEmail,
};

Related

Scalable AWS API Gateway WebSocket broadcast?

In our scalable AWS serverless application (DynamoDB, Lambda, API Gateway WebSockets) we want to broadcast messages from a Lambda to very many connected browser sessions simultaneously.
We have many topics, and to limit the load on the system we want to limit each browser session to subscribe to max. two topics.
The AWS example app linked in this official tutorial does this by looping through the connectionIds and doing an await postToConnection for each of them, which doesn't scale well as each postToConnection takes 40 ms (average):
const AWS = require('aws-sdk');
const ddb = new AWS.DynamoDB.DocumentClient();
exports.handler = async function (event, context) {
let connections;
try {
connections = await ddb.scan({ TableName: process.env.table }).promise();
} catch (err) {
return {
statusCode: 500,
};
}
const callbackAPI = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint:
event.requestContext.domainName + '/' + event.requestContext.stage,
});
const message = JSON.parse(event.body).message;
const sendMessages = connections.Items.map(async ({ connectionId }) => {
if (connectionId !== event.requestContext.connectionId) {
try {
await callbackAPI
.postToConnection({ ConnectionId: connectionId, Data: message })
.promise();
} catch (e) {
console.log(e);
}
}
});
try {
await Promise.all(sendMessages);
} catch (e) {
console.log(e);
return {
statusCode: 500,
};
}
return { statusCode: 200 };
};
How can we make this broadcast scalable?

How to call AWS AppSync from lambda?

I am trying to call AWS AppSync service from AWS Lambda function using IAM permissions. Just a basic mutation or query call. I found this tutorial:
https://aws.amazon.com/blogs/mobile/supporting-backend-and-internal-processes-with-aws-appsync-multiple-authorization-types/
but it no longer works with the latest sdks. Errors out on lines 3, 4, etc.
require('isomorphic-fetch');
const AWS = require('aws-sdk/global');
const AUTH_TYPE = require('aws-appsync').AUTH_TYPE;
const AWSAppSyncClient = require('aws-appsync').default;
const gql = require('graphql-tag');
const config = {
url: process.env.APPSYNC_ENDPOINT,
region: process.env.AWS_REGION,
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: AWS.config.credentials,
},
disableOffline: true
};
const createLogMutation =
`mutation createLog($input: CreateLogInput!) {
createLog(input: $input) {
id
event
detail
}
}`;
const client = new AWSAppSyncClient(config);
exports.handler = (event, context, callback) => {
// An expected payload has the following format:
// {
// "event": "sample event",
// "detail": "sample detail"
// }
const payload = event['Records'][0]["Sns"]['Message'];
if (!payload['event']) {
callback(Error("event must be provided in the message body"));
return;
}
const logDetails = {
event: payload['event'],
detail: payload['detail']
};
(async () => {
try {
const result = await client.mutate({
mutation: gql(createLogMutation),
variables: {input: logDetails}
});
console.log(result.data);
callback(null, result.data);
} catch (e) {
console.warn('Error sending mutation: ', e);
callback(Error(e));
}
})();
};
Can someone please post a basic code for calling query/mutation from lambda using IAM permissions?

AWS javascript sdk fleet provisioning ResourceNotFound exception

I am trying to implement fleet provisioning in AWS Lambda function. As a starting point, I have this code:
'use strict';
var AWS = require('aws-sdk');
var iot = new AWS.Iot({
endpoint: 'apiendpoint',
accessKeyId: "AAAABBBBBCCCCDDDDD",
secretAccessKey: "AAAAABBBBCCCDD/1234122311222",
region: 'ap-south-1'
});
exports.handler = async (event, context) => {
var params = {
setAsActive: true
};
return {
statusCode: 200,
body:JSON.stringify(await createCertAndKey(params))
}
}
const createCertAndKey = async (params) => {
return new Promise((resolve, reject) => {
iot.createKeysAndCertificate(params, function(err, data){
if(err){
console.log(err);
reject(err)
}
else{
console.log("success?");
resolve(data)
}
})
})
}
I get a ResourceNotFound exception for calling createKeysAndCertificate. I also tried calling other functions of iot, but it gives the same exception.
What am I doing wrong here?
endpoint passed when intialzing an object should be generic AWS service in format https://{service}.{region}.amazonaws.com. we don't need to pass it, AWS will assume based on region and object we are initializing.
var iot = new AWS.Iot({
endpoint: 'iot.ap-south-1.amazonaws.com',
accessKeyId: "AAAABBBBBCCCCDDDDD",
secretAccessKey: "AAAAABBBBCCCDD/1234122311222",
region: 'ap-south-1'
});

How to scan the dynamodb table form the AWS Lambda function

I am trying to scan the Dynamodb table form my following code, can anyone please guide me what is wrong here.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB({
region: "eu-west-1",
apiVersion: "2012-08-10"
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
dynamodb.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
I have given full dynamodb access role to the function but still it gives me the null response. Any idea what can be wrong here?
Response:
I tried with dynaomClient which not working too.
const AWS = require("aws-sdk");
const db = new AWS.DynamoDB.DocumentClient({
region : 'eu-west-1'
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
db.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
Your Lambda function is async but your code uses callbacks. By the time the callback is reached, your function has already been terminated because it ran asynchronously. I'd speculate that the null output you see is the return value from the Lambda function, not your console.log.
Replace your call to scan with the following:
try{
let results = await db.scan(params).promise()
console.log(results);
} catch(err){
console.log(err)
}
For more info, check out the AWS documentation about working with promises.

How to get the attributes of an added item in DynamoDB using Lambda function

I have an AWS Lambda function which is being triggered by AWS DynamoDB. The function checks if the operation in the DB is INSERT, and if it does, then it sends a new push message using AWS SNS:
console.log('Loading function');
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';
exports.handler = function(event, context, callback) {
console.log("\n\nLoading handler\n\n");
var sns = new AWS.SNS();
console.log(JSON.stringify(event, null, 2));
event.Records.forEach(function(record) {
if (record.eventName == "INSERT") {
sns.publish({
Subject: 'Test',
Message: 'Test publish to SNS from Lambda',
TopicArn: 'TOPIC-ARN'
}, function(err, data) {
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
context.done(null, 'Function Finished!');
});
}
});
callback(null, "message");
};
Is there a way that I could get the attributes of the newly added item?
var id = record.dynamodb.Keys.Id.N;