Files
sage-home/lib/email.ts
砂糖 70f337bb92 init
2026-01-24 16:54:44 +08:00

91 lines
2.2 KiB
TypeScript

const DISPOSABLE_EMAIL_DOMAINS = [
'tempmail.com',
'throwawaymail.com',
'tempmail100.com'
];
export type EmailValidationError =
| 'invalid_email_format'
| 'email_part_too_long'
| 'disposable_email_not_allowed'
| 'invalid_characters';
const EMAIL_REGEX = /^(?=[a-zA-Z0-9@._%+-]{6,254}$)[a-zA-Z0-9._%+-]{1,64}@(?:[a-zA-Z0-9-]{1,63}\.){1,8}[a-zA-Z]{2,63}$/;
export function validateEmail(email: string): {
isValid: boolean;
error?: string;
} {
// validate email format
if (!EMAIL_REGEX.test(email)) {
return {
isValid: false,
error: 'invalid_email_format'
};
}
// check domain length
const [localPart, domain] = email.split('@');
if (domain.length > 255 || localPart.length > 64) {
return {
isValid: false,
error: 'email_part_too_long'
};
}
// check if it's a disposable email
if (DISPOSABLE_EMAIL_DOMAINS.includes(domain.toLowerCase())) {
return {
isValid: false,
error: 'disposable_email_not_allowed'
};
}
// check for special characters
if (/[<>()[\]\\.,;:\s@"]+/.test(localPart)) {
return {
isValid: false,
error: 'invalid_characters'
};
}
return { isValid: true };
}
// email validation (including alias detection)
export function normalizeEmail(email: string): string {
if (!email) return '';
// convert to lowercase
let normalizedEmail = email.toLowerCase();
// separate email local part and domain part
const [localPart, domain] = normalizedEmail.split('@');
// handle different email service provider alias rules
switch (domain) {
case 'gmail.com':
// remove dot and + suffix
const gmailBase = localPart
.replace(/\./g, '')
.split('+')[0];
return `${gmailBase}@${domain}`;
case 'outlook.com':
case 'hotmail.com':
case 'live.com':
// remove + suffix
const microsoftBase = localPart.split('+')[0];
return `${microsoftBase}@${domain}`;
case 'yahoo.com':
// remove - suffix
const yahooBase = localPart.split('-')[0];
return `${yahooBase}@${domain}`;
default:
// for other emails, only remove + suffix
const baseLocalPart = localPart.split('+')[0];
return `${baseLocalPart}@${domain}`;
}
}