From 902fe682b3ba3058ab483f8a24e5c133f96cf983 Mon Sep 17 00:00:00 2001 From: EgoAleSum Date: Sun, 25 Sep 2016 13:33:43 -0400 Subject: [PATCH] normalizeEmail: supports Outlook.com, iCloud and Yahoo Mail in addition to GMail, and adds more granular control over options. --- src/lib/normalizeEmail.js | 201 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 192 insertions(+), 9 deletions(-) diff --git a/src/lib/normalizeEmail.js b/src/lib/normalizeEmail.js index 848e784c1..097df49b1 100644 --- a/src/lib/normalizeEmail.js +++ b/src/lib/normalizeEmail.js @@ -2,32 +2,215 @@ import isEmail from './isEmail'; import merge from './util/merge'; const default_normalize_email_options = { - lowercase: true, - remove_dots: true, - remove_extension: true, + // The following options apply to all email addresses + // Lowercases the local part of the email address. + // Please note this may violate RFC 5321 as per http://stackoverflow.com/a/9808332/192024). + // The domain is always lowercased, as per RFC 1035 + all_lowercase: true, + + // The following conversions are specific to GMail + // Lowercases the local part of the GMail address (known to be case-insensitive) + gmail_lowercase: true, + // Removes dots from the local part of the email address, as that's ignored by GMail + gmail_remove_dots: true, + // Removes the subaddress (e.g. "+foo") from the email address + gmail_remove_subaddress: true, + // Conversts the googlemail.com domain to gmail.com + gmail_convert_googlemaildotcom: true, + + // The following conversions are specific to Outlook.com / Windows Live / Hotmail + // Lowercases the local part of the Outlook.com address (known to be case-insensitive) + outlookdotcom_lowercase: true, + // Removes the subaddress (e.g. "+foo") from the email address + outlookdotcom_remove_subaddress: true, + + // The following conversions are specific to Yahoo + // Lowercases the local part of the Yahoo address (known to be case-insensitive) + yahoo_lowercase: true, + // Removes the subaddress (e.g. "-foo") from the email address + yahoo_remove_subaddress: true, + + // The following conversions are specific to iCloud + // Lowercases the local part of the iCloud address (known to be case-insensitive) + icloud_lowercase: true, + // Removes the subaddress (e.g. "+foo") from the email address + icloud_remove_subaddress: true, }; +// List of domains used by iCloud +const icloud_domains = [ + 'icloud.com', + 'me.com', +]; + +// List of domains used by Outlook.com and its predecessors +// This list is likely incomplete. +// Partial reference: +// https://blogs.office.com/2013/04/17/outlook-com-gets-two-step-verification-sign-in-by-alias-and-new-international-domains/ +const outlookdotcom_domains = [ + 'hotmail.at', + 'hotmail.be', + 'hotmail.ca', + 'hotmail.cl', + 'hotmail.co.il', + 'hotmail.co.nz', + 'hotmail.co.th', + 'hotmail.co.uk', + 'hotmail.com', + 'hotmail.com.ar', + 'hotmail.com.au', + 'hotmail.com.br', + 'hotmail.com.gr', + 'hotmail.com.mx', + 'hotmail.com.pe', + 'hotmail.com.tr', + 'hotmail.com.vn', + 'hotmail.cz', + 'hotmail.de', + 'hotmail.dk', + 'hotmail.es', + 'hotmail.fr', + 'hotmail.hu', + 'hotmail.id', + 'hotmail.ie', + 'hotmail.in', + 'hotmail.it', + 'hotmail.jp', + 'hotmail.kr', + 'hotmail.lv', + 'hotmail.my', + 'hotmail.ph', + 'hotmail.pt', + 'hotmail.sa', + 'hotmail.sg', + 'hotmail.sk', + 'live.be', + 'live.co.uk', + 'live.com', + 'live.com.ar', + 'live.com.mx', + 'live.de', + 'live.es', + 'live.eu', + 'live.fr', + 'live.it', + 'live.nl', + 'msn.com', + 'outlook.at', + 'outlook.be', + 'outlook.cl', + 'outlook.co.il', + 'outlook.co.nz', + 'outlook.co.th', + 'outlook.com', + 'outlook.com.ar', + 'outlook.com.au', + 'outlook.com.br', + 'outlook.com.gr', + 'outlook.com.pe', + 'outlook.com.tr', + 'outlook.com.vn', + 'outlook.cz', + 'outlook.de', + 'outlook.dk', + 'outlook.es', + 'outlook.fr', + 'outlook.hu', + 'outlook.id', + 'outlook.ie', + 'outlook.in', + 'outlook.it', + 'outlook.jp', + 'outlook.kr', + 'outlook.lv', + 'outlook.my', + 'outlook.ph', + 'outlook.pt', + 'outlook.sa', + 'outlook.sg', + 'outlook.sk', + 'passport.com', +]; + +// List of domains used by Yahoo Mail +// This list is likely incomplete +const yahoo_domains = [ + 'rocketmail.com', + 'yahoo.ca', + 'yahoo.co.uk', + 'yahoo.com', + 'yahoo.de', + 'yahoo.fr', + 'yahoo.in', + 'yahoo.it', + 'ymail.com', +]; + export default function normalizeEmail(email, options) { options = merge(options, default_normalize_email_options); + if (!isEmail(email)) { return false; } const parts = email.split('@', 2); + + // The domain is always lowercased, as it's case-insensitive per RFC 1035 parts[1] = parts[1].toLowerCase(); + if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') { - if (options.remove_extension) { + // Address is GMail + if (options.gmail_remove_subaddress) { parts[0] = parts[0].split('+')[0]; } - if (options.remove_dots) { + if (options.gmail_remove_dots) { parts[0] = parts[0].replace(/\./g, ''); } if (!parts[0].length) { return false; } - parts[0] = parts[0].toLowerCase(); - parts[1] = 'gmail.com'; - } else if (options.lowercase) { - parts[0] = parts[0].toLowerCase(); + if (options.all_lowercase || options.gmail_lowercase) { + parts[0] = parts[0].toLowerCase(); + } + parts[1] = options.gmail_convert_googlemaildotcom ? 'gmail.com' : parts[1]; + } else if (~icloud_domains.indexOf(parts[1])) { + // Address is iCloud + if (options.icloud_remove_subaddress) { + parts[0] = parts[0].split('+')[0]; + } + if (!parts[0].length) { + return false; + } + if (options.all_lowercase || options.icloud_lowercase) { + parts[0] = parts[0].toLowerCase(); + } + } else if (~outlookdotcom_domains.indexOf(parts[1])) { + // Address is Outlook.com + if (options.outlookdotcom_remove_subaddress) { + parts[0] = parts[0].split('+')[0]; + } + if (!parts[0].length) { + return false; + } + if (options.all_lowercase || options.outlookdotcom_lowercase) { + parts[0] = parts[0].toLowerCase(); + } + } else if (~yahoo_domains.indexOf(parts[1])) { + // Address is Yahoo + if (options.yahoo_remove_subaddress) { + let components = parts[0].split('-'); + parts[0] = (components.length > 1) ? components.slice(0, -1).join('-') : components[0]; + } + if (!parts[0].length) { + return false; + } + if (options.all_lowercase || options.yahoo_lowercase) { + parts[0] = parts[0].toLowerCase(); + } + } else { + // Any other address + if (options.all_lowercase) { + parts[0] = parts[0].toLowerCase(); + } } return parts.join('@'); }