繁体   English   中英

Nodemailer Nextjs Typescript 表单不发送电子邮件

[英]Nodemailer Nextjs Typescript form not sending emails

我正在使用Next.js TypescriptNodemailer开展个人项目。 这是我第一次使用Nodemailer 我在使它工作时遇到问题。 我正在关注本教程 这是我在下面的代码,因为它在教程中。

Nodemailer.ts :在这里我不得不替换any类型的APIResponse ,因为代码给了我错误, VSCode建议我在文件底部创建该函数。 此外,此文件的位置是/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 :它在/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;

目前我在浏览器网络上遇到错误 500,但是当我打开链接时,错误引用了Nodemailer.ts处理程序“ Begone ”的 404。 任何帮助都会非常感谢它。

安东回答后更新在此处输入图像描述

在此处输入图像描述

首先,您需要安装@types/nodemailer作为 devDependencies。

Form.tsx中,您尝试发送常规对象(类)而不是 JSON。 您必须使用JSON.stringify()序列化数据,还可以在此处添加标头 为简化起见,您可以直接将值(状态)放入 JSON.stringify() 并删除所有formData

表格.tsx

const response = await fetch('/api/nodemailer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name, email, mobile, message }), // Serialize JSON
});

我删除了强大的Promise()函数,因为我们从处理函数和req.body 接收和处理所有数据。

节点邮件程序.ts

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

type Fields = {
  name: string;
  message: string;
  mobile: string;
  email: string;
};

type Response = {
  error?: string;
  status?: string;
  message?: 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 = async (req: NextApiRequest, res: NextApiResponse<Response>) => {
  const { name, email, message } = req.body as Fields;

  if (req.method !== 'POST') {
    return res.status(404).send({ status: 'fail', error: 'Begone.' });
  }

  try {
    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).send({ status: 'done', message: 'message has been sent' });
  } catch (error) {
    res.status(500).send({ status: 'fail', error: `${error}` });
  }
};

export default handler;

这适用于我的 nodemailer Gmail选项。

使用export const config = {api: {bodyParser: false}}

在此处输入图像描述

没有

在此处输入图像描述

凭据问题:错误:缺少“LOGIN”/“PLAIN”的凭据

在此处输入图像描述

我有LOGIN而不是PLAIN因为我的.env中有其他值,你需要检查你的.env 如果没问题,在第二步中,创建一个应用密码,因为您不能使用与登录相同的密码。

如何设置应用密码Gmail , Hotmail

此外,您可以在此处找到有关“PLAIN”缺少凭据的答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM