import { PrismaClient as PrismaClientAuth } from '../node_modules/.prisma/client-auth'; import { Resend } from 'resend'; import * as dotenv from 'dotenv'; import crypto from 'crypto'; dotenv.config(); const prismaAuth = new PrismaClientAuth({ datasourceUrl: process.env.DATABASE_URL_AUTH, }); const resend = new Resend(process.env.RESEND_API_KEY); async function checkAndResend() { try { console.log('šŸ” Checking users in database...\n'); // Find users that are not verified const unverifiedUsers = await prismaAuth.user.findMany({ where: { emailVerified: false, }, select: { id: true, email: true, name: true, emailConfirmationToken: true, emailConfirmationTokenExpiry: true, createdAt: true, }, orderBy: { createdAt: 'desc', }, }); if (unverifiedUsers.length === 0) { console.log('āœ… No unverified users found.'); console.log('\nšŸ“‹ All users:'); const allUsers = await prismaAuth.user.findMany({ select: { id: true, email: true, name: true, emailVerified: true, createdAt: true, }, orderBy: { createdAt: 'desc', }, }); allUsers.forEach(user => { console.log(` - ${user.email} (${user.name}) - Verified: ${user.emailVerified}`); }); return; } console.log(`Found ${unverifiedUsers.length} unverified user(s):\n`); for (const user of unverifiedUsers) { console.log(`šŸ“§ User: ${user.email} (${user.name})`); console.log(` Created: ${user.createdAt}`); console.log(` Has token: ${user.emailConfirmationToken ? 'Yes' : 'No'}`); if (user.emailConfirmationTokenExpiry) { const isExpired = user.emailConfirmationTokenExpiry < new Date(); console.log(` Token expires: ${user.emailConfirmationTokenExpiry} ${isExpired ? '(EXPIRED)' : ''}`); } console.log(''); } // Get the most recent unverified user const latestUser = unverifiedUsers[0]; console.log(`\nšŸ“¤ Attempting to resend confirmation email to: ${latestUser.email}\n`); // Generate new token if needed let token = latestUser.emailConfirmationToken; if (!token || (latestUser.emailConfirmationTokenExpiry && latestUser.emailConfirmationTokenExpiry < new Date())) { console.log('šŸ”„ Generating new confirmation token...'); token = crypto.randomBytes(32).toString('hex'); const tokenExpiry = new Date(); tokenExpiry.setHours(tokenExpiry.getHours() + 24); await prismaAuth.user.update({ where: { id: latestUser.id }, data: { emailConfirmationToken: token, emailConfirmationTokenExpiry: tokenExpiry, }, }); console.log('āœ… New token generated'); } // Send email const baseUrl = process.env.NEXTAUTH_URL || process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3001'; const confirmationUrl = `${baseUrl}/api/auth/verify-email?token=${token}`; const fromEmail = process.env.RESEND_FROM_EMAIL?.trim().replace(/^["']|["']$/g, '') || 'onboarding@resend.dev'; console.log(`šŸ“§ Sending email from: ${fromEmail}`); console.log(`šŸ“§ Sending email to: ${latestUser.email}`); console.log(`šŸ”— Confirmation URL: ${confirmationUrl}\n`); try { const result = await resend.emails.send({ from: fromEmail, to: latestUser.email, subject: 'Confirm your email address', html: ` Confirm your email

Confirm your email address

Hi ${latestUser.name},

You requested a new confirmation email. Please confirm your email address by clicking the button below:

Confirm Email Address

Or copy and paste this link into your browser:

${confirmationUrl}

This link will expire in 24 hours. If you didn't request this email, you can safely ignore it.

`, }); if (result.error) { console.error('āŒ Error from Resend API:'); console.error(' Status:', result.error.statusCode); console.error(' Message:', result.error.message); console.error(' Name:', result.error.name); if (result.error.message?.includes('domain')) { console.error('\nāš ļø IMPORTANT: Domain verification issue!'); console.error(' Resend\'s test domain (onboarding@resend.dev) can only send to:'); console.error(' - The email address associated with your Resend account'); console.error(' - To send to other addresses, you need to verify your own domain'); console.error(' - Go to: https://resend.com/domains to verify a domain'); } } else { console.log('āœ… Email sent successfully!'); console.log(' Email ID:', result.data?.id); console.log(`\nšŸ“¬ Check the inbox for: ${latestUser.email}`); console.log(' (Also check spam/junk folder)'); } } catch (error: any) { console.error('āŒ Error sending email:'); console.error(' Message:', error.message); if (error.response) { console.error(' Response:', JSON.stringify(error.response, null, 2)); } } } catch (error: any) { console.error('āŒ Error:', error.message); if (error.message?.includes('email_verified')) { console.error('\nāš ļø Database migration may not have been run!'); console.error(' Run: sudo -u postgres psql -d punimtag_auth -f migrations/add-email-verification-columns.sql'); } } finally { await prismaAuth.$disconnect(); } } checkAndResend();