Search code examples
javascriptajaxexpressform-datax-www-form-urlencoded

Undefined values in email response


I'm trying to use AJAX for my contact form which sends the form data to the server. Which should then email me users information through the input fields.

The issue I'm having is, the formData seems to doing as normal (appears in the network on the browser) But when my email comes through i'm getting undefined values?

const submit = document.querySelector('.contact-btn');

submit.addEventListener('click', send);

function send(event){
    event.preventDefault();
    const url = "https://us-central1-selexin-website.cloudfunctions.net/app/sendemail";
    let form = document.querySelector('form');
    let formData = new FormData(form);
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
        if(xhr.readyState === XMLHttpRequest.DONE){
            console.log(formData)
    // Make a pop up message in green below the textarea box to notify user email was sent.

    }   
}
    xhr.open('POST', url, true);
    xhr.send(formData);
};

Below is the field being emailed to me. As you can see, in the email body I've added "run test"as a string and that returns perfect in the email. Why is req.body giving me undefined values?

const transport = nodemailer.createTransport(sendgridTransport({
    auth: {
        api_key: apiKey
    },
}));

app.use(express.urlencoded({extended: false}));
app.use(cors({ origin: true }));

app.post('/sendemail', (req, res) => {
  const {name, email, number, message} = req.body;
    return transport.sendMail({
    to: 'email receiving', 
    from: 'from this email',
    subject: 'New Contact Request',
    html: `
    <p>You have a new Contact Request</p>
    <h3>Contact Details</h3>
    <ul>
        <li>Name: 'Run test'</li>
        <li>Email: ${email}</li>
        <li>Number: ${number}</li>
        <li>Message: ${message}</li>
    </ul>
    `
    }).then(() => {
      if(res.sendStatus(200)){
        console.log('it logs');
      };
    })
 });

exports.app=functions.https.onRequest(app);

Solution

  • You're sending your request body as multipart/form-data, not application/x-www-form-urlencoded.

    If you wanted to handle the former, you'd need something like the Multer middleware in your express app.

    The quick and easy solution is to wrap your FormData in URLSearchParams

    xhr.send(new URLSearchParams(formData))
    

    This will post your data as application/x-www-form-urlencoded which is handled by the express.urlencoded() middleware you're already using.


    I also highly recommend adding the event listener to your form's submit event instead of a button click. That way, you can catch things like "type Enter to submit"

    document.querySelector("form").addEventListener("submit", e => {
      e.preventDefault()
      const formData = new FormData(e.target)
    
      // ...and the rest of your "send" logic
    })