I am working on a personal project with Next.js
Typescript
and Nodemailer
. It is my first time using Nodemailer
. I am having issues making it work. I am following this tutorial. This is my code below as it is on the tutorial.
Nodemailer.ts
: here I had to replace the type APIResponse
for any
due to the code gave me errors, and VSCode
suggested me to create that function at the bottom of the file. Also, the location of this file is /pages/api/nodemailer.ts
import { NextApiHandler, NextApiRequest } from "next";
import nodemailer from "nodemailer";
type Fields = {
name: string;
message: string;
email: string;
};
const transporter = nodemailer.createTransport({
service: 'hotmail',
auth: {
user: process.env.NEXT_PUBLIC_EMAIL_ADDRESS,
pass: process.env.NEXT_PUBLIC_PASSWORD,
},
});
export const config = {
api: {
bodyParser: false,
},
};
const handler: NextApiHandler<any> = async(req, res) => {
if (req.method !== "POST") {
return res.status(404).send({ error: "Begone." });
}
res.setHeader("Content-Type", "application/json")
try {
const { fields } = await formidablePromise(req, {});
const { name, email, message } = fields;
if (!name || !name.trim()) {
throw new Error("Please provide a valid name.");
}
if (!email || !email.trim()) {
throw new Error("Please provide a valid email address.");
}
if (!message || !message.trim()) {
throw new Error("Please provide a valid email message.");
}
await transporter.sendMail({
to: 'info@someemail.com.au',
from: 'info@someemail.com.au',
replyTo: email,
subject: `Hello from ${name}`,
text: message,
html: `<p>${message.replace(/(?:\r\n|\r|\n)/g, "<br>")}</p>`,
});
res.status(200).json({});
} catch (error) {
res.status(500).json({ error: error });
}
}
export default handler;
function formidablePromise(req: NextApiRequest, arg1: {}): { fields: any; } | PromiseLike<{ fields: any; }> {
throw new Error("Function not implemented.");
}
Form.tsx
: It is in /components/Form.tsx
import { FaFacebook, FaTwitter } from 'react-icons/fa';
import React, { ChangeEvent, FormEvent, useRef, useState } from 'react';
import styles from './Form.module.css';
export interface FormProps {
result: boolean
isChecked: boolean
callTime: {time: string, isChecked: boolean}[]
loading: boolean
}
const Form: React.FC<FormProps> = () => {
const [loading, setLoading] = useState<boolean>(false)
const [name, setName] = useState<string>("");
const [email, setEmail] = useState<string>("");
const [mobile, setMobile] = useState<string | number | any>("");
const [message, setMessage] = useState<string>("");
console.log('NAme:', name, ', email', email, ', mobile', mobile, ', message', message);
async function sendEmail(event: FormEvent) {
event.preventDefault();
setLoading(true);
try {
const formData = new FormData();
if (!name.trim()) {
throw new Error("Please provide a valid name.");
}
if (!email.trim()) {
throw new Error("Please provide a valid email address.");
}
if (!mobile.trim()) {
throw new Error("Please provide a valid mobile number.");
}
if (!message.trim()) {
throw new Error("Please provide a valid message.");
}
formData.append("name", name);
formData.append("email", email);
formData.append("mobile", mobile);
formData.append("message", message);
console.log('form data', formData);
const response = await fetch("/api/nodemailer", {
method: "POST",
body: formData,
});
const responseData = await response.json();
console.log('form responseData', responseData);
if (responseData.error) {
throw new Error(responseData.error);
}
console.log("Thanks, we will be in touch soon!");
setName("");
setEmail("");
setMobile("");
setMessage("");
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
console.log('send email', sendEmail);
return (
<>
<div className={styles.wrapper}>
<form
onSubmit={sendEmail}
className={styles.formContainer}>
<h3>Get <span>in</span> touch</h3>
<label>Full Name<span className={styles.required}>*</span></label>
<input
type="text"
name="name"
required
value={name}
onChange={({ target }: ChangeEvent) => setName(( target as HTMLInputElement ).value)}
/>
<div className={styles.twoInputs}>
<div className={styles.innerInputs}>
<label>Email</label>
<input
type="email"
name="email"
pattern=".+@.+\..+"
value={email}
onChange={({ target }: ChangeEvent) => setEmail(( target as HTMLInputElement ).value)}
/>
</div>
<div className={styles.innerInputs}>
<label>Mobile<span className={styles.required}>*</span></label>
<input
type="tel"
name="tel"
required
value={mobile}
onChange={({ target }: ChangeEvent) => setMobile((target as HTMLInputElement ).value)} />
</div>
</div>
<label>Message<span className={styles.required}>*</span></label>
<textarea
name="message"
rows={6}
required
value={message}
maxLength={1000}
onChange={({ target }: ChangeEvent) => setMessage(( target as HTMLInputElement ).value)}
/>
<input type="submit" value="Send" />
<small><span className={styles.required}>*</span>Required</small>
</form>
</div>
</>
)
}
export default Form;
At the moment I having an error 500 on the browser network, but when I opened the link the error references to the 404 of the Nodemailer.ts
handler "Begone."
Any help would be much appreacciate it.