An attempt to retrieve information from the app/api/sendmail/route.ts endpoint returns a 405 method not permitted error in Nextjs version 14.1

Encountering an issue with a POST request while trying to submit a form in my application using Nextjs 14.1.0 and TypeScript. The form is being submitted via fetch to a serverless function (sendemail.ts) for Nodemailer. I've confirmed that the URL is correct (no more 404 errors) and checked the server-side code for handling POST requests. Upon network inspection, it shows a 405 method not allowed error. I am looking for help in identifying and fixing this issue. Any insights or assistance 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: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3054455d5d4970575d51595c1e535f5d">[email protected]</a>",
          pass: "*****",
        },
      });

      // Send email
      await transporter.sendMail({
        from: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f094859d9d89b0979d91999cde939f9d">[email protected]</a>", 
        to: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="04607169697d446369656d682a676b69">[email protected]</a>", 
        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" });
  }
}

Answer №1

It seems like you're combining the usage of app router (new router) and pages router (old router).

With the pages router, you could create a file within the pages/api directory like pages/api/send-mail.js where you can write the same code provided in the second code block. You can then make requests to it using

fetch("/api/send-mail")

However, with the introduction of the app router in NextJS version 13.4, you can create a file similar to what you've already done: app/api/send-mail/route.js (you can name the api folder differently if needed). In this case, you would export functions named after the HTTP 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
        })
    }
}

To learn more about route handlers, you can refer to the official documentation (https://nextjs.org/docs/app/building-your-application/routing/route-handlers)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In Angular 12, encountering the error "Unable to bind to 'formGroup' as it is not a recognized property of 'form'" is not uncommon

Encountering a problem that seems to have been addressed previously. Error: Can't bind to 'formGroup' since it isn't a known property of 'form'. I followed the steps by importing ReactiveFormsModule and FormsModule in the req ...

A guide on showing an image from a JSON file path

As a beginner in Angular, I am currently working with Angular 8. I have a list of image paths stored in the 'dataSource' variable in JSON format, like so: hotdeals: Array(4) 0: {uri: "/Home/HotDeals/hotdeal1.png", id: "2"} 1: {uri: "/Ho ...

I possess a function that can retrieve the key of an Object, but now I am faced with the task of accessing the actual Object using this value in JavaScript

This is my first time seeking advice on a technical issue. I'm currently working with the following function: export function sendRequest<T>(req: RawRequest, options) { const start = Date.now(); const reqOptions: CoreOptions = { ...

Arranging an array of arrays based on the mm/dd/yyyy date field

Currently, I am facing an issue while attempting to sort data obtained from an API by date in the client-side view. Here is an example of the data being received: address: "1212 Test Ave" address2: "" checkNumber : "" city: "La Grange" country: "" email: ...

How can I correctly annotate property 'firebase' on type '{ children?: ReactNode; }' in order to resolve the error?

My firebase object is provided through a higher order component as shown below: const FirebaseContextInterfaceLocal: FirebaseContextInterface = { value: new Firebase() } ReactDOM.render( <Router history={history}> <FirebaseContext.Provi ...

Using typescript, we can pass a generic class as a parameter to a function

Currently, I am faced with the challenge of passing a class reference as a function parameter, and then calling a static method on this particular class. Additionally, there is a possibility that in the future, I may need to instantiate the class and inclu ...

Transferring a webm blob to node.js and storing it securely on the server

Struggling to save an incoming webm blob on the server. Utilizing react-video-recorder with NextJS like this: <VideoRecorder onRecordingComplete={(videoBlob) => { // Do something with the video... fetch(& ...

Having trouble converting the response into a valid TypeScript value for storage

These are the interfaces I have described: enum ProductType {current, closed, coming} export interface CurrentProductForCarousel { type_product:ProductType.current; offers: ProductMainInfo[] } export interface ProductMainInfo { id: number; disclai ...

Loop through a collection of map instances in TypeScript

In my TypeScript code, I am making a call to an API method in a Java class that returns a list of maps. The TypeScript file includes the code snippet below. When attempting to retrieve data from dataBody, it displays as [Object Object]. I need assistance ...

Encountering crashes while initializing the router in the constructor of a service in Angular 4.3

I've been scratching my head over this problem. It seems like I'm overlooking something simple. Let me show you what's inside my home.component.ts file: import { Component, OnInit } from '@angular/core'; import { AuthService } f ...

Having difficulty in maintaining a function's parameter interface while utilizing React.useContext()?

After recently starting to use TypeScript, I noticed an issue with the compiler not enforcing the shape of data a function accepts when accessed through React.useContext(). Although the setup here is not an exact representation of my situation, it highlig ...

Encountering an error with ResizeObserver.observe when using Next.js and ag-grid to render client side

I designed a product page that includes a searchbar component and a grid component with the ag-grid import and setup. Here is a simplified version of the product page: // Code for dynamic client side rendering import const ProductGrid = dynamic(() => ...

Prevent Event Bubbling in Next.js for a Link Element within a Nested Component

I'm encountering an issue with clickable tiles on my site. These tiles have a button inside that should direct the user to an internal page, while clicking anywhere else on the tile should send them to an external page. However, I'm facing a prob ...

ReactiveX: Continuous flow of modal dialogs

My challenge is to display multiple bootstrap popups sequentially to the user, each containing a stream of messages. However, if I simply subscribe and show the messages one after the other, it might not wait for the user to dismiss a popup before showing ...

Angular 7 ERROR: The SystemJS reference is missing

In the process of developing an Angular 7 project with systemjs for dynamic module loading, I encountered an issue. Upon attempting to utilize it, I encountered the following error: ERROR ReferenceError: SystemJS is not defined Within my package.json f ...

What is the rationale behind placing the CSS outside of the React function components, near the imports?

Recently, I encountered an issue with loading CSS inside a React function component using Material UI. Even though I managed to resolve it, I am still intrigued by the underlying reason. Initially, I had something like this setup where I placed both makeSt ...

Designing a platform for dynamic components in react-native - the ultimate wrapper for all elements

export interface IWEProps { accessibilityLabel: string; onPress?: ((status: string | undefined) => void) | undefined; localePrefix: string; children: JSX.Element[]; style: IWEStyle; type?: string; } class WrappingElement extends React.Pure ...

Ways to decline requests using interceptors depending on the content of the request?

Is there a way to achieve a status of 200 and stop the controller call if a certain key in the request payload meets my criteria? I've implemented Interceptors in my application, but I'm struggling to send a status of "200" without causing an ex ...

I am interested in understanding the significance of importing `Footer` before `components/Menu` in terms of import order

What is the reason behind this happening? ./pages/index.tsx 3:1 Error: The import of components/Footer/Footer should come before the import of components/Menu. This relates to import order. ...

Alphabetically sorting objects in an array using Angular

If your TypeScript code looks something like this: items: { size: number, name: string }[] = []; ngOnInit(): void { this.items = [ { size: 3, name: 'Richard' }, { size: 17, name: 'Alex' }, ...