Esta guía explica cómo usar Resend desde cualquier aplicación desplegada en Coolify para enviar emails (transaccionales, notificaciones, recuperación de contraseñas, etc.).
mail.pampl.ing (DKIM + SPF configurados)RESEND_API_KEY — clave de API (secreta)EMAIL_FROM — remitente por defecto: Pampling <noreply@mail.pampl.ing>En Coolify, dentro de la app que va a enviar emails:
| Key | Value |
|---|---|
RESEND_API_KEY |
{{ team.RESEND_API_KEY }} |
EMAIL_FROM |
{{ team.EMAIL_FROM }} |
Coolify resolverá las plantillas automáticamente al desplegar y la app recibirá los valores reales como variables de entorno estándar.
RESEND_API_KEY como secret (no se mostrará en logs)Instalar el SDK:
pip install resend
Uso básico:
import os
import resend
resend.api_key = os.environ["RESEND_API_KEY"]
def enviar_email(destinatario: str, asunto: str, html: str):
resend.Emails.send({
"from": os.environ["EMAIL_FROM"],
"to": [destinatario],
"subject": asunto,
"html": html,
})
Ejemplo de uso desde un endpoint FastAPI:
from fastapi import FastAPI
app = FastAPI()
@app.post("/recover-password")
def recover_password(email: str):
enviar_email(
destinatario=email,
asunto="Recupera tu contraseña",
html="<p>Pulsa <a href='https://...'>aquí</a> para restablecer.</p>",
)
return {"status": "sent"}
Instalar:
npm install resend
Uso:
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);
export async function enviarEmail(destinatario: string, asunto: string, html: string) {
const { data, error } = await resend.emails.send({
from: process.env.EMAIL_FROM!,
to: [destinatario],
subject: asunto,
html: html,
});
if (error) throw new Error(error.message);
return data;
}
Composer:
composer require resend/resend-php
Uso:
$resend = Resend::client(getenv('RESEND_API_KEY'));
$resend->emails->send([
'from' => getenv('EMAIL_FROM'),
'to' => ['destinatario@ejemplo.com'],
'subject' => 'Asunto',
'html' => '<p>Contenido</p>',
]);
Si no hay SDK, llamada HTTP directa:
curl -X POST https://api.resend.com/emails \
-H "Authorization: Bearer $RESEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "'"$EMAIL_FROM"'",
"to": ["destinatario@ejemplo.com"],
"subject": "Asunto",
"html": "<p>Contenido</p>"
}'
noreply@mail.pampl.ing para emails automáticos sin respuesta esperadaPampling <noreply@mail.pampl.ing>) mejora la confianza del usuarioUsa React Email o MJML para crear plantillas HTML responsivas. Resend integra muy bien con React Email.
Mejor que poner HTML inline en el código:
# Mal
html = f"<p>Hola {nombre}</p>"
# Mejor: cargar desde plantilla
with open("templates/welcome.html") as f:
html = f.read().replace("{{nombre}}", nombre)
Reply-To: si quieres que las respuestas vayan a otra direcciónTags: para agrupar emails por categoría en Resend logsresend.Emails.send({
"from": EMAIL_FROM,
"to": [destinatario],
"subject": asunto,
"html": html,
"reply_to": "soporte@pampling.com",
"tags": [{"name": "category", "value": "password-reset"}],
})
try:
resend.Emails.send(payload)
except resend.exceptions.ResendError as e:
# log + reintento o cola
logger.error(f"Resend error: {e}")
Para emails críticos (recuperación de contraseña, confirmaciones de pago) usa una cola con reintentos (Celery, RQ, BullMQ, etc.) en vez de enviar directamente desde el endpoint HTTP.
Plan gratuito de Resend:
Si superas el límite, devuelve 429 Too Many Requests. Implementa backoff exponencial.
https://resend.com → menú lateral Logs
Verás cada email enviado con:
Resend puede notificar a tu app cuando un email se entrega, abre, rebota, etc. Útil para:
Configurar en Resend → Webhooks → URL del endpoint en tu app.
| Error | Causa | Solución |
|---|---|---|
403 Forbidden |
API key inválida o revocada | Crear nueva key, actualizar en Coolify |
422 Unprocessable Entity: from is invalid |
Dominio no verificado o from no coincide |
Usar noreply@mail.pampl.ing o subdominio verificado |
429 Too Many Requests |
Has superado rate limit | Implementar backoff o subir de plan |
| Email llega a spam | DKIM/SPF mal configurados, contenido sospechoso | Revisar logs en Resend, mejorar contenido |
Si en el futuro quieres enviar desde notificaciones.pampl.ing o cualquier otro subdominio:
| Elemento | Estado |
|---|---|
Dominio mail.pampl.ing verificado en Resend |
✅ |
| DKIM en DNS | ✅ |
| SPF en DNS | ✅ |
| MX (feedback) en DNS | ✅ |
| API key creada | ✅ |
| Variables compartidas en Coolify | ✅ (RESEND_API_KEY, EMAIL_FROM) |
| Apps integradas | Pendiente — añadir cuando se necesite |
Mantén actualizada esta tabla cuando integres una app nueva.