Files
send-mail/main.js

206 lines
6.9 KiB
JavaScript
Raw Normal View History

2025-06-14 23:03:31 +02:00
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");
2020-02-29 23:01:03 +01:00
function getText(textOrFile, convertMarkdown) {
2025-06-14 23:03:31 +02:00
let text = textOrFile;
// Read text from file
if (textOrFile.startsWith("file://")) {
2025-06-14 23:03:31 +02:00
const file = textOrFile.replace("file://", "");
text = fs.readFileSync(file, "utf8");
}
// Convert Markdown to HTML
if (convertMarkdown) {
2025-06-14 23:03:31 +02:00
const converter = new showdown.Converter({ tables: true });
text = converter.makeHtml(text);
2020-02-29 23:01:03 +01:00
}
2025-06-14 23:03:31 +02:00
return text;
2020-02-29 23:01:03 +01:00
}
2020-09-24 10:24:29 +02:00
function getFrom(from, username) {
2021-04-25 16:14:13 +02:00
if (from.match(/.+ <.+@.+>/)) {
2025-06-14 23:03:31 +02:00
return from;
2020-03-25 16:18:35 +01:00
}
2025-06-14 23:03:31 +02:00
return `"${from}" <${username}>`;
2020-03-25 16:18:35 +01:00
}
2021-06-22 19:18:21 +02:00
async function getAttachments(attachments) {
2025-06-14 23:03:31 +02:00
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(/^.*[\\\/]/, ""),
}));
2021-06-22 19:18:21 +02:00
}
2024-02-14 12:26:05 +01:00
function sleep(ms) {
return new Promise((resolve) => {
2025-06-14 23:03:31 +02:00
setTimeout(resolve, ms);
2024-02-14 12:26:05 +01:00
});
}
2020-02-29 23:01:03 +01:00
async function main() {
2020-02-29 23:13:30 +01:00
try {
2025-06-14 23:03:31 +02:00
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) {
2025-06-14 23:03:31 +02:00
secure = serverPort === "465" ? "true" : "false";
}
2025-06-14 23:03:31 +02:00
const connectionUrl = core.getInput("connection_url");
if (connectionUrl) {
2025-06-14 23:03:31 +02:00
const url = new URL(connectionUrl);
switch (url.protocol) {
default:
2025-06-14 23:03:31 +02:00
throw new Error(
`Unsupported connection protocol '${url.protocol}'`
);
case "smtp:":
2025-06-14 23:03:31 +02:00
serverPort = "25";
secure = "false";
break;
case "smtp+starttls:":
2025-06-14 23:03:31 +02:00
serverPort = "465";
secure = "true";
break;
}
if (url.hostname) {
2025-06-14 23:03:31 +02:00
serverAddress = url.hostname;
}
if (url.port) {
2025-06-14 23:03:31 +02:00
serverPort = url.port;
}
if (url.username) {
2025-06-14 23:03:31 +02:00
username = unescape(url.username);
}
if (url.password) {
2025-06-14 23:03:31 +02:00
password = unescape(url.password);
}
}
2025-06-14 23:03:31 +02:00
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 });
2020-02-29 23:01:03 +01:00
// if neither to, cc or bcc is provided, throw error
if (!to && !cc && !bcc) {
2025-06-14 23:03:31 +02:00
throw new Error(
"At least one of 'to', 'cc' or 'bcc' must be specified"
);
}
2025-06-14 23:03:31 +02:00
if (!serverAddress) {
2025-06-14 23:03:31 +02:00
throw new Error("Server address must be specified");
}
2020-03-24 14:03:35 +01:00
const transport = nodemailer.createTransport({
host: serverAddress,
2025-06-14 23:03:31 +02:00
auth:
username && password
? {
user: username,
pass: password,
}
: undefined,
port: serverPort,
secure: secure === "true",
2025-06-14 23:03:31 +02:00
tls:
ignoreCert == "true"
? {
rejectUnauthorized: false,
}
: undefined,
logger: nodemailerdebug == "true" ? true : nodemailerlog,
debug: nodemailerdebug,
2025-06-14 23:10:25 +02:00
proxy: process.env.HTTP_PROXY,
2025-06-14 23:03:31 +02:00
});
2021-04-25 16:14:13 +02:00
2024-02-14 12:26:05 +01:00
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,
2025-06-14 23:03:31 +02:00
html: htmlBody
? getText(htmlBody, convertMarkdown)
: undefined,
2024-02-14 12:26:05 +01:00
priority: priority ? priority : undefined,
2025-06-14 23:03:31 +02:00
attachments: attachments
? await getAttachments(attachments)
: undefined,
envelope:
envelopeFrom || envelopeTo
? {
from: envelopeFrom ? envelopeFrom : undefined,
to: envelopeTo ? envelopeTo : undefined,
}
: undefined,
2024-02-14 12:26:05 +01:00
});
break;
} catch (error) {
if (!error.message.includes("Try again later,")) {
2025-06-14 23:03:31 +02:00
core.setFailed(error.message);
2024-02-14 12:26:05 +01:00
break;
}
if (i > 10) {
2025-06-14 23:03:31 +02:00
core.setFailed(error.message);
2024-02-14 12:26:05 +01:00
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++;
}
}
2020-02-29 23:13:30 +01:00
} catch (error) {
2025-06-14 23:03:31 +02:00
core.setFailed(error.message);
2020-02-29 23:13:30 +01:00
}
2020-02-29 23:01:03 +01:00
}
2025-06-14 23:03:31 +02:00
main();