emailr_
Tous les articles
usecase·10 min

Email B2B : Modèles de notifications pour l’entreprise

b2benterprisepatterns

L’email B2B diffère fondamentalement de l’email grand public. Les clients d’entreprise attendent de la fiabilité, des informations détaillées et une intégration à leurs workflows. Voici comment concevoir des systèmes de notification B2B.

Caractéristiques de l’email B2B

L’email pour l’entreprise doit gérer :

  • Plusieurs destinataires par organisation
  • Notifications basées sur les rôles
  • Exigences d’audit et de conformité
  • Intégration avec les outils d’entreprise
  • Attentes de délivrabilité plus élevées

Notifications au niveau de l’organisation

Alertes d’équipe

interface TeamAlert {
  organization: {
    id: string;
    name: string;
  };
  alert: {
    type: 'security' | 'billing' | 'usage' | 'system';
    severity: 'info' | 'warning' | 'critical';
    title: string;
    details: string;
  };
  recipients: TeamMember[];
}


async function sendTeamAlert(alert: TeamAlert) {
  // Filter recipients by role and preferences
  const recipients = alert.recipients.filter(member => 
    shouldReceiveAlert(member, alert.alert.type, alert.alert.severity)
  );

  for (const recipient of recipients) {
    await sendEmail({
      to: recipient.email,
      subject: `[${alert.alert.severity.toUpperCase()}] ${alert.alert.title}`,
      template: 'team-alert',
      data: {
        organization: alert.organization,
        alert: alert.alert,
        recipient,
        actionUrl: getAlertActionUrl(alert)
      },
      headers: {
        'X-Priority': alert.alert.severity === 'critical' ? '1' : '3'
      }
    });
  }
}

Notifications administrateur

interface AdminNotification {
  type: 'user_added' | 'user_removed' | 'role_changed' | 'settings_changed';
  actor: { name: string; email: string };
  target?: { name: string; email: string };
  details: Record<string, any>;
  timestamp: Date;
}

// Notify all admins of security-relevant changes
async function notifyAdmins(org: Organization, notification: AdminNotification) {
  const admins = await getOrgAdmins(org.id);
  
  for (const admin of admins) {
    await sendEmail({
      to: admin.email,
      subject: `[${org.name}] ${formatNotificationType(notification.type)}`,
      template: 'admin-notification',
      data: {
        org,
        notification,
        auditLogUrl: `${baseUrl}/admin/audit-log`
      }
    });
  }
}

Notifications basées sur les rôles

Envoi tenant compte des permissions

interface RoleBasedEmail {
  organization: Organization;
  emailType: string;
  data: Record<string, any>;
}

async function sendRoleBasedEmail(config: RoleBasedEmail) {
  const roleConfig = {
    'billing.invoice': ['owner', 'billing_admin'],
    'security.alert': ['owner', 'security_admin', 'admin'],
    'usage.warning': ['owner', 'admin'],
    'user.joined': ['owner', 'admin', 'hr_admin'],
    'feature.announcement': ['owner', 'admin', 'user']
  };

  const allowedRoles = roleConfig[config.emailType] || ['owner'];
  const recipients = await getOrgMembersByRoles(config.organization.id, allowedRoles);

  for (const recipient of recipients) {
    await sendEmail({
      to: recipient.email,
      template: config.emailType.replace('.', '-'),
      data: {
        ...config.data,
        recipient,
        organization: config.organization
      }
    });
  }
}

Modèles d’escalade

interface EscalationConfig {
  initialRecipients: string[];  // roles
  escalateAfter: number;        // minutes
  escalateTo: string[];         // roles
  maxEscalations: number;
}

async function sendWithEscalation(
  org: Organization,
  alert: Alert,
  config: EscalationConfig
) {
  // Send initial notification
  await sendToRoles(org, alert, config.initialRecipients);
  
  // Schedule escalation check
  await scheduleJob({
    type: 'check_escalation',
    runAt: addMinutes(new Date(), config.escalateAfter),
    data: {
      alertId: alert.id,
      orgId: org.id,
      escalationLevel: 1,
      config
    }
  });
}

async function checkEscalation(job: EscalationJob) {
  const alert = await getAlert(job.data.alertId);
  
  if (alert.acknowledged) return;
  
  if (job.data.escalationLevel < job.data.config.maxEscalations) {
    // Escalate to next level
    await sendToRoles(
      await getOrg(job.data.orgId),
      alert,
      job.data.config.escalateTo
    );
    
    // Schedule next escalation
    await scheduleJob({
      ...job,
      runAt: addMinutes(new Date(), job.data.config.escalateAfter),
      data: {
        ...job.data,
        escalationLevel: job.data.escalationLevel + 1
      }
    });
  }
}

Emails de facturation d’entreprise

Notifications de facture

interface InvoiceEmail {
  organization: Organization;
  invoice: {
    id: string;
    number: string;
    amount: number;
    currency: string;
    dueDate: Date;
    lineItems: LineItem[];
    pdfUrl: string;
  };
}

await sendEmail({
  to: billingContact.email,
  subject: `Invoice #${invoice.number} for ${org.name}`,
  template: 'invoice',
  data: {
    organization: org,
    invoice,
    paymentUrl: `${baseUrl}/billing/pay/${invoice.id}`,
    supportEmail: '[email protected]'
  },
  attachments: [
    {
      filename: `invoice-${invoice.number}.pdf`,
      path: invoice.pdfUrl
    }
  ]
});

Alertes d’usage

const usageAlertThresholds = [
  { percent: 75, template: 'usage-warning-75' },
  { percent: 90, template: 'usage-warning-90' },
  { percent: 100, template: 'usage-limit-reached' }
];

async function checkUsageAlerts(org: Organization) {
  const usage = await getOrgUsage(org.id);
  const limit = org.plan.limits;
  const percent = (usage.current / limit.max) * 100;

  for (const threshold of usageAlertThresholds) {
    if (percent >= threshold.percent && !await hasAlertedThreshold(org.id, threshold.percent)) {
      await sendRoleBasedEmail({
        organization: org,
        emailType: 'usage.warning',
        data: {
          currentUsage: usage.current,
          limit: limit.max,
          percent,
          upgradeUrl: `${baseUrl}/billing/upgrade`
        }
      });
      
      await markThresholdAlerted(org.id, threshold.percent);
    }
  }
}

Conformité et audit

Emails de piste d’audit

// Send audit summary to compliance team
async function sendAuditDigest(org: Organization) {
  const events = await getAuditEvents(org.id, {
    since: subDays(new Date(), 7),
    types: ['security', 'access', 'data']
  });

  const complianceContacts = await getComplianceContacts(org.id);

  for (const contact of complianceContacts) {
    await sendEmail({
      to: contact.email,
      subject: `Weekly audit digest for ${org.name}`,
      template: 'audit-digest',
      data: {
        organization: org,
        period: 'Last 7 days',
        summary: {
          totalEvents: events.length,
          byType: groupBy(events, 'type'),
          flaggedEvents: events.filter(e => e.flagged)
        },
        fullReportUrl: `${baseUrl}/admin/audit-log`
      }
    });
  }
}

Notifications d’export de données

// GDPR data export ready
await sendEmail({
  to: requester.email,
  subject: `Data export ready for ${org.name}`,
  template: 'data-export-ready',
  data: {
    organization: org,
    export: {
      requestedAt: exportRequest.createdAt,
      expiresAt: addDays(new Date(), 7),
      downloadUrl: exportRequest.downloadUrl,
      format: 'JSON'
    },
    securityNote: 'This link expires in 7 days. Download contains sensitive data.'
  }
});

Notifications d’intégration

Alertes d’échec de webhook

await sendEmail({
  to: techContact.email,
  subject: `[Action Required] Webhook failures for ${org.name}`,
  template: 'webhook-failures',
  data: {
    organization: org,
    webhook: {
      url: webhook.url,
      failureCount: webhook.consecutiveFailures,
      lastError: webhook.lastError,
      lastAttempt: webhook.lastAttemptAt
    },
    action: webhook.consecutiveFailures >= 10 
      ? 'Webhook has been disabled' 
      : 'Will retry automatically',
    settingsUrl: `${baseUrl}/settings/webhooks`
  }
});

Préférences de notification d’entreprise

interface EnterpriseNotificationPrefs {
  // Organization-level defaults
  orgDefaults: {
    securityAlerts: 'all_admins' | 'security_team' | 'owner_only';
    billingNotifications: 'billing_contact' | 'all_admins';
    usageAlerts: boolean;
    weeklyDigest: boolean;
  };
  
  // Per-user overrides
  userOverrides: {
    [userId: string]: {
      emailEnabled: boolean;
      digestFrequency: 'daily' | 'weekly' | 'never';
      alertTypes: string[];
    };
  };
}

Meilleures pratiques

  1. Diffusion basée sur les rôles - Envoyez aux bonnes personnes selon leurs responsabilités
  2. Niveaux de gravité clairs - Rendez l’urgence évidente dans les objets
  3. Contenu actionnable - Incluez des liens directs pour résoudre les problèmes
  4. Auditez tout - Journalisez toutes les notifications pour la conformité
  5. Parcours d’escalade - Assurez-vous que les alertes critiques atteignent quelqu’un
  6. Respectez les préférences - Offrez un contrôle granulaire des notifications

L’email B2B repose sur la fiabilité et la confiance. Vos notifications doivent aider les organisations à fonctionner sans accroc tout en maintenant des standards de sécurité et de conformité.

e_

Écrit par l'équipe emailr

Nous construisons l'infrastructure email pour les développeurs

Prêt à commencer à envoyer ?

Obtenez votre clé API et envoyez votre premier email en moins de 5 minutes. Aucune carte de crédit requise.