Getban
Getban

Reputation: 41

Fetching from app/api/sendmail/route.ts produces a 405 method not allowed. Nextjs 14.1.0

Using Nextjs 14.1.0 typescript and facing issue with POST request when attempting to submit a form in my application using fetch to a serverless (Nodemailer) function (sendemail.ts). Verified correct URL (no more 404 error) and server-side code for handling POST requests. Network inspection shows 405 method not allowed. Seeking assistance in identifying and resolving the this error. Any insights would be greatly appreciated. Thank you!

contact.tsx

 const [submissionError, setSubmissionError] = useState<string | null>(null);

  const handleSubmit = async (
    values: typeof initialValues,
    { setSubmitting }: { setSubmitting: (isSubmitting: boolean) => void }
  ) => {
    try {
      const response = await fetch("/api/sendmail", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(values),
      });

      if (!response.ok) {
        throw new Error("Failed to submit form");
      }

      console.log("Form submitted successfully");
    } catch (error) {
      console.error("Error submitting form:", error);
      setSubmissionError("Failed to submit form. Please try again later.");
    } finally {
      setSubmitting(false);
    }
  };

route.ts


import { NextApiRequest, NextApiResponse } from "next";
import nodemailer from "nodemailer";

export async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "POST") {
    const { name, mobileNumber, email, option, requirements } = req.body;

    try {
      
      const transporter = nodemailer.createTransport({
        host: "smtp.gmail.com",
        port: 587,
        secure: false, 
        auth: {
          user: "[email protected]",
          pass: "*****",
        },
      });

      // Send email
      await transporter.sendMail({
        from: "[email protected]", 
        to: "[email protected]", 
        subject: "New Contact Form Submission", 
        text: `
          Name: ${name}
          Mobile Number: ${mobileNumber}
          Email: ${email}
          Option: ${option}
          Requirements: ${requirements}
        `, 
      });

      res.status(200).json({ success: true });
    } catch (error) {
      console.error("Error occurred while sending email:", error);
      res.status(500).json({ success: false, error: "Failed to send email" });
    }
  } else {
    res.status(405).json({ success: false, error: "Method Not Allowed" });
  }
}

Upvotes: 1

Views: 282

Answers (1)

Arash Jahan Bakhshan
Arash Jahan Bakhshan

Reputation: 1160

You are actually mixing the pattern of app router (new router) and pages router (old router).

In the pages router, we could create a file in pages/api folder such as pages/api/send-mail.js and we could write the same code that you've provided here (2nd code block) and then we could send our request to it fetch("/api/send-mail")

but in the app router which was introduced in NextJS version 13.4. We can create a file as you've already done: app/api/send-mail/route.js (we could name the api folder anything but api is more convenient). Then we export functions with the same name of the methods in UPPERCASE:

export const POST = (req: Request) => {
    const { name, mobileNumber, email, option, requirements } = await req.json()

    try {
        ...

        return Response.json({ success: true })
    } catch (e) {
        return new Response(JSON.stringify({ success: false }), {
            status: 500
        })
    }
}

You can read more about route handlers in the official documentation (https://nextjs.org/docs/app/building-your-application/routing/route-handlers)

Upvotes: 1

Related Questions