Skip to content

Lambda + SES error (InvalidParameterValue: Missing final '@domain')

0

Edited the thread because it was getting out of hand. I get a Error 500 ("message":"Failed to send email"). Here is what gets shown in the browser.

Enter image description here Enter image description here

Here is the JS I'm using on my site:

const submitBtn = document.getElementById('submit-btn'), //submit form button
  htmlForm = document.getElementById('contact-form'), //contact form
  endpoint = "https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/Email"; //call lambda function

submitBtn.addEventListener('click', () => {
  const formData = new FormData(htmlForm), // capture form data
  urlEncodedData = new URLSearchParams(); // format data
  for (const pair of formData.entries()) {
	urlEncodedData.append(pair[0], pair[1]);
  }
  htmlForm.requestSubmit(); // only sends if form is valid
  fetch(endpoint, {
	method: "post",
	body: urlEncodedData,
	headers: {
	  "Content-Type": "application/x-www-form-urlencoded"
	}
  }).then(response => {
	if (response.ok) {
	  resetForm();
	  contactDialog.close();
	} else {
	  throw new Error('HTTP error. Status: ${response.status}');
	}
  }).catch(error => {
	console.log('Something is wrong *shrugs*');
  });
});

htmlForm.addEventListener('submit', (event) => {
  event.preventDefault(); // prevents submitting to self (page)
});

Current Lambda code:

const AWS = require('aws-sdk'),
  ses = new AWS.SES(),
  querystring = require('querystring');

exports.handler = async (event) => {
  const formData = querystring.parse(event.body),
        toAddress = formData.toAddress, 
        message = formData.message, 
        replyTo = formData.replyTo, 
        sourceEmail = formData.sourceEmail, 
        subject = formData.subject;

  // Construct the email message
  const emailParams = {
    Destination: {
      ToAddresses: [`${toAddress}`] 
    },
    Message: { 
      Subject: { 
        Data: `${subject}`
      },
      Body: { 
        Text: {
          Data: `${message}`
        }
      }
    },
    ReplyToAddresses: [`${replyTo}`], 
    Source: `${sourceEmail}`
  };

  // Send the email using SES
  try {
    await ses.sendEmail(emailParams).promise();
    return {
      statusCode: 200,
      body: JSON.stringify({ message: 'Email sent successfully' })
    };
  } catch (err) {
    console.log(err);
    return {
      statusCode: 500,
      body: JSON.stringify({ message: 'Failed to send email' })
    };
  }
};
7 Answers
1

Let me know the results when you get the test done.

EXPERT
answered 3 years ago
  • I am getting a different error now when I adjusted it to simply return whatever the error code is from AWS, it is actually error 400 not 500. It is the message from before though still. Perhaps since the API requires some strings in the fields the values aren't being processed correctly or input properly? (as a string)

  • It is possible that the correct parameters are not being sent to Lambda.

  • @Riku_Kobayashi: I altered the code a bit to return the response body and it's base64 encoded for some reason?! If I alter the Lambda script to decode it first it might all work out.

  • Decoding the body first ends with the email getting sent! Thought there is some other weird stuff going on, but that's a different topic.

  • I see that you are now able to send emails! Congratulations!

1

If you give me the "console.log(event)" information, I will check it too.

EXPERT
answered 3 years ago
  • I am putting in this and console.log(event.body) into the Lambda function to see.

    New Lambda code for testing: // Send the email using SES try { await ses.sendEmail(emailParams).promise(); const successMessage = 'Email sent successfully\n' + 'Here is the event data: ' + JSON.stringify(event) + '\n' + 'Here is the event body: ' + event.body; console.log(successMessage); return { statusCode: 200, body: JSON.stringify({ message: successMessage }) }; } catch (err) { console.log(err); const errorMessage = 'Failed to send email\n' + 'Here is the event data: ' + JSON.stringify(event) + '\n' + 'Here is the event body: ' + event.body; return { statusCode: err.statusCode || 500, body: JSON.stringify({ message: err.message || errorMessage }) }; } };

  • With the new code I put in, AWS is actually returning a code 400 (message: Missing final '@domain') now.

0
Accepted Answer

Decoding the body from Base64 encoding in the Lambda function solves the issues. Sending the data as JSON looks like an even more efficient way of doing things, but attempting it leads to its own issues.

answered 3 years ago
0

If I enter an email address directly in ToAddresses:, does it still result in an error?
What is the overall formData?
Missing final '@domain' may appear if emailParams is bad

EXPERT
answered 3 years ago
0

If you want to test with that json, your code should look like this
Can you show us what is actually in the event you are sent?

const AWS = require('aws-sdk'),
      ses = new AWS.SES(),
      querystring = require('querystring');

exports.handler = async (event) => {
  // Get form data from the request body
//  const formData = querystring.parse(event.body),
  // Extract the form fields from the parsed data
//       toAddress = formData.toAddress, // required
         toAddress = event.toAddress,
//         message = formData.message, // required
         message = event.message,
//         replyTo = formData.replyTo, // recommended
         replyTo = event.replyTo,
//     sourceEmail = formData.sourceEmail, // required
     sourceEmail = event.sourceEmail,
//         subject = formData.subject, // required
         subject = event.subject,
  // Construct the email message
  emailParams = {
    Destination: {
      ToAddresses: [`${toAddress}`,] // required
    },
    Message: { // required
      Subject: { // required
        Data: `${subject}`
      },
      Body: { // required
        Text: {
          Data: `${message}`
        }
      }
    },
    ReplyToAddresses: [`${replyTo}`,], // recommended
    Source: `${sourceEmail}` // required
  };
  
  return ses.sendEmail(emailParams).promise();
};
EXPERT
answered 3 years ago
0

With the following code and JSON for testing, we were able to confirm that the email could be sent
That leads me to believe that there is nothing wrong with the part about sending the email.
If there is a problem, it is most likely the content of the body that is fetched by "const formData = querystring.parse(event.body)".
For example, you use "console.log()" to display "formData.toAddress", "formData.message", "formData.replyTo", "formData.sourceEmail", "formData.subject What do you see when you do this?

Code

const AWS = require('aws-sdk'),
      ses = new AWS.SES(),
      querystring = require('querystring');

exports.handler = async (event) => {
  // Get form data from the request body
//  const formData = querystring.parse(event.body),
  // Extract the form fields from the parsed data
//       toAddress = formData.toAddress, // required
    const   toAddress = event.toAddress,
//         message = formData.message, // required
         message = event.message,
//         replyTo = formData.replyTo, // recommended
         replyTo = event.replyTo,
//     sourceEmail = formData.sourceEmail, // required
     sourceEmail = event.sourceEmail,
//         subject = formData.subject, // required
         subject = event.subject,
  // Construct the email message
  emailParams = {
    Destination: {
      ToAddresses: [`${toAddress}`,] // required
    },
    Message: { // required
      Subject: { // required
        Data: `${subject}`
      },
      Body: { // required
        Text: {
          Data: `${message}`
        }
      }
    },
    ReplyToAddresses: [`${replyTo}`,], // recommended
    Source: `${sourceEmail}` // required
  };
  
  return ses.sendEmail(emailParams).promise();
};

Test JSON

{
"replyTo": "<a_real_email_address_here>@gmail.com",
"subject": "Final Test?",
"message": "Here is some text I hope you receive it",
"sourceEmail": "form@<my_verified_domain_tld>",
"toAddress": "<my_actual_email>@gmail.com"
}
EXPERT
answered 3 years ago
0

It is possible. Give it a try.

EXPERT
answered 3 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.