Muévete desde Mailgun
Conserva el SDK de Mailgun y envía a través de OpenEmail. Cambia su URL base y su clave, y tu código de envío queda como está.
Qué cambiar
Apunta el SDK a https://api.openemail.uk/compat/mailgun y dale, en lugar de la clave de Mailgun, una clave de API de OpenEmail con el permiso emails:send. Viaja como contraseña del mismo inicio de sesión HTTP Basic, y el nombre de usuario no se comprueba. El dominio de la ruta tiene que ser uno de los dominios del espacio de trabajo, y la dirección From decide si un mensaje puede salir, como en todo OpenEmail.
import formData from 'form-data'import Mailgun from 'mailgun.js' const mailgun = new Mailgun(formData)const mg = mailgun.client({ username: 'api', key: process.env.OPENEMAIL_API_KEY, url: 'https://api.openemail.uk/compat/mailgun',}) await mg.messages.create('acme.com', { from: 'Acme Billing <[email protected]>', to: ['[email protected]'], subject: 'Your invoice', html: '<p>Your invoice is attached.</p>',})En Ruby, el segundo argumento es el host y la ruta sin esquema. En PHP, el SDK solo conserva el host del endpoint que recibe, así que la ruta se añade con AddPathPlugin de php-http, que el SDK ya instala. El paquete oficial de Python puede registrar un aviso de que el host no es el de Mailgun, y envía igualmente. También reintenta una solicitud que falló con 429 o un 5xx, por eso OpenEmail responde 400 en vez de 5xx cuando ya ha salido parte de un lote.
Qué corresponde a qué
El endpoint que se sirve es POST /v3/{domain}/messages, como multipart/form-data, que necesitan los adjuntos, o como application/x-www-form-urlencoded. Un nombre de campo que termina en [] se lee sin ese final.
| Mailgun | En OpenEmail |
|---|---|
| from | El remitente, con su nombre. |
| to | Destinatarios, repetidos o separados por comas. Con cc y bcc, hasta 50 por mensaje. |
| subject | El asunto. |
| html | El cuerpo HTML. text pasa a ser el cuerpo de texto, y uno de los dos, o template, es obligatorio. |
| attachment | Archivos, 20 como máximo y 5 MB en total. |
| inline | Una imagen que el HTML usa como cid: con su nombre de archivo se incrusta donde aparece. Cualquier otro archivo insertado llega como adjunto normal. |
| o:tag | Etiquetas llamadas tag, tag_2 y así sucesivamente, cada una con una etiqueta. |
| v: | Cada variable se convierte en una etiqueta con su nombre y su valor. Con o:tag, como máximo 10 por mensaje. |
| o:deliverytime | Un envío programado, con hasta un año de antelación. Una hora ya pasada envía en el acto. |
| o:tracking | Junto con o:tracking-clicks y o:tracking-opens, activa o desactiva el seguimiento del mensaje. htmlonly cuenta como activado. |
| o:testmode | yes registra el mensaje como enviado sin entregarlo, como hace una clave oe_test_. |
| h:Reply-To | La dirección de respuesta. Cualquier otro campo h: se convierte en una cabecera propia: X-*, List-*, Precedence, Auto-Submitted, Importance, Priority y Feedback-ID. |
| recipient-variables | Un envío por lotes. Cada dirección de to recibe su propio mensaje, con %recipient.key% rellenado con sus variables y %recipient% con su dirección, y cc y bcc van en cada uno. Un marcador sin valor queda como está. |
| template | El slug o el id (tpl_...) de una plantilla de OpenEmail, rellenada con t:variables, o si no con h:X-Mailgun-Variables. t:version elige una versión por su número. |
Qué se rechaza, y por qué
- Un
templateconhtmlotext, porque una plantilla de OpenEmail aporta todo el cuerpo, y unt:versionque no es un número de versión. o:deliverytime-optimize-periodyo:time-zone-localize, porque OpenEmail no elige una hora de envío para cada destinatario. Otras cabecerash:X-Mailgun-, que son instrucciones para Mailgun: usa en su lugar la opcióno:correspondiente.amp-htmlpor sí solo. Junto ahtmlotextse deja fuera, porque estos ya llevan el mensaje.- Más de una dirección de respuesta, más de 10 etiquetas, un nombre de etiqueta con algo distinto de letras, dígitos,
_y-, y un lote de más de 100 destinatarios. Mailgun acepta 1000, así que divide los lotes más grandes.
o:dkim, o:require-tls, o:skip-verification, o:sending-ip, o:sending-ip-pool, o:tracking-pixel-location-top, o:archive-to, o:deliver-within y t:text se aceptan y no cambian nada.
Respuestas y errores
- Un envío responde 200 con el mensaje
Queued. Thank you.y unid: el id del mensaje de OpenEmail entre corchetes angulares, queGET /emails/{id}y los webhooks usan sin ellos. Un envío por lotes crea un mensaje por destinatario, cada uno con su propio id, y responde con el primero. Una cabeceraIdempotency-Keyfunciona como en el resto de la API. - Una clave ausente o desconocida responde 401 con el texto plano
Forbidden, y un dominio que el espacio de trabajo no tiene responde 404 conDomain not found. Todo lo demás llega como unmessage: 400 para un mensaje que no se puede enviar, 403 para una clave sinemails:send, una dirección From que la clave no puede usar, un dominio que aún no puede enviar o un espacio de trabajo que ha agotado su cupo de envío, y 413 para un cuerpo de más de 25 MB o adjuntos de más de 5 MB. - Cuando un destinatario de un lote falla después de que se aceptaran otros, el error nombra los mensajes ya enviados y responde 400, para que un SDK que reintenta no los envíe dos veces.