jstedfast/MailKit · error · SmtpCommandException
SmtpStatusCode.TransactionFailed
SmtpStatusCode.TransactionFailed
Error message
No recipients were accepted.
What it means
SmtpCommandException (SmtpErrorCode.MessageNotAccepted, SmtpStatusCode.TransactionFailed) thrown when every RCPT TO was rejected by the server, so the MAIL transaction cannot proceed. MailKit raises NoRecipientsAccepted first, then throws. Note this differs from the local validation error: here the server refused the recipients.
Solutions
- Subscribe to MessageSent / check the recipient results, or use Send with explicit recipient list and validate addresses first.
- Catch SmtpCommandException, inspect StatusCode/StatusLine, and remove or fix rejected recipients.
- Ensure client.Authenticate succeeded — most 'relay access denied' rejections are unauthenticated relay attempts.
- Verify recipient domains have valid MX records before sending.
- Check OnNoRecipientsAccepted/NoRecipientsAccepted event to log server-side rejection reasons.
Example fix
// before
client.Send(message); // throws if all recipients rejected
// after
try {
client.Send(message);
} catch (SmtpCommandException ex) when (ex.ErrorCode == SmtpErrorCode.MessageNotAccepted) {
logger.LogWarning("All recipients rejected: {0}", ex.Message);
// remove/fix recipients and retry
} Defensive patterns
Strategy: try-catch
Validate before calling
if (recipients == null || recipients.Count == 0)
throw new InvalidOperationException("No recipients");
foreach (var r in recipients)
if (!System.Text.RegularExpressions.Regex.IsMatch(r.Address ?? "", @"^[^@\s]+@[^@\s]+\.[^@\s]+$"))
throw new InvalidOperationException("Bad recipient: " + r); Type guard
bool HasValidRecipients(IEnumerable<MailboxAddress> rcpts) => rcpts != null && rcpts.Any(r => !string.IsNullOrEmpty(r.Address));
Try / catch
try { client.Send(message); }
catch (SmtpCommandException ex) when (ex.ErrorCode == SmtpErrorCode.MessageNotAccepted && ex.StatusCode == SmtpStatusCode.TransactionFailed) {
// log ex.Message, prune recipients, optionally re-send
} Prevention
- Authenticate before sending — relay denial is a common cause.
- Prune stale addresses from mailing lists.
- Check the NoRecipientsAccepted event for server-side reasons.
- Use per-message recipients you control rather than blind bulk overrides.
When it happens
Trigger: Calling Send/SendAsync where all RCPT TO commands receive rejections (nonexistent mailboxes, relay denied, no auth for relay, greylisted/over-quota recipients); using explicit sender/recipients overrides that contain bad addresses; a server that rejects unknown domains during RCPT.
Common situations: Typo'd or expired recipient addresses; relaying through a server that doesn't accept your domain without SMTP AUTH; bulk-sending to stale lists where every address in one message bounces; authenticated user lacks relay permission to external domains.
Related errors
- Value cannot be null. (Parameter 'message')
- Value cannot be null. (Parameter 'response')
- The SmtpClient must be connected before you can…
- The SmtpClient is already authenticated.
- The SMTP server does not support authentication.
AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15).
Data as JSON: /api/errors/cd9151b82696236e.
Report an issue: GitHub.
Appendix: source
Thrown at MailKit/Net/Smtp/SmtpClient.cs:2478
if (RcptTo (format, message, recipients[i], pipeline, cancellationToken))
recipientsAccepted++;
}
if (queued.Count > 0) {
// Note: if PIPELINING is supported, this will flush all outstanding
// MAIL FROM and RCPT TO commands to the server and then process
// all of their responses.
var results = FlushCommandQueue (message, sender, recipients, cancellationToken);
recipientsAccepted = results.RecipientsAccepted;
if (results.FirstException != null)
throw results.FirstException;
}
if (recipientsAccepted == 0) {
OnNoRecipientsAccepted (message);
throw new SmtpCommandException (SmtpErrorCode.MessageNotAccepted, SmtpStatusCode.TransactionFailed, "No recipients were accepted.");
}
if (bdat)
return Bdat (format, message, size, cancellationToken, progress);
var dataResponse = Stream.SendCommand ("DATA\r\n", cancellationToken);
ParseDataResponse (dataResponse);
return MessageData (format, message, size, cancellationToken, progress);
} catch (ServiceNotAuthenticatedException ex) {
operation.SetError (ex);
// do not disconnect
Reset (cancellationToken);
throw;
} catch (SmtpCommandException ex) {
operation.SetError (ex);View on GitHub (pinned to 9d3859a785)