Email marketing V2
This commit is contained in:
@@ -26,11 +26,22 @@ export const authOptions: NextAuthOptions = {
|
||||
where: { email: credentials.email },
|
||||
});
|
||||
|
||||
if (!user || !user.password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isPasswordValid = await comparePassword(
|
||||
if (!user || !user.password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Existing legacy accounts may not have this field populated. New
|
||||
// password signups have a pending verification token until they
|
||||
// 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() } },
|
||||
select: { token: true },
|
||||
});
|
||||
if (pendingVerification) return null;
|
||||
}
|
||||
|
||||
const isPasswordValid = await comparePassword(
|
||||
credentials.password,
|
||||
user.password
|
||||
);
|
||||
@@ -83,4 +94,4 @@ export const authOptions: NextAuthOptions = {
|
||||
error: '/login',
|
||||
},
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -561,6 +561,20 @@ function createSmtpTransport() {
|
||||
|
||||
const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://www.qrmaster.net';
|
||||
|
||||
export async function sendEmailVerificationEmail(email: string, name: string, verificationUrl: string) {
|
||||
const transport = createSmtpTransport();
|
||||
const firstName = name.trim().split(/\s+/)[0] || 'there';
|
||||
|
||||
await transport.sendMail({
|
||||
from: 'Timo from QR Master <timo@qrmaster.net>',
|
||||
replyTo: 'support@qrmaster.net',
|
||||
to: email,
|
||||
subject: 'Confirm your QR Master email address',
|
||||
html: `<!doctype html><html><body style="margin:0;background:#f5f4ef;color:#1b1c19;font-family:Arial,sans-serif;"><table role="presentation" width="100%" cellspacing="0" cellpadding="0"><tr><td align="center" style="padding:32px 12px;"><table role="presentation" width="600" cellspacing="0" cellpadding="0" style="width:100%;max-width:600px;background:#fff;"><tr><td style="padding:20px 32px;border-bottom:1px solid #e3e3de;font-size:11px;font-weight:bold;letter-spacing:2px;">QR MASTER</td></tr><tr><td style="padding:36px 32px;"><h1 style="margin:0 0 18px;font-family:Georgia,serif;font-size:30px;font-weight:normal;line-height:1.2;">Confirm your email address</h1><p style="margin:0;font-size:16px;line-height:1.65;">Hi ${escapeHtml(firstName)},</p><p style="font-size:16px;line-height:1.65;">Click the button below to finish creating your QR Master account.</p><a href="${verificationUrl}" style="display:inline-block;margin:10px 0 22px;background:#0047ff;color:#fff;padding:14px 22px;text-decoration:none;font-size:14px;font-weight:bold;">CONFIRM EMAIL</a><p style="margin:0;color:#747878;font-size:13px;line-height:1.6;">This link expires in 24 hours. If you did not create an account, you can ignore this email.</p></td></tr></table></td></tr></table></body></html>`,
|
||||
text: `Hi ${firstName},\n\nConfirm your QR Master email address: ${verificationUrl}\n\nThis link expires in 24 hours.`,
|
||||
});
|
||||
}
|
||||
|
||||
/** Marketing announcement with a per-recipient, functional unsubscribe link. */
|
||||
export async function sendDesignerAnnouncementEmail(email: string, unsubscribeUrl: string) {
|
||||
await waitForRateLimit();
|
||||
|
||||
Reference in New Issue
Block a user