DEV Community

Cover image for Building a Super Cool Contact Form That Actually Sends Emails πŸš€βœ‰οΈ
Fred
Fred

Posted on

Building a Super Cool Contact Form That Actually Sends Emails πŸš€βœ‰οΈ

Hey there, web dev enthusiasts! Ever wanted to create a contact form that doesn't just sit there looking pretty, but actually sends emails? Buckle up, because I'm about to show you how to build a contact form that'll make your portfolio website feel like a pro communication machine!

Prerequisites

  • A sprinkle of Javascript magic
  • A Gmail account. (because who doesn't have one?)
  • Node.js and npm installed. Install here.

Step 1: Project Setup

Let’s start by creating a new Node.js project.
Type below on your terminal and run:

mkdir email-form-project
cd email-form-project
npm init -y
Enter fullscreen mode Exit fullscreen mode

Next, we grab some necessary dependencies:

npm install express nodemailer body-parser multer dotenv
Enter fullscreen mode Exit fullscreen mode

We'll check out what each one individually handles.

Step 2: The Secret Sauce- .env File

Time to keep our secrets.. secret!We store our email credentials in an .env file. This keeps sensitive data, like your Gmail credentials, out of the light, like a digital ninja.

EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-app-password
Enter fullscreen mode Exit fullscreen mode

Set environment variables in the file .env for Email and App Password . I used Google App passwords. Read about it here.

Step 3: Create the Server in server.js

We’ll set up an Express server and configure the route that handles form submissions. Inside server.js add this code:

require("dotenv").config(); // module to load environment variables from .env file
const express = require("express"); // express is a webframework for Node.js
const nodemailer = require("nodemailer"); // nodemailer is  a module to send emails
const bodyParser = require("body-parser"); // middleware to parse incoming request bodies
const path = require("path"); // handle file and directory paths
const multer = require("multer"); // middleware to manage form data
Enter fullscreen mode Exit fullscreen mode
const app = express();
const upload = multer();

app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.none());
Enter fullscreen mode Exit fullscreen mode
  • express.json() : parses incoming requests with JSON payloads.
  • bodyParser.urlencoded({ extended: true }): parses URL-encoded data(tyically used in HTML forms).
  • upload.none(): tells muter not to handle file uploads in the form, since there no file attachments.
// Serve the index.html file
app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "index.html"));
});

// Serve static files from the "static" folder
// Uncomment below code if you include css files, and images in your static folder
// app.use("/static", express.static("static"));
Enter fullscreen mode Exit fullscreen mode
// Setting up Nodemailer Transporter
const transporter = nodemailer.createTransport({
  host: "smtp.gmail.com", 
  port: 587, // specific port for non-secure SMTP communication
  secure: false,
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS,
  },
});
Enter fullscreen mode Exit fullscreen mode
// Handling POST requests and Sending emails
app.post("/submit", async (req, res) => {
  const { name, email, subject, message } = req.body;

  try {
    const info = await transporter.sendMail({
      from: `"${name}" <${email}>`,
      to: `"your-name" <your-name@gmail.com>`, // Your target email address
      subject: subject,
      text: message,
      html: `<b>${message}</b>`,
      replyTo: `"${name}" <${email}>`,
    });
    console.log("Message sent: %s", info.messageId);
    res.status(200).send("Email sent successfully!");
  } catch (error) {
    console.error("Error sending email: ", error);
    res.status(500).send("Failed to send email");
  }
});
Enter fullscreen mode Exit fullscreen mode

transporter.sendMail() is an asynchronous operation that could take some time. It behaves like a super-efficient assistant who can handle time-consuming tasks without making everything else wait in line!
More about async/await here.

// Starting the Express Server
const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

This sets up a simple Express server that:

  • Serves an HTML form, accepts form submissions via a POST request.
  • Uses Nodemailer to send the form data as an email to a specified address.

Step 4: The HTML Form in index.html

Create an html form for our users to input their contact details.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Email Form</title>
</head>
<body>
  <h1>Contact Us</h1>
  <form action="/submit" method="POST">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required><br><br>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required><br><br>

    <label for="subject">Subject:</label>
    <input type="text" id="subject" name="subject" required><br><br>

    <label for="message">Message:</label><br>
    <textarea id="message" name="message" rows="4" required></textarea><br><br>

    <button type="submit">Send Message</button>
  </form>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

A snippet of what our HTML code looks like on a browser:
An image of a webpage with a contact form with name, email, subject, message fields and a submit button

Time to Test! πŸ•ΉοΈ

Run below commands in your terminal:

node server.js
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000/ and BAM!. πŸ’₯ Your contact form is ready to send emails like a communication superhero!

Pro Tips

  • Always use app passwords for Gmail
  • Keep your .env file top-secret (add it to .gitignore)
  • Test, test, and test again!

Ready to level up your portfolio website? Go forth and communicate! πŸš€πŸ“§
Catch the full project on my GitHub: Project Link
Want to see it in action? Check out my portfolio: www.gitongacode.co.ke

Top comments (0)