Captures accumulated hijack-alerts.json/aspa-adoption-history.json growth since the 2026-07-16 snapshot commit, plus the manually-uploaded server.js/public/index.html/package.json/local-db-client.js/src/backend/ files from the same-day ASPA-fix deploy, before switching this checkout to the merge-prod-snapshot branch (which has the full src/api/ + src/routes/ tree needed for the new API server, missing here since this checkout was never git-pulled, only individually file-uploaded).
79 lines
3.2 KiB
JavaScript
79 lines
3.2 KiB
JavaScript
const tls = require('tls');
|
|
const net = require('net');
|
|
|
|
const SMTP_HOST = 'mail.fichtmueller.org';
|
|
const SMTP_PORT = 587;
|
|
const MAIL_TO = 'peercortex@context-x.org';
|
|
const MAIL_FROM = 'PeerCortex Feedback <rene@fichtmueller.org>';
|
|
|
|
function sendFeedbackMail(entry) {
|
|
const SMTP_USER = process.env.SMTP_USER;
|
|
const SMTP_PASS = process.env.SMTP_PASS;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
var b64 = function(s) { return Buffer.from(s).toString('base64'); };
|
|
var CRLF = '\r\n';
|
|
var body = 'Category : ' + entry.category + CRLF +
|
|
'Name : ' + entry.name + CRLF +
|
|
'ASN : ' + (entry.asn || '-') + CRLF +
|
|
'Time : ' + entry.timestamp + CRLF + CRLF +
|
|
entry.message + CRLF + CRLF + '-' + CRLF + 'PeerCortex Feedback';
|
|
var subj = '[PeerCortex Feedback] ' + entry.category + (entry.asn ? ' - AS' + entry.asn : '');
|
|
var msg = 'From: ' + MAIL_FROM + CRLF +
|
|
'To: ' + MAIL_TO + CRLF +
|
|
'Subject: ' + subj + CRLF +
|
|
'MIME-Version: 1.0' + CRLF +
|
|
'Content-Type: text/plain; charset=UTF-8' + CRLF + CRLF +
|
|
body;
|
|
|
|
var socket = net.connect(SMTP_PORT, SMTP_HOST);
|
|
var tlsSocket = null;
|
|
var buf = '';
|
|
var step = 0;
|
|
var done = false;
|
|
|
|
function send(line) {
|
|
var s = tlsSocket || socket;
|
|
s.write(line + CRLF);
|
|
}
|
|
|
|
function onData(data) {
|
|
buf += data.toString();
|
|
var lines = buf.split(CRLF);
|
|
buf = lines.pop();
|
|
for (var i = 0; i < lines.length; i++) {
|
|
var line = lines[i];
|
|
var code = parseInt(line.slice(0, 3));
|
|
if (isNaN(code) || line[3] === '-') continue;
|
|
if (step === 0 && code === 220) { send('EHLO peercortex.org'); step = 1; }
|
|
else if (step === 1 && code === 250) { send('STARTTLS'); step = 2; }
|
|
else if (step === 2 && code === 220) {
|
|
tlsSocket = tls.connect({ socket: socket, servername: SMTP_HOST, rejectUnauthorized: false }, function() {
|
|
tlsSocket.on('data', onData);
|
|
send('EHLO peercortex.org');
|
|
step = 3;
|
|
});
|
|
tlsSocket.on('error', function(e) { if (!done) { done = true; reject(e); } });
|
|
}
|
|
else if (step === 3 && code === 250) { send('AUTH LOGIN'); step = 4; }
|
|
else if (step === 4 && code === 334) { send(b64(SMTP_USER)); step = 5; }
|
|
else if (step === 5 && code === 334) { send(b64(SMTP_PASS)); step = 6; }
|
|
else if (step === 6 && code === 235) { send('MAIL FROM:<' + SMTP_USER + '>'); step = 7; }
|
|
else if (step === 7 && code === 250) { send('RCPT TO:<' + MAIL_TO + '>'); step = 8; }
|
|
else if (step === 8 && code === 250) { send('DATA'); step = 9; }
|
|
else if (step === 9 && code === 354) { send(msg + CRLF + '.'); step = 10; }
|
|
else if (step === 10 && code === 250) { send('QUIT'); if (!done) { done = true; resolve(); } }
|
|
else if (code >= 400) { if (!done) { done = true; reject(new Error('SMTP ' + code + ': ' + line)); } }
|
|
}
|
|
}
|
|
|
|
socket.on('data', onData);
|
|
socket.on('error', function(e) { if (!done) { done = true; reject(e); } });
|
|
setTimeout(function() { if (!done) { done = true; reject(new Error('SMTP timeout')); } }, 15000);
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
sendFeedbackMail
|
|
};
|