我使用表单通过 emailjs 验证电子邮件,将电子邮件值发送到 next.js API。在 API route.js 中,我创建并散列令牌,将其存储在数据库中并创建确认链接(到目前为止,console.logs 告诉我一切正常),然后在 sendEmail 中(我以另一种形式使用它,它有效)我收到的功能:“电子邮件发送失败:未定义 投资组合3d-nextjs-app-1 |发送电子邮件失败: 错误:发送电子邮件失败 投资组合3d-nextjs-app-1 | 在 sendEmail (webpack-内部:". 另一个信息是我使用 Docker 映像来运行我的项目。 有人可以给我建议如何解决这个问题吗?
'use client';
import React from 'react';
import { useForm } from 'react-hook-form';
import { Toaster, toast } from 'sonner';
import { MailCheck, MailX } from 'lucide-react';
export default function EmailConfirmationForm() {
const { register, handleSubmit, formState: { errors }, reset } = useForm();
// Send confirmation email
const handleSendConfirmationEmail = async (email) => {
try {
const response = await fetch(`/api/sendConfirmationEmail?email=${email}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
});
if (!response.ok) throw new Error('Failed to send confirmation email');
toast.success('Confirmation email sent!', {
duration: 5000,
icon: <MailCheck />,
style: {
backgroundColor: '#1B1B1B',
border: 'none',
},
});
return true;
} catch (error) {
toast.error('Failed to send confirmation email.', {
duration: 5000,
icon: <MailX />,
style: {
backgroundColor: '#1B1B1B',
border: 'none',
},
});
return false;
}
};
const onSubmit = async (data) => {
try {
await handleSendConfirmationEmail(data.email);
reset();
} catch (error) {
console.error('Failed to send confirmation email:', error);
}
};
return (
<>
<Toaster position="bottom-left" richColors />
<form onSubmit={handleSubmit(onSubmit)} className="max-w-md w-full flex flex-col items-center justify-center space-y-4">
{/* Email input */}
<label htmlFor="email" className="self-start">Email Confirmation</label>
<input
id="email"
type="email"
placeholder="Email Confirmation"
{...register("email", {
required: 'This field is required',
pattern: { value: /^\S+@\S+$/i, message: 'Invalid email format' }
})}
className="w-full p-2 rounded-md shadow-lg text-foreground focus:outline-none focus:ring-2 focus:ring-accent/50 custom-bg"
aria-label="Email"
/>
{errors.email && <span className="inline-block self-start text-red-500">{errors.email.message}</span>}
<input
value="Cast your message!"
className="px-10 py-4 rounded-md shadow-lg bg-background border border-accent/30 hover:shadow-glass-sm backdrop-blur-sm text-foreground focus:outline-none focus:ring-2 focus:ring-accent/50 cursor-pointer capitalize"
type="submit"
/>
</form>
</>
);
}
import { NextResponse } from 'next/server';
import { sendEmail } from '@/app/../../service/service.email';
import redisClient, { connectRedis } from '@/app/../../service/redisClient';
import { generateToken, hashToken } from '@/app/../../service/tokenService';
import { rateLimiter } from '@/app/../../service/rateLimiter';
export async function POST(req) {
const { searchParams } = new URL(req.url);
const email = searchParams.get('email');
const ip = req.headers.get('x-forwarded-for') || req.socket.remoteAddress || req.ip;
// if (!rateLimiter(ip)) {
// return NextResponse.json({ message: 'Too many requests, please try again later.' }, { status: 429 });
// }
await connectRedis();
const token = generateToken();
const hashedToken = await hashToken(token);
const expiresAt = Date.now() + 3600 * 1000;
try {
await redisClient.setEx(`confirm_tokens:${hashedToken}`, 3600, JSON.stringify({ email, expiresAt }));
const storedToken = await redisClient.get(`confirm_tokens:${hashedToken}`);
console.log('Token stored in Redis:', storedToken); // Log to verify storage
} catch (redisError) {
console.error('Error saving token in Redis:', redisError);
return NextResponse.json({ message: 'Error saving confirmation token to Redis.' }, { status: 500 });
}
const confirmationLink = `${process.env.NEXT_PUBLIC_APP_URL}/api/confirmEmail?token=${token}&email=${email}`;
console.log(`Confirmation link: ${confirmationLink}`);
try {
const templateParams = {
to: email,
from_name: 'Email Confirmation',
reply_to: email,
message: `Please confirm your email by clicking the link: ${confirmationLink}`,
};
await sendEmail(templateParams);
return NextResponse.json({ message: 'Confirmation email sent!' }, { status: 200 });
} catch (error) {
console.error('Failed to send email:', error);
return NextResponse.json({ message: 'Failed to send confirmation email.' }, { status: 500 });
}
}
import emailjs from '@emailjs/browser';
export const sendEmail = async (params) => {
try {
const response = await emailjs.send(
process.env.NEXT_PUBLIC_SERVICE_ID,
process.env.NEXT_PUBLIC_TEMPLATE_ID,
params,
{
publicKey: process.env.NEXT_PUBLIC_PUBLIC_KEY,
limitRate: {
throttle: 5000,
},
}
);
console.log('Email sent successfully:', response);
return response;
} catch (error) {
console.error('Email send failed:', error.text);
if (error.response) {
console.error('Error response from email service:', error.response);
}
throw new Error(error.text || 'Failed to send email');
}
};
我认为您正在服务器端“@emailjs/browser”上使用此节点包。虽然这仅用于客户端。 请在服务器端代码上使用此包https://www.npmjs.com/package/@emailjs/nodejs。