Hi,
I have a simple email function that fires inside a netlify lambda function. It uses the AWS SES service.
Sitename: bleachlondon-develop.netlify.app,
The user enters their email, it sends the email address to the function endpoint and we validate and send an email with a magic link in it, code below:
const { v4: uuid } = require("uuid")
const AWS = require("aws-sdk")
AWS.config.update({
accessKeyId: process.env.VUE_APP_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.VUE_APP_AWS_SECRET_ACCESS_KEY,
region: "eu-west-2"
})
const cognito = new AWS.CognitoIdentityServiceProvider()
const ses = new AWS.SES({
region: "eu-west-2"
})
/**
* Returns just type and subtype from Content-Type HTTP header value.
*
* @param {string|undefined} headerValue
* @return {string}
*/
function parseContentType(headerValue) {
return (headerValue || "").split(/;\s+/, 2)[0]
}
// module.exports.handler = async (event, context, callback)
exports.handler = async function(event) {
if (event["httpMethod"] !== "POST") {
return {
statusCode: 200, // <-- Important!
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
body: "This was not a POST request!"
}
}
if (
parseContentType(event["headers"]["content-type"]) !==
"application/json;charset=UTF-8"
) {
return {
statusCode: 200, // <-- Important!
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
body: `Unexpected content type "${event["headers"]["content-type"]}"`
}
}
try {
const { email } = JSON.parse(event.body)
const poolId = process.env.VUE_APP_AWS_USER_POOLS_ID
// Store challenge as a custom attribute in Cognito
const authChallenge = uuid()
await cognito
.adminUpdateUserAttributes({
UserAttributes: [
{
Name: "custom:authChallenge",
Value: `${authChallenge},${Math.round(new Date().valueOf() / 1000)}`
}
],
UserPoolId: poolId,
Username: email
})
.promise()
const errs = []
if (!email) errs.push("no-email")
if (errs.length > 0) {
return {
statusCode: 400,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
body: JSON.stringify({
error: "Sorry, there is an issue with your account",
errorDetail: errs
})
}
}
const link = `${process.env.VUE_APP_BASE_URL_SERVERLESS}/login?validation=${authChallenge}&email=${email}`
sendEmail(email, link)
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
body: JSON.stringify({
message: "email sent",
data: link
})
}
} catch (e) {
return {
statusCode: 400,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
body: JSON.stringify({
error: "Sorry, we could not find your account.",
errorDetail: e.message
})
}
}
/**
* Sends email via AWS SES API.
*
* @param {string} replyTo
* @param {string} text
* @param {!NetlifyCallback} callback
*/
function sendEmail(email, url) {
ses.sendEmail(
{
Source: "no-reply@***********",
Destination: {
ToAddresses: [email]
},
Message: {
Subject: {
Charset: "UTF-8",
Data: "Your Sign In link"
},
Body: {
Html: {
Charset: "UTF-8",
Data: `<html><body><p>This is your magic link:</p>
<h3>See below</h3><br>${url}</body></html>`
},
Text: {
Charset: "UTF-8",
Data: `Your Sign in link`
}
}
}
},
(err, data) => {
if (err) {
console.error("Error while sending email via AWS SES:", err)
return {
statusCode: 400, // <-- Important!
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
},
body: err
}
}
emailData = data
}
)
}
}
This is taken from a function inside my front-end code that posts to the endpoint like so:
try {
const { data } = axios.post(
`${process.env.VUE_APP_SERVERLESS_FUNCTION_URL}/login`,
{
email
},
{
headers: {
"Access-Control-Allow-Origin": "*",
Accept: "application/json;charset=UTF-8"
}
}
)
return data
} catch (e) {
console.log("Request failed", e)
console.log(e.response.data)
}
There are no errors that come through, I get successful return but the error is in the delivery of the email. The functionality works fine locally but not in build but I cannot find why?
Can anyone help?