diff --git a/plugins/rms.auth.otp_email/index.js b/plugins/rms.auth.otp_email/index.js index ea60138..574ff27 100644 --- a/plugins/rms.auth.otp_email/index.js +++ b/plugins/rms.auth.otp_email/index.js @@ -1,4 +1,59 @@ +let nodemailer = null; +try { + nodemailer = require("nodemailer"); +} catch { + nodemailer = null; +} + async function createPlugin(ctx) { + let transporter = null; + let transportKey = ""; + + function readTransportConfig() { + const host = String(ctx.getSetting("host", ctx.env.SMTP_HOST || "")).trim(); + const portRaw = Number(ctx.getSetting("port", ctx.env.SMTP_PORT || 587)); + const secure = String(ctx.getSetting("secure", ctx.env.SMTP_SECURE || "false")) === "true"; + const authUser = String(ctx.getSetting("authUser", ctx.env.SMTP_USER || "")).trim(); + const authPass = String(ctx.getSetting("authPass", ctx.env.SMTP_PASS || "")).trim(); + const allowInvalidCert = String(ctx.getSetting("allowInvalidCert", ctx.env.SMTP_ALLOW_INVALID_CERT || "false")) === "true"; + return { + host, + port: Number.isFinite(portRaw) && portRaw > 0 ? portRaw : 587, + secure, + authUser, + authPass, + allowInvalidCert + }; + } + + 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") { @@ -14,14 +69,27 @@ async function createPlugin(ctx) { via: "rms.auth.otp_email", to: recipient, from: String(ctx.getSetting("from", ctx.env.SMTP_FROM || "noreply@arcg.at")), + replyTo: String(ctx.getSetting("replyTo", ctx.env.SMTP_REPLY_TO || "")), 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: true, transport: "otp-email-plugin" }; + 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 }; } }; diff --git a/plugins/rms.auth.otp_email/manifest.json b/plugins/rms.auth.otp_email/manifest.json index 3c9b2bc..7a38be5 100644 --- a/plugins/rms.auth.otp_email/manifest.json +++ b/plugins/rms.auth.otp_email/manifest.json @@ -12,7 +12,14 @@ "settingsSchema": { "type": "object", "properties": { - "from": { "type": "string" } + "host": { "type": "string" }, + "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, + "secure": { "type": "boolean" }, + "authUser": { "type": "string" }, + "authPass": { "type": "string" }, + "from": { "type": "string" }, + "replyTo": { "type": "string" }, + "allowInvalidCert": { "type": "boolean" } }, "additionalProperties": false },