Beta privataMailbeam è in beta privata: l'API pubblica non è ancora aperta.Iscriviti alla lista d'attesa

Mailbeam
ASP.NET Core + C#Intermedio20 minutiAggiornato a gennaio 2025

Verifica delle email in .NET

Questo tutorial integra Mailbeam in un'applicazione ASP.NET Core con modelli idiomatici di .NET: un HttpClient tipizzato, il modello delle opzioni per la configurazione, l'iniezione delle dipendenze e un attributo di validazione riutilizzabile. Funziona allo stesso modo nelle minimal API e nei controller MVC.

Che cosa costruirai

  • Un servizio IEmailVerifier sostenuto da un HttpClient tipizzato
  • Un attributo di validazione [VerifiedEmail] per il binding dei modelli
  • Un endpoint di registrazione con minimal API che rifiuta gli indirizzi non recapitabili

Prerequisiti

  • SDK di .NET 8 o successivo
  • Una chiave API di Mailbeam (iscriviti gratis)
  • Conoscenze di base sull'iniezione delle dipendenze in ASP.NET Core

Passo 1 — Configura la chiave

Conserva la chiave nei segreti utente in locale e in variabili d'ambiente o Key Vault in produzione:

dotnet user-secrets init
dotnet user-secrets set "Mailbeam:ApiKey" "mb_live_xxxxxxxxxxxxxxxxxxxx"

Collegala con il modello delle opzioni:

// Options/MailbeamOptions.cs
public sealed class MailbeamOptions
{
    public string ApiKey { get; set; } = "";
    public int MinScore { get; set; } = 60;
}

Passo 2 — Registra un HttpClient tipizzato

// Program.cs
builder.Services.Configure<MailbeamOptions>(
    builder.Configuration.GetSection("Mailbeam"));

builder.Services.AddHttpClient<IEmailVerifier, MailbeamVerifier>((sp, client) =>
{
    var opts = sp.GetRequiredService<IOptions<MailbeamOptions>>().Value;
    client.BaseAddress = new Uri("https://api.mailbeam.dev/");
    client.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue("Bearer", opts.ApiKey);
    client.Timeout = TimeSpan.FromSeconds(5);
});

Passo 3 — Costruisci il servizio di verifica

// Services/IEmailVerifier.cs
public interface IEmailVerifier
{
    Task<bool> IsAcceptableAsync(string email, CancellationToken ct = default);
}

// Services/MailbeamVerifier.cs
public sealed class MailbeamVerifier : IEmailVerifier
{
    private readonly HttpClient _http;
    private readonly MailbeamOptions _opts;
    private readonly ILogger<MailbeamVerifier> _log;

    public MailbeamVerifier(
        HttpClient http,
        IOptions<MailbeamOptions> opts,
        ILogger<MailbeamVerifier> log)
    {
        _http = http;
        _opts = opts.Value;
        _log = log;
    }

    private sealed record VerifyResponse(bool Valid, int Score, string? Reason);

    public async Task<bool> IsAcceptableAsync(string email, CancellationToken ct = default)
    {
        try
        {
            var resp = await _http.PostAsJsonAsync(
                "v1/verify", new { email = email.Trim().ToLowerInvariant() }, ct);
            resp.EnsureSuccessStatusCode();

            var result = await resp.Content.ReadFromJsonAsync<VerifyResponse>(ct);
            return result is not null
                && result.Valid
                && result.Score >= _opts.MinScore;
        }
        catch (Exception ex)
        {
            // Lascia passare: un guasto dell'API non deve bloccare le registrazioni
            _log.LogError(ex, "Verifica di Mailbeam fallita per {Email}", email);
            return true;
        }
    }
}

Passo 4 — Aggiungi un attributo di validazione

In MVC e nel binding dei modelli, un attributo tuo tiene la validazione dichiarativa:

// Validation/VerifiedEmailAttribute.cs
public sealed class VerifiedEmailAttribute : ValidationAttribute
{
    protected override ValidationResult? IsValid(
        object? value, ValidationContext context)
    {
        if (value is not string email || string.IsNullOrWhiteSpace(email))
            return ValidationResult.Success; // lascia i vuoti a [Required]

        var verifier = context.GetRequiredService<IEmailVerifier>();
        // Gli attributi sono sincroni; blocca brevemente sulla chiamata asincrona
        var ok = verifier.IsAcceptableAsync(email).GetAwaiter().GetResult();

        return ok
            ? ValidationResult.Success
            : new ValidationResult("Inserisci un indirizzo email valido e recapitabile.");
    }
}

Passo 5 — Verifica in un endpoint di minimal API

// Program.cs
app.MapPost("/api/signup", async (
    SignupRequest req,
    IEmailVerifier verifier,
    CancellationToken ct) =>
{
    if (!await verifier.IsAcceptableAsync(req.Email, ct))
        return Results.ValidationProblem(new Dictionary<string, string[]>
        {
            ["email"] = ["Inserisci un indirizzo email valido e recapitabile."]
        });

    var user = await CreateUserAsync(req.Email, req.Password, ct);
    return Results.Created($"/users/{user.Id}", user);
});

public record SignupRequest(string Email, string Password);

Passo 6 — Aggiungi la cache

Usa IMemoryCache (o una cache distribuita) per evitare interrogazioni ripetute:

public async Task<bool> IsAcceptableAsync(string email, CancellationToken ct = default)
{
    var key = $"mb:{email.Trim().ToLowerInvariant()}";
    if (_cache.TryGetValue<bool>(key, out var cached))
        return cached;

    // ... esegui la chiamata di verifica come nel passo 3 ...
    var ok = result is not null && result.Valid && result.Score >= _opts.MinScore;
    _cache.Set(key, ok, TimeSpan.FromHours(24));
    return ok;
}

Prove

Simula il client tipizzato oppure punta i test ai domini di prova di Mailbeam, che sono deterministici e non consumano quota:

[Fact]
public async Task Disposable_Email_Is_Rejected()
{
    var verifier = CreateVerifier(); // collegato alla configurazione di test
    var ok = await verifier.IsAcceptableAsync("temp@disposable.mailbeam-test.dev");
    Assert.False(ok);
}

[Fact]
public async Task Valid_Email_Is_Accepted()
{
    var verifier = CreateVerifier();
    var ok = await verifier.IsAcceptableAsync("user@valid.mailbeam-test.dev");
    Assert.True(ok);
}

Buone pratiche

PraticaPerché
HttpClient tipizzato con AddHttpClientPool di connessioni, resilienza e simulazione facile
Modello delle opzioni per la chiaveConfigurazione pulita, senza stringhe magiche
Lasciar passare davanti alle eccezioniUn guasto dell'API non rompe le registrazioni
Impostare un Timeout di 5 sNon lasciare la richiesta appesa a un sondaggio lento
Mettere in cache con IMemoryCacheRiduce le chiamate doppie nei ritentativi

Lista di controllo per la produzione

  • Chiave API nei segreti utente o in Key Vault, mai nel codice
  • Tempo di attesa massimo dell'HttpClient configurato
  • Registrazione degli errori sui fallimenti di verifica
  • Cache distribuita nelle pubblicazioni con più istanze
  • Domini di prova usati nei test unitari

Prossimi passi