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

  1. Subscribe to MessageSent / check the recipient results, or use Send with explicit recipient list and validate addresses first.
  2. Catch SmtpCommandException, inspect StatusCode/StatusLine, and remove or fix rejected recipients.
  3. Ensure client.Authenticate succeeded — most 'relay access denied' rejections are unauthenticated relay attempts.
  4. Verify recipient domains have valid MX records before sending.
  5. 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

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


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)