No description
Find a file
Bram Buijs c70d5f02c1 docs: vraag erbij, catchall per domein of een mailbox per alias
Gemeten: info@ bestaat niet als mailbox, dus een mail erheen bereikt de
webhook nooit. Odoo's aliasmodel vraagt een catchall; een mailbox per
alias schaalt niet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HzHCr7zmrACmvFtrgiVAyZ
2026-09-14 18:31:44 +02:00
la_suite_messages feat: herkansen bij tijdelijke fouten, fallback per aliasdomein, tests 2026-09-12 13:37:20 +02:00
ALIASSEN-EN-DOMEINEN.md docs: een koppeling, meerdere mailboxen en domeinen via native aliassen 2026-09-12 13:22:10 +02:00
MAIL-VIA-API.md docs: de lessen als gids voor wie Odoo-mail via een API bouwt 2026-09-10 17:09:46 +02:00
OPENSTAAND.md docs: vraag erbij, catchall per domein of een mailbox per alias 2026-09-14 18:31:44 +02:00
README.md Merge messages-connector: mosa_messages-module + beantwoorde vragen 2026-09-11 10:46:16 +02:00

mosa-odoo-addons

Odoo 18 CE-modules voor de koppeling met mosa.cloud. Eerste doel: uitgaande post van Odoo via de HTTP-API van mosa.cloud, zonder SMTP. Werkt dat, dan gaat de module naar de omgevingen die via mosa.cloud mailen.

Waarom een API en geen SMTP: ons cluster draait bij OVH, en daar zijn uitgaande poorten 25, 465 en 587 dicht, naar elke bestemming. HTTPS (443) staat open.

De testomgeving

https://mosa.bb-open.com        Odoo 18 CE, kale database, jij bent beheerder

Deze repo IS de code op die omgeving. Bij elke podstart wordt tak 18.0 gekloond naar /odoo/extra-addons/mosa-odoo-addons, en dat pad staat in addons_path. Dus:

  • Modules staan in de root van de tak, elk in een eigen map (mosa_mailer/__manifest__.py, niet addons/mosa_mailer/...).
  • Een nieuwe versie uitrollen: pushen naar 18.0, verder niets. Het cluster kijkt elke twee minuten naar de kop van die tak. Is er een nieuwe commit, dan herstart Odoo, haalt de tak opnieuw op en draait odoo -u <elke module in deze repo>. Dat werkt de Apps-lijst bij en upgradet wat al geïnstalleerd is. Reken op twee tot vier minuten van push tot nieuwe code.
  • Een NIEUWE module installeer je één keer zelf, onder Apps (hij staat daar na de push). Daarna gaan upgrades vanzelf.
  • Een push herstart Odoo. Ben je of iemand anders op dat moment aan het klikken, dan valt die sessie even weg.
  • Mislukt de upgrade, dan start Odoo toch, met de vorige stand van je module in de database. Zie je je wijziging niet terug, vraag Bram om de log van upgrade-mosa-addons.
  • Er draait één Odoo-proces, met de crons erin, dus ook de mailwachtrij. Werk op een eigen tak zolang iets half af is: alles op 18.0 staat binnen een paar minuten live.
  • Je ziet de serverlog niet. Er is geen clustertoegang voor deze omgeving. Ontwerp dus zo dat een fout in Odoo zelf zichtbaar is: de reden hoort op het mail.mail-record (failure_reason, zichtbaar onder Instellingen > Technisch

    E-mails). Wil je toch een log, vraag Bram.

  • Mislukt de kloon (tak weg, repo onbereikbaar), dan start Odoo gewoon, met een lege map. Je module is dan "niet installeerbaar". Kijk bij rare verschijnselen eerst of je laatste push er echt staat.
  • Alleen wat in het image zit is beschikbaar aan Python-pakketten. requests is er. Heb je iets anders nodig, overleg eerst: dat vraagt een nieuwe imagebouw.

Deze omgeving draait bewust de kop van de tak en is dus niet reproduceerbaar. Naar een klantomgeving gaat een module via onze addons-repo en een vastgezet image, niet via deze kloon.

Lees eerst MAIL-VIA-API.md

We hebben dit al een keer gebouwd, voor Lettermint: module lettermint_mailer in bb-open/bb-open-addons op git.edano.eu (Bram geeft je leesrecht). Wat we daarvan geleerd hebben staat in MAIL-VIA-API.md: hoe Odoo post verstuurt en waar je inhaakt, de keuzes die je vooraf moet maken, hoe je het MIME-bericht omzet, een testlijst, en de negentien dingen die bij ons misgingen, met de commit die ze oploste.

De vijf die het meeste tijd kostten:

  1. Test Connection werkt, de wachtrij niet. mail.mail.send() roept eerst connect() aan en opent een SMTP-sessie naar een dichte poort. Overschrijf connect() met een nep-sessie, en test altijd via de wachtrij-cron.
  2. Wie send_email volledig overneemt, verliest Odoo's afzenderlogica. Kijk of je _prepare_email_message kunt blijven gebruiken.
  3. Geef de RFC Message-Id terug, niet het id van de provider, anders breekt de draad bij antwoorden.
  4. Bijlagen en platte tekst zijn waar de 422's vandaan komen: lege platte tekst, CSS in de tekst, een bijlage die niet decodeert, inline-afbeeldingen die verdwijnen.
  5. Groen in Odoo betekent alleen "aangenomen door de API". Zorg dat een kapotte koppeling zichtbaar is zonder serverlog.

Kijk in lettermint_mailer op tak 19.0 voor de laatste fixes; 18.0 mist v1.4.4 en v1.4.5. github.com/brambuijs/lettermint_mailer is een oude kopie van v1.2, gebruik die niet.

Antwoorden van mosa.cloud

De open vragen van hierboven, beantwoord vanuit de Messages-broncode (defaults; per omgeving instelbaar via env-variabelen):

  • Eindpunt en authenticatie. POST /api/v1.0/submit/ op de instance-URL (bv. https://mail.demo.mosacloud.eu), body message/rfc822. Headers: X-Channel-Id + X-API-Key (een msgk_…-key) plus X-Mail-From (mailbox-UUID) en X-Rcpt-To (envelop, komma-gescheiden; hier horen ook de BCC's — een Bcc-header wordt geweigerd). NIET Authorization: Bearer (les 14). Keys zijn "channels" met een scope: per mailbox, per maildomein of instance-breed (global). Wij gebruiken een global key met messages:send + mailboxes:read; die tweede scope geeft GET /api/v1.0/provisioning/mailboxes/?email=… voor adres→UUID-resolutie. Elke omgeving eigen channels; provisioning gebeurt met een idempotente Job in de mosa.cloud-infra die de credentials in een Kubernetes-Secret schrijft (odoo-connector-credentials) — geen mens kopieert een one-time-secret.
  • Afzenderdomein. Messages tekent DKIM zelf bij de submit; de From moet exact bij de mailbox-UUID horen, anders 403. De benodigde DNS-records per domein zijn op te vragen via GET /api/v1.0/provisioning/maildomains/dns/ (scope maildomains:read).
  • Limieten. Uitgaand MIME max ± 33 MB (body 5 MiB + bijlagen 20 MiB × 1,4 base64-factor), maximaal 500 ontvangers per bericht (to+cc+bcc). Throttling op externe ontvangers per mailbox/maildomein is instelbaar (standaard uit) en geeft HTTP 429. Inkomend max 10 MiB.
  • Inline-afbeeldingen en eigen headers. Geen beperking: de rauwe MIME gaat onaangetast door, dus Content-ID's, Message-Id, In-Reply-To en References blijven exact zoals Odoo ze bouwde.
  • Afleverstatus en bounces. Bestaat nog niet: de webhooktriggers zijn vandaag alleen inkomend (message.inbound/delivering/delivered); message.sent staat in de Messages-code genoteerd als toekomstig event. Groen in Odoo betekent dus ook hier "aangenomen door de API" (les 15).
  • Inkomende post via webhook. Ja: webhookchannel met format: eml en trigger message.delivered, POST van de rauwe RFC 822 naar /mosa_messages/webhook. Ondertekening: statische whk_…-key of HS256-JWT met body_sha256-claim (beide gedekt door de module). Bezorging is at-least-once; Odoo dedupliceert op Message-ID.
  • SMTP-poort naast de API. Nee. De mta-in van Messages doet alleen inkomend; er is geen submission-poort à la Lettermint 2525. De API is de route — en dat is ook de bedoeling: alleen zo staat de mail in de verzonden-items van de gedeelde mailbox.

Afspraken

  • Tak 18.0 is wat er op de testomgeving draait. Werk op een eigen tak en voeg samen als het werkt, dan blijft de omgeving bruikbaar.
  • Versie in het manifest als 18.0.x.y.z.
  • Geen tokens, wachtwoorden of klantgegevens in deze repo, ook niet in voorbeelden of tests.
  • Vragen, herstarts, logs: Bram.