Esempio n. 1
0
        /// <summary>
        /// Send a message via SMTP, optionally, bypass the RCPT TO recipients with the added rcpto collection.
        /// Otherwise, default behavior is to send to all recipients listed in To, Cc, and Bcc.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="rcptToRecipients"></param>
        public void Send(MailMessage message, IEnumerable <MailAddress> rcptToRecipients = null)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this, message);
            }

            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
            try
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, $"DeliveryMethod={DeliveryMethod}");
                    NetEventSource.Associate(this, message);
                }

                SmtpFailedRecipientException recipientException = null;

                if (InCall)
                {
                    throw new InvalidOperationException(Strings.net_inasync);
                }

                if (message == null)
                {
                    throw new ArgumentNullException(nameof(message));
                }

                if (DeliveryMethod == SmtpDeliveryMethod.Network)
                {
                    CheckHostAndPort();
                }

                MailAddressCollection recipients = new MailAddressCollection();

                if (message.From == null)
                {
                    throw new InvalidOperationException(Strings.SmtpFromRequired);
                }

                var rcptTo = (rcptToRecipients ?? Enumerable.Empty <MailAddress>()).ToArray();

                if (rcptTo.Length > 0)
                {
                    foreach (var i in rcptTo)
                    {
                        recipients.Add(i);
                    }
                }
                else
                {
                    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(Strings.SmtpRecipientRequired);
                }

                _transport.IdentityRequired = false;  // everything completes on the same thread.

                try
                {
                    InCall    = true;
                    _timedOut = false;
                    _timer    = new Timer(new TimerCallback(TimeOutCallback), null, Timeout, Timeout);
                    bool   allowUnicode    = false;
                    string pickupDirectory = PickupDirectoryLocation;

                    MailWriter writer;
                    switch (DeliveryMethod)
                    {
                    case SmtpDeliveryMethod.PickupDirectoryFromIis:
                        throw new NotSupportedException(Strings.SmtpGetIisPickupDirectoryNotSupported);

                    case SmtpDeliveryMethod.SpecifiedPickupDirectory:
                        if (EnableSsl)
                        {
                            throw new SmtpException(Strings.SmtpPickupDirectoryDoesnotSupportSsl);
                        }

                        allowUnicode = IsUnicodeSupported();     // Determend by the DeliveryFormat paramiter
                        ValidateUnicodeRequirement(message, recipients, allowUnicode);
                        writer = GetFileMailWriter(pickupDirectory);
                        break;

                    case SmtpDeliveryMethod.Network:
                    default:
                        GetConnection();
                        // Detected durring GetConnection(), restrictable using the DeliveryFormat paramiter
                        allowUnicode = IsUnicodeSupported();
                        ValidateUnicodeRequirement(message, recipients, allowUnicode);
                        writer = _transport.SendMail(message.Sender ?? message.From, recipients,
                                                     message.BuildDeliveryStatusNotificationString(), allowUnicode, out recipientException);
                        break;
                    }
                    _message = message;
                    message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network, allowUnicode);
                    writer.Close();
                    _transport.ReleaseConnection();

                    //throw if we couldn't send to any of the recipients
                    if (DeliveryMethod == SmtpDeliveryMethod.Network && recipientException != null)
                    {
                        throw recipientException;
                    }
                }
                catch (Exception e)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Error(this, e);
                    }

                    if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal)
                    {
                        throw;
                    }

                    Abort();
                    if (_timedOut)
                    {
                        throw new SmtpException(Strings.net_timeout);
                    }

                    if (e is SecurityException ||
                        e is AuthenticationException ||
                        e is SmtpException)
                    {
                        throw;
                    }

                    throw new SmtpException(Strings.SmtpSendMailFailure, e);
                }
                finally
                {
                    InCall = false;
                    if (_timer != null)
                    {
                        _timer.Dispose();
                    }
                }
            }
            finally
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
            }
        }