#!/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 Empfänger (Pflicht, außer bei --verify) --number Invoice-Nummer (default: TEST-1001) --stripe Stripe-Zahlungslink (optional) --text Eigener Nachrichtentext (optional) --pdf 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 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) : `

Hallo,

dies ist eine Test-Rechnung zur Prüfung der Zustellbarkeit über den Docker-Mailserver-Relay.

Wenn diese Mail ankommt, funktioniert der neue Sendeweg.

Viele Grüße
Bay Area Affiliates, Inc.

`; 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();