Ir a la documentación
CLI

Dominios y direcciones

Añade y verifica dominios, lee los registros DNS que necesitan, gestiona sus direcciones y comprueba desde qué direcciones puedes enviar.

Descripción general

Dos espacios de nombres cubren tus dominios. openemail domains gestiona los dominios vinculados al espacio de trabajo: añadirlos y quitarlos, los registros DNS que necesita cada uno, si puede recibir y enviar, su catch-all, sus dominios de seguimiento y de archivos, y sus direcciones. openemail addresses responde a una pregunta más concreta: desde qué direcciones puede enviar la clave o el inicio de sesión que estás usando.

  • Un comando de dominio acepta el id del dominio, un UUID de domains list o domains create. El nombre de host no se acepta en su lugar, así que openemail domains get acme.com da 404 y sale con el código 5.
  • Un comando de dirección acepta el id del dominio y después el id de la dirección, un UUID de domains list-addresses o domains create-address.
  • domain y address también funcionan como nombres de espacio de nombres. Los verbos de dominio responden a los alias habituales, como ls, show, new, edit y rm, y lo mismo addresses list. Los cinco verbos para las direcciones de un dominio, como create-address, no tienen ninguno.
  • openemail <command> --help lista cada argumento y opción con su tipo, el scope que necesita la llamada, su método y ruta, y lo que devuelve. Añade --json para obtener la misma página como datos.

Todos los comandos

ComandoQué hace
openemail domains listListar los dominios del espacio de trabajo, por orden alfabético, con su estado de recepción, envío, seguimiento y archivos
openemail domains get <id>Leer un dominio con sus direcciones, cada registro DNS que usa y si se encontró cada uno, y su lectura de DMARC
openemail domains create --domain <value>Añadir un dominio. La respuesta contiene cada registro DNS que hay que publicar, ya comprobado una vez
openemail domains verify <id>Comprobar al momento el DNS del dominio y devolver el dominio tal como lo dejó la comprobación
openemail domains update <id>Activar o desactivar el catch-all, y definir o quitar el dominio de seguimiento y el dominio de archivos
openemail domains delete <id>Quitar el dominio y todas sus direcciones. Pide que confirmes
openemail domains list-addresses <id>Listar las direcciones de un dominio con sus ids, sus etiquetas, si están activadas y cuándo recibió correo cada una por última vez
openemail domains create-address <id> --local-part <value>Crear una dirección en el dominio, activada, con una --label opcional
openemail domains get-address <id> <address-id>Leer una dirección de un dominio
openemail domains update-address <id> <address-id>Renombrar una dirección con --label, o desactivarla y activarla con --no-enabled y --enabled
openemail domains delete-address <id> <address-id>Quitar una dirección de su dominio. Pide que confirmes
openemail addresses listListar las direcciones desde las que puedes enviar con esta clave o este inicio de sesión, y el estado de recepción y envío de cada dominio

Cada opción está en la ayuda de su comando, por ejemplo openemail domains update --help u openemail domains create-address --help.

Recepción y envío

Un dominio informa de dos hechos independientes. receiving.verified es true en cuanto el DNS público responde con sus registros MX y su registro TXT _openemail-challenge, y a partir de entonces recibe correo. sending.status es el estado de firma tal como lo vio la última comprobación: verified, pending, failed, no_identity o unknown. sending.canSend indica si ahora mismo se aceptaría un envío desde el dominio, y un veredicto negativo de más de un día cuenta como desconocido, así que un script debe ramificar según canSend y no según status. Mientras sea false, un envío desde el dominio se rechaza con 409 domain_not_sendable.

  • domains create hace la primera comprobación de DNS durante la llamada, así que cada entrada de records ya lleva un status: found, missing, o null cuando aún no se ha comprobado. Publica cada registro exactamente como se da, ya que los valores son propios del dominio.
  • domains verify comprueba al momento. En los 10 segundos siguientes a la última comprobación no comprueba nada nuevo y devuelve el dominio tal como está. En un dominio verificado vuelve a comprobar los registros de firma, así que sending está al día.
  • domains get sobre un dominio sin verificar vuelve a comprobar cuando la última comprobación tiene más de 20 segundos, así que consultar get periódicamente también funciona y solo necesita domains:read, mientras que verify necesita domains:write.
  • Un registro publicado hace un momento puede tardar unos minutos en aparecer en el DNS público.

En un terminal, get, create y verify muestran un campo por línea, con los bloques anidados como receiving, sending y records en JSON compacto. Añade --json y léelos con una herramienta como jq, como hacen los ejemplos de abajo.

Catch-all y dominios de seguimiento y de archivos

domains update cambia tres ajustes que no dependen entre sí. Una opción que omitas no se toca, y sin ninguna opción el dominio vuelve sin cambios.

OpciónQué cambia
--catch-all, --no-catch-allActivado, acepta correo para cualquier dirección del dominio que nadie creó, y la dirección aparece en list-addresses desde su primer mensaje. Desactivado, rechaza el correo para cada dirección no creada a mano, incluidas las que el catch-all recogió antes. Un dominio nuevo empieza con él activado
--tracking-host <value>Un subdominio como links.acme.com para los enlaces con seguimiento y el píxel de apertura. null lo quita
--storage-host <value>Un subdominio como files.acme.com para los enlaces de descarga de los archivos enviados desde el dominio. null lo quita
  • Un host nuevo se guarda y se comprueba en la misma llamada. Publica un registro CNAME con el nombre record.name y el valor record.value del bloque tracking o storage de la respuesta, con cualquier proxy desactivado. Configurar un host de nuevo puede darle un valor distinto, así que publica el que indique la respuesta más reciente.
  • Hasta que pasa una comprobación, el host aparece como pending y el correo nuevo mantiene el host predeterminado de OpenEmail. Cuando pasa una, aparece como active. OpenEmail sigue comprobando por su cuenta, y un host activo que falla tres comprobaciones seguidas, o cuya última comprobación superada tiene 2 horas, aparece como failed mientras el correo nuevo vuelve al host predeterminado.
  • Quita un host con null, como en --tracking-host null. Un valor vacío como --tracking-host= es un error de uso en la CLI y sale con el código 2.
  • Un host nuevo necesita el dominio verificado, o al menos su registro TXT _openemail-challenge publicado. Si no, la llamada se rechaza con 409 domain_not_verified.
  • Las opciones se aplican en orden: el catch-all, luego el dominio de seguimiento y luego el dominio de archivos. Una opción posterior que se rechaza puede dejar guardado un cambio anterior, así que envíalas en llamadas separadas cuando cada una tenga que valer por sí sola.

Direcciones de un dominio

Un dominio contiene las direcciones creadas a mano o mediante la API, y las que su catch-all recogió cuando les llegó correo por primera vez. list-addresses muestra ambos tipos, incluidas las desactivadas. El catch-all en sí no es una fila: es receiving.catchAll en el dominio.

  • create-address acepta --local-part, la parte delante de la @, y una --label opcional. El dominio no tiene que estar verificado todavía, pero la dirección no recibe nada hasta que lo esté. * por sí solo se rechaza, ya que así se escribe el catch-all.
  • Crear una dirección que ya existe, o una que se quitó, no es un error. Vuelve activada, con la etiqueta que enviaste o sin ninguna, y conserva su id. Una dirección que recogió el catch-all pasa a ser una creada a mano, así que sigue recibiendo después de desactivar el catch-all.
  • Con el catch-all activado, una dirección nueva empieza con los ajustes por dirección del catch-all, como su firma y su seguimiento, salvo los ajustes de privacidad. Se copian una vez y no se mantienen sincronizados.
  • update-address --no-enabled hace que la dirección deje de aceptar correo, así que los remitentes reciben un rebote, y no se puede enviar nada desde ella. Conserva su correo, sus ajustes y las personas que tienen acceso a ella, y --enabled retoma donde lo dejó. --label la renombra, y --label null quita el nombre.
  • delete-address va más allá. El correo a la dirección se rechaza aunque el catch-all esté activado, su reenvío se detiene, sus ajustes se eliminan, las personas con acceso a ella lo pierden y su inicio de sesión con contraseña se revoca. El correo que ya recibió se queda en el buzón. Volver a crearla recupera el mismo id, sin los ajustes ni los accesos anteriores.

Desde qué direcciones puedes enviar

openemail addresses list responde a la pregunta que hay detrás de un 403 from_address_forbidden: qué direcciones puede poner en From la clave o el inicio de sesión con el que llamas. Necesita emails:send en lugar de un scope de lectura, porque describe lo que aceptaría un envío.

  • En un terminal muestra dos tablas: las direcciones, cada una indicando si está activada y si puedes enviar desde ella, y después los dominios, cada uno indicando si está verificado para recibir y para enviar, y su catch-all.
  • unrestricted es true cuando nada restringe la credencial. En ese caso se puede enviar desde cualquier parte local de los dominios del espacio de trabajo, incluidas las que nadie creó. Si no, canSend es true solo para una dirección activada que cubre la credencial, a través de un dominio entero que tiene o de su propia lista de direcciones.
  • canSend es false para una dirección desactivada, para una que la credencial no cubre y para una cuyo dominio aún no puede firmar.
  • Solo se listan las direcciones creadas. Una credencial que tiene un dominio entero puede enviar igualmente desde cualquier parte local de él, y una dirección de su lista sin buzón detrás puede usarse para enviar sin aparecer aquí.
  • Con --json muestra { unrestricted, addresses, domains, hasMore, nextCursor } para una página, y { unrestricted, addresses, domains } con --all, en lugar del documento { items, hasMore, nextCursor } que muestran otras listas. Con --all en un pipe, o con --ndjson, muestra una dirección por línea.

status, open y proveedores de DNS

openemail status lee tu inicio de sesión, addresses list y domains list a la vez y los muestra juntos. Su tabla Sender addresses muestra cada dirección indicando si puede enviar y si está activada. Su tabla Domains muestra cada dominio como verified o not verified para la recepción, su estado de envío y su catch-all. Muestra los 100 primeros de cada una y nombra el comando --all para el resto.

  • Una parte que tu credencial no puede leer, como los dominios sin domains:read o las direcciones sin emails:send, dice Not available con el motivo, y el resto se muestra igualmente.
  • Si aún no hay direcciones, sugiere openemail domains create --domain example.com.
  • openemail status --json muestra un objeto con account, addresses, domains y unavailable, donde unavailable da el motivo de cada parte que no se pudo leer.

Vincular un proveedor de DNS, para que los registros de un dominio nuevo se escriban por ti, solo se hace en la app web en 0.0.2. openemail open providers, u open dns, abre esa página. open domains abre los dominios y sus registros DNS, y open addresses las direcciones. El reenvío también está en la app web, y open forwarding <address> lo abre para una dirección. --print muestra el enlace en lugar de abrir un navegador.

Cuando OpenEmail escribió él mismo el DNS de un dominio, domains delete retira esos registros y lista en leftBehind los que no pudo, para que los quites en tu proveedor de DNS. Los registros que publicaste tú nunca se tocan, así que quítalos también cuando el dominio ya no esté.

Ejemplos

Añadir un dominio y publicar sus registros
openemail domains create --domain acme.com --json > acme.jsonjq -r '.records[] | [.type, .name, .value, (.priority // "")] | @tsv' acme.jsonopenemail domains verify "$(jq -r .id acme.json)"
Esperar a que reciba y luego comprobar el envío
id=b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6funtil openemail domains get "$id" --json | jq -e .receiving.verified > /dev/null; do  sleep 30doneopenemail domains get "$id" --json | jq '.sending | {status, canSend, error}'
Desactivar el catch-all conservando una dirección
openemail domains list-addresses "$id" --allopenemail domains create-address "$id" --local-part invoices --label Invoicesopenemail domains update "$id" --no-catch-all --dry-runopenemail domains update "$id" --no-catch-all

Crear invoices a mano hace que siga recibiendo una vez desactivado el catch-all, mientras que el correo a cualquier otra dirección que recogió el catch-all se rechaza. La simulación muestra el PATCH y su cuerpo sin enviarlo.

Definir un dominio de seguimiento y luego quitarlo
openemail domains update "$id" --tracking-host links.acme.com --json | jq '.tracking | {status, record, error}'openemail domains update "$id" --tracking-host null
Retirar una dirección
address_id=$(openemail domains list-addresses "$id" --all | jq -r 'select(.address == "[email protected]") | .id')openemail domains update-address "$id" "$address_id" --no-enabledopenemail domains delete-address "$id" "$address_id" --yes

Desactivar primero la dirección se puede deshacer con --enabled. La eliminación no, y en un script necesita --yes. Con un inicio de sesión con el navegador también pide un código de verificación, que --yes nunca se salta.

Auditar desde un script
openemail domains list --all | jq -r 'select(.sending.canSend | not) | [.domain, .sending.status] | @tsv'openemail addresses list --all --json | jq -r '.addresses[] | select(.canSend) | .address'

Scopes, confirmaciones y errores

ScopeComandos
domains:readdomains list, get, list-addresses, get-address
domains:writedomains create, verify, update, delete, create-address, update-address, delete-address
emails:sendaddresses list
  • Un inicio de sesión o una clave sin el scope se detiene con el código de salida 4, nombra el scope que falta y explica cómo obtenerlo.
  • domains delete y domains delete-address piden que confirmes. Responder que no sale con el código 10 y no cambia nada. Sin supervisión y sin --yes, se detienen con el código de salida 2 antes de enviar nada.
  • Con un inicio de sesión con el navegador, esas dos eliminaciones también piden un código de verificación, como hace la app web. Sin supervisión nadie puede escribirlo, así que el comando se detiene con el código de salida 4. Ejecuta primero openemail verify y los 60 minutos siguientes no necesitan código. A una clave de API nunca se le pide.
  • --dry-run muestra la solicitud que enviaría un cambio, con su cuerpo, y sale con el código 0 sin enviarla ni pedirte que confirmes.
  • Una lista lee una página: --limit acepta de 1 a 100 y el servidor envía 25 cuando se omite, y --cursor acepta el nextCursor de la página anterior. --all lee todas las páginas, --max <n> se detiene tras esa cantidad de elementos, y --ndjson, o --all en un pipe, muestra un objeto JSON por línea. Con --json, domains list y list-addresses muestran un único documento { items, hasMore, nextCursor }.
  • Una clave o un inicio de sesión limitados a determinados dominios o direcciones siguen viendo todos los dominios y direcciones. No pueden añadir un dominio, y cualquier otro cambio necesita el dominio entero entre los dominios que tienen, o la llamada se rechaza con 422 capability_unsupported.
  • Un rechazo sale con el código de su estado: 4 para un 403, como domain_allowance_reached cuando el plan no permite más dominios, 5 para un 404, 6 para un 409, como domain_already_added o domain_claimed, y 7 para un 422, como invalid_tracking_host o workspace_limit_reached.
  • El último dominio de un espacio de trabajo no se puede quitar desde la CLI. Eso es un 409 last_domain, porque quitarlo elimina todo el buzón, algo que la app web confirma antes. Un dominio que contiene direcciones de cuenta reservadas da un 409 domain_holds_reserved_addresses.
  • domains create y las dos eliminaciones nunca se reintentan tras un fallo de red. Un 409 domain_already_added, o un 404 en tu propio segundo intento tras perder la respuesta, significa que el primero funcionó. verify, update, create-address y update-address se reintentan solos, ya que enviar uno dos veces deja el mismo resultado.

Adónde ir después

Tu bandeja de entrada,
en tus propios términos.

Infraestructura de correo para empresas, IA, agentes y correo personal. Creada para escalar, con privacidad y control. Todo lo que el correo debería haber tenido desde el primer día.

OpenEmail

Infraestructura de correo para empresas, IA, agentes y correo personal. Creada para escalar, con privacidad y control. Todo lo que el correo debería haber tenido desde el primer día.

© 2026 OpenEmail. Todos los derechos reservados.