sanitizeEmail
Paquete: @tiendana/utils
Limpia direcciones de email: recorta espacios y, solo si el email no cumple Patterns.EMAIL, remueve caracteres fuera de un conjunto permitido. No valida: el resultado puede seguir siendo inválido.
Características
✅ Elimina espacios al inicio y final
✅ Retorna sin cambios un email que cumple Patterns.EMAIL
✅ Remueve caracteres fuera de a-zA-Z0-9_, / a @ y . si no cumple
✅ Case-sensitive (no cambia mayúsculas)
Firma
function sanitizeEmail(email: string): string
Parámetros
| Parámetro | Tipo | Descripción | Requerido |
|---|---|---|---|
email | string | Dirección de email a sanitizar | ✅ |
Retorno
Tipo: string
- El email recortado (
trim) y sin más cambios si cumplePatterns.EMAIL - Si no lo cumple, el email recortado y sin los caracteres que no estén permitidos (puede seguir siendo inválido)
Ejemplos de Uso
Sanitización Básica
import { sanitizeEmail } from '@tiendana/utils';
sanitizeEmail(' juan@example.com ');
// 'juan@example.com'
sanitizeEmail('juan@example.com');
// 'juan@example.com'
Email con Caracteres Inválidos
sanitizeEmail('juan perez@example.com');
// 'juanperez@example.com'
sanitizeEmail('juan @ex ample.com');
// 'juan@example.com'
sanitizeEmail('(juan)@example.com');
// 'juan@example.com'
#, !, $ y + son válidos en el local-partPatterns.EMAIL acepta ! # $ % & ' * + / = ? ^ { | } ~ (y la comilla invertida) antes de la @, así que un email que solo los contiene se retorna intacto:
sanitizeEmail('juan#$%@example.com'); // 'juan#$%@example.com'
sanitizeEmail('user!name@domain.com'); // 'user!name@domain.com'
sanitizeEmail('juan+tag@example.com'); // 'juan+tag@example.com'
sanitizeEmail('test@@example.com'); // 'test@@example.com' (no se colapsan las @)
Validación de Form Input
function validateEmailInput(input: string): string {
const cleaned = sanitizeEmail(input);
// Validar adicionalmente con Patterns.EMAIL
if (!Patterns.EMAIL.test(cleaned)) {
throw new Error('Email inválido después de sanitizar');
}
return cleaned;
}
Normalizar Email de Usuario
interface UserRegistration {
name: string;
email: string;
password: string;
}
function processRegistration(data: UserRegistration) {
return {
...data,
email: sanitizeEmail(data.email)
};
}
const user = processRegistration({
name: 'Juan',
email: ' juan@example.com ',
password: 'pass123'
});
// user.email: 'juan@example.com'
Limpiar Lista de Emails
function sanitizeEmailList(emails: string[]): string[] {
return emails.map(email => sanitizeEmail(email));
}
const emails = [
' user1@example.com ',
'user 2@example.com',
'user3@example.com'
];
const cleaned = sanitizeEmailList(emails);
// ['user1@example.com', 'user2@example.com', 'user3@example.com']
Importar Contactos
function importContacts(csvData: string): string[] {
return csvData
.split('\n')
.map(line => line.split(',')[1]) // Columna email
.map(email => sanitizeEmail(email))
.filter(email => Patterns.EMAIL.test(email)); // Solo emails válidos
}
Form Submit
function handleEmailSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const rawEmail = formData.get('email') as string;
const cleanEmail = sanitizeEmail(rawEmail);
if (Patterns.EMAIL.test(cleanEmail)) {
// Procesar email válido
submitEmail(cleanEmail);
} else {
// Mostrar error
alert('Email inválido');
}
}
API Request
async function subscribeNewsletter(email: string) {
const sanitized = sanitizeEmail(email);
const response = await fetch('/api/newsletter/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: sanitized })
});
return response.json();
}
Validación en Tiempo Real
function EmailInput() {
const [email, setEmail] = useState('');
const [error, setError] = useState('');
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setEmail(value);
const cleaned = sanitizeEmail(value);
if (value !== cleaned) {
setError('Email contiene caracteres inválidos');
} else if (!Patterns.EMAIL.test(cleaned)) {
setError('Formato de email inválido');
} else {
setError('');
}
};
return (
<div>
<input type="email" value={email} onChange={handleChange} />
{error && <span className="error">{error}</span>}
</div>
);
}
Deduplicación
function deduplicateEmails(emails: string[]): string[] {
const sanitized = emails.map(email => sanitizeEmail(email));
return [...new Set(sanitized)];
}
const emails = [
'juan@example.com',
' juan@example.com ',
'JUAN@EXAMPLE.COM' // ⚠️ No convierte a lowercase
];
deduplicateEmails(emails);
// ['juan@example.com', 'JUAN@EXAMPLE.COM']
// Nota: mantiene case sensitivity
Casos de Uso Comunes
- Form inputs: Limpiar emails de formularios
- Validación: Preparar emails para validación
- Importación: Limpiar emails de archivos CSV/Excel
- API requests: Sanitizar antes de enviar a servidor
- Normalización: Normalizar emails de múltiples fuentes
- Deduplicación: Limpiar antes de eliminar duplicados
- Database storage: Sanitizar antes de guardar en BD
Comportamiento
Email Válido
Si el email (ya recortado) cumple Patterns.EMAIL:
- Elimina espacios al inicio y al final con
.trim() - Retorna el email sin más cambios
sanitizeEmail(' juan@example.com ');
// 'juan@example.com'
sanitizeEmail('user.name+tag@example.co.uk');
// 'user.name+tag@example.co.uk'
Email Inválido
Si el email NO cumple Patterns.EMAIL:
- Elimina espacios al inicio y al final con
.trim() - Remueve todo carácter que no coincida con
[a-zA-Z0-9_/-@.] - Retorna el resultado
sanitizeEmail('user name@example.com');
// 'username@example.com' (remueve el espacio)
sanitizeEmail('juan,perez@example.com');
// 'juanperez@example.com' (remueve la coma)
sanitizeEmail(' user#!@exa mple.com');
// 'user@example.com' (el email es inválido, así que también se remueven # y !)
Caracteres Permitidos
Solo cuando el email NO cumple Patterns.EMAIL, se conservan estos caracteres:
- Letras:
a-z,A-Z - Números:
0-9 - Guion bajo:
_ - El rango
/a@(códigos 0x2F a 0x40):/ 0-9 : ; < = > ? @. En la expresión[^a-zA-Z0-9_/-@.]el fragmento/-@es un rango, no los caracteres sueltos/,-y@. - Punto:
.
Esto significa que el guion - y el + NO están en el conjunto: - queda fuera del rango (es 0x2D) y se elimina si el email no cumple el patrón.
sanitizeEmail('user name@example.com'); // 'username@example.com'
sanitizeEmail('user-na me@example.com'); // 'username@example.com' (el email era inválido: se pierde el guion)
sanitizeEmail('user-name@example.com'); // 'user-name@example.com' (válido: se retorna intacto)
Notas Técnicas
- Patterns.EMAIL: Importa
Patternsdesde@tiendana/utils(no existe el subpath@tiendana/utils/patterns). El patrón no tiene la banderai, así que un email con mayúsculas no lo cumple y pasa por la rama de limpieza - Regex de limpieza:
/[^a-zA-Z0-9_/-@.]/g - Trim: Usa
.trim()para eliminar espacios - Case-sensitive: NO convierte a lowercase (preserva mayúsculas/minúsculas)
- Inmutabilidad: No modifica el string original
- Performance: O(n) donde n es la longitud del email
Limitaciones
La función NO convierte el email a minúsculas, lo que puede causar problemas de deduplicación:
sanitizeEmail('JUAN@EXAMPLE.COM');
// 'JUAN@EXAMPLE.COM' (mantiene mayúsculas)
// Para normalizar completamente:
function normalizeEmail(email: string): string {
return sanitizeEmail(email).toLowerCase();
}
normalizeEmail('JUAN@EXAMPLE.COM');
// 'juan@example.com'
La función NO valida que el dominio exista o sea válido, solo el formato:
sanitizeEmail('user@nonexistentdomain123456.com');
// 'user@nonexistentdomain123456.com' (válido en formato, pero dominio no existe)
// Para validación completa, necesitas verificar el dominio:
async function validateEmailDomain(email: string): Promise<boolean> {
const cleaned = sanitizeEmail(email);
const domain = cleaned.split('@')[1];
try {
const response = await fetch(`https://dns-api.com/check/${domain}`);
return response.ok;
} catch {
return false;
}
}
Si el email es muy inválido, el resultado puede ser inesperado:
sanitizeEmail('this is not an email');
// 'thisisnotanemail' (remueve espacios pero no hay @)
sanitizeEmail('@@@@');
// '@@@@' (las @ pertenecen al rango permitido, no se eliminan)
// Siempre valida el resultado:
const cleaned = sanitizeEmail(input);
if (!Patterns.EMAIL.test(cleaned)) {
throw new Error('Email inválido');
}