Production-ready .NET integration examples for the BounceZero email verification API: IHttpClientFactory, ASP.NET Core minimal API middleware, background IHostedService for queue processing, and Polly retry policies for resilient verification pipelines.
| Field | C# type | Description |
|---|---|---|
| result | string | "valid" | "invalid" | "unknown" |
| is_disposable | bool | true for known throwaway email services |
| is_role_address | bool | true for info@, admin@, support@, etc. |
| catch_all_score | double | 0.0-1.0 confidence score for catch-all domains |
| mx_found | bool | false = domain has no mail server |
| free_provider | bool | true for gmail.com, outlook.com, etc. |
| smtp_code | int | SMTP response code from live probe |
Program.csAlways use IHttpClientFactory - avoids socket exhaustion from direct HttpClient instantiation.
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient<BounceZeroService>(client =>
{
client.BaseAddress = new Uri("https://api.bouncezero.io/");
client.DefaultRequestHeaders.Add(
"X-API-Key",
builder.Configuration["BounceZero:ApiKey"]
);
client.Timeout = TimeSpan.FromSeconds(10);
});
// appsettings.json
// "BounceZero": { "ApiKey": "YOUR_API_KEY" }
// BounceZeroService.cs
using System.Net.Http.Json;
public record VerifyResult(
string Email,
string Result,
bool IsDisposable,
bool IsRoleAddress,
double CatchAllScore,
bool MxFound,
bool FreeProvider,
int SmtpCode
);
public class BounceZeroService(HttpClient http)
{
public async Task<VerifyResult?> VerifyAsync(
string email,
CancellationToken ct = default)
{
var url = $"v1/verify?email={Uri.EscapeDataString(email)}";
return await http.GetFromJsonAsync<VerifyResult>(url, ct);
}
public bool IsAcceptable(VerifyResult result) =>
result.Result != "invalid" &&
!result.IsDisposable &&
(result.Result != "unknown" || result.CatchAllScore >= 0.5);
}
Fail-open: if the verification service is unavailable, the request proceeds.
// Program.cs (continued)
app.MapPost("/api/signup", async (
SignupRequest req,
BounceZeroService bz,
CancellationToken ct) =>
{
try
{
var verification = await bz.VerifyAsync(req.Email, ct);
if (verification is not null && !bz.IsAcceptable(verification))
{
return Results.UnprocessableEntity(new
{
error = "invalid_email",
message = "Please use a valid work email address."
});
}
}
catch (Exception)
{
// fail-open: API unavailable > allow the signup
}
// proceed with account creation...
return Results.Ok(new { status = "created" });
});
record SignupRequest(string Email, string Name);
IHostedService - async bulk queueFor user import flows: enqueue addresses, verify in background, mark unverified accounts for email confirmation.
// EmailVerificationWorker.cs
public class EmailVerificationWorker(
IServiceScopeFactory scopeFactory,
Channel<string> queue) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
await foreach (var email in queue.Reader.ReadAllAsync(ct))
{
await using var scope = scopeFactory.CreateAsyncScope();
var bz = scope.ServiceProvider.GetRequiredService<BounceZeroService>();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
try
{
var result = await bz.VerifyAsync(email, ct);
var user = await db.Users.FirstAsync(u => u.Email == email, ct);
user.EmailVerified = result?.Result == "valid";
user.IsDisposable = result?.IsDisposable ?? false;
user.VerifiedAt = DateTimeOffset.UtcNow;
await db.SaveChangesAsync(ct);
}
catch (Exception ex)
{
// log and move on - don't block the queue
}
}
}
}
// Register in Program.cs:
// builder.Services.AddSingleton(Channel.CreateBounded<string>(1000));
// builder.Services.AddHostedService<EmailVerificationWorker>();
Use IHttpClientFactory to call the BounceZero REST API. Set the X-API-Key header, pass the email as a query parameter, and deserialise the JSON response into a record. Check Result and IsDisposable before allowing the address through.
Always use IHttpClientFactory. Direct HttpClient instantiation causes socket exhaustion under load because TCP connections are not released immediately on dispose. IHttpClientFactory manages a shared pool of HttpMessageHandler instances safely across the application lifetime.
Sign up for a BounceZero account, get your API key, and paste the typed client above. 100 free verifications - no credit card required.
Deep-dive guides on how email verification and inbox placement work
272,446-domain census: DMARC gap, provider divide, catch-all rates
10.2M verifications: 12.3% of addresses are dead, and where they hide
826K re-verifications: only 19% of valid addresses survive 90 days
True catch-all is 1.4% - most of what looks catch-all is unprobeable providers
info@ bounces 4.5x more than personal addresses - measured, not guessed
The 3x invalid-rate gap that vanishes when you control for domain size
Explore other topics