Skip to main content

Valider un email en temps réel

Ce guide couvre les scénarios courants d'intégration de la validation email unitaire.

Cas d'usage

  • Formulaire d'inscription → valider l'email avant de créer le compte
  • Lead generation → qualifier les emails à l'entrée
  • CRM → vérifier les emails d'une fiche contact

Validation simple (sans SMTP)

Gratuite, instantanée (~100-300ms). Idéale pour la validation en temps réel.

curl -X POST https://api.yeswecheck.fr/v2/email/validate \
-H "X-API-Key: $YESWECHECK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]"}'

Validation avec SMTP

Recommandée pour les listes de haute valeur. Consomme 1 crédit par email validé.

const result = await validateEmail('[email protected]');

// Résultat avec SMTP activé
const fullResult = await fetch('https://api.yeswecheck.fr/v2/email/validate', {
method: 'POST',
headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
email: '[email protected]',
smtp: true,
smtpTimeout: 8000, // 8 secondes (défaut)
}),
}).then(r => r.json());

console.log(fullResult.smtp);
// {
// performed: true,
// deliverable: true,
// responseCode: 250,
// responseMessage: "OK"
// }

Logique de décision recommandée

function shouldAcceptEmail(result: ValidationResult): {
accept: boolean;
reason?: string;
suggestion?: string;
} {
// 1. Syntaxe invalide → refus immédiat
if (!result.syntax.valid) {
return { accept: false, reason: 'Adresse email invalide' };
}

// 2. Pas de MX records → domaine inexistant
if (!result.dns.hasMxRecords) {
return { accept: false, reason: 'Domaine email inexistant' };
}

// 3. Email jetable → refus ou avertissement
if (result.disposable.isDisposable) {
return {
accept: false,
reason: 'Les adresses email temporaires ne sont pas acceptées',
};
}

// 4. Typo détectée → suggérer la correction
if (result.typo.hasTypo && result.typo.suggestions.length > 0) {
return {
accept: true,
suggestion: result.typo.suggestions[0],
};
}

// 5. Role account → accepter avec avertissement
if (result.roleAccount.isRoleAccount) {
return {
accept: true,
reason: 'Conseil : utilisez une adresse personnelle plutôt que info@ ou support@',
};
}

// 6. SMTP échoué → email n'existe pas
if (result.smtp.performed && !result.smtp.deliverable) {
return { accept: false, reason: 'Cette boîte email n\'existe pas' };
}

return { accept: true };
}

Intégration dans un formulaire React

import { useState, useCallback } from 'react';

function EmailInput({ onValidated }: { onValidated: (email: string, valid: boolean) => void }) {
const [email, setEmail] = useState('');
const [status, setStatus] = useState<'idle' | 'checking' | 'valid' | 'invalid' | 'risky'>('idle');
const [suggestion, setSuggestion] = useState<string | null>(null);
const [message, setMessage] = useState('');

const validate = useCallback(async (value: string) => {
if (!value || !value.includes('@')) return;

setStatus('checking');
setSuggestion(null);

try {
// Appel via votre API backend (ne pas exposer la clé en frontend)
const result = await fetch('/api/validate-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: value }),
}).then(r => r.json());

setStatus(result.status);

if (result.typo?.hasTypo && result.typo.suggestions[0]) {
setSuggestion(result.typo.suggestions[0]);
setMessage(`Vouliez-vous dire ${result.typo.suggestions[0]} ?`);
} else if (result.status === 'invalid') {
setMessage('Adresse email invalide');
} else if (result.disposable?.isDisposable) {
setStatus('invalid');
setMessage('Les adresses temporaires ne sont pas acceptées');
} else {
setMessage('');
}

onValidated(value, result.status === 'valid');
} catch {
setStatus('idle');
}
}, [onValidated]);

return (
<div>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
onBlur={e => validate(e.target.value)}
placeholder="[email protected]"
style={{
borderColor:
status === 'valid' ? '#10B981' :
status === 'invalid' ? '#EF4444' :
status === 'risky' ? '#F59E0B' : '#E2E8F0',
}}
/>
{status === 'checking' && <span>⏳ Vérification...</span>}
{message && (
<p style={{ color: status === 'risky' ? '#F59E0B' : '#EF4444' }}>
{message}
</p>
)}
{suggestion && (
<button onClick={() => { setEmail(suggestion); validate(suggestion); }}>
Utiliser {suggestion}
</button>
)}
</div>
);
}

Suggestions de domaine (autocomplétion)

// Obtenir des suggestions de domaines populaires pour la France
const suggestions = await fetch('https://api.yeswecheck.fr/v2/email/suggest/domain', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
// Pas d'auth requise pour ce endpoint
body: JSON.stringify({ country: 'FR', partial: 'gm', count: 5 }),
}).then(r => r.json());

// { suggestions: [{ domain: "gmail.com", provider: "Google", ... }] }

Détection de fautes de frappe

curl -X POST https://api.yeswecheck.fr/v2/email/suggest/typo-domain \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]"}'
{
"original": "[email protected]",
"hasTypo": true,
"suggestion": "[email protected]",
"confidence": 0.97
}