const nodemailer = require("nodemailer"); const core = require("@actions/core"); const glob = require("@actions/glob"); const fs = require("fs"); const showdown = require("showdown"); const path = require("path"); function getText(textOrFile, convertMarkdown) { let text = textOrFile; // Read text from file if (textOrFile.startsWith("file://")) { const file = textOrFile.replace("file://", ""); text = fs.readFileSync(file, "utf8"); } // Convert Markdown to HTML if (convertMarkdown) { const converter = new showdown.Converter({ tables: true }); text = converter.makeHtml(text); } return text; } function getFrom(from, username) { if (from.match(/.+ <.+@.+>/)) { return from; } return `"${from}" <${username}>`; } async function getAttachments(attachments) { const globber = await glob.create(attachments.split(",").join("\n")); const files = await globber.glob(); return files.map((f) => ({ filename: path.basename(f), path: f, cid: f.replace(/^.*[\\\/]/, ""), })); } function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } async function main() { try { let serverAddress = core.getInput("server_address"); let serverPort = core.getInput("server_port"); let secure = core.getInput("secure"); let username = core.getInput("username"); let password = core.getInput("password"); if (!secure) { secure = serverPort === "465" ? "true" : "false"; } const connectionUrl = core.getInput("connection_url"); if (connectionUrl) { const url = new URL(connectionUrl); switch (url.protocol) { default: throw new Error( `Unsupported connection protocol '${url.protocol}'` ); case "smtp:": serverPort = "25"; secure = "false"; break; case "smtp+starttls:": serverPort = "465"; secure = "true"; break; } if (url.hostname) { serverAddress = url.hostname; } if (url.port) { serverPort = url.port; } if (url.username) { username = unescape(url.username); } if (url.password) { password = unescape(url.password); } } const subject = core.getInput("subject", { required: true }); const from = core.getInput("from", { required: true }); const to = core.getInput("to", { required: false }); const body = core.getInput("body", { required: false }); const htmlBody = core.getInput("html_body", { required: false }); const cc = core.getInput("cc", { required: false }); const bcc = core.getInput("bcc", { required: false }); const replyTo = core.getInput("reply_to", { required: false }); const inReplyTo = core.getInput("in_reply_to", { required: false }); const attachments = core.getInput("attachments", { required: false }); const convertMarkdown = core.getInput("convert_markdown", { required: false, }); const ignoreCert = core.getInput("ignore_cert", { required: false }); const priority = core.getInput("priority", { required: false }); const nodemailerlog = core.getInput("nodemailerlog", { required: false, }); const nodemailerdebug = core.getInput("nodemailerdebug", { required: false, }); const envelopeFrom = core.getInput("envelope_from", { required: false, }); const envelopeTo = core.getInput("envelope_to", { required: false }); // if neither to, cc or bcc is provided, throw error if (!to && !cc && !bcc) { throw new Error( "At least one of 'to', 'cc' or 'bcc' must be specified" ); } if (!serverAddress) { throw new Error("Server address must be specified"); } const transport = nodemailer.createTransport({ host: serverAddress, auth: username && password ? { user: username, pass: password, } : undefined, port: serverPort, secure: secure === "true", tls: ignoreCert == "true" ? { rejectUnauthorized: false, } : undefined, logger: nodemailerdebug == "true" ? true : nodemailerlog, debug: nodemailerdebug, proxy: process.env.HTTP_PROXY, }); var i = 1; while (true) { try { const info = await transport.sendMail({ from: getFrom(from, username), to: to, subject: getText(subject, false), cc: cc ? cc : undefined, bcc: bcc ? bcc : undefined, replyTo: replyTo ? replyTo : undefined, inReplyTo: inReplyTo ? inReplyTo : undefined, references: inReplyTo ? inReplyTo : undefined, text: body ? getText(body, false) : undefined, html: htmlBody ? getText(htmlBody, convertMarkdown) : undefined, priority: priority ? priority : undefined, attachments: attachments ? await getAttachments(attachments) : undefined, envelope: envelopeFrom || envelopeTo ? { from: envelopeFrom ? envelopeFrom : undefined, to: envelopeTo ? envelopeTo : undefined, } : undefined, }); break; } catch (error) { if (!error.message.includes("Try again later,")) { core.setFailed(error.message); break; } if (i > 10) { core.setFailed(error.message); break; } console.log("Received: " + error.message); if (i < 2) { console.log("Trying again in a minute..."); } else { console.log("Trying again in " + i + " minutes..."); } await sleep(i * 60000); i++; } } } catch (error) { core.setFailed(error.message); } } main();