160 lines
5.5 KiB
JavaScript

import nodemailer from "nodemailer";
import juice from "juice";
//
// Create reusable transporter object
//
export const mailer = nodemailer.createTransport({
host: "mail.crawlerx.co", // your Hestia mail host
port: 587, // STARTTLS
secure: false, // must be false for 587
auth: {
user: "info@crawlerx.co", // e.g. info@crawlerx.co
pass: "CrawlerX@2025", // mailbox password
},
name: "mail.crawlerx.co", // explicitly set hostname
tls: {
rejectUnauthorized: false, // allow self-signed certs
},
logger: true, // optional: logs connection steps
debug: true, // optional: debug SMTP connection
});
//
// Send welcome / signup email
//
export async function sendSignupMail(toEmail) {
try {
await mailer.sendMail({
from: `"CrawlerX" info@crawlerx.co`,
to: toEmail,
subject: "Welcome to CrawlerX",
html: `
<h2>Welcome!</h2>
<p>Your signup was successful. You can now log in and start using the app.</p>
`,
});
console.log(`✅ Signup email sent to ${toEmail}`);
} catch (err) {
console.error("❌ Error sending signup email:", err);
}
}
//
// Send reset-password email with 4-digit code or token link
//
export async function sendResetPasswordMail(email, token) {
try {
const resetURL = `${process.env.FRONTEND_URL}/reset-password?email=${email}&token=${token}`;
await mailer.sendMail({
from: `"CrawlerX" <${process.env.SMTP_USER}>`,
to: email,
subject: "Reset your password",
html: `
<p>You requested a password reset.</p>
<p>Click here to reset: <a href="${resetURL}">${resetURL}</a></p>
<p>This link is valid for 1 hour.</p>
`,
});
console.log(`✅ Reset password email sent to ${email}`);
} catch (err) {
console.error("❌ Error sending reset password email:", err);
}
}
// Send cake order email
export const sendCakeOrderMail = async (toEmail, orderData) => {
try {
const transporter = nodemailer.createTransport({
host: "mail.crawlerx.co",
port: 587,
secure: false,
auth: {
user: "info@crawlerx.co",
pass: "CrawlerX@2025",
},
tls: { rejectUnauthorized: false },
});
// Build table rows
let orderRows = "";
Object.entries(orderData).forEach(([category, flavours]) => {
Object.entries(flavours).forEach(([flavour, qty]) => {
orderRows += `
<tr>
<td style="padding:10px 12px;">${category}</td>
<td style="padding:10px 12px;">${flavour}</td>
<td style="padding:10px 12px;">${qty}</td>
</tr>
`;
});
});
// HTML content with local images via cid
const htmlContent = `
<div style="max-width:750px;margin:30px auto;background-color:#fff;border-radius:20px;overflow:hidden;font-family:'Segoe UI',Tahoma,sans-serif;color:#333;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color:#faf4f0;padding:15px 25px;">
<tr>
<td align="left">
<img src="cid:logo" width="150" style="display:block;" />
</td>
<td align="right" style="font-size:14px;color:#d72631;font-weight:600;">
Order Date: ${new Date().toLocaleString()}
</td>
</tr>
</table>
<div style="text-align:center;padding:30px 0;">
<img src="cid:banner" style="width:100%;max-height:300px;object-fit:cover;border-radius:0 0 20px 20px;"/>
</div>
<div style="padding:15px 25px;text-align:center;">
<h2 style="color:rgb(255 135 174);font-family:'Brush Script MT',cursive;font-size:22px;margin-bottom:12px;font-weight:700;">Order Details</h2>
<table style="width:100%;border-collapse:collapse;font-size:14px;margin:0 auto 15px;">
<thead>
<tr style="background-color:#faf4f0;color:#d72631;font-weight:600;">
<th style="padding:10px 12px;text-align:left;">Treats</th>
<th style="padding:10px 12px;text-align:left;">Flavour</th>
<th style="padding:10px 12px;text-align:left;">Quantity</th>
</tr>
</thead>
<tbody>
${orderRows}
</tbody>
</table>
<a href="https://maisondetreats.com/" style="display:inline-block;background-color:#d72631;color:#fff;padding:10px 25px;border-radius:30px;text-decoration:none;font-weight:bold;margin-top:15px;">Visit Our Website</a>
</div>
<div style="text-align:center;padding:30px 0;background-color:#d72631;color:#fff;">
<img src="cid:footer" style="width:100%;max-height:100px;object-fit:cover;"/>
</div>
</div>
`;
const mailOptions = {
from: '"Maison de Treats" <info@crawlerx.co>',
to: toEmail,
subject: "🎉 Your Cake Order Confirmation",
html: htmlContent,
attachments: [
{
filename: "logo-2.webp",
path: "./public/maisondetreats/img/logo-2.webp",
cid: "logo",
},
{
filename: "thank-you.png",
path: "./public/maisondetreats/img/thank-you.png",
cid: "banner",
},
{
filename: "bottom.png",
path: "./public/maisondetreats/img/bottom.png",
cid: "footer",
},
],
};
await transporter.sendMail(mailOptions);
console.log("✅ Cake order email sent to", toEmail);
} catch (err) {
console.error("❌ Failed to send cake order email:", err);
}
};