New in .NET 4: Don’t Forget to Dispose() your SmtpClient Instances
It seems the System.Net.Mail.SmptClient class has gotten a bit of a facelift in .NET 4.
Wow, it seems like forever since I’ve written a blog post. That’s because I’ve been heads-down on my new book, part of which involves getting up to speed on all of the newest features in ASP.NET 4.0.
I gotta admit that this one caught me by surprise though.
For the record, I will admit that I'm a little fanatical about disposing objects. As you (I hope) already know, that means remembering to call the Dispose() method on objects whose classes implement the IDisposable interface. It’s often tricky to remember which objects you need to dispose, since in many cases it’s not immediately obvious.
I thought I had this disposing stuff pretty much in my back pocket. That’s why I was so surprised when running some static code analysis on my Cyclemania project and seeing the following warning:
Warning 20 CA2000 : Microsoft.Reliability : In method 'TestEmail.btnSendTest_Click(object, EventArgs)', call System.IDisposable.Dispose on object 'new SmtpClient()' before all references to it are out of scope.
Whaaa??? What’s this? This can’t be right…
Well, as it turns out, the SmtpClient class does implement IDisposable, starting in .NET 4.
This is actually a good thing. The .NET 4 implementation of the SmtpClient class pools SMTP connections, which avoids the overhead of re-establishing a connection for every message when sending multiple messages to the same server. Since the same connection can be reused over and over in an application, there’s no way to determine when an application is finished using the client object. Calling Dispose() on it iterates through all established connections and sends a QUIT message, which allows the server to free up its own connection resources and begin processing. The TCP connection is then terminated, and any resources used by the underlying socket are released.
This means that, when you’re using SmtpClient to send mail in your .NET 4 application, you should adhere to the following:
// correct try { using (MailMessage message = new MailMessage()) { message.Subject = "Test Email"; message.Body = "This is a test email from .NET 4!"; message.To.Add("[email protected]"); using (SmtpClient client = new SmtpClient()) { client.Send(message); } } } catch (SmtpException) { // handle exception here } // wrong try { using (MailMessage message = new MailMessage()) { message.Subject = "Test Email"; message.Body = "This is a test email from .NET 3.5!"; message.To.Add("[email protected]"); new SmtpClient().Send(message); } } catch (SmtpException) { // handle exception here }
Just one more .NET 4 “gotcha” to keep in mind.
UPDATE: Jeff Tucker (the guy who implemented this new feature) also points out in the comments below that SmtpClient will also close existing connections if you switch the host or port. Nice!
Subscribe to this blog for more cool content like this!
Pingback from Dew Drop – February 24, 2010 | Alvin Ashcraft's Morning Dew
Pingback from Dew Drop – February 24, 2010 | Alvin Ashcraft's Morning Dew
Thank you for submitting this cool story - Trackback from DotNetShoutout
Linked - List
Pingback from The Morning Brew - Chris Alcock » The Morning Brew #547
.NET Pulse 3/3/2010