邮件在 next.js 项目的部署中不起作用

问题描述 投票:0回答:1

将正在开发但未在生产/部署的作品邮寄到 VERCEL 我创建了一个 Tsx 组件,用于在 Next.js 应用程序中发送电子邮件,如下所示:

import React from "react";
import { useForm, SubmitHandler } from "react-hook-form";
import { PhoneIcon, MapPinIcon, EnvelopeIcon } from "@heroicons/react/24/solid";
import { useState } from "react";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { PageInfo } from "../typing";

type Props = {
  adressContact: PageInfo;
};

type Inputs = {
  name: string;
  email: string;
  subject: string; 
  content: string;
};

export default function ContactMe({ adressContact }: Props) {
  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<Inputs>();

  //state
  const [isLoading, setIsLoading] = useState(false);

  const onSubmit: SubmitHandler<Inputs> = async (formData) => {
      console.log(formData);
    if (!isLoading) {
      setIsLoading(true);
      const response = await fetch("/api/contact", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(formData),

      });

      const result = await response.json();

      setIsLoading(false);
      if (!response.ok) {
        console.log("error sending email:", result);
      } else {
        reset();
        toast.success("I have received your message!", {
          position: "top-right",
          autoClose: 5000,
          hideProgressBar: false,
          closeOnClick: true,
          pauseOnHover: true,
          draggable: true,
          progress: undefined,
          theme: "colored",
        });
        console.log("ok");
      }
      return result;
    }


  };

  return (
    <div className="h-screen flex relative flex-col text-center md:text-left  max-w-7xl 
       px-10 justify-evenly mx-auto items-center ">
      <h3 className="uppercase tracking-widest text-teal-400 text-2xl ">
        Contact
      </h3>
      <h2 className="text-xl md:text-2xl lg:text-4xl font-semibold text-center">
        I have got just what you need?{" "}
        <span className=" decoration-teal-500/50 underline">
          Let &lsquo;s Talk{" "}
        </span>
      </h2>
      <div className="flex-col space-y-2">

        <div className="flex space-x-5 justify-start">
          <PhoneIcon className="text-teal-500 h-7 w-7 animate-pulse" />
          <p className=" text-base md:text-2xl">{adressContact.phoneNumber}</p>
        </div>
        <div className="flex  space-x-5 justify-start">
          <EnvelopeIcon className="text-teal-500 h-7 w-7 animate-pulse" />
          <p className=" text-base md:text-2xl">
            {adressContact.email}
          </p>
        </div>
        <div className="flex  space-x-5 justify-start">
          <MapPinIcon className="text-teal-500 h-7 w-7 animate-pulse" />
          <p className="text-base md:text-2xl">
            {adressContact.address}
          </p>
        </div>
      </div>
      <form
        onSubmit={handleSubmit(onSubmit)}
        className="flex flex-col space-y-2 w-11/12 md:w-auto mx-auto "
      >
        <div className=" flex space-x-2">
          <input
            {...register("name", { required: true })}
            id="name"
            placeholder="Name"
            className="contactInput w-1/3"
            type="text"
          />
          {errors.name && (
            <p className="text-yellow-400">Please,enter your name</p>
          )}
          <input
            {...register("email", { required: true })}
            id="email"
            placeholder="Email"
            className="contactInput w-2/3"
            type="email"
          />
          {errors.email && (
            <p className="text-yellow-400">Please, enter your email</p>
          )}
        </div>

        <input
          {...register("subject")}
          id="subject"
          placeholder="Subject"
          className="contactInput"
          type="text"
        />

        <textarea
          {...register("content", { required: true })}
          id="content"
          placeholder="Message"
          className="contactInput"
        />
        {errors.content && (
          <p className="text-yellow-400">
            You may have forget to write your message
          </p>
        )}
        {!isLoading && (
          <button
            type="submit"
            className="bg-teal-500 py-5 px-10 rounded-md text-white font-bold text-lg"
          >
            Submit
          </button>
        )}
        {
          isLoading && (
            <div className="flex items-center justify-center mt-auto">
             
                <svg className="animate-spin h-20 w-20" viewBox="0 0 24 24">
                  <circle className="opacity-25" cx="12" cy="12" r="10" 
                    stroke="currentColor" strokeWidth="4" />
                  <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8" 
                       stroke="currentColor" strokeWidth="4" />
                </svg>
              
            </div>)
        }
        <ToastContainer />
      </form>
    </div>

  );
}

这是我使用 nodemailer 发送它们的 api。

export default async function handler(req, res) {



 if (req.method !== "POST") {
    res.status(406).json({ message: "INVALID_METHOD" });
    return;
  } 

  // Check if the necessary properties exist in req.body
  if (!req.body || !req.body.name || !req.body.email || !req.body.content) {
    res.status(400).json({ message: "INVALID_PARAMETER" });
    return;
  }

  // Variables
  var name = req.body.name.toString();
  var email = req.body.email.toString();
  
  var form_subject = "";
  if (req.body.subject == null || req.body.subject == "") {
     form_subject = "sans objet";
  } else {
     form_subject = req.body.subject.toString();
  }

  var content = req.body.content.toString();


  if (!name || !email || !form_subject || !content) {
    res.status(400).json({ message: "INVALID_PARAMETER" });
    return;
  }

  // Syntaxe adresse email
  const pattern =/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0- 
  9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  
  if (!pattern.test(email)) {
    res.status(400).send({
      message: "EMAIL_SYNTAX_INCORRECT",
    });
    return;
  }

  // Transformer les retours à la ligne pour le HTML
  const message = content
    .replace(/\n/g, "<br>")
    .replace(/\r/g, "<br>")
    .replace(/\t/g, "<br>")
    .replace(/<(?!br\s*\/?)[^>]+>/g, ""); // supprime tout le html en autorisant 
    uniquement les balises <br>

  //INITIALISATION DE NODEMAILER
  const back_email = process.env.EMAIL;
  const back_pass = process.env.EMAIL_PASS;
  

  var nodemailer = require("nodemailer");

  const transporter = nodemailer.createTransport({
    port: 465,
    host: "smtp.gmail.com",
    auth: {
      user: back_email,
      pass: back_pass,
      clientId: process.env.CLIENT_ID,
      clientSecret: process.env.CLIENT_SECRET,
     /*  refreshToken: process.env.REFRESH_TOKEN,
      accessToken: process.env.ACCESS_TOKEN */
    },
    secure:true,
  });
  
 const mailData ={
  from: back_email,
  to: back_email,
  subject: form_subject,
  text: email,
  html: `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NodeMailer Email Template</title>
<style>
  .container {
  width: 100%;
  height: 100%;
  padding: 20px;
  background-color: #f4f4f4;
  }
  .email {
  width: 80%;
  margin: 0 auto;
  background-color: #fff;
  padding: 20px;
  }
  .email-header {
  background-color: #333;
  color: #fff;
  padding: 20px;
  text-align: center;
  }
  .email-body {
  padding: 20px;
  }
  .email-footer {
  background-color: #333;
  color: #fff;
  padding: 20px;
  text-align: center;
  }
</style>
</head>
<body>
<div class="container">
  <div class="email">
  <div class="email-header">
    <h1>MESSAGE DU PORTFOLIO</h1>
  </div>
  <div class="email-body">
    <p>${message}</p>
  </div>
  <div class="email-footer">
    <p>Expediteur:       ${name}<br>Email de l'expediteur :       ${email}</p>
  </div>
  </div>
</div>
</body>
</html>`,
}

await new Promise((resolve, reject) => {
    // verify connection configuration
    transporter.verify(function (error, success) {
        if (error) {
            console.log(error);
            reject(error);
        } else {
            console.log("Server is ready to take our messages");
            resolve(success);
        }
    });
  // send mail
  transporter.sendMail(mailData, (err, info) => {
      if (err) {
          console.error(err);
          reject(err);
      } else {
          console.log(info);
          resolve(info);
      }
  });
});

res.status(200).json({ status: "OK" });
}

它在开发服务器上运行得很好,但部署后总是出现“INVALID_METHOD”之类的错误。我意识到我在 api 代码中放置了错误检查条件。但为什么这些错误在开发中没有出现呢?我尝试解决它,console.log 身体数据,但一切似乎都很好。在 vercel 上部署它时我需要了解什么吗?我们将非常感谢您的帮助。谢谢,提前。

next.js vercel nodemailer react-hook-form
1个回答
0
投票

确认您还在 vercel 上添加了

.env

© www.soinside.com 2019 - 2024. All rights reserved.