emailr_
Todos los artículos
usecase·9 min

Emails de alerta de seguridad de la cuenta: Patrones y textos

securityalertspatterns

Los emails de alerta de seguridad son fundamentales para proteger las cuentas de usuario. Deben ser claros, accionables y llegar al instante. Aquí te explico cómo diseñar notificaciones de seguridad efectivas.

Tipos de alertas de seguridad

Notificaciones de inicio de sesión

interface LoginAlert {
  user: { email: string; name: string };
  login: {
    timestamp: Date;
    ip: string;
    location?: { city: string; country: string };
    device: string;
    browser: string;
  };
  isNewDevice: boolean;
  isNewLocation: boolean;
}

await sendEmail({
  to: user.email,
  subject: login.isNewDevice 
    ? 'New device signed in to your account'
    : 'New sign-in to your account',
  template: 'login-alert',
  data: {
    user,
    login,
    secureAccountUrl: `${baseUrl}/security`,
    notYouUrl: `${baseUrl}/security/report?session=${sessionId}`
  },
  priority: 'high'
});

Confirmación de cambio de contraseña

await sendEmail({
  to: user.email,
  subject: 'Your password was changed',
  template: 'password-changed',
  data: {
    user,
    changedAt: new Date(),
    device: request.device,
    location: request.location,
    resetUrl: `${baseUrl}/reset-password`,
    supportEmail: '[email protected]'
  }
});

Advertencia de actividad sospechosa

interface SuspiciousActivityAlert {
  user: User;
  activity: {
    type: 'failed_logins' | 'unusual_location' | 'api_abuse' | 'data_export';
    details: string;
    timestamp: Date;
    riskLevel: 'low' | 'medium' | 'high';
  };
  recommendedActions: string[];
}

await sendEmail({
  to: user.email,
  subject: '⚠️ Unusual activity detected on your account',
  template: 'suspicious-activity',
  data: {
    user,
    activity,
    recommendedActions: [
      'Change your password',
      'Review recent activity',
      'Enable two-factor authentication'
    ],
    securityDashboardUrl: `${baseUrl}/security`,
    lockAccountUrl: `${baseUrl}/security/lock?token=${lockToken}`
  },
  priority: 'high'
});

Emails de autenticación de dos factores

Confirmación de 2FA activada

await sendEmail({
  to: user.email,
  subject: 'Two-factor authentication enabled',
  template: '2fa-enabled',
  data: {
    user,
    method: '2fa.method', // 'authenticator' | 'sms' | 'email'
    backupCodes: user.hasBackupCodes,
    manageUrl: `${baseUrl}/security/2fa`
  }
});

Códigos de respaldo regenerados

await sendEmail({
  to: user.email,
  subject: 'New backup codes generated',
  template: 'backup-codes-regenerated',
  data: {
    user,
    generatedAt: new Date(),
    device: request.device,
    warning: 'Your old backup codes no longer work',
    viewCodesUrl: `${baseUrl}/security/backup-codes`
  }
});

Gestión de sesiones y dispositivos

Nuevo dispositivo agregado

await sendEmail({
  to: user.email,
  subject: 'New device added to your account',
  template: 'new-device',
  data: {
    user,
    device: {
      name: deviceInfo.name,
      type: deviceInfo.type,
      browser: deviceInfo.browser,
      os: deviceInfo.os,
      addedAt: new Date()
    },
    location: deviceInfo.location,
    removeDeviceUrl: `${baseUrl}/security/devices/${deviceId}/remove`,
    viewAllDevicesUrl: `${baseUrl}/security/devices`
  }
});

Todas las sesiones cerradas

await sendEmail({
  to: user.email,
  subject: 'All sessions signed out',
  template: 'sessions-terminated',
  data: {
    user,
    terminatedAt: new Date(),
    terminatedBy: 'you', // or 'admin' or 'security_system'
    sessionsCount: terminatedCount,
    reason: 'Password change', // or 'Security concern' or 'User request'
    signInUrl: `${baseUrl}/login`
  }
});

Alertas de API y tokens de acceso

Clave de API creada

await sendEmail({
  to: user.email,
  subject: 'New API key created',
  template: 'api-key-created',
  data: {
    user,
    apiKey: {
      name: key.name,
      prefix: key.prefix, // First 8 chars only
      permissions: key.permissions,
      createdAt: new Date()
    },
    manageKeysUrl: `${baseUrl}/settings/api-keys`
  }
});

Actividad inusual de la API

await sendEmail({
  to: user.email,
  subject: 'Unusual API activity detected',
  template: 'api-activity-alert',
  data: {
    user,
    activity: {
      keyName: key.name,
      requestCount: activity.count,
      timeWindow: '1 hour',
      normalRange: '100-500 requests',
      actualCount: activity.count
    },
    revokeKeyUrl: `${baseUrl}/settings/api-keys/${key.id}/revoke`,
    viewLogsUrl: `${baseUrl}/settings/api-keys/${key.id}/logs`
  }
});

Flujo de cambio de email

Cambio de email solicitado

// Send to OLD email
await sendEmail({
  to: user.currentEmail,
  subject: 'Email change requested',
  template: 'email-change-requested',
  data: {
    user,
    newEmail: maskEmail(newEmail),
    requestedAt: new Date(),
    cancelUrl: `${baseUrl}/security/email-change/cancel?token=${cancelToken}`,
    expiresIn: '24 hours'
  }
});

// Send to NEW email
await sendEmail({
  to: newEmail,
  subject: 'Verify your new email address',
  template: 'email-change-verify',
  data: {
    user,
    verifyUrl: `${baseUrl}/security/email-change/verify?token=${verifyToken}`,
    expiresIn: '24 hours'
  }
});

Buenas prácticas de alertas de seguridad

Prioridad y tiempos

const securityEmailConfig = {
  // Immediate, high priority
  immediate: [
    'password_changed',
    'email_changed',
    'suspicious_activity',
    '2fa_disabled',
    'all_sessions_terminated'
  ],
  
  // Can batch or slight delay
  batchable: [
    'new_login_known_device',
    'api_key_created',
    'settings_changed'
  ]
};

async function sendSecurityAlert(type: string, data: any) {
  const isImmediate = securityEmailConfig.immediate.includes(type);
  
  await sendEmail({
    ...data,
    priority: isImmediate ? 'high' : 'normal',
    headers: {
      'X-Priority': isImmediate ? '1' : '3',
      'X-Security-Alert': 'true'
    }
  });
}

Acciones claras

// Always include:
// 1. What happened
// 2. When it happened
// 3. What to do if it was you
// 4. What to do if it wasn't you

const securityEmailStructure = {
  whatHappened: 'Your password was changed',
  when: formatDateTime(event.timestamp),
  where: `${event.location.city}, ${event.location.country}`,
  device: event.device,
  ifYou: 'No action needed. You can ignore this email.',
  ifNotYou: {
    actions: [
      { label: 'Reset your password', url: resetUrl },
      { label: 'Contact support', url: supportUrl }
    ],
    urgency: 'Do this immediately to secure your account'
  }
};

Mejores prácticas

  1. Enviar de inmediato - Las alertas de seguridad deben llegar en tiempo real
  2. Asuntos claros - El usuario debe entender el problema solo con leer el asunto
  3. Incluir contexto - Hora, ubicación e información del dispositivo
  4. Proporcionar acciones - Pasos claros para ambos escenarios
  5. No incluir datos sensibles - Nada de contraseñas ni tokens completos en los emails
  6. Branding consistente - Para que los usuarios reconozcan alertas legítimas
  7. Probar la entregabilidad - Los emails de seguridad deben llegar a la bandeja de entrada, no a spam

Las alertas de seguridad generan confianza. Cuando los usuarios saben que estás velando por su seguridad, se sienten más seguros usando tu producto.

e_

Escrito por el equipo de emailr

Construyendo infraestructura de email para desarrolladores

¿Listo para empezar a enviar?

Obtén tu clave API y envía tu primer email en menos de 5 minutos. No se requiere tarjeta de crédito.