UNPKG

@hyperbytes/wappler-imap-manager

Version:

IMAP eMail Management for Wappler

179 lines (146 loc) 6.2 kB
const nodemailer = require("nodemailer"); const imap = require("imap"); const fs = require("fs"); const path = require("path"); const { toSystemPath } = require("../../../lib/core/path"); exports.imapsendmail = async function (options) { const upload = this.parseOptional(options.attachments, '*', []); console.log("Attachments: " + JSON.stringify(upload)) const upload2 = this.parseOptional(options.server_attachments, '*', []); console.log("Server_Attachments: " + JSON.stringify(upload2)) const combinedJson = { "attachments": [upload, upload2] }; console.log('CombinedJson: ' + JSON.stringify(combinedJson)) // Ensure attachments are properly formatted and converted to system paths const attachmentList = Array.isArray(upload) ? upload.map(file => ({ ...file, // Keep existing properties systemPath: toSystemPath(file.path) // Convert relative path to system path })) : []; console.log("Attachment upload initially:", upload); console.log("Transformed Attachments List:", attachmentList); const smtpFile = this.parseOptional(options.smtp_file, '*', 'default'); // const SMTP_SETTINGS_PATH = toSystemPath(`/.wappler/targets/${process.env.NODE_ENV}/app/modules/Mailer/${smtpFile}.json`); const SMTP_SETTINGS_PATH = toSystemPath(`/app/modules/Mailer/${smtpFile}.json`); console.log("SMTP Config Path:", SMTP_SETTINGS_PATH); // Load SMTP settings dynamically function loadSMTPSettings() { try { const settingsData = fs.readFileSync(SMTP_SETTINGS_PATH, "utf8"); const settings = JSON.parse(settingsData); return settings.options; } catch (error) { console.error("Error loading SMTP settings:", error); return null; } } const smtpConfig = loadSMTPSettings(); if (!smtpConfig) { return { status: 401, error: "Failed to load SMTP settings." }; } const to = this.parseRequired(options.to, '*', "No to email address specified"); const cc = this.parseOptional(options.cc, '*', ""); const bcc = this.parseOptional(options.bcc, '*', ""); const from = this.parseRequired(options.from, '*', "No from email address specified"); const subject = this.parseOptional(options.subject, '*', ""); const body = this.parseRequired(options.body, '*', "No email body specified"); const saveToSent = this.parseOptional(options.save_to_send, '*', false); try { const transporter = nodemailer.createTransport({ host: smtpConfig.host, port: smtpConfig.port, secure: smtpConfig.useSSL, auth: { user: smtpConfig.username, pass: smtpConfig.password, }, logger: false, // Enable logging debug: false, // Enable debugging }); // Prepare attachments for Nodemailer const formattedAttachments = attachmentList.map(file => ({ filename: path.basename(file.systemPath), path: file.systemPath // Use transformed system path })); const mailOptions = { from: from, to: to, cc: cc, bcc: bcc, subject: subject, text: body, html: body, attachments: formattedAttachments }; console.log("Final Attachments List:", formattedAttachments); let info = await transporter.sendMail(mailOptions); console.log("Email sent:", info.messageId); // Save to Sent Items if requested if (saveToSent) { await saveToSentFolder(options, mailOptions); } return { status: 200, messageId: info.messageId }; } catch (error) { console.error("Error sending email:", error); return { status: 400, error: error.message }; } }; // Function to **save email & attachments** in Sent Items (Promise-based) async function saveToSentFolder(options, mailOptions) { return new Promise((resolve, reject) => { const imapConfig = { user: process.env.IMAP_USER, password: process.env.IMAP_PASSWORD, host: process.env.IMAP_HOST, port: process.env.IMAP_PORT, tls: true, }; let emailContent = `From: ${mailOptions.from} To: ${mailOptions.to} Subject: ${mailOptions.subject} Content-Type: multipart/mixed; boundary="boundary" --boundary Content-Type: text/plain ${mailOptions.text || ""} `; // Attach files in MIME format for (let attachment of mailOptions.attachments) { try { const fileData = fs.readFileSync(attachment.path).toString("base64"); emailContent += `--boundary Content-Type: application/octet-stream; name="${attachment.filename}" Content-Disposition: attachment; filename="${attachment.filename}" Content-Transfer-Encoding: base64 ${fileData} `; } catch (err) { console.error(`Error reading attachment file: ${attachment.path}`, err); return reject(err); } } emailContent += "--boundary--"; // Closing MIME boundary const imapClient = new imap(imapConfig); imapClient.once("ready", () => { imapClient.openBox("Sent", true, (err) => { if (err) { console.error("Error opening Sent Items folder:", err); return reject(err); } imapClient.append(Buffer.from(emailContent), { mailbox: "Sent" }, (err) => { if (err) { console.error("Failed to save email to Sent Items:", err); return reject(err); } console.log("Email successfully saved to Sent Items with attachments."); imapClient.end(); resolve(); }); }); }); imapClient.once("error", (err) => { console.error("IMAP connection error:", err); reject(err); }); imapClient.connect(); }); }