# Mail-Service mit Brevo SMTP Ein Node.js-basierter Mail-Service mit Weboberfläche zum Versenden von E-Mails über Brevo (ehemals Sendinblue) SMTP. Inklusive persistenter Versand-Historie und eingebettetem Bild-Footer. ## Features - **Weboberfläche** zum Versenden von E-Mails (Empfänger, CC, Betreff, Text/HTML) - **Persistente Historie** in SQLite-Datenbank - **Eingebetteter Bild-Footer** via CID-Attachment (wird ohne "Bilder anzeigen" dargestellt) - **REST-API** für programmatischen Zugriff - **Brevo SMTP** mit DKIM/SPF/DMARC-Unterstützung ## Projektstruktur ``` mail-service/ ├── .env # Konfiguration (nicht im Git) ├── .env.example # Vorlage ├── package.json ├── src/ │ ├── server.js # Express-Server, API-Routen │ ├── mailer.js # Nodemailer mit CID-Footer │ └── database.js # SQLite-Setup und Queries ├── public/ │ ├── index.html # Weboberfläche │ ├── style.css # Styling │ └── script.js # Frontend-Logik ├── assets/ │ └── homeicon.png # Footer-Bild (40x40 PNG) └── data/ └── emails.db # SQLite-Datenbank (automatisch erstellt) ``` ## Installation ```bash # Repository klonen git clone https://git.unixweb.net/joachim/mail-service-embedded.git cd mail-service-embedded # Dependencies installieren npm install # Konfiguration erstellen cp .env.example .env # .env bearbeiten und SMTP-Credentials eintragen ``` ## Konfiguration (.env) ```env # Server PORT=3000 # Email Configuration MAIL_PROVIDER=smtp MAIL_FROM_EMAIL=noreply@example.com MAIL_FROM_NAME=Secure Portal MAIL_FOOTER_NAME=Dein Name # SMTP (Brevo) SMTP_HOST=smtp-relay.brevo.com SMTP_PORT=587 SMTP_USER=deine-email@example.com SMTP_PASSWORD=dein-brevo-smtp-key SMTP_SECURE=false ``` ### Brevo SMTP-Key erstellen 1. Bei [Brevo](https://www.brevo.com) einloggen 2. Gehe zu: Einstellungen → SMTP & API → SMTP 3. "SMTP-Schlüssel generieren" klicken 4. Schlüssel in `.env` als `SMTP_PASSWORD` eintragen ## Starten ```bash # Produktion npm start # Entwicklung (mit Auto-Reload) npm run dev ``` Server läuft auf: http://localhost:3000 ## API-Endpunkte | Methode | Route | Beschreibung | |---------|-------|--------------| | GET | `/` | Weboberfläche | | POST | `/api/send` | E-Mail versenden | | GET | `/api/history` | Historie abrufen (letzte 50) | | DELETE | `/api/history/:id` | Einzelnen Eintrag löschen | | DELETE | `/api/history` | Gesamte Historie löschen | ### POST /api/send **Request Body:** ```json { "to": "empfaenger@example.com", "cc": "optional@example.com", "subject": "Betreff", "body": "Nachrichteninhalt", "isHtml": false } ``` **Response (Erfolg):** ```json { "success": true, "message": "E-Mail erfolgreich gesendet", "messageId": "", "id": 1 } ``` **Response (Fehler):** ```json { "success": false, "error": "Versand fehlgeschlagen: Connection refused", "id": 2 } ``` ## Datenbank-Schema **Tabelle `emails`:** | Spalte | Typ | Beschreibung | |--------|-----|--------------| | id | INTEGER | Primary Key, Auto-Increment | | to_email | TEXT | Empfänger-Adresse | | cc_email | TEXT | CC-Adresse (optional) | | subject | TEXT | Betreff | | body | TEXT | Nachrichteninhalt | | is_html | INTEGER | 0 = Text, 1 = HTML | | status | TEXT | "success" oder "failed" | | error_message | TEXT | Fehlermeldung (bei Fehler) | | created_at | TEXT | ISO-Timestamp | ## Bild-Footer mit CID-Embedding Der Footer mit eingebettetem Bild wird automatisch an jede E-Mail angehängt. ### Warum CID statt externe URL? | Methode | Gmail-Verhalten | |---------|-----------------| | `` | Blockiert, "Bilder anzeigen" nötig | | `` | Sofort sichtbar | ### Implementierung (mailer.js) ```javascript // 1. Bild als Anhang mit Content-ID attachments: [ { filename: 'homeicon.png', path: '/pfad/zu/assets/homeicon.png', cid: 'homeicon' // Referenz-ID } ] // 2. Im HTML referenzieren ``` ### Footer anpassen 1. **Bild ändern:** `assets/homeicon.png` ersetzen (empfohlen: 40x40 PNG) 2. **Name ändern:** In `.env` setzen: `MAIL_FOOTER_NAME=Neuer Name` 3. **Layout ändern:** In `src/mailer.js` die Funktion `getHtmlFooter()` bearbeiten ## Dependencies | Paket | Version | Beschreibung | |-------|---------|--------------| | express | ^4.18.0 | Webserver | | nodemailer | ^6.9.0 | E-Mail-Versand | | better-sqlite3 | ^11.0.0 | SQLite-Datenbank | | dotenv | ^16.4.0 | Umgebungsvariablen | ## Integration in andere Projekte ### Als Standalone-Service ```javascript // Externer Aufruf der API const response = await fetch('http://localhost:3000/api/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ to: 'empfaenger@example.com', subject: 'Test', body: 'Hallo Welt', isHtml: false }) }); const result = await response.json(); ``` ### Mailer-Modul extrahieren Die Datei `src/mailer.js` kann direkt in andere Node.js-Projekte kopiert werden: ```javascript require('dotenv').config(); const mailer = require('./mailer'); // E-Mail senden await mailer.sendMail({ to: 'empfaenger@example.com', cc: null, subject: 'Betreff', body: '

HTML-Inhalt

', isHtml: true }); // SMTP-Verbindung prüfen const status = await mailer.verifyConnection(); console.log(status.success ? 'OK' : status.error); ``` ## Fehlerbehandlung | Fehler | Ursache | Lösung | |--------|---------|--------| | `ECONNREFUSED` | SMTP-Server nicht erreichbar | Host/Port in .env prüfen | | `Invalid login` | Falsche Credentials | SMTP_USER/PASSWORD prüfen | | `EADDRINUSE` | Port bereits belegt | Anderen PORT in .env setzen | | `Ungültige E-Mail` | Validierung fehlgeschlagen | E-Mail-Format prüfen | ## Lizenz ISC