πŸ“§ MailPlatform β€” Documentatie

Laatst bijgewerkt: 2026-06-04 Β· server: vps-079bea53 (51.75.247.161) Β· mail.vindlokaal.eu

Inhoud

1. Architectuur

                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   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      β”‚
                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Services & poorten

ServicePortStatus checkLogs
Postfix (SMTP)25, 587 (submission)systemctl status postfix/var/log/mail.log
Dovecot (IMAP/LMTP)993 IMAPS, 24 LMTPsystemctl status dovecotjournalctl -u dovecot
Rspamd (spam filter)11334 (web UI)systemctl status rspamd/var/log/rspamd/
Pocketbase (backend)8090 (lokaal)systemctl status pocketbasejournalctl -u pocketbase
MailPlatform orchestrator3001 webhooksystemctl status mailplatform-orchestratorjournalctl -u mailplatform-orchestrator -f
Nginx (reverse proxy)80, 443systemctl status nginx/var/log/nginx/
Roundcube (webmail)via nginx /webmail/β€”/var/log/php-fpm/
Redis (Rspamd cache)6379 (lokaal)systemctl status redisjournalctl -u redis
Belangrijk: Nginx proxy_pass naar Pocketbase MOET proxy_http_version 1.1; hebben anders breken realtime websockets en sommige queries (default HTTP/1.0 mismatch met Go HTTP/2 backend).

3. Domeinen & mailboxen

DomeinMailboxBrandStatus
vindlokaal.euinfo@, noreply@VindLokaal (blauw)active, verified
simpelscherm.nlinfo@Simpelscherm (paars)active
displayscherm.nlinfo@Displayscherm (rood)active
safescherm.nlinfo@Safescherm (oranje)active
safetycircle.liveinfo@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}'

4. Credentials

Alle gevoelige keys staan in /home/jojo/.credentials/ (chmod 600). Per file:

FileInhoud
mail-users.jsonMailbox-wachtwoorden voor IMAP/SMTP
mail-master-pwDovecot master-user wachtwoord (orchestrator gebruikt dit om als elke mailbox in te loggen)
resend-api-keyResend Pro API key ($20/maand plan)
resend-webhook-secretHMAC signing secret voor webhook events
openai-api-keyOpenAI key (gpt-4o-mini, ~$0.0003 per email)
ovh.jsonOVH API (appKey, appSecret, consumerKey)

Op de VPS staat een kopie in /etc/mailplatform/.env (systemd reads this).

5. Orchestrator (AI-laag)

De orchestrator is een Node.js service die elke 60 seconden:

  1. Pending dashboard-approvals verstuurt (status=approve_requested)
  2. Bulk-mail campagnes verwerkt (rate-limited per uur)
  3. IMAP polled voor alle actieve mailboxen
  4. Nieuwe mails classificeert via OpenAI (gpt-4o-mini)
  5. FAQ matched op trigger-keywords β†’ kant-en-klare reply
  6. Vragen logt in questions_log voor self-learning
  7. Auto-reply verstuurt (na 4 loop-checks) of escaleert naar Telegram

File: /home/ubuntu/mailplatform/orchestrator/orchestrator.js

Systemd: /etc/systemd/system/mailplatform-orchestrator.service

Env: /etc/mailplatform/.env

Auto-reply loop-prevention

4 checks om mail-loops te voorkomen:

  1. Subject begint met "Re: Re:" β†’ skip (te diep)
  2. From-adres == eigen mailbox β†’ skip (self-loop)
  3. From-adres staat in opt_outs β†’ skip
  4. AI concept_reply is leeg of trigger == auto_reply/bounce/spam β†’ skip

6. Dashboard

Vanilla JS SPA met Pocketbase SDK. Tabs:

Login: superuser (ravensbosmedia@gmail.com) via PB authStore.

7. Bulk-mail campagnes

Workflow:

  1. Maak email-lijst (Campagnes tab β†’ + Nieuwe lijst)
  2. Importeer CSV: email,name,company per regel, header optioneel
  3. Maak campagne: kies lijst + mailbox, schrijf subject/body met {{name}}, {{email}}, {{company}} placeholders, zet rate (default 25/uur)
  4. Klik Start β†’ orchestrator pikt elke minuut tot rate-limit bereikt
Bv: 500 leads, 25/uur = 20 uur doorlooptijd. Opt-outs worden automatisch geskipt. Bounces β†’ status=failed, geen retry.

Programmatic campagne aanmaken

// 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

8. FAQ & self-learning

faq_templates collection bevat kant-en-klare antwoorden:

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/.

9. Nieuw domein toevoegen

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:

  1. Resend: domain aanmaken + DNS records ophalen
  2. OVH: MX + SPF + DKIM + DMARC records toevoegen
  3. Postfix: domain + info@ mailbox aanmaken in SQLite (random pw)
  4. Pocketbase: domain + mailbox + agent records aanmaken
  5. Resend verify triggeren
Vereiste: domein moet in OVH-zones staan. Voor andere registrars: DNS handmatig. Mailbox-wachtwoord toevoegen aan /home/jojo/.credentials/mail-users.json. Theme toevoegen in orchestrator.js (functie wrapEmailHtml, themes-map).

10. Troubleshooting

Orchestrator stuurt niet

ssh vindlokaal-mail 'sudo systemctl status mailplatform-orchestrator'
ssh vindlokaal-mail 'sudo journalctl -u mailplatform-orchestrator -n 50 --no-pager'

Mails komen niet binnen

ssh vindlokaal-mail 'sudo tail -50 /var/log/mail.log'
# check Postfix queue:
ssh vindlokaal-mail 'sudo mailq'

Dashboard laadt niets

Check Pocketbase + nginx HTTP/1.1 setting (zie hierboven). Browser console β†’ check websocket connection.

Resend webhook werkt niet

# Test endpoint:
curl https://mail.vindlokaal.eu/webhook/health
# Bekijk dashboard.resend.com β†’ Webhooks β†’ Recent deliveries

11. Backup & recovery

Belangrijk om te backuppen:

WatLocatie 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)/

12.

πŸ”Œ Complete API docs: marketing.vindlokaal.eu/docs/api.html

12.

βœ… Checklist nieuw platform: stappenplan voor toevoegen van een platform

12. Updates juni 2026 β€” wat is er bijgekomen

Nieuwe features die het mail-platform uitbreiden β€” niet uitgebreid hier gedocumenteerd, alleen kort vermeld zodat je weet dat ze bestaan. Volledige uitleg: zie /marketing.vindlokaal.eu/docs/.

12.1 Marketing-hub gekoppeld

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.

12.2 Kennisbank v2 (semantic search)

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.

12.3 Categorie-regels per platform

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.

12.4 Zelflerend systeem

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.

12.5 Watchman controller

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).

12.6 Inbox v2

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).

12.7 Image uploads (templates + KB)

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.

12.8 Facturen mailboxen

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.

12.9 todlertube.com toegevoegd

7e platform: TodlerTube β€” veilig videoplatform voor toddlers. Roze branding-theme.

12.10 Billing-hub gemigreerd

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.