Supporttickets, antwoorden op meldingen, documenten die naar een bot worden gemaild: mail aan een adres op uw domein komt als één ondertekende JSON-POST binnen op uw HTTPS-endpoint, met de tekst, de HTML en alle bijlagen. Geen mailbox om te pollen en geen IMAP.
email:write.$ nameocean email forwards on example.com
Hiermee verwijst het MX-record van het domein naar de mailforwarders van NameOcean. Heeft het domein al MX-records, voor mailboxen elders, dan stopt het commando en toont het deze: alle mail voor het domein zou dan hierheen gaan. Voeg --replace-mx alleen toe als u dat echt wilt.
Mail naar een URL posten wordt per account vrijgegeven na een korte beoordeling, om spamrelays te weren. Vraag het aan op de pagina van het domein onder Dashboard → E-mail doorsturen, met een korte toelichting op waarvoor u het gebruikt. Tot die tijd antwoordt de API met 403 not_approved.
$ nameocean email inbound add example.com support https://app.example.com/hooks/mail
$ curl -X POST https://nameocean.net/api/v1/email/forwarding/example.com/webhooks \ -H "Authorization: Bearer $NAMEOCEAN_API_KEY" -H "Content-Type: application/json" \ -d '{"localpart": "support", "url": "https://app.example.com/hooks/mail"}'
Het antwoord bevat het ondertekeningsgeheim (whsec_…); bewaar dit in de instellingen van uw app. Met localpart * wordt elk adres van het domein doorgestuurd dat geen eigen alias heeft. Een domein kan maximaal drie van deze webhooks hebben.
Verifieer de handtekening over de onbewerkte body en lees daarna de JSON. Een kleine Flask-ontvanger:
import base64, hashlib, hmac, json, os, time
from flask import Flask, abort, request
app = Flask(__name__)
SECRET = os.environ["NAMEOCEAN_WEBHOOK_SECRET"] # whsec_...
def verified(header, body, tolerance=300):
fields = dict(part.split("=", 1) for part in header.split(",") if "=" in part)
ts = int(fields.get("t", "0"))
if abs(time.time() - ts) > tolerance:
return False
expected = hmac.new(SECRET.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, fields.get("v1", ""))
@app.post("/hooks/mail")
def mail():
body = request.get_data()
if not verified(request.headers.get("X-NameOcean-Signature", ""), body):
abort(401)
mail = json.loads(body)
print(mail["envelope"]["from"], "→", mail["envelope"]["to"], mail["subject"])
for a in mail["attachments"]:
data = base64.b64decode(a["content_base64"])
print(" attachment", a["filename"], a["content_type"], len(data), "bytes")
return "", 204 # any 2xx: delivered
X-NameOcean-Event: email.received
X-NameOcean-Delivery: 6f1c2a4e-8b3d-4f5a-9c7e-1d2b3a4c5e6f
X-NameOcean-Signature: t=1794300000,v1=5f2b…
{
"id": "6f1c2a4e-8b3d-4f5a-9c7e-1d2b3a4c5e6f",
"event": "email.received",
"received_at": "2026-11-11T09:30:12+00:00",
"envelope": {"from": "alice@example.org", "to": "support@example.com"},
"from": "Alice <alice@example.org>",
"to": "support@example.com",
"cc": null,
"reply_to": null,
"subject": "Order 1042",
"date": "Wed, 11 Nov 2026 09:30:05 +0000",
"message_id": "<…@example.org>",
"in_reply_to": null,
"references": null,
"text": "Hi…",
"html": "<p>Hi…</p>",
"headers": [["From", "Alice <alice@example.org>"], …],
"attachments": [{"filename": "invoice.pdf", "content_type": "application/pdf", "content_id": null,
"size": 48211, "content_base64": "JVBERi0…"}],
"spam_score": 0.4,
"size": 66120
}
id blijft gelijk wanneer een mail opnieuw wordt gepost, dus gebruik dit om duplicaten over te slaan. in_reply_to en references vertellen u op welke van uw eigen mails iemand heeft geantwoord.
nameocean email forwards log example.com (of GET /email/forwarding/example.com/messages) en geef hem vrij: hij wordt dan nogmaals gepost, met dezelfde id.