Desarrolladores → Guías

Reciba correo en su aplicación

Tickets de soporte, respuestas a notificaciones, documentos enviados a un bot: el correo dirigido a una dirección de su dominio llega a su endpoint HTTPS como un único POST JSON firmado, con el texto, el HTML y todos los archivos adjuntos. Sin buzones que consultar y sin IMAP.

Qué necesita

  • Un dominio registrado en NameOcean: el reenvío y el correo a webhook son gratuitos para estos dominios.
  • Un endpoint HTTPS en una dirección pública que responda en menos de 20 segundos.
  • La CLI de nameocean, o una clave de API con email:write.

1. Active el reenvío para el dominio

nameocean
$ nameocean email forwards on example.com

Esto apunta el registro MX del dominio a los servidores de reenvío de correo de NameOcean. Si el dominio ya tiene registros MX, para buzones alojados en otro lugar, el comando se detiene y los enumera: todo el correo del dominio pasaría a llegar aquí. Añada --replace-mx solo si eso es lo que desea.

2. Solicite el correo a webhook

El envío de correo a una URL se habilita por cuenta tras una breve revisión, para evitar los relays de spam. En la página del dominio, en Panel → Reenvío de correo, solicítelo indicando brevemente para qué lo utilizará. Hasta entonces, la API responde 403 not_approved.

3. Envíe una dirección a su 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"}'

La respuesta incluye el secreto de firma (whsec_…); guárdelo en la configuración de su aplicación. Con localpart * se envían todas las direcciones del dominio que no tengan un alias propio. Un dominio puede tener hasta tres de estos webhooks.

4. Recíbalo

Verifique la firma sobre el cuerpo sin procesar y, a continuación, lea el JSON. Un pequeño receptor en 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

Qué llega

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 no cambia cuando un correo se vuelve a enviar, así que utilícelo para descartar duplicados. in_reply_to y references le indican a cuál de sus propios correos ha respondido alguien.

Cuando su endpoint no está disponible

  • Una respuesta 2xx significa entregado. Un 408, 429, 5xx, un tiempo de espera agotado (20 segundos) o la falta de conexión se reintenta durante 6 horas.
  • Cualquier otro 4xx es definitivo: el correo no se vuelve a enviar automáticamente.
  • El correo que no se pudo enviar se conserva durante 30 días. Búsquelo con nameocean email forwards log example.com (o GET /email/forwarding/example.com/messages) y libérelo: se enviará una vez más, con el mismo id.
  • Se envían a webhooks hasta 500 correos al día por dominio; el correo que supere esa cifra se retiene de la misma manera.