Utvecklare → Guider

Ta emot e-post i din app

Supportärenden, svar på aviseringar, dokument som mejlas till en bot: e-post till en adress på din domän kommer fram till din HTTPS-endpoint som en enda signerad JSON-POST, med texten, HTML-koden och alla bilagor. Ingen brevlåda att polla och ingen IMAP.

Det här behöver du

  • En domän registrerad hos NameOcean: vidarebefordran och e-post till webhook är gratis för sådana.
  • En HTTPS-endpoint på en publik adress som svarar inom 20 sekunder.
  • nameocean-CLI:t, eller en API-nyckel med email:write.

1. Aktivera vidarebefordran för domänen

nameocean
$ nameocean email forwards on example.com

Detta pekar domänens MX-post mot NameOceans e-postvidarebefordrare. Om domänen redan har MX-poster, för brevlådor någon annanstans, avbryts kommandot och listar dem: all e-post till domänen skulle flyttas hit. Lägg bara till --replace-mx när det är vad du vill.

2. Ansök om e-post till webhook

Att posta e-post till en URL öppnas per konto efter en kort granskning, för att hålla spamreläer borta. På domänens sida under Kontrollpanel → E-postvidarebefordran ansöker du om det med en rad om vad du ska använda det till. Fram till dess svarar API:et 403 not_approved.

3. Skicka en adress till din endpoint

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 innehåller signeringshemligheten (whsec_…); spara den i din apps inställningar. localpart * skickar varje adress på domänen som saknar ett eget alias. En domän kan ha upp till tre sådana webhooks.

4. Ta emot den

Verifiera signaturen mot den råa bodyn och läs sedan JSON-datan. En liten mottagare i Flask:

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

Det här kommer fram

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 förblir detsamma när ett meddelande postas igen, så använd det för att hoppa över dubbletter. in_reply_to och references visar vilket av dina egna meddelanden någon har svarat på.

När din endpoint är nere

  • Ett 2xx-svar innebär levererat. En 408, 429, 5xx, en timeout (20 sekunder) eller ingen anslutning försöks igen i 6 timmar.
  • Alla andra 4xx är slutgiltiga: meddelandet postas inte igen automatiskt.
  • E-post som inte kunde postas sparas i 30 dagar. Hitta den med nameocean email forwards log example.com (eller GET /email/forwarding/example.com/messages) och släpp den: den postas en gång till, med samma id.
  • Upp till 500 meddelanden per dag och domän går till webhooks; e-post utöver det hålls kvar på samma sätt.