waitlist-mailer
Version:
Modern, modular TypeScript library for managing waitlists with pluggable storage and mail providers. Supports MongoDB, SQL databases, and custom adapters with zero required dependencies for basic usage.
120 lines (118 loc) • 3.77 kB
JavaScript
// lib/adapters/mail/NodemailerProvider.ts
import nodemailer from "nodemailer";
var NodemailerProvider = class {
/**
* Create a new NodemailerProvider instance.
* @param config - SMTP configuration
* @throws {Error} If nodemailer is not installed
*/
constructor(config) {
this.config = config;
try {
if (!nodemailer || !nodemailer.createTransport) {
throw new Error("nodemailer is not properly initialized");
}
} catch (error) {
throw new Error(
"NodemailerProvider requires nodemailer to be installed. Install it with: npm install nodemailer"
);
}
this.fromEmail = config.from || config.user;
this.fromName = config.name || "Waitlist Manager";
this.transporter = nodemailer.createTransport({
host: config.host,
port: config.port,
secure: config.secure ?? config.port === 465,
auth: {
user: config.user,
pass: config.pass
}
});
}
/**
* Verify the transporter configuration.
* @returns true if configuration is valid
*/
async verify() {
try {
await this.transporter.verify();
return true;
} catch (error) {
console.error("Nodemailer verification failed:", error);
return false;
}
}
/**
* Send a confirmation email.
* @param email - Recipient email address
* @param context - Template context with variables
* @returns true if the email was sent successfully
*/
async sendConfirmation(email, context) {
try {
const subject = this.buildSubject(context);
const html = this.buildHtml(context);
const mailOptions = {
from: `"${this.fromName}" <${this.fromEmail}>`,
to: email,
subject,
html
};
await this.transporter.sendMail(mailOptions);
return true;
} catch (error) {
console.error(`Failed to send email to ${email}:`, error);
return false;
}
}
/**
* Build the email subject.
* Allows customization through context.
*/
buildSubject(context) {
return context.subject || `Welcome to ${context.companyName || "our platform"}`;
}
/**
* Build the HTML body.
* Provides a default template if customHtml is not provided.
*/
buildHtml(context) {
if (context.customHtml) {
return context.customHtml;
}
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #007bff; color: white; padding: 20px; text-align: center; }
.content { padding: 20px; }
.footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Welcome to ${context.companyName || "Our Platform"}</h1>
</div>
<div class="content">
<p>Hello,</p>
<p>Thank you for joining our waitlist! We're excited to have you on board.</p>
<p>You'll be among the first to know when we launch.</p>
${context.customUrl ? `<p><a href="${context.customUrl}" style="background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px; display: inline-block;">Learn More</a></p>` : ""}
</div>
<div class="footer">
<p>© 2024 ${context.companyName || "Our Platform"}. All rights reserved.</p>
</div>
</div>
</body>
</html>
`;
}
};
export {
NodemailerProvider
};