is-noise-email.ts2.0 KBView on GitHub
/**
 * Heuristics for filtering out non-human / automated contacts that get auto-added
 * to conversations (mailer-daemons, notification senders, the user themselves, etc.).
 */

const AUTOMATED_LOCAL_PARTS = new Set([
  'noreply',
  'no-reply',
  'donotreply',
  'do-not-reply',
  'mailer-daemon',
  'postmaster',
  'notifications',
  'notification',
  'notify',
  'alerts',
  'alert',
  'bounce',
  'bounces',
  'hello',
]);

function extractDomain(email: string): string {
  const parts = email.toLowerCase().split('@');
  return parts.length > 1 ? parts[1] : '';
}

function extractLocalPart(email: string): string {
  return email.toLowerCase().split('@')[0] ?? '';
}

/**
 * Automated/system senders — bouncers, transactional notifications, no-reply, etc.
 */
export function isAutomatedSenderEmail(email: string): boolean {
  const local = extractLocalPart(email);
  if (AUTOMATED_LOCAL_PARTS.has(local)) return true;
  // Catch variants like `notifications-foo@`, `no-reply+x@`, `mailer-daemon-...@`
  for (const prefix of AUTOMATED_LOCAL_PARTS) {
    if (local.startsWith(`${prefix}+`) || local.startsWith(`${prefix}-`)) return true;
  }
  return false;
}

/**
 * True when the email shares the user's own domain (or is the user's exact address).
 * Handles the consumer-domain case where the full email is stored as a "domain".
 */
export function isInternalEmail(email: string, userEmail: string | null | undefined): boolean {
  if (!userEmail) return false;

  const normalizedEmail = email.toLowerCase();
  const normalizedUserEmail = userEmail.toLowerCase();

  if (normalizedEmail === normalizedUserEmail) return true;

  const emailDomain = extractDomain(normalizedEmail);
  const userDomain = extractDomain(normalizedUserEmail);
  return emailDomain !== '' && emailDomain === userDomain;
}

/**
 * Combined predicate: should this contact be hidden from human-facing contact lists?
 */
export function isNoiseContactEmail(
  email: string,
  userEmail: string | null | undefined,
): boolean {
  return isAutomatedSenderEmail(email) || isInternalEmail(email, userEmail);
}