Laatst bijgewerkt: 2026-06-04 Β· server: vps-079bea53 (51.75.247.161) Β· mail.vindlokaal.eu
βββββββββββββββ
inkomende mail βββΆ β Postfix β βββΆ Dovecot LMTP βββΆ /var/vmail/<domain>/<user>/
(port 25 SMTP) β multi-domainβ IMAP (port 993 TLS)
β + Rspamd β β²
βββββββββββββββ β
β master-user auth
β
βββββββββββββββββββββββββββββββββ
β Orchestrator (Node.js) β
β - polls IMAP every 60s β
β - classifies via OpenAI β
β - matcht FAQ β
β - logs questions β
β - sends via Resend API β
β - rate-limited campagnes β
β - webhook :3001 (Resend) β
βββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββ
β Pocketbase (port 8090) β
β - mailboxes / agents β
β - email_events β
β - faq_templates β
β - questions_log β
β - opt_outs β
β - campaigns / lists β
ββββββββββββββββββββββββββββββ
β²
β websocket realtime
ββββββββββββββββββββββββββββββ
β Dashboard (HTML/JS SPA) β
β /var/www/dashboard/ β
β served by nginx :443 β
ββββββββββββββββββββββββββββββ
| Service | Port | Status check | Logs |
|---|---|---|---|
| Postfix (SMTP) | 25, 587 (submission) | systemctl status postfix | /var/log/mail.log |
| Dovecot (IMAP/LMTP) | 993 IMAPS, 24 LMTP | systemctl status dovecot | journalctl -u dovecot |
| Rspamd (spam filter) | 11334 (web UI) | systemctl status rspamd | /var/log/rspamd/ |
| Pocketbase (backend) | 8090 (lokaal) | systemctl status pocketbase | journalctl -u pocketbase |
| MailPlatform orchestrator | 3001 webhook | systemctl status mailplatform-orchestrator | journalctl -u mailplatform-orchestrator -f |
| Nginx (reverse proxy) | 80, 443 | systemctl status nginx | /var/log/nginx/ |
| Roundcube (webmail) | via nginx /webmail/ | β | /var/log/php-fpm/ |
| Redis (Rspamd cache) | 6379 (lokaal) | systemctl status redis | journalctl -u redis |
proxy_http_version 1.1; hebben anders breken realtime websockets en sommige queries (default HTTP/1.0 mismatch met Go HTTP/2 backend).| Domein | Mailbox | Brand | Status |
|---|---|---|---|
| vindlokaal.eu | info@, noreply@ | VindLokaal (blauw) | active, verified |
| simpelscherm.nl | info@ | Simpelscherm (paars) | active |
| displayscherm.nl | info@ | Displayscherm (rood) | active |
| safescherm.nl | info@ | Safescherm (oranje) | active |
| safetycircle.live | info@ | SafetyCircle (groen) | active |
Resend DKIM/SPF/DMARC records staan in OVH DNS van elk domein. Verification status checken:
curl -H "Authorization: Bearer $(cat /home/jojo/.credentials/resend-api-key)" \
https://api.resend.com/domains | jq '.data[] | {name, status}'
Alle gevoelige keys staan in /home/jojo/.credentials/ (chmod 600). Per file:
| File | Inhoud |
|---|---|
mail-users.json | Mailbox-wachtwoorden voor IMAP/SMTP |
mail-master-pw | Dovecot master-user wachtwoord (orchestrator gebruikt dit om als elke mailbox in te loggen) |
resend-api-key | Resend Pro API key ($20/maand plan) |
resend-webhook-secret | HMAC signing secret voor webhook events |
openai-api-key | OpenAI key (gpt-4o-mini, ~$0.0003 per email) |
ovh.json | OVH API (appKey, appSecret, consumerKey) |
Op de VPS staat een kopie in /etc/mailplatform/.env (systemd reads this).
De orchestrator is een Node.js service die elke 60 seconden:
File: /home/ubuntu/mailplatform/orchestrator/orchestrator.js
Systemd: /etc/systemd/system/mailplatform-orchestrator.service
Env: /etc/mailplatform/.env
4 checks om mail-loops te voorkomen:
Vanilla JS SPA met Pocketbase SDK. Tabs:
Login: superuser (ravensbosmedia@gmail.com) via PB authStore.
Workflow:
email,name,company per regel, header optioneel{{name}}, {{email}}, {{company}} placeholders, zet rate (default 25/uur)// node script
const pb = new PocketBase('https://mail.vindlokaal.eu');
await pb.collection('_superusers').authWithPassword(...);
const list = await pb.collection('email_lists').create({name, domain, description});
for (const email of leads) {
await pb.collection('list_members').create({list: list.id, email, name, status: 'active'});
}
const camp = await pb.collection('campaigns').create({
name, list: list.id, mailbox: mbId,
subject: 'Hoi {{name}}', body_html: '<p>...</p>',
rate_per_hour: 25, status: 'draft', total_recipients: leads.length,
});
// Dan campaign_recipients records aanmaken + status='running' zetten
faq_templates collection bevat kant-en-klare antwoorden:
code β unieke identifier (bv "claim_pagina")triggers β JSON array met keywords (bv ["claim", "claimen"])subject, body_html β template (mag {{name}} bevatten)help_url β link naar handleiding-paginadomain β beperkt tot 1 domein, of leeg = alleuse_count β counter (wordt opgehoogd bij match)Self-learning: elke mail wordt geanalyseerd door OpenAI, krijgt een topic-label (bv "vragen over claim-proces"). Per topic+mailbox combinatie wordt counter opgehoogd in questions_log. Bij count β₯ 3 zonder FAQ-match β suggested_for_faq=true β dashboard toont "β οΈ Maak FAQ?" badge.
Handleiding-pagina's: /var/www/dashboard/help/ met screenshots in /var/www/dashboard/help-images/.
Volledig geautomatiseerd via één script:
node /home/jojo/mailplatform/scripts/add-domain.cjs \ <domain> <brand> <accent_hex> <grad1> <grad2> "<tagline>" # Voorbeeld: node add-domain.cjs simpelscherm.nl Simpelscherm "#9b59b6" "#9b59b6" "#8e44ad" \ "Het simpele digitale infoscherm voor jouw bedrijf"
Dit doet automatisch:
/home/jojo/.credentials/mail-users.json. Theme toevoegen in orchestrator.js (functie wrapEmailHtml, themes-map).ssh vindlokaal-mail 'sudo systemctl status mailplatform-orchestrator' ssh vindlokaal-mail 'sudo journalctl -u mailplatform-orchestrator -n 50 --no-pager'
ssh vindlokaal-mail 'sudo tail -50 /var/log/mail.log' # check Postfix queue: ssh vindlokaal-mail 'sudo mailq'
Check Pocketbase + nginx HTTP/1.1 setting (zie hierboven). Browser console β check websocket connection.
# Test endpoint: curl https://mail.vindlokaal.eu/webhook/health # Bekijk dashboard.resend.com β Webhooks β Recent deliveries
Belangrijk om te backuppen:
| Wat | Locatie op VPS |
|---|---|
| Pocketbase database | /home/ubuntu/pocketbase/pb_data/ |
| Postfix mailusers SQLite | /etc/postfix/sqlite/mailusers.db |
| Mailboxes (vmail) | /var/vmail/ |
| Postfix config | /etc/postfix/ |
| Dovecot config | /etc/dovecot/ |
| Nginx vhost | /etc/nginx/sites-enabled/mail.vindlokaal.eu |
| Orchestrator code | /home/ubuntu/mailplatform/ |
| Dashboard | /var/www/dashboard/ |
| Let's Encrypt certs | /etc/letsencrypt/ |
Snapshot suggestie: OVH snapshot dagelijks via control panel, of rsync naar Jojo-server:
rsync -avz vindlokaal-mail:/home/ubuntu/pocketbase/pb_data/ \ /home/jojo/backups/mailplatform/pb_data-$(date +%Y%m%d)/
π Complete API docs: marketing.vindlokaal.eu/docs/api.html
β Checklist nieuw platform: stappenplan voor toevoegen van een platform
Apart subdomein marketing.vindlokaal.eu draait nu naast mail-platform. Bevat: funnels (drip campaigns), templates-library, kennisbank met semantic search, categorie-regels, learning queue. Deelt zelfde Pocketbase-database β wijzigingen werken direct door in mail-orchestrator.
Naast de oude knowledge_base (korte snippets) is er nu kb_documents + kb_chunks met OpenAI embeddings. Upload PDF/MD docs β automatisch gechunkt + embed. AI zoekt semantisch (niet alleen keywords). Per doc scope: internal / customer_facing / both. Mail-orchestrator gebruikt deze via marketing-hub /api/v1/ask.
Per (platform, categorie) bepaal je: welke docs AI mag raadplegen, strictness (STRICT_DOCS / SOEPEL_DOCS / ALTIJD_ESCALATE / AUTO_RESPOND / AUTO_DELETE), min confidence. Defense-in-depth: bij klant-replies wordt internal docs automatisch geweigerd.
Bij elke ESCALATE β automatisch in learning_queue. Mens antwoordt vanuit dashboard. Met 1-klik "π Voeg toe aan KB" wordt vraag+antwoord aan kennisbank toegevoegd. AI weet het volgende keer.
Systemd service die elke 5 min checkt op anomalieΓ«n (te veel escalaties, failed mails, bouncerate, engine-stall) en alerts stuurt via Telegram. Plus dagelijks 08:00 rapport met mail-volumes, conversies, OpenAI-kosten. Alerts gedupliceerd (zelfde alert max 1Γ per uur).
Inbox-tab in dashboard heeft nu: KPI-cards bovenaan (Wacht op JOU / Door AI / Binnen vandaag), 3 tabjes (Wacht op JOU / Alles / Afgehandeld), urgent-mails krijgen rode rand + URGENT-badge, status-tooltips met uitleg, prominente "Reden"-blok bij failed/escalated mails, auto-refresh via websocket (geen F5 meer nodig).
In marketing-hub template-editor en KB-doc-editor: knop "π· Plak screenshot/image" β file picker β upload naar /var/www/marketing/uploads/ β image-tag automatisch ingevoegd. Bestanden publiek via https://marketing.vindlokaal.eu/uploads/..., max 5MB.
Naast info@ heeft elk domein nu ook facturen@ met eigen agent + facturatie-prompt (categorieΓ«n: factuur_kwijt, betalingstermijn, bedrag_klopt_niet, etc.). 13 mailboxen totaal.
7e platform: TodlerTube β veilig videoplatform voor toddlers. Roze branding-theme.
Parallel op billing.vindlokaal.eu β eigen Postgres + cookie-login + p-queue (anti-crash). Pollers nog op Jojo tot user "cutover" zegt.
Voor vragen / aanpassingen: zie source in /home/ubuntu/mailplatform/ op de VPS, of /home/jojo/mailplatform/scripts/ lokaal.