Utviklere → Veiledninger

Motta e-post i appen din

Supportsaker, svar på varsler, dokumenter sendt til en bot: e-post til en adresse på domenet ditt kommer til HTTPS-endepunktet ditt som én signert JSON-POST, med teksten, HTML-en og alle vedlegg. Ingen postkasse å polle og ingen IMAP.

Dette trenger du

  • Et domene registrert hos NameOcean: videresending og e-post til webhook er gratis for disse.
  • Et HTTPS-endepunkt på en offentlig adresse som svarer innen 20 sekunder.
  • nameocean-CLI-en, eller en API-nøkkel med email:write.

1. Slå på videresending for domenet

nameocean
$ nameocean email forwards on example.com

Dette peker domenets MX-post til NameOceans e-postvideresendere. Hvis domenet allerede har MX-poster, for postkasser et annet sted, stopper kommandoen og viser dem: all e-post til domenet ville blitt flyttet hit. Legg til --replace-mx bare når det er det du ønsker.

2. Be om e-post til webhook

Posting av e-post til en URL åpnes per konto etter en kort gjennomgang, for å holde spam-reléer ute. På domenets side under Dashbord → E-postvideresending kan du be om det med en linje om hva du skal bruke det til. Inntil da svarer API-et 403 not_approved.

3. Send en adresse til endepunktet ditt

nameocean
$ nameocean email inbound add example.com support https://app.example.com/hooks/mail
curl
$ 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"}'

Svaret inneholder signeringshemmeligheten (whsec_…); lagre den i appens innstillinger. localpart * sender alle adresser på domenet som ikke har et eget alias. Et domene kan ha opptil tre slike webhooker.

4. Motta den

Verifiser signaturen over den rå meldingskroppen, og les deretter JSON-en. En liten Flask-mottaker:

app.py
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

Dette kommer frem

POST https://app.example.com/hooks/mail
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 forblir den samme når en e-post postes på nytt, så bruk den til å hoppe over duplikater. in_reply_to og references forteller deg hvilke av dine egne e-poster noen svarte på.

Når endepunktet ditt er nede

  • Et 2xx-svar betyr levert. En 408, 429, 5xx, et tidsavbrudd (20 sekunder) eller ingen tilkobling forsøkes på nytt i 6 timer.
  • Alle andre 4xx er endelige: e-posten postes ikke på nytt av seg selv.
  • E-post som ikke kunne postes, lagres i 30 dager. Finn den med nameocean email forwards log example.com (eller GET /email/forwarding/example.com/messages) og frigi den: den postes én gang til, med samme id.
  • Opptil 500 e-poster per dag per domene går til webhooker; e-post utover det holdes tilbake på samme måte.