简体   繁体   中英

How do I properly dispose SMTP object?

I have a loop where if you dropped a file into a folder, it would email you on success/failure. I tried the 'using' statement which implements Dispose() automatically.

I also tried a 'try/finally' statement (recommended here: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement . Both of which gave me this error:

Cannot access a disposed object. Object name 'system.net.mail.smtpclient'

Attempt 1:

private int _disposed;
        private readonly string _fromEmail;
        private readonly SmtpClient _client;

public Emailer()
        {
            _disposed = 0;
            _fromEmail = "email";
            _client = new SmtpClient("domain-com.mail.protection.outlook.com", 25)
            {
                EnableSsl = true,
                Credentials = new NetworkCredential(_fromEmail, "password")
            };
        }

public async Task SendEmailAsync(IList<string> to, string subject, string body)
        {
            using (MailMessage mail = new MailMessage())
            {
                mail.From = new MailAddress(_fromEmail);
                foreach (string toEmail in to)
                    mail.To.Add(toEmail);
                
                mail.Subject = subject;
                mail.Body = body;
                mail.IsBodyHtml = true;

                using (SmtpClient smtp = _client)
                {
                    smtp.Credentials = _client.Credentials;
                    smtp.EnableSsl = _client.EnableSsl;
                    await smtp.SendMailAsync(mail);
                }
            }
        }

Attempt 2:

private int _disposed;
        private readonly string _fromEmail;
        private readonly SmtpClient _client;

public Emailer()
        {
            _disposed = 0;
            _fromEmail = "email";
            _client = new SmtpClient("domain-com.mail.protection.outlook.com", 25)
            {
                EnableSsl = true,
                Credentials = new NetworkCredential(_fromEmail, "password")
            };
        }

public async Task SendEmailAsync(IList<string> to, string subject, string body)
        {
            using (MailMessage mail = new MailMessage())
            {
                mail.From = new MailAddress(_fromEmail);
                foreach (string toEmail in to)
                    mail.To.Add(toEmail);
                
                mail.Subject = subject;
                mail.Body = body;
                mail.IsBodyHtml = true;

                try
                {
                    SmtpClient smtp = _client;
                    smtp.Credentials = _client.Credentials;
                    smtp.EnableSsl = _client.EnableSsl;
                    await smtp.SendMailAsync(mail);
                }
                finally
                {
                    Dispose();
                }
            }
        }

My Dispose() Method

public void Dispose()
        {
            if (Interlocked.CompareExchange(ref _disposed, 1, 0) != 0)
                return;

            _client.Dispose();
        }
    }
}

You are disposing a Smtp object on your first call. You need to expose method to dispose smtp object and once your loop gets complete call this method to dispose your smtp object and get rid of your using statement.

public void DisposeSMTPClient()
{
    _client.Dispose();
}

public async Task SendEmailAsync(IList<string> to, string subject, string body)
        {
            var mail = new MailMessage();
            
                mail.From = new MailAddress(_fromEmail);
                foreach (string toEmail in to)
                    mail.To.Add(toEmail);
                
                mail.Subject = subject;
                mail.Body = body;
                mail.IsBodyHtml = true;

                    await _client.SendMailAsync(mail);
            
        }


Call DisposeSMTPClient this function after your loops end

My problem was using 2 using statements.

I fixed it by using a try catch block for sending the email and the original using statement along with implementing the IDisposable class.

using (MailMessage mail = new MailMessage())
            {
                mail.From = new MailAddress(_fromEmail);
                foreach (string toEmail in to)
                    mail.To.Add(toEmail);

                mail.Subject = subject;
                mail.Body = body;
                mail.IsBodyHtml = true;
                //mail.Attachments.Add(new Attachment("D:\\TestFile.txt"));//--Uncomment this to send any attachment  
                try
                {
                    SmtpClient smtp = _client;
                    smtp.Credentials = _client.Credentials;
                    smtp.EnableSsl = _client.EnableSsl;
                    await smtp.SendMailAsync(mail);
                }
                catch
                { }
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM