Contact Us Form using Nodemailer and Google App password

Google App Password

Go to https://myaccount.google.com/apppasswords. The MAILER_EMAIL we’re going to use to generate the App Password should be the email pointed in the arrow which is of the current user. Click the create button, and give it a name.

App Email and Password

Then, this pops up the Generated app password which you can use for the environment variables later.

Generated App Password

Click the done button. The mailer should appear in the list of your app passwords.

New App Password

[!WARNING] Don’t worry my app password is going to be deleted after this. That make me vulnerable.

Front-End

Scaffold your frontend, or you could just add the dependency to the existing project

npm create astro@latest # not needed for existing projects
npm install nodemailer

Add both of the following variables in the .env file with:

MAILER_EMAIL=<your-email>
MAILER_PASSWORD=anhxysfjqecbgvyk

Create a new file named index.ts at src so that you can post your form with the action value of just /.

export const prerender = false; // Not needed in 'server' mode
import nodemailer from "nodemailer";
const { APP_EMAIL, APP_PASSWORD } = import.meta.env;
import type { APIRoute } from 'astro';

export const POST: APIRoute = async ({ request, redirect }) => {
    const data = await request.formData();
    const name = data.get("name");
    const email = data.get("email");
    const message = data.get("message");
    const transporter = nodemailer.createTransport({
        service: "gmail",
        auth: {
            user: APP_EMAIL,
            pass: APP_PASSWORD,
        },
    });
    const mailOptions = {
        from: APP_EMAIL,
        to: email as string,
        subject: "New Contact Form Submission",
        text: `Name: ${name}\nEmail: ${email}\nMessage: ${message}`,
    };
    await transporter.sendMail(mailOptions);
    return redirect('/', 302);
};

You can reuse the index.astro file for this example to add a simple form UI with nice styling.

---
import Layout from "../layouts/Layout.astro";
---

<Layout>
	<h1>Contact Us</h1>
	<form method="POST" action="/">
		<label for="name">Name</label>
		<input type="text" id="name" name="name" required />
		<label for="email">Email</label>
		<input type="email" id="email" name="email" required />
		<label for="message">Message</label>
		<textarea id="message" name="message" required></textarea>
		<button type="submit">Submit</button>
	</form>
</Layout>

<style>
	* {
		box-sizing: border-box;
		font-family: ui-sans-serif, system-ui, sans-serif;
		margin: 0;
		padding: 0;
	}
	h1 {
		text-align: center;
		margin-block: 20px;
	}

	form {
		display: flex;
		flex-direction: column;
		gap: 10px;
		max-width: 600px;
		margin: 0 auto;
		padding: 20px;
	}

	label {
		font-weight: bold;
	}

	input,
	textarea {
		width: 100%;
		padding: 10px;
		border: 1px solid #ccc;
		border-radius: 5px;
	}

	button {
		background-color: #000;
		color: #fff;
		padding: 10px;
		border: none;
		border-radius: 5px;
		cursor: pointer;
	}

	button:hover {
		background-color: #333;
	}
</style>

Trying out

This should be the UI generated above. And we can fill up the required fields, and then try to submit.

Contact Us Form

After some time, the following should be the message you’ll recieved after the submission.

Mail Recieved

There you go! You should get the same expected behavior above. You could use Microsoft’s outlook’s App Passwords, or Looking into Google’s Oauth2 for sending mail. You could extend this further too by customizing what the body of the email looks like.