不正确"/>
函数调用不正确
我正在开发一个 React 应用程序,我想向我创建的用户发送一封包含随机生成密码的电子邮件,以便他可以访问他的网站。我关注了一些 youtube 视频并在后端设置了 server.js 和 sendEmail 函数。我测试了关于 insomnia 的 API 请求,邮件已成功发送。当我单击添加用户按钮时返回前端应用程序,用户将在 firestore 中创建,但尚未发送任何电子邮件。
我的问题 是没有调用 sendEmail 函数,我尝试了很多解决方案,但仍然没有任何改变。任何人都可以为我找出错误吗?谢谢。
这是控制台中显示的error:
Error sending email:
Object { stack: "AxiosError@http://localhost:3000/static/js/bundle.js:365235:18\nhandleAbort@http://localhost:3000/static/js/bundle.js:364614:14\nEventHandlerNonNull*dispatchXhrRequest@http://localhost:3000/static/js/bundle.js:364610:5\n./node_modules/axios/lib/adapters/xhr.js/__WEBPACK_DEFAULT_EXPORT__<@http://localhost:3000/static/js/bundle.js:364530:10\ndispatchRequest@http://localhost:3000/static/js/bundle.js:365713:10\nrequest@http://localhost:3000/static/js/bundle.js:365152:77\nhttpMethod@http://localhost:3000/static/js/bundle.js:365186:19\nwrap@http://localhost:3000/static/js/bundle.js:366285:15\nsendEmail@http://localhost:3000/static/js/bundle.js:752:76\n./src/Admin/components/AddUser.jsx/AddUser/onSubmit/</<@http://localhost:3000/static/js/bundle.js:792:20\npromise callback*./src/Admin/components/AddUser.jsx/AddUser/onSubmit/<@http://localhost:3000/static/js/bundle.js:790:126\npromise callback*onSubmit@http://localhost:3000/static/js/bundle.js:772:149\n./node_modules/formik/dist/formik.esm.js/useFormik/executeSubmit<@http://localhost:3000/static/js/bundle.js:51616:12\n./node_modules/formik/dist/formik.esm.js/useEventCallback/<@http://localhost:3000/static/js/bundle.js:51898:24\n./node_modules/formik/dist/formik.esm.js/useFormik/submitForm</<@http://localhost:3000/static/js/bundle.js:51539:32\npromise callback*./node_modules/formik/dist/formik.esm.js/useFormik/submitForm<@http://localhost:3000/static/js/bundle.js:51517:43\n./node_modules/formik/dist/formik.esm.js/useEventCallback/<@http://localhost:3000/static/js/bundle.js:51898:24\n./node_modules/formik/dist/formik.esm.js/useFormik/handleSubmit<@http://localhost:3000/static/js/bundle.js:51596:5\n./node_modules/formik/dist/formik.esm.js/useEventCallback/<@http://localhost:3000/static/js/bundle.js:51898:24\ncallCallback@http://localhost:3000/static/js/bundle.js:61559:18\ninvokeGuardedCallbackDev@http://localhost:3000/static/js/bundle.js:61603:20\ninvokeGuardedCallback@http://localhost:3000/static/js/bundle.js:61660:35\ninvokeGuardedCallbackAndCatchFirstError@http://localhost:3000/static/js/bundle.js:61674:29\nexecuteDispatch@http://localhost:3000/static/js/bundle.js:65818:46\nprocessDispatchQueueItemsInOrder@http://localhost:3000/static/js/bundle.js:65844:26\nprocessDispatchQueue@http://localhost:3000/static/js/bundle.js:65855:41\ndispatchEventsForPlugins@http://localhost:3000/static/js/bundle.js:65864:27\n./node_modules/react-dom/cjs/react-dom.development.js/dispatchEventForPluginEventSystem/<@http://localhost:3000/static/js/bundle.js:66024:16\nbatchedUpdates$1@http://localhost:3000/static/js/bundle.js:80416:16\nbatchedUpdates@http://localhost:3000/static/js/bundle.js:61407:16\ndispatchEventForPluginEventSystem@http://localhost:3000/static/js/bundle.js:66023:21\ndispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay@http://localhost:3000/static/js/bundle.js:63529:42\ndispatchEvent@http://localhost:3000/static/js/bundle.js:63523:88\ndispatchDiscreteEvent@http://localhost:3000/static/js/bundle.js:63500:22\nEventListener.handleEvent*addEventBubbleListener@http://localhost:3000/static/js/bundle.js:63722:14\naddTrappedEventListener@http://localhost:3000/static/js/bundle.js:65946:33\nlistenToNativeEvent@http://localhost:3000/static/js/bundle.js:65890:30\n./node_modules/react-dom/cjs/react-dom.development.js/listenToAllSupportedEvents/<@http://localhost:3000/static/js/bundle.js:65901:34\nlistenToAllSupportedEvents@http://localhost:3000/static/js/bundle.js:65896:25\ncreateRoot@http://localhost:3000/static/js/bundle.js:83179:33\ncreateRoot$1@http://localhost:3000/static/js/bundle.js:83525:14\n./node_modules/react-dom/client.js/exports.createRoot@http://localhost:3000/static/js/bundle.js:83601:16\n./src/index.js@http://localhost:3000/static/js/bundle.js:6036:60\noptions.factory@http://localhost:3000/static/js/bundle.js:373603:31\n__webpack_require__@http://localhost:3000/static/js/bundle.js:373049:33\n@http://localhost:3000/static/js/bundle.js:374185:56\n@http://localhost:3000/static/js/bundle.js:374187:12\n", message: "Request aborted", name: "AxiosError", code: "ECONNABORTED", config: {…}, request: XMLHttpRequest }
这些是代码:
Server.js
const dotenv = require("dotenv").config();
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const sendEmail = require("./utils/sendEmail");
const app = express();
// Middleware
app.use(express.json());
app.use(bodyParser.json());
app.use(cors());
// Route
app.get("/", (req, res) => {
res.send("Home Page");
});
app.post("/api/sendemail", async (req, res) => {
const { email } = req.body;
try {
const send_to = email;
const sent_from = "**********@gmail";
const reply_to = email;
const subject = "Testing nodemailer";
const message = `
<h3>Hello</h3>
<p>This is a test</p>
<p>Regards...</p>
`;
await sendEmail(subject, message, send_to, sent_from, reply_to);
res.status(200).json({ success: true, message: "Email Sent" });
} catch (error) {
res.status(500).json(error.message);
}
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}...`);
});
发送电子邮件.js
const nodemailer = require("nodemailer");
const sendEmail = async (subject, message, send_to, sent_from) => {
const transporter = nodemailer.createTransport({
host: "smtp.gmail",
port: "587",
auth: {
user: "******@gmail",
pass: "**********",
},
tls: {
rejectUnauthorized: false,
},
});
const mailOpt = {
from: sent_from,
to: send_to, //values.email,
subject: subject,
html: message,
};
transporter.sendMail(mailOpt, (error, info) => {
if (error) {
console.log(error);
} else {
console.log("email sent: " + info.response);
}
});
};
module.exports = sendEmail;
AddUser.jsx
import React from "react";
import { useFormik } from "formik";
import { TfiPlus } from "react-icons/tfi";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "../../Firebase";
import { addDoc } from "firebase/firestore";
import { usersRef } from "../../Firebase";
import axios from "axios";
const AddUser = (props) => {
const generatePassword = () => {
const length = 10;
const charset =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let pwd = "";
for (let i = 0; i < length; i++) {
pwd += charset.charAt(Math.floor(Math.random() * charset.length));
}
return pwd;
};
const sendEmail = async (email) => {
//e.preventDefault();
const data = {
email,
};
try {
const response = await axios.post(
"http://localhost:5000/api/sendemail",
data
);
console.log("Email sent successfully:", response);
} catch (error) {
console.error("Error sending email:", error);
}
};
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
email: "",
company: "",
jobTitle: "",
country: "",
phone: "",
role: "",
},
onSubmit: (values) => {
console.log(values);
const pwd = generatePassword();
createUserWithEmailAndPassword(auth, values.email, pwd)
.then((userCredential) => {
const user = userCredential.user;
const userDoc = {
uid: user.uid,
firstName: values.firstName,
lastName: values.lastName,
email: values.email,
company: valuespany,
jobTitle: values.jobTitle,
country: values.country,
phone: values.phone,
role: values.role,
};
/*addDoc(usersRef, userDoc).then(() => {
window.location.reload(false);
});*/
addDoc(usersRef, userDoc).then(() => {
console.log("User added to Firestore:", userDoc);
sendEmail(values.email);
window.location.reload(false);
});
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.error("Error adding user to Firestore:", error);
});
},
});
const options = ["admin", "client", "human resources", "webmaster"];
return (
<form
onSubmit={formik.handleSubmit}
className="border-t border-gray-200 grid grid-cols-1 md:grid-cols-2 px-8 pb-4 gap-y-3"
>
<div>
<label className="justify label">
<span className="label-text">First Name</span>
</label>
<input
id="firstName"
name="firstName"
placeholder="First Name"
className="input input-primary input-bordered w-full max-w-xs"
type="text"
onChange={formik.handleChange}
value={formik.values.firstName}
/>
</div>
<div>
<label className="justify label">
<span className="label-text">Last Name</span>
</label>
<input
id="lastName"
name="lastName"
placeholder="Last Name"
className="input input-primary input-bordered w-full max-w-xs"
type="text"
onChange={formik.handleChange}
value={formik.values.lastName}
/>
</div>
<div>
<label className="justify label">
<span className="label-text">Email</span>
</label>
<input
id="email"
name="email"
placeholder="Email"
className="input input-primary input-bordered w-full max-w-xs"
type="text"
onChange={formik.handleChange}
value={formik.values.email}
/>
</div>
<div>
<label className="justify label">
<span className="label-text">Company</span>
</label>
<input
id="company"
name="company"
placeholder="Company"
className="input input-primary input-bordered w-full max-w-xs"
type="text"
onChange={formik.handleChange}
value={formik.valuespany}
/>
</div>
<div>
<label className="justify label">
<span className="label-text">Job Title</span>
</label>
<input
id="jobTitle"
name="jobTitle"
placeholder="Job Title"
className="input input-primary input-bordered w-full max-w-xs"
type="text"
onChange={formik.handleChange}
value={formik.values.jobTitle}
/>
</div>
<div>
<label className="justify label">
<span className="label-text">Country</span>
</label>
<input
id="country"
name="country"
placeholder="Country"
className="input input-primary input-bordered w-full max-w-xs"
type="text"
onChange={formik.handleChange}
value={formik.values.country}
/>
</div>
<div>
<label className="justify label">
<span className="label-text">Phone</span>
</label>
<input
id="phone"
name="phone"
placeholder="Phone"
className="input input-primary input-bordered w-full max-w-xs"
type="number"
onChange={formik.handleChange}
value={formik.values.phone}
/>
</div>
<div>
<div className="form-control w-full max-w-xs">
<label className="justify-start label">
<span className="label-text">Role</span>
</label>
<select
id="role"
name="role"
className="select select-primary select-bordered"
type="text"
options={options}
onChange={formik.handleChange}
value={formik.values.role}
>
<option selected>--Select role--</option>
{options.map((option) => {
return <option>{option}</option>;
})}
</select>
</div>
</div>
<div className="col-span-2 flex">
<button className="btn btn-primary ml-auto" type="submit">
<TfiPlus className="mr-2" />
Add user
</button>
</div>
</form>
);
};
export default AddUser;
回答如下:
更多推荐
函数调用不正确
发布评论