create-auth-js-boiler
Version:
Create a new auth-js-boiler project
283 lines (262 loc) • 18.7 kB
text/typescript
import nodemailer from "nodemailer";
export const sendVerificationEmail = async (email: string, token: string) => {
const confirmLink = `${process.env.NEXTAUTH_URL}/auth/new-verification?token=${token}`;
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL,
pass: process.env.EMAIL_PASS_KEY,
},
});
// HTML email template with inline styles for maximum compatibility
const htmlContent = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Verify your email</title>
</head>
<body style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; font-size: 16px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%; background-color: #f6f6f6;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;"> </td>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;">
<div style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- HEADER -->
<div style="text-align: center; margin-bottom: 30px; margin-top: 30px;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top; padding-bottom: 20px; text-align: center;">
<h1 style="color: #03045e; font-size: 24px; font-weight: bold; margin: 0; margin-bottom: 8px;">Auth JS Boiler</h1>
<span style="color: #90a4ae; font-size: 14px;">Complete Authentication Solution</span>
</td>
</tr>
</table>
</div>
<!-- MAIN CONTENT -->
<div style="background: #ffffff; border-radius: 8px; padding: 30px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;">
<h2 style="color: #2b3a4a; font-size: 20px; font-weight: bold; margin: 0 0 20px;">Verify Your Email Address</h2>
<p style="font-family: sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #4a5568;">Thank you for registering. To complete your registration and access all features, please verify your email address.</p>
<p style="font-family: sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 24px; color: #4a5568;">This link will expire in 10 minutes.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; width: 100%; box-sizing: border-box;">
<tr>
<td align="center" style="font-family: sans-serif; font-size: 16px; vertical-align: top; padding-bottom: 16px;">
<a href="${confirmLink}" target="_blank" style="display: inline-block; color: #ffffff; background-color: #03045e; border-radius: 4px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: bold; margin: 0; padding: 12px 24px; border: none;">
Verify Email Address
</a>
</td>
</tr>
</table>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px; color: #718096;">If the button doesn't work, copy and paste this link into your browser:</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px; color: #718096;"><a href="${confirmLink}" style="color: #03045e; text-decoration: underline;">${confirmLink}</a></p>
</td>
</tr>
</table>
</div>
<!-- FOOTER -->
<div style="clear: both; margin-top: 24px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #9ca3af; font-size: 12px; text-align: center;">
<p style="margin: 0; margin-bottom: 5px;">This email was sent to ${email}</p>
<p style="margin: 0; margin-bottom: 5px;">If you didn't create an account, you can safely ignore this email.</p>
<p style="margin: 0; margin-bottom: 5px;">© ${new Date().getFullYear()} Auth JS Boiler. All rights reserved.</p>
</td>
</tr>
</table>
</div>
</div>
</td>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;"> </td>
</tr>
</table>
</body>
</html>
`;
// Send mail with defined transport object
await transporter.sendMail({
from: `"Auth JS Boiler" <${process.env.EMAIL}>`, // Formatted sender
to: email,
subject: "Verify Your Email Address",
text: `Thanks for signing up! Please verify your email by clicking this link: ${confirmLink}`,
html: htmlContent,
});
};
export const sendPasswordResetEmail = async (email: string, token: string) => {
const resetLink = `${process.env.NEXTAUTH_URL}/auth/new-password?token=${token}`;
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL,
pass: process.env.EMAIL_PASS_KEY,
},
});
// HTML email template with inline styles for maximum compatibility
const htmlContent = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Reset your password</title>
</head>
<body style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; font-size: 16px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%; background-color: #f6f6f6;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;"> </td>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;">
<div style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- HEADER -->
<div style="text-align: center; margin-bottom: 30px; margin-top: 30px;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top; padding-bottom: 20px; text-align: center;">
<h1 style="color: #03045e; font-size: 24px; font-weight: bold; margin: 0; margin-bottom: 8px;">Auth JS Boiler</h1>
<span style="color: #90a4ae; font-size: 14px;">Complete Authentication Solution</span>
</td>
</tr>
</table>
</div>
<!-- MAIN CONTENT -->
<div style="background: #ffffff; border-radius: 8px; padding: 30px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;">
<h2 style="color: #2b3a4a; font-size: 20px; font-weight: bold; margin: 0 0 20px;">Reset Your Password</h2>
<p style="font-family: sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #4a5568;">You recently requested to reset your password for your account. Click the button below to create a new password.</p>
<p style="font-family: sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 24px; color: #4a5568;">This link will expire in 10 minutes for security reasons.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; width: 100%; box-sizing: border-box;">
<tr>
<td align="center" style="font-family: sans-serif; font-size: 16px; vertical-align: top; padding-bottom: 16px;">
<a href="${resetLink}" target="_blank" style="display: inline-block; color: #ffffff; background-color: #03045e; border-radius: 4px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 16px; font-weight: bold; margin: 0; padding: 12px 24px; border: none;">
Reset Password
</a>
</td>
</tr>
</table>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px; color: #718096;">If the button doesn't work, copy and paste this link into your browser:</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px; color: #718096;"><a href="${resetLink}" style="color: #03045e; text-decoration: underline;">${resetLink}</a></p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px; color: #718096;">If you did not request a password reset, please ignore this email or contact support if you have concerns about your account.</p>
</td>
</tr>
</table>
</div>
<!-- FOOTER -->
<div style="clear: both; margin-top: 24px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #9ca3af; font-size: 12px; text-align: center;">
<p style="margin: 0; margin-bottom: 5px;">This email was sent to ${email}</p>
<p style="margin: 0; margin-bottom: 5px;">If you didn't request a password reset, you can safely ignore this email.</p>
<p style="margin: 0; margin-bottom: 5px;">© ${new Date().getFullYear()} Auth JS Boiler. All rights reserved.</p>
</td>
</tr>
</table>
</div>
</div>
</td>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;"> </td>
</tr>
</table>
</body>
</html>
`;
// Send mail with defined transport object
await transporter.sendMail({
from: `"Auth JS Boiler" <${process.env.EMAIL}>`, // Formatted sender
to: email,
subject: "Reset Your Password",
text: `You recently requested a password reset for your account. Please reset your password by clicking this link: ${resetLink} (This link will expire in 10 minutes)`,
html: htmlContent,
});
};
export const sendTwoFactorTokenEmail = async (email: string, token: string) => {
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL,
pass: process.env.EMAIL_PASS_KEY,
},
});
// HTML email template with inline styles for maximum compatibility
const htmlContent = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Your Authentication Code</title>
</head>
<body style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; font-size: 16px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%; background-color: #f6f6f6;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;"> </td>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;">
<div style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- HEADER -->
<div style="text-align: center; margin-bottom: 30px; margin-top: 30px;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top; padding-bottom: 20px; text-align: center;">
<h1 style="color: #03045e; font-size: 24px; font-weight: bold; margin: 0; margin-bottom: 8px;">Auth JS Boiler</h1>
<span style="color: #90a4ae; font-size: 14px;">Complete Authentication Solution</span>
</td>
</tr>
</table>
</div>
<!-- MAIN CONTENT -->
<div style="background: #ffffff; border-radius: 8px; padding: 30px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;">
<h2 style="color: #2b3a4a; font-size: 20px; font-weight: bold; margin: 0 0 20px;">Your Authentication Code</h2>
<p style="font-family: sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #4a5568;">To complete the sign-in process, please use the following verification code:</p>
<!-- CODE DISPLAY -->
<div style="background-color: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; margin: 24px 0; padding: 16px; text-align: center;">
<p style="font-family: monospace; font-size: 32px; font-weight: bold; letter-spacing: 4px; margin: 0; color: #03045e;">${token}</p>
</div>
<p style="font-family: sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px; color: #4a5568;">This code will expire in 10 minutes for security purposes.</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-top: 24px; color: #718096;">If you did not request this code, please ignore this email and ensure your account is secure.</p>
</td>
</tr>
</table>
</div>
<!-- FOOTER -->
<div style="clear: both; margin-top: 24px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; width: 100%;">
<tr>
<td style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #9ca3af; font-size: 12px; text-align: center;">
<p style="margin: 0; margin-bottom: 5px;">This email was sent to ${email}</p>
<p style="margin: 0; margin-bottom: 5px;">If you didn't attempt to sign in, you can safely ignore this email.</p>
<p style="margin: 0; margin-bottom: 5px;">© ${new Date().getFullYear()} Auth JS Boiler. All rights reserved.</p>
</td>
</tr>
</table>
</div>
</div>
</td>
<td style="font-family: sans-serif; font-size: 16px; vertical-align: top;"> </td>
</tr>
</table>
</body>
</html>
`;
// Send mail with defined transport object
await transporter.sendMail({
from: `"Auth JS Boiler" <${process.env.EMAIL}>`, // Formatted sender
to: email,
subject: "Your Two-Factor Authentication Code",
text: `Your verification code is: ${token}\n\nThis code will expire in 10 minutes.\n\nIf you didn't request this code, please ignore this email.`,
html: htmlContent,
});
};