184 lines
7.1 KiB
JavaScript
184 lines
7.1 KiB
JavaScript
import nodemailer from "nodemailer";
|
|
//import juice from "juice";
|
|
//
|
|
// Create reusable transporter object
|
|
//
|
|
export const mailer = nodemailer.createTransport({
|
|
host: "mail.metatron-admin-backend.metatronhost.com", // your Hestia mail host
|
|
port: 587, // STARTTLS
|
|
secure: false, // must be false for 587
|
|
auth: {
|
|
user: "info@metatron-admin-backend.metatronhost.com", // e.g. info@metatron-admin-backend.metatronhost.com
|
|
pass: "MetatronBackendAdmin@2025", // mailbox password
|
|
},
|
|
name: "mail.metatron-admin-backend.metatronhost.com", // 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@metatron-admin-backend.metatronhost.com`,
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
export const sendCakeOrderMail = async (email, order, totalPieces, totalPrice, hst) => {
|
|
try {
|
|
const transporter = nodemailer.createTransport({
|
|
host: "mail.metatron-admin-backend.metatronhost.com",
|
|
port: 587,
|
|
secure: false,
|
|
auth: {
|
|
user: "info@metatron-admin-backend.metatronhost.com",
|
|
pass: "MetatronBackendAdmin@2025",
|
|
},
|
|
tls: { rejectUnauthorized: false },
|
|
});
|
|
|
|
// ✅ Auto-calculate HST if not provided
|
|
const hstAmount = hst && hst > 0 ? hst : totalPrice * 0.13;
|
|
const grandTotal = totalPrice + hstAmount;
|
|
|
|
// Build table rows
|
|
let orderRows = "";
|
|
Object.entries(order).forEach(([category, items]) => {
|
|
items.forEach(({ flavour, pieces, unitPrice, totalPrice: lineTotal }) => {
|
|
orderRows += `
|
|
<tr>
|
|
<td style="padding:10px 12px;">${category}</td>
|
|
<td style="padding:10px 12px;">${flavour}</td>
|
|
<td style="padding:10px 12px;">${pieces}</td>
|
|
<td style="padding:10px 12px;">$${unitPrice.toFixed(2)}</td>
|
|
<td style="padding:10px 12px;">$${lineTotal.toFixed(2)}</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
});
|
|
|
|
// ✅ New version: Show “HST (13%) included in total”
|
|
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="padding:15px 25px;text-align:center;">
|
|
<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>
|
|
<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>
|
|
<th style="padding:10px 12px;">Unit Price</th>
|
|
<th style="padding:10px 12px;">Total Price</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${orderRows}
|
|
<tr style="font-weight:bold;background-color:#f8f8f8;">
|
|
<td colspan="2" style="text-align:right;padding:10px 12px;">Total Pieces</td>
|
|
<td style="padding:10px 12px;">${totalPieces}</td>
|
|
<td style="text-align:right;padding:10px 12px;">Subtotal ($)</td>
|
|
<td style="padding:10px 12px;">$${totalPrice.toFixed(2)}</td>
|
|
</tr>
|
|
<tr style="font-weight:bold;background-color:#f8f8f8;">
|
|
<td colspan="4" style="text-align:right;padding:10px 12px;">HST (13%)</td>
|
|
<td style="padding:10px 12px;">$${hstAmount.toFixed(2)}</td>
|
|
</tr>
|
|
<tr style="font-weight:bold;background-color:#faf4f0;">
|
|
<td colspan="4" style="text-align:right;padding:10px 12px;">Grand Total (includes 13% HST)</td>
|
|
<td style="padding:10px 12px;color:#d72631;">$${grandTotal.toFixed(2)}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<p style="font-size:13px;color:#777;margin-top:8px;">
|
|
<em>Note: Grand total includes 13% HST.</em>
|
|
</p>
|
|
|
|
<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@metatron-admin-backend.metatronhost.com>',
|
|
to: email,
|
|
subject: "🎉 New Cake Order from Website Form",
|
|
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", email);
|
|
} catch (err) {
|
|
console.error("❌ Failed to send cake order email:", err);
|
|
}
|
|
};
|
|
|