public void SendAsync(MailMessage message, object userToken)
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().FullName);
}
if (NetEventSource.IsEnabled)
{
NetEventSource.Enter(this, message, userToken, _transport);
}
try
{
if (InCall)
{
throw new InvalidOperationException(SR.net_inasync);
}
if (message == null)
{
throw new ArgumentNullException(nameof(message));
}
if (DeliveryMethod == SmtpDeliveryMethod.Network)
{
CheckHostAndPort();
}
_recipients = new MailAddressCollection();
if (message.From == null)
{
throw new InvalidOperationException(SR.SmtpFromRequired);
}
if (message.To != null)
{
foreach (MailAddress address in message.To)
{
_recipients.Add(address);
}
}
if (message.Bcc != null)
{
foreach (MailAddress address in message.Bcc)
{
_recipients.Add(address);
}
}
if (message.CC != null)
{
foreach (MailAddress address in message.CC)
{
_recipients.Add(address);
}
}
if (_recipients.Count == 0)
{
throw new InvalidOperationException(SR.SmtpRecipientRequired);
}
try
{
InCall = true;
_cancelled = false;
_message = message;
string pickupDirectory = PickupDirectoryLocation;
CredentialCache cache;
// Skip token capturing if no credentials are used or they don't include a default one.
// Also do capture the token if ICredential is not of CredentialCache type so we don't know what the exact credential response will be.
_transport.IdentityRequired = Credentials != null && (ReferenceEquals(Credentials, CredentialCache.DefaultNetworkCredentials) || (cache = Credentials as CredentialCache) == null || IsSystemNetworkCredentialInCache(cache));
_asyncOp = AsyncOperationManager.CreateOperation(userToken);
switch (DeliveryMethod)
{
case SmtpDeliveryMethod.PickupDirectoryFromIis:
throw new NotSupportedException(SR.SmtpGetIisPickupDirectoryNotSupported);
case SmtpDeliveryMethod.SpecifiedPickupDirectory:
{
if (EnableSsl)
{
throw new SmtpException(SR.SmtpPickupDirectoryDoesnotSupportSsl);
}
_writer = GetFileMailWriter(pickupDirectory);
bool allowUnicode = IsUnicodeSupported();
ValidateUnicodeRequirement(message, _recipients, allowUnicode);
message.Send(_writer, true, allowUnicode);
if (_writer != null)
{
_writer.Close();
}
_transport.ReleaseConnection();
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(null, false, _asyncOp.UserSuppliedState);
InCall = false;
_asyncOp.PostOperationCompleted(_onSendCompletedDelegate, eventArgs);
break;
}
case SmtpDeliveryMethod.Network:
default:
_operationCompletedResult = new ContextAwareResult(_transport.IdentityRequired, true, null, this, s_contextSafeCompleteCallback);
lock (_operationCompletedResult.StartPostingAsyncOp())
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(this, $"Calling BeginConnect. Transport: {_transport}");
}
_transport.BeginGetConnection(_operationCompletedResult, ConnectCallback, _operationCompletedResult, Host, Port);
_operationCompletedResult.FinishPostingAsyncOp();
}
break;
}
}
catch (Exception e)
{
InCall = false;
if (NetEventSource.IsEnabled)
{
NetEventSource.Error(this, e);
}
if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal)
{
throw;
}
Abort();
if (_timedOut)
{
throw new SmtpException(SR.net_timeout);
}
if (e is SecurityException ||
e is AuthenticationException ||
e is SmtpException)
{
throw;
}
throw new SmtpException(SR.SmtpSendMailFailure, e);
}
}
finally
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Exit(this);
}
}
}