0

I'm trying to set up a contact form on my site, I feel I am close but there is something funky going on with the source address value. I'm passing the data as URL encoded instead of multipart as I only need some text.

Contact form:

<form id='contact-form'>
  <label for='replyTo'>Email</label>
  <input name='replyTo' id='replyTo' type='email' autocomplete='email' required>
  <label for='subject'>Subject</label>
  <input name='subject' id='subject' required>
  <label for='message'>Message</label>
  <textarea name='message' id='message' autocapitalize='sentences' maxlength='3000' minlength='10' placeholder='Comment text' rows='3' spellcheck='true' required></textarea>
  <button id='submit-btn' type='button'>Send</button>
</form>

Javascript handler:

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

submitBtn.addEventListener('click', () => {
  const formData = new FormData(htmlForm),
  urlEncodedData = new URLSearchParams();
  for (const pair of formData.entries()) {
    urlEncodedData.append(pair[0], pair[1]);
  }
  htmlForm.requestSubmit();
  fetch(endpoint, {
    method: "post",
    body: urlEncodedData,
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    }
  }).then(response => {
    if (response.ok) {
      resetForm();
    } else {
      throw new Error('HTTP error. Status: ${response.status}');
    }
  });
});

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

Lambda function:

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

exports.handler = async (event) => {
  const formData = querystring.parse(event.body),
        message = formData.message,
        replyTo = formData.replyTo,
        subject = formData.subject,
  emailParams = {
    Source: "form@<verified_domain_tld_here>",
    Destination: {
      ToAddresses: ["<my actual email address>"]
    },
    Message: {
      Subject: {
        Data: `${subject}`
      },
      Body: {
        Text: {
          Data: `${message}`
        }
      }
    },
    ReplyToAddresses: [`${replyTo}`]
  };
  try {
    await ses.sendEmail(emailParams).promise();
    console.log(successMessage);
    return {
      statusCode: 200,
      body: JSON.stringify({ message: successMessage })
    };
  } catch (err) {
    console.log(err);
    return {
      statusCode: err.statusCode || 500,
      body: JSON.stringify({ message: err.message || errorMessage })
    };
  }
};
1
  • I altered the code a bit to return the response body, and it is base64 encoded. This might be preventing the Lambda function from parsing it!
    – leecalvink
    Commented Apr 7, 2023 at 0:45

1 Answer 1

0

Turns out the data was being encoded into Base64 by this: const formData = new FormData(htmlForm) which means I had to decode it on the server side before the body could be properly parsed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .