Skip to content
Commencez avec 100 crédits de vérification gratuits
Qualisend
Tous les articles
Ingénierie / 13 juin 2026

Comment valider une adresse e-mail en C#

8 minutes read

Qualisend team
Une fenêtre de code C# validant un e-mail à travers les couches syntaxe, DNS et SMTP

Pour valider une adresse e-mail en C#, la plupart des développeurs se tournent vers System.Net.Mail.MailAddress et passent à autre chose. C'est un premier réflexe légitime — le type est intégré au framework et rejette les entrées absurdes sans regex bricolée à la main — mais il ne répond qu'à la première des trois questions que pose une vraie validation. L'adresse est-elle correctement formée ? Son domaine peut-il recevoir du courrier ? La boîte aux lettres existe-t-elle réellement ? La bibliothèque de classes de base .NET répond proprement à la première, a besoin d'un package NuGet bien connu pour la deuxième, et laisse la troisième à un problème réseau qu'il vaut mieux déléguer. Ce guide construit la validation d'e-mail en C# en trois couches, avec du code async/await idiomatique pour chacune, et montre exactement où MailAddress s'arrête.

La réponse courte#

Utilisez MailAddress.TryCreate pour la syntaxe, le package DnsClient.NET pour la recherche MX et une API de vérification pour le contrôle SMTP de la boîte aux lettres — le moins coûteux d'abord, en court-circuitant dès qu'une couche est décisive. N'ouvrez pas de sockets SMTP bruts depuis votre application pour sonder les boîtes aux lettres vous-même : le port 25 sortant est bloqué sur la plupart des hébergeurs, et la réponse dépend de la réputation de l'IP d'envoi et du greylisting que vous ne voulez pas réimplémenter. Chaque couche écarte les adresses à moindre coût que la précédente ; seule la dernière peut valider une adresse. Si vous voulez simplement un verdict pour une seule adresse tout de suite, collez-la dans le vérificateur d'e-mail gratuit et oubliez le code — le reste de ce guide sert à intégrer le contrôle dans une application. Pour les concepts qui sous-tendent chaque étape, voyez ce qu'est la vérification d'e-mail.

Couche 1 : la syntaxe avec MailAddress.TryCreate#

MailAddress est le bon outil pour la première couche. Privilégiez la surcharge TryCreate ajoutée dans .NET 5 : elle renvoie un bool au lieu de lever une FormatException sur une entrée incorrecte, ce qui vous permet de la contrôler sans envelopper chaque appel dans un try/catch.

using System.Net.Mail;

public static bool IsValidSyntax(string email)
{
    return !string.IsNullOrWhiteSpace(email)
        && email.Length <= 320
        && MailAddress.TryCreate(email, out var parsed)
        && parsed.Address == email;
}
IsValidSyntax("jane@example.com");           // true
IsValidSyntax("not-an-email");               // false
IsValidSyntax("Jane <jane@example.com>");    // false

Cette dernière comparaison a son importance. MailAddress est un analyseur de courrier, pas un validateur strict — il accepte volontiers les formes avec nom d'affichage comme Jane <jane@example.com> et expose la partie adresse via parsed.Address. Comparer parsed.Address à l'entrée brute rejette ces formes ainsi que les espaces parasites, ce que vous attendez d'un filtre de syntaxe oui/non sur une saisie utilisateur. Le garde-fou des 320 caractères relève de la ceinture et des bretelles : rien de plus long ne peut être une vraie adresse, et il est moins coûteux de rejeter tôt que de transmettre une chaîne gigantesque à quoi que ce soit en aval.

Sur .NET Framework ou toute cible antérieure à .NET 5, TryCreate n'existe pas ; repliez-vous alors sur le constructeur et interceptez l'exception :

try { _ = new MailAddress(email); /* syntax ok */ }
catch (FormatException) { /* reject */ }

Si vous utilisez déjà des annotations de données sur un modèle, le System.ComponentModel.DataAnnotations.EmailAddressAttribute ([EmailAddress]) fait le même travail de façon déclarative et constitue un choix tout à fait valable dans la validation de modèle d'ASP.NET Core. Quelle que soit votre option, traitez un résultat positif comme « à vérifier sérieusement », jamais comme « valide ». Un contrôle de syntaxe ne sait rien du DNS ni des boîtes aux lettres — c'est la raison même pour laquelle la validation d'e-mail par regex échoue : la forme et la délivrabilité sont deux questions distinctes, l'une portant sur la chaîne de caractères, l'autre sur Internet.

Couche 2 : le domaine peut-il recevoir du courrier ?#

Un domaine sans route de messagerie ne peut recevoir de courrier pour personne ; cette unique recherche élimine donc les domaines morts, les noms d'entreprise mal orthographiés et les TLD inventés avant même que vous ne sollicitiez réellement le réseau. Le hic : .NET ne dispose d'aucun résolveur MX intégré. System.Net.Dns résout les enregistrements A et AAAA mais pas les MX ; la réponse idiomatique est donc DnsClient.NET — un package NuGet très répandu et bien maintenu vers lequel se tournent la plupart des projets .NET dès qu'ils ont besoin de DNS au-delà des recherches d'hôte. Installez-le et interrogez le type d'enregistrement MX :

using System.Linq;
using DnsClient; // dotnet add package DnsClient

// LookupClient is thread-safe and caches responses — create one and reuse it.
private static readonly LookupClient Dns = new();

public static async Task<bool> HasMailRouteAsync(string domain)
{
    try
    {
        var response = await Dns.QueryAsync(domain, QueryType.MX);
        return response.Answers.MxRecords().Any();
    }
    catch (DnsResponseException)
    {
        // No reachable resolver, SERVFAIL, and similar — treat as "check later".
        return false;
    }
}
await HasMailRouteAsync("gmail.com");               // true
await HasMailRouteAsync("company-that-folded.com"); // false

Deux idiomes à reprendre. Créez le LookupClient une seule fois et réutilisez-le — il est thread-safe et met les réponses en cache, si bien qu'une instance par requête ne fait que jeter ce cache. Et détachez le domaine de l'adresse au dernier @ à l'aide d'une expression de plage, afin de ne jamais mal analyser une adresse qui (légalement) en contient plusieurs :

var domain = email[(email.LastIndexOf('@') + 1)..];

Certains domaines acceptent le courrier sur un enregistrement A sans MX (un MX implicite). Si vous tenez à gérer ce cas limite, repliez-vous sur QueryType.A lorsque l'ensemble MX est vide — mais pour l'immense majorité des adresses réelles, un contrôle MX est le bon filtre. Une précaution pour un parcours d'inscription : une requête DNS se bloque sur un résolveur, de sorte qu'un incident DNS passager ne devrait pas rejeter catégoriquement un vrai client. Traitez une recherche qui échoue comme « à revérifier plus tard », pas comme « invalide ».

Couche 3 : la boîte aux lettres existe-t-elle réellement ?#

Les couches un et deux ne peuvent qu'écarter une adresse. Un domaine peut publier des enregistrements MX parfaits et n'avoir malgré tout aucune boîte aux lettres à l'adresse que vous détenez — noreply-9f2x@gmail.com est syntaxiquement valide sur un domaine doté d'une route de messagerie active, et reste une boîte aux lettres qui n'a jamais été créée. Confirmer qu'une boîte aux lettres précise existe suppose la conversation de remise SMTP : se connecter au serveur de messagerie, émettre RCPT TO, lire la réponse et se déconnecter avant d'envoyer quoi que ce soit. Comment fonctionne la vérification d'e-mail détaille tout ce pipeline, y compris les domaines catch-all qui acceptent toutes les adresses et déjouent un sondage naïf.

En principe, vous pouvez scripter cela en C# avec un TcpClient et des commandes SMTP brutes. En pratique, vous ne devriez pas l'exécuter depuis votre serveur applicatif. La plupart des fournisseurs cloud bloquent le port 25 sortant, si bien qu'un sondage qui fonctionne sur votre ordinateur portable échoue discrètement en production. La réponse dépend de la réputation de l'IP depuis laquelle vous vous connectez, et pas seulement de l'adresse que vous contrôlez. Par ailleurs, les serveurs destinataires appliquent le greylisting et limitent le débit des expéditeurs inconnus ; sonder à un tant soit peu de volume vous vaut donc un report ou une inscription sur liste de blocage. C'est la couche qu'il vaut la peine de déléguer à une infrastructure conçue pour cela.

Appeler une API de vérification depuis C##

Le point de terminaison de vérification de Qualisend exécute tout le pipeline — syntaxe, DNS et sondage SMTP de la boîte aux lettres — depuis une infrastructure à réputation gérée, et renvoie un verdict en temps réel. HttpClient accompagné de System.Text.Json suffit ; modélisez l'enveloppe de réponse sous forme de records et laissez le générateur de source JSON ou le désérialiseur par réflexion les remplir :

using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Serialization;

public record VerifyResponse(
    [property: JsonPropertyName("result")] VerifyResult Result);

public record VerifyResult(
    [property: JsonPropertyName("status")] string Status,
    [property: JsonPropertyName("score")] int Score,
    [property: JsonPropertyName("reason")] string? Reason,
    [property: JsonPropertyName("sub_flags")] IReadOnlyDictionary<string, bool> SubFlags);
// One HttpClient for the whole app — don't new one up per request.
private static readonly HttpClient Http = new()
{
    BaseAddress = new Uri("https://api.qualisend.com/v1/"),
};

public static async Task<VerifyResult> VerifyAsync(string email)
{
    using var request = new HttpRequestMessage(HttpMethod.Post, "verify")
    {
        Content = JsonContent.Create(new { email }),
    };
    request.Headers.Authorization = new AuthenticationHeaderValue(
        "Bearer", Environment.GetEnvironmentVariable("QUALISEND_API_KEY"));

    using var response = await Http.SendAsync(request);
    response.EnsureSuccessStatusCode();

    var body = await response.Content.ReadFromJsonAsync<VerifyResponse>();
    return body!.Result; // status: deliverable | risky | undeliverable | unknown
}

POST https://api.qualisend.com/v1/verify est une forme indicative — consultez la référence de l'API sur /developers pour connaître le point de terminaison exact, le format de clé à portée limitée et l'ensemble des champs. Lisez la clé depuis une variable d'environnement plutôt que de coder en dur YOUR_API_KEY, et réutilisez un unique HttpClient pour éviter l'épuisement des sockets. La réponse revient au sein d'une enveloppe result :

{
  "result": {
    "status": "deliverable",
    "score": 95,
    "reason": null,
    "sub_flags": { "role": false, "disposable": false, "free": false, "catch_all": false }
  }
}

status est votre verdict principal — deliverable, risky, undeliverable ou unknown. score note la confiance, reason explique un résultat négatif, et sub_flags détaille des signaux comme role, disposable, free et catch-all afin que vous puissiez appliquer votre propre politique (rejeter undeliverable, mettre risky en attente de revue, signaler disposable à l'inscription).

Assembler les couches pour valider une adresse e-mail en C##

Le moins coûteux d'abord, on s'arrête dès qu'on a une réponse :

public static async Task<VerifyResult> ValidateEmailAsync(string email)
{
    if (!IsValidSyntax(email))
        return new VerifyResult("undeliverable", 0, "invalid_email",
            new Dictionary<string, bool>());

    var domain = email[(email.LastIndexOf('@') + 1)..];
    if (!await HasMailRouteAsync(domain))
        return new VerifyResult("undeliverable", 0, "invalid_domain",
            new Dictionary<string, bool>());

    return await VerifyAsync(email); // deliverable | risky | undeliverable | unknown
}

Les deux couches locales ne coûtent rien et interceptent l'essentiel des déchets instantanément ; la couche API ne s'exécute que sur les adresses qui méritent l'aller-retour réseau. Cet ordre est toute l'astuce — la même structure que vous retrouverez dans les versions Node.js, Python et PHP de ce guide, car c'est le découpage en couches, et non le langage, qui fait fonctionner la validation.

Foire aux questions#

MailAddress ou EmailAddressAttribute suffisent-ils à valider un e-mail en C# ?#

Pour la syntaxe, oui : ce sont deux contrôles solides de première couche, préférables à une regex bricolée à la main, MailAddress.TryCreate vous fournissant un booléen sans exception. Mais ils valident la forme, pas la délivrabilité : ni l'un ni l'autre ne résout le DNS ni ne contacte un serveur de messagerie, si bien qu'un résultat positif signifie « ressemble à un e-mail », pas « sera délivré ». Associez le contrôle de syntaxe à une recherche MX et à une vérification SMTP de la boîte aux lettres avant d'accorder votre confiance à l'adresse.

Le .NET dispose-t-il d'un moyen intégré de rechercher les enregistrements MX ?#

Non. System.Net.Dns résout les enregistrements d'hôte A et AAAA mais ne prend pas en charge les MX, d'où le recours standard au package NuGet DnsClient.NET. Interrogez QueryType.MX, réutilisez un seul LookupClient et considérez un ensemble de réponses vide — ou une DnsResponseException — comme l'absence de route de messagerie plutôt que de laisser l'exception se propager.

Puis-je vérifier l'existence d'une boîte aux lettres en C# sans API ?#

En partie seulement. DnsClient.NET confirme que le domaine accepte le courrier, ce qui écarte les domaines morts à moindre coût. Confirmer la boîte aux lettres elle-même suppose une conversation SMTP que vous pouvez tenter avec un TcpClient mais que vous ne devriez pas exécuter depuis votre serveur applicatif — le port 25 sortant est largement bloqué et le résultat dépend de la réputation de votre IP d'envoi. C'est la couche qu'un service de vérification existe pour gérer, et il vaut la peine de comparer les fournisseurs avant de la construire vous-même.

Dois-je valider les e-mails à l'inscription ou lors du nettoyage d'une liste ?#

Les deux, mais à des profondeurs différentes. Exécutez la syntaxe et la recherche MX de façon synchrone à l'inscription — elles sont assez rapides pour bloquer la requête et donner un retour instantané — et agissez aussi sur le verdict immédiat de l'API à cet endroit ; le guide d'inscription serverless montre le schéma de bout en bout. Réservez une vérification plus poussée, par lots, au nettoyage d'une liste existante, où la latence importe peu et où la rigueur, elle, compte.


Prêt à ajouter la couche SMTP ? La référence de l'API contient la forme exacte de /verify, les clés à portée limitée et des exemples à copier-coller ; sinon, déposez une adresse dans le vérificateur d'e-mail gratuit pour voir une chaîne approuvée par MailAddress revenir en undeliverable.

Your reputation, protected.

Clean your first list in minutes. 100 free credits, no card required.

Get started