Files
invoice-system/send-test-invoice.js
2026-07-07 13:43:00 -05:00

169 lines
6.3 KiB
JavaScript

#!/usr/bin/env node
// send-test-invoice.js
//
// Eigenständiges CLI-Tool zum Testen von email-service.js OHNE die Invoicing-App.
// Nutzt denselben SMTP-Relay-Weg (Docker-Mailserver -> SES) wie der echte Versand,
// damit du die M365-Zustellbarkeit isoliert prüfen kannst.
//
// -----------------------------------------------------------------------------
// SETUP
// 1) Lege email-service.js im selben Ordner ab (oder passe den require-Pfad an).
// 2) Setze die SMTP-Env-Variablen (siehe email-service.js), z.B. per .env:
// export SMTP_HOST=mail.bayarea-cc.com
// export SMTP_PORT=587
// export SMTP_USER=accounting@bayarea-cc.com
// export SMTP_PASS='...'
// 3) npm i nodemailer mjml (falls noch nicht vorhanden)
//
// -----------------------------------------------------------------------------
// VERWENDUNG
//
// # Nur die SMTP-Verbindung prüfen (Login + TLS), ohne zu senden:
// node send-test-invoice.js --verify
//
// # Test-Rechnung an eine Adresse senden:
// node send-test-invoice.js --to lcart@meyernow.com
//
// # Mit Stripe-Link und echtem PDF-Anhang:
// node send-test-invoice.js --to lcart@meyernow.com \
// --stripe https://buy.stripe.com/test_xxx \
// --pdf ./sample-invoice.pdf \
// --number TEST-1001
//
// # Mehrere Empfänger (kommagetrennt):
// node send-test-invoice.js --to a@x.com,b@y.com
//
// # Ohne Stripe-Button, eigener Text:
// node send-test-invoice.js --to lcart@meyernow.com \
// --text "Hallo, anbei die Test-Rechnung. Viele Grüße"
//
// -----------------------------------------------------------------------------
const fs = require('fs');
const path = require('path');
// Pfad ggf. anpassen, falls email-service.js woanders liegt
const { sendInvoiceEmail, verifyConnection } = require('./src/services/email-service');
// ------------------------------------------------------------
// Minimaler Arg-Parser (--key value und --flag)
// ------------------------------------------------------------
function parseArgs(argv) {
const args = {};
for (let i = 0; i < argv.length; i++) {
const a = argv[i];
if (a.startsWith('--')) {
const key = a.slice(2);
const next = argv[i + 1];
if (next === undefined || next.startsWith('--')) {
args[key] = true; // boolean flag
} else {
args[key] = next;
i++;
}
}
}
return args;
}
function printHelp() {
console.log(`
send-test-invoice.js — Test-Tool für email-service.js
Optionen:
--to <addr[,addr]> Empfänger (Pflicht, außer bei --verify)
--number <str> Invoice-Nummer (default: TEST-1001)
--stripe <url> Stripe-Zahlungslink (optional)
--text <str> Eigener Nachrichtentext (optional)
--pdf <pfad> PDF-Anhang von Datei (optional)
--verify Nur SMTP-Verbindung prüfen, nicht senden
--help Diese Hilfe
Beispiel:
node send-test-invoice.js --to lcart@meyernow.com --number TEST-1001 \\
--stripe https://buy.stripe.com/test_xxx --pdf ./sample.pdf
`);
}
async function main() {
const args = parseArgs(process.argv.slice(2));
if (args.help) {
printHelp();
return;
}
// --- Nur Verbindung prüfen ---
if (args.verify) {
process.stdout.write(`Prüfe SMTP-Verbindung zu ${process.env.SMTP_HOST || 'mail.bayarea-cc.com'} ... `);
try {
await verifyConnection();
console.log('OK — Login und TLS erfolgreich.');
} catch (err) {
console.log('FEHLGESCHLAGEN.');
console.error(err && err.message ? err.message : err);
process.exitCode = 1;
}
return;
}
// --- Empfänger prüfen ---
if (!args.to || args.to === true) {
console.error('Fehler: --to <adresse> ist erforderlich (oder --verify verwenden).');
printHelp();
process.exitCode = 1;
return;
}
const recipients = String(args.to).split(',').map(s => s.trim()).filter(Boolean);
// --- PDF-Anhang optional laden ---
let pdfBuffer = null;
if (args.pdf && args.pdf !== true) {
const pdfPath = path.resolve(String(args.pdf));
if (!fs.existsSync(pdfPath)) {
console.error(`Fehler: PDF nicht gefunden: ${pdfPath}`);
process.exitCode = 1;
return;
}
pdfBuffer = fs.readFileSync(pdfPath);
console.log(`PDF-Anhang geladen: ${pdfPath} (${pdfBuffer.length} Bytes)`);
}
// --- Test-Invoice-Objekt ---
const invoice = {
id: 'test',
invoice_number: args.number && args.number !== true ? String(args.number) : 'TEST-1001',
};
const customText = (args.text && args.text !== true)
? String(args.text)
: `<p>Hallo,</p><p>dies ist eine <strong>Test-Rechnung</strong> zur Prüfung der Zustellbarkeit über den Docker-Mailserver-Relay.</p><p>Wenn diese Mail ankommt, funktioniert der neue Sendeweg.</p><p>Viele Grüße<br/>Bay Area Affiliates, Inc.</p>`;
const stripeUrl = (args.stripe && args.stripe !== true) ? String(args.stripe) : null;
console.log('---');
console.log('An: ', recipients.join(', '));
console.log('Invoice-Nummer:', invoice.invoice_number);
console.log('Stripe-Link: ', stripeUrl || '(keiner)');
console.log('PDF-Anhang: ', pdfBuffer ? 'ja' : 'nein');
console.log('---');
try {
const info = await sendInvoiceEmail(invoice, recipients, customText, stripeUrl, pdfBuffer);
console.log('Gesendet.');
console.log(' messageId:', info.messageId);
if (info.accepted) console.log(' accepted: ', info.accepted.join(', '));
if (info.rejected && info.rejected.length) console.log(' rejected: ', info.rejected.join(', '));
if (info.response) console.log(' response: ', info.response);
console.log('\nHinweis: "accepted" bedeutet nur, dass der Docker-Mailserver die Mail');
console.log('angenommen hat. Ob M365 sie zustellt oder quarantänisiert, zeigt erst');
console.log('der Posteingang/Quarantäne des Empfängers bzw. das SES-Delivery-Event.');
} catch (err) {
console.error('Senden fehlgeschlagen:');
console.error(err && err.message ? err.message : err);
process.exitCode = 1;
}
}
main();