dotnet/AspNetCore.Docs · critical · Exception
Null EmailAuthKey
Error message
Null EmailAuthKey
What it means
Exception("Null EmailAuthKey") thrown by the sample EmailSender before calling the Mandrill API. The IOptions<AuthMessageSenderOptions>.EmailAuthKey is read in SendEmailAsync; if it is null or empty the sample refuses to send because the API key is required to authenticate with Mandrill. Guards against sending with no credentials.
Source
Thrown at aspnetcore/blazor/security/account-confirmation-and-password-recovery.md:208
string confirmationLink) => SendEmailAsync(email, "Confirm your email",
"<html lang=\"en\"><head></head><body>Please confirm your account by " +
$"<a href='{confirmationLink}'>clicking here</a>.</body></html>");
public Task SendPasswordResetLinkAsync(ApplicationUser user, string email,
string resetLink) => SendEmailAsync(email, "Reset your password",
"<html lang=\"en\"><head></head><body>Please reset your password by " +
$"<a href='{resetLink}'>clicking here</a>.</body></html>");
public Task SendPasswordResetCodeAsync(ApplicationUser user, string email,
string resetCode) => SendEmailAsync(email, "Reset your password",
"<html lang=\"en\"><head></head><body>Please reset your password " +
$"using the following code:<br>{resetCode}</body></html>");
public async Task SendEmailAsync(string toEmail, string subject, string message)
{
if (string.IsNullOrEmpty(Options.EmailAuthKey))
{
throw new Exception("Null EmailAuthKey");
}
await Execute(Options.EmailAuthKey, subject, message, toEmail);
}
public async Task Execute(string apiKey, string subject, string message,
string toEmail)
{
var api = new MandrillApi(apiKey);
var mandrillMessage = new MandrillMessage("sarah@contoso.com", toEmail,
subject, message);
await api.Messages.SendAsync(mandrillMessage);
logger.LogInformation("Email to {EmailAddress} sent!", toEmail);
}
}
```
View on GitHub (pinned to c67a80103a)
Solutions
- Set the EmailAuthKey in user secrets (Development) or environment variables/secrets store (Production): dotnet user-secrets set "EmailAuthKey" "<key>".
- Confirm AuthMessageSenderOptions is bound via builder.Configuration.GetSection(...).Get<AuthMessageSenderOptions>() or IOptions<AuthMessageSenderOptions>.
- Validate options at startup (ValidateOnStart) so misconfiguration fails fast rather than at first email send.
- Throw a more specific ConfigurationException with the key name for clearer diagnostics.
Example fix
// before
if (string.IsNullOrEmpty(Options.EmailAuthKey))
{
throw new Exception("Null EmailAuthKey");
}
// after — validated options + clearer exception
builder.Services.AddOptions<AuthMessageSenderOptions>()
.Bind(builder.Configuration.GetSection("AuthMessageSender"))
.ValidateDataAnnotations()
.ValidateOnStart();
// in sender
if (string.IsNullOrWhiteSpace(Options.EmailAuthKey))
{
throw new InvalidOperationException(
"Configuration value 'AuthMessageSender:EmailAuthKey' is missing. " +
"Set it via user-secrets (Development) or environment variable (Production).");
} Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrWhiteSpace(builder.Configuration["AuthMessageSender:EmailAuthKey"])) {
throw new InvalidOperationException("EmailAuthKey is not configured.");
} Try / catch
try { await emailSender.SendEmailAsync(to, subject, body); }
catch (Exception ex) when (ex.Message.Contains("EmailAuthKey"))
{
logger.LogCritical(ex, "Email provider not configured.");
} Prevention
- Set EmailAuthKey via user-secrets (Development) and secrets/env (Production).
- Bind AuthMessageSenderOptions and validate with DataAnnotations + ValidateOnStart.
- Use named configuration keys consistently across code and config files.
- Document required secrets in onboarding material.
When it happens
Trigger: EmailAuthKey configuration value is missing from appsettings/secrets/user-secrets, or the AuthMessageSenderOptions was never bound from configuration. Any password-reset/confirmation flow that triggers SendEmailAsync will throw.
Common situations: Forgetting to set the EmailAuthKey user secret in Development; deployment missing the environment variable/secret; configuration section name mismatch so options binding yields null; running locally without `dotnet user-secrets set`.
Related errors
- Missing base address!
- No URI!
- HttpContext not available
- No server address available.
- ${this.type} `template` option must consist of exactly 1 top
AI-assisted analysis of dotnet/AspNetCore.Docs@c67a80103a (2026-08-13).
Data as JSON: /api/errors/7ab944253e755887.
Report an issue: GitHub.