sync: auto-sync from DESKTOP-0O8A1RL at 2026-04-21 18:46:45
Author: Mike Swanson Machine: DESKTOP-0O8A1RL Timestamp: 2026-04-21 18:46:45
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Failure notification via email.
|
||||
*
|
||||
* Reads SMTP config from config/notify.json (gitignored, written by deploy-to-ad2.py).
|
||||
* Silently swallows send errors so a notification failure never masks the real error.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const CONFIG_PATH = path.join(__dirname, '..', 'config', 'notify.json');
|
||||
|
||||
function loadConfig() {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
||||
} catch (err) {
|
||||
console.error(`[NOTIFY] Could not read ${CONFIG_PATH}: ${err.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a failure notification email.
|
||||
* @param {string} subject
|
||||
* @param {string} body - plain text
|
||||
*/
|
||||
async function sendFailureEmail(subject, body) {
|
||||
const cfg = loadConfig();
|
||||
if (!cfg) return;
|
||||
|
||||
let nodemailer;
|
||||
try {
|
||||
nodemailer = require('nodemailer');
|
||||
} catch (err) {
|
||||
console.error('[NOTIFY] nodemailer not installed — skipping email');
|
||||
return;
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: cfg.smtp.host,
|
||||
port: cfg.smtp.port,
|
||||
secure: false,
|
||||
requireTLS: true,
|
||||
auth: {
|
||||
user: cfg.smtp.user,
|
||||
pass: cfg.smtp.pass,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await transporter.sendMail({
|
||||
from: cfg.from,
|
||||
to: cfg.to,
|
||||
subject,
|
||||
text: body,
|
||||
});
|
||||
console.log(`[NOTIFY] Failure email sent: ${subject}`);
|
||||
} catch (err) {
|
||||
console.error(`[NOTIFY] Failed to send email: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { sendFailureEmail };
|
||||
Reference in New Issue
Block a user