const nodemailer = require('nodemailer'); const fs = require('fs'); const path = require('path'); /** * Sends a premium custom email with the PDF attachment. * @param {string} toEmail - The recipient's email address * @param {Object} orderData - The Shopify order payload * @param {Buffer} pdfBuffer - The invoice PDF data buffer * @param {Buffer} [shippingLabelBuffer] - Optional shipping label PDF buffer */ const sendEmailWithAttachment = async (toEmail, orderData, pdfBuffer, shippingLabelBuffer = null) => { const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT) || 465, secure: process.env.SMTP_SECURE === 'true', auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS, }, tls: { rejectUnauthorized: false } }); const orderNumber = orderData.order_number || orderData.name; const currencySymbol = orderData.currency === 'INR' ? 'Rs. ' : `${orderData.currency} `; // Check if local logo exists for CID inline attachment const localLogoPath = path.join(__dirname, 'logo.png'); const logoExists = fs.existsSync(localLogoPath); // Use a remote URL if you have one, or stick to text fallback to avoid the "logo.png" attachment pill const logoImgTag = `RAY AARI SHOP`; // --- 1. Generate Order Summary Rows HTML --- let orderRowsHtml = ''; if (orderData.line_items && orderData.line_items.length > 0) { orderData.line_items.forEach((item, index) => { const itemPrice = parseFloat(item.price).toFixed(2); const rowBg = index % 2 === 0 ? '#ffffff' : '#f8fafc'; orderRowsHtml += ` ${item.title || item.name} ${item.variant_title ? `
${item.variant_title}` : ''} ${item.quantity} ${currencySymbol}${itemPrice} `; }); } // --- 2. Calculate Totals --- const subtotal = parseFloat(orderData.subtotal_price).toFixed(2); const shipping = parseFloat(orderData.total_shipping_price_set?.shop_money?.amount || 0).toFixed(2); const taxes = parseFloat(orderData.total_tax || 0).toFixed(2); const total = parseFloat(orderData.total_price).toFixed(2); let taxRow = ''; if (parseFloat(taxes) > 0) { taxRow = ` Taxes ${currencySymbol}${taxes} `; } // --- 3. Billing Address Details HTML --- const billing = orderData.billing_address || {}; const contactNumber = orderData.note_attributes?.find?.((attr) => attr.name === 'Contact Number')?.value || orderData.attributes?.['Contact Number']?.contact_phone || orderData.attributes?.['Contact Number'] || orderData.contact_phone || orderData.attributes?.contact_phone; let billingAddressHtml = ''; if (billing.first_name || billing.last_name) { billingAddressHtml += `${billing.first_name || ''} ${billing.last_name || ''}
`; } if (billing.address1) billingAddressHtml += `${billing.address1}
`; if (billing.address2) billingAddressHtml += `${billing.address2}
`; if (billing.city || billing.province || billing.zip) { billingAddressHtml += `${billing.city || ''} ${billing.province || ''} ${billing.zip || ''}
`; } if (billing.country) billingAddressHtml += `${billing.country}
`; if (billing.phone || orderData.phone) { billingAddressHtml += `${billing.phone || orderData.phone}`; } if (contactNumber) { billingAddressHtml += `
Contact: ${contactNumber}`; } const paymentMethod = orderData.gateway || 'Request Quote'; const shippingMethod = orderData.shipping_lines?.[0]?.title || 'Economy'; // --- 4. Beautiful Responsive HTML Template --- const htmlTemplate = ` Order Confirmation
${logoImgTag}

New Order: #${orderNumber}

You've received the following order from ${orderData.billing_address ? `${orderData.billing_address.first_name || ''} ${orderData.billing_address.last_name || ''}`.trim() : (orderData.contact_email || 'a customer')}:

${orderData.order_status_url ? `[Order #${orderNumber}]` : `[Order #${orderNumber}]` } (${new Date(orderData.created_at || Date.now()).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })})

${orderRowsHtml}
Product Quantity Price
${taxRow}
Total ${currencySymbol}${total}

Customer informations

Billing address ${billingAddressHtml} Payment method ${paymentMethod} Shipping method ${shippingMethod}
`; // --- Customer attachments: Invoice PDF only --- const customerAttachments = [ { filename: `Invoice_${orderNumber}.pdf`, content: pdfBuffer, contentType: 'application/pdf' } ]; // --- Seller attachments: Invoice PDF only --- const sellerAttachments = [ { filename: `Invoice_${orderNumber}.pdf`, content: pdfBuffer, contentType: 'application/pdf' } ]; try { // 1. Send to customer (Invoice only) const customerMail = await transporter.sendMail({ from: `"${process.env.SHOP_NAME || 'Your Store'}" <${process.env.SMTP_FROM_EMAIL}>`, to: toEmail, subject: `Invoice for your order #${orderNumber}`, text: `Thank you for your order! Attached is the invoice for order #${orderNumber}.`, html: htmlTemplate, attachments: customerAttachments }); console.log(`Customer email sent: ${customerMail.messageId}`); // 2. Send to seller (Invoice + Shipping Label) const sellerEmail = process.env.SELLER_EMAIL; if (sellerEmail) { const sellerMail = await transporter.sendMail({ from: `"${process.env.SHOP_NAME || 'Your Store'}" <${process.env.SMTP_FROM_EMAIL}>`, to: sellerEmail, subject: `[NEW ORDER] #${orderNumber} - Invoice`, text: `New order #${orderNumber} received. Invoice attached.`, html: htmlTemplate, attachments: sellerAttachments }); console.log(`Seller email sent: ${sellerMail.messageId}`); } return customerMail; } catch (error) { console.error('Error sending email:', error); throw error; } }; module.exports = { sendEmailWithAttachment };