Email marketing V3
This commit is contained in:
@@ -15,6 +15,28 @@ import {
|
||||
} from '@/lib/revops';
|
||||
import { triggerLifecycleScoring } from '@/lib/revops-server';
|
||||
|
||||
async function issueVerificationEmail(user: { email: string; name: string | null }) {
|
||||
const verificationToken = crypto.randomBytes(32).toString('base64url');
|
||||
const verificationUrl = new URL('/api/auth/verify-email', process.env.NEXT_PUBLIC_APP_URL || 'https://www.qrmaster.net');
|
||||
verificationUrl.searchParams.set('token', verificationToken);
|
||||
|
||||
await db.verificationToken.deleteMany({ where: { identifier: user.email } });
|
||||
await db.verificationToken.create({
|
||||
data: {
|
||||
identifier: user.email,
|
||||
token: verificationToken,
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await sendEmailVerificationEmail(user.email, user.name ?? 'there', verificationUrl.toString());
|
||||
} catch (error) {
|
||||
await db.verificationToken.deleteMany({ where: { token: verificationToken } });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
// CSRF Protection
|
||||
@@ -63,6 +85,16 @@ export async function POST(request: NextRequest) {
|
||||
});
|
||||
|
||||
if (existingUser) {
|
||||
if (!existingUser.emailVerified && existingUser.password && await bcrypt.compare(password, existingUser.password)) {
|
||||
try {
|
||||
await issueVerificationEmail(existingUser);
|
||||
return NextResponse.json({ success: true, requiresEmailVerification: true, email: existingUser.email });
|
||||
} catch (emailError) {
|
||||
console.error('Email verification resend failed:', emailError);
|
||||
return NextResponse.json({ error: 'We could not send the confirmation email. Please try again.' }, { status: 503 });
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: 'User already exists' },
|
||||
{ status: 400 }
|
||||
@@ -96,25 +128,11 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
triggerLifecycleScoring(user.id, 'signup');
|
||||
|
||||
const verificationToken = crypto.randomBytes(32).toString('base64url');
|
||||
const verificationUrl = new URL('/api/auth/verify-email', process.env.NEXT_PUBLIC_APP_URL || 'https://www.qrmaster.net');
|
||||
verificationUrl.searchParams.set('token', verificationToken);
|
||||
|
||||
await db.verificationToken.deleteMany({ where: { identifier: user.email } });
|
||||
await db.verificationToken.create({
|
||||
data: {
|
||||
identifier: user.email,
|
||||
token: verificationToken,
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
// A confirmed address is required before the account can be used or receive campaigns.
|
||||
try {
|
||||
await sendEmailVerificationEmail(user.email, user.name ?? 'there', verificationUrl.toString());
|
||||
await issueVerificationEmail(user);
|
||||
} catch (emailError) {
|
||||
console.error('Email verification message failed:', emailError);
|
||||
await db.verificationToken.deleteMany({ where: { token: verificationToken } });
|
||||
await db.user.delete({ where: { id: user.id } });
|
||||
return NextResponse.json({ error: 'We could not send the confirmation email. Please try again.' }, { status: 503 });
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export const authOptions: NextAuthOptions = {
|
||||
// confirm their email, and cannot sign in before doing so.
|
||||
if (!user.emailVerified) {
|
||||
const pendingVerification = await db.verificationToken.findFirst({
|
||||
where: { identifier: user.email, expires: { gt: new Date() } },
|
||||
where: { identifier: user.email },
|
||||
select: { token: true },
|
||||
});
|
||||
if (pendingVerification) return null;
|
||||
|
||||
Reference in New Issue
Block a user