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 })
    };
  }
};
Falken
  • 1
  • 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! – Falken Apr 07 '23 at 00:45

1 Answers1

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.

Falken
  • 1
  • 1