Skip to main content

Email Validation

validateEmailAddress

Validate an email address according to RFC 5322.
function validateEmailAddress(email: string): boolean
email
string
required
Email address to validate
return
boolean
True if email is valid, false otherwise
import { validateEmailAddress } from '@proton/shared/lib/helpers/email';

validateEmailAddress('[email protected]'); // true
validateEmailAddress('invalid@'); // false
validateEmailAddress('@invalid.com'); // false
validateEmailAddress('[email protected]'); // true

Features

  • Validates local part (before @)
  • Validates domain part (after @)
  • Supports quoted strings
  • Supports comments in local part
  • Follows RFC 5322 specification

validateLocalPart

Validate only the local part of an email address (before @).
function validateLocalPart(localPart: string): boolean
localPart
string
required
Local part of email to validate
import { validateLocalPart } from '@proton/shared/lib/helpers/email';

validateLocalPart('user'); // true
validateLocalPart('user+tag'); // true
validateLocalPart('user..name'); // false (consecutive dots)
validateLocalPart('.user'); // false (starts with dot)

Validation Rules

  • Cannot start or end with a dot
  • Cannot have consecutive dots
  • Supports alphanumeric and special characters: !#$%&’*+/=?^_`{|}~.-
  • Supports quoted strings with escaped characters
  • Supports comments in parentheses

validateDomain

Validate the domain part of an email address (after @).
function validateDomain(domain: string): boolean
domain
string
required
Domain to validate
import { validateDomain } from '@proton/shared/lib/helpers/email';

validateDomain('example.com'); // true
validateDomain('sub.example.com'); // true
validateDomain('[192.168.1.1]'); // true (IP literal)
validateDomain('xn--example-xya.com'); // true (IDN)
validateDomain('invalid'); // false (no TLD)

Validation Rules

  • Maximum 255 characters
  • Requires at least two labels (e.g., example.com)
  • Supports subdomains
  • Supports IP address literals
  • Supports internationalized domain names (IDN)
  • Labels can contain alphanumeric, hyphens, and underscores
  • Cannot start or end with hyphen

Email Parsing

getEmailParts

Split an email address into local part and domain.
function getEmailParts(
  email: string
): [localPart: string, domain: string]
email
string
required
Email address to parse
return
[string, string]
Tuple of [localPart, domain]
import { getEmailParts } from '@proton/shared/lib/helpers/email';

const [local, domain] = getEmailParts('[email protected]');
// local: 'user'
// domain: 'example.com'

parseMailtoURL

Parse a mailto: URL to extract recipients and headers.
function parseMailtoURL(
  mailtoURL: string,
  decode?: boolean
): { to: string[] }
mailtoURL
string
required
Mailto URL to parse
decode
boolean
default:"true"
Whether to decode URI components
import { parseMailtoURL } from '@proton/shared/lib/helpers/email';

const { to } = parseMailtoURL('mailto:[email protected]');
// to: ['[email protected]']

Email Normalization

canonicalizeEmail

Normalize an email address using a specific canonicalization scheme.
function canonicalizeEmail(
  email: string,
  scheme?: CANONICALIZE_SCHEME
): string

enum CANONICALIZE_SCHEME {
  DEFAULT,  // Lowercase only
  PLUS,     // Remove plus aliases
  GMAIL,    // Gmail rules (remove dots, plus aliases)
  PROTON    // Proton rules (remove dots, hyphens, underscores, plus aliases)
}
email
string
required
Email address to canonicalize
scheme
CANONICALIZE_SCHEME
default:"DEFAULT"
Canonicalization scheme to use
import { canonicalizeEmail } from '@proton/shared/lib/helpers/email';

canonicalizeEmail('[email protected]');
// '[email protected]'

canonicalizeEmailByGuess

Automatically detect and apply the appropriate canonicalization scheme.
function canonicalizeEmailByGuess(email: string): string
email
string
required
Email address to canonicalize
import { canonicalizeEmailByGuess } from '@proton/shared/lib/helpers/email';

// Proton domains
canonicalizeEmailByGuess('[email protected]');
// '[email protected]'

// Gmail
canonicalizeEmailByGuess('[email protected]');
// '[email protected]'

// Hotmail (plus addressing only)
canonicalizeEmailByGuess('[email protected]');
// '[email protected]'

// Other domains (lowercase only)
canonicalizeEmailByGuess('[email protected]');
// '[email protected]'

Supported Domains

Proton scheme:
  • protonmail.com
  • protonmail.ch
  • pm.me
  • proton.me
Gmail scheme:
  • gmail.com
  • googlemail.com
  • google.com
Plus scheme:
  • hotmail.com
  • hotmail.co.uk
  • hotmail.fr
  • outlook.com
  • yandex.ru
  • mail.ru

canonicalizeInternalEmail

Canonicalize a Proton email address.
function canonicalizeInternalEmail(email: string): string
import { canonicalizeInternalEmail } from '@proton/shared/lib/helpers/email';

const canonical = canonicalizeInternalEmail(
  '[email protected]'
);
// '[email protected]'

Email Utilities

addPlusAlias

Add a plus alias to an email address.
function addPlusAlias(
  email?: string,
  plus?: string
): string
email
string
Base email address
plus
string
Plus alias to add
import { addPlusAlias } from '@proton/shared/lib/helpers/email';

addPlusAlias('[email protected]', 'shopping');
// '[email protected]'

addPlusAlias('[email protected]', 'new');
// '[email protected]' (already has plus)

removePlusAliasLocalPart

Remove plus alias from email local part.
function removePlusAliasLocalPart(localPart?: string): string
import { removePlusAliasLocalPart } from '@proton/shared/lib/helpers/email';

removePlusAliasLocalPart('user+tag');
// 'user'

removePlusAliasLocalPart('user');
// 'user'

isNoReplyEmail

Check if an email is a no-reply address.
function isNoReplyEmail(email: string): boolean
import { isNoReplyEmail } from '@proton/shared/lib/helpers/email';

isNoReplyEmail('[email protected]'); // true
isNoReplyEmail('[email protected]'); // true
isNoReplyEmail('[email protected]'); // true
isNoReplyEmail('[email protected]'); // false

extractEmailFromUserID

Extract email from a user ID string (e.g., ā€œName <[email protected]>ā€).
function extractEmailFromUserID(userID: string): string | undefined
import { extractEmailFromUserID } from '@proton/shared/lib/helpers/email';

extractEmailFromUserID('John Doe <[email protected]>');
// '[email protected]'

extractEmailFromUserID('[email protected]');
// undefined (no angle brackets)

Usage Examples

Form Validation

import { validateEmailAddress } from '@proton/shared/lib/helpers/email';
import { useState } from 'react';

function EmailForm() {
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = () => {
    if (!validateEmailAddress(email)) {
      setError('Please enter a valid email address');
      return;
    }
    // Submit form
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => {
          setEmail(e.target.value);
          setError('');
        }}
      />
      {error && <div className="error">{error}</div>}
      <button type="submit">Submit</button>
    </form>
  );
}

Email Comparison

import { canonicalizeEmailByGuess } from '@proton/shared/lib/helpers/email';

function areEmailsEqual(email1: string, email2: string): boolean {
  const canonical1 = canonicalizeEmailByGuess(email1);
  const canonical2 = canonicalizeEmailByGuess(email2);
  return canonical1 === canonical2;
}

// Same inbox
areEmailsEqual(
  '[email protected]',
  '[email protected]'
); // true

// Same inbox (dots ignored in Gmail)
areEmailsEqual(
  '[email protected]',
  '[email protected]'
); // true

Domain Extraction

import { getEmailParts } from '@proton/shared/lib/helpers/email';

function getDomain(email: string): string {
  const [, domain] = getEmailParts(email);
  return domain;
}

const domain = getDomain('[email protected]');
// 'example.com'

Build docs developers (and LLMs) love