Use rms.auth.smtp_relay settings as the primary source for OTP mail transport (host/port/auth/tls/from/replyTo), with existing OTP/env values only as fallback. This lets OTP delivery work immediately when relay settings are already configured.
126 lines
3.9 KiB
JavaScript
126 lines
3.9 KiB
JavaScript
let nodemailer = null;
|
|
try {
|
|
nodemailer = require("nodemailer");
|
|
} catch {
|
|
nodemailer = null;
|
|
}
|
|
|
|
async function createPlugin(ctx) {
|
|
let transporter = null;
|
|
let transportKey = "";
|
|
|
|
function readTransportConfig() {
|
|
const relaySetting = typeof ctx.getPluginSetting === "function"
|
|
? (key, fallback = null) => ctx.getPluginSetting("rms.auth.smtp_relay", key, fallback)
|
|
: (_key, fallback = null) => fallback;
|
|
|
|
const host = String(
|
|
relaySetting("host", ctx.getSetting("host", ctx.env.SMTP_HOST || ""))
|
|
).trim();
|
|
const portRaw = Number(
|
|
relaySetting("port", ctx.getSetting("port", ctx.env.SMTP_PORT || 587))
|
|
);
|
|
const secure = String(
|
|
relaySetting("secure", ctx.getSetting("secure", ctx.env.SMTP_SECURE || "false"))
|
|
) === "true";
|
|
const authUser = String(
|
|
relaySetting("authUser", ctx.getSetting("authUser", ctx.env.SMTP_USER || ""))
|
|
).trim();
|
|
const authPass = String(
|
|
relaySetting("authPass", ctx.getSetting("authPass", ctx.env.SMTP_PASS || ""))
|
|
).trim();
|
|
const allowInvalidCert = String(
|
|
relaySetting("allowInvalidCert", ctx.getSetting("allowInvalidCert", ctx.env.SMTP_ALLOW_INVALID_CERT || "false"))
|
|
) === "true";
|
|
const from = String(
|
|
relaySetting("from", ctx.getSetting("from", ctx.env.SMTP_FROM || "noreply@arcg.at"))
|
|
).trim() || "noreply@arcg.at";
|
|
const replyTo = String(
|
|
relaySetting("replyTo", ctx.getSetting("replyTo", ctx.env.SMTP_REPLY_TO || ""))
|
|
).trim();
|
|
return {
|
|
host,
|
|
port: Number.isFinite(portRaw) && portRaw > 0 ? portRaw : 587,
|
|
secure,
|
|
authUser,
|
|
authPass,
|
|
allowInvalidCert,
|
|
from,
|
|
replyTo
|
|
};
|
|
}
|
|
|
|
async function deliverViaSmtp(entry) {
|
|
const config = readTransportConfig();
|
|
if (!config.host || !nodemailer) {
|
|
return false;
|
|
}
|
|
const key = JSON.stringify(config);
|
|
if (!transporter || transportKey !== key) {
|
|
transporter = nodemailer.createTransport({
|
|
host: config.host,
|
|
port: config.port,
|
|
secure: config.secure,
|
|
auth: config.authUser ? { user: config.authUser, pass: config.authPass } : undefined,
|
|
tls: config.allowInvalidCert ? { rejectUnauthorized: false } : undefined
|
|
});
|
|
transportKey = key;
|
|
}
|
|
|
|
await transporter.sendMail({
|
|
from: entry.from,
|
|
to: entry.to,
|
|
replyTo: entry.replyTo || undefined,
|
|
subject: entry.subject,
|
|
text: entry.text,
|
|
html: entry.html || undefined
|
|
});
|
|
return true;
|
|
}
|
|
|
|
return {
|
|
async execute(action, input) {
|
|
if (action !== "send_challenge") {
|
|
throw new Error(`Unknown action: ${action}`);
|
|
}
|
|
const payload = input && input.payload ? input.payload : {};
|
|
const recipient = input && input.recipient ? String(input.recipient) : "";
|
|
if (!recipient) {
|
|
throw new Error("recipient missing");
|
|
}
|
|
const transportConfig = readTransportConfig();
|
|
const entry = {
|
|
at: new Date().toISOString(),
|
|
via: "rms.auth.otp_email",
|
|
to: recipient,
|
|
from: transportConfig.from,
|
|
replyTo: transportConfig.replyTo,
|
|
subject: String(payload.subject || "ARCG OTP"),
|
|
text: String(payload.text || ""),
|
|
html: String(payload.html || "")
|
|
};
|
|
let delivered = false;
|
|
try {
|
|
delivered = await deliverViaSmtp(entry);
|
|
} catch (error) {
|
|
entry.smtpError = String(error && error.message ? error.message : error);
|
|
}
|
|
entry.delivered = delivered;
|
|
entry.transport = delivered ? "smtp" : "outbox-fallback";
|
|
await ctx.appendMailOutbox(entry);
|
|
return { ok: true, delivered, transport: delivered ? "smtp" : "outbox-fallback" };
|
|
},
|
|
async health() {
|
|
const config = readTransportConfig();
|
|
if (config.host && !nodemailer) {
|
|
return { ok: false, message: "nodemailer nicht installiert" };
|
|
}
|
|
return { ok: true };
|
|
}
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
createPlugin
|
|
};
|