I recently (re?)learned a harsh lesson at work. We migrated a critical application’s e-mail client code to use System.Net.Mail‘s classes instead of those in the deprecated System.Web.Mail.
After doing this, we immediately had three problems, mostly with the Attachment class:
- Our automated test software could no longer read the attachments
- Attachments started having names of Directory_Directory_FileName (they were just Filename)
- The software could no longer delete the attachment files from disk after they were e-mailed (the file was still in use).
With problem 1, it turned out that the default encoding in the old MailAttachment class was 7Bit and the test program (which I didn’t write) was directly scraping the mail queue (on a Linux system) and reading the encoded text, looking for recognizable tokens. The new class’s default encoding was Base64–gibberish, to this test program. It wouldn’t really matter to our end-users, but the taking the “easy” way out in writing the test program locked us into an encoding. It just so happens, though, that 7Bit encoding is preferable in our circumstances, even for end-users (Base64 adds significant e-mail overhead–some of our users pay by kilobyte).
The 2nd problem took me a little longer to figure out. At first I thought it was a bug in the attachment naming code, but I couldn’t find anything either in code or the file system. It turns out that the name of the file that the Attachment class is giving includes the directory structure in the name–this seems quite odd–I mean, how often do you want a file name like that? So I manually set the ContentDisposition.FileName property to be just the filename.
I still haven’t completely figured out #3. I think it’s because the MailMessage class is locking the file during send, and not releasing it as early as the old class. In any case, I haven’t directly solved the problem, just come up with a semi-elegant workaround.
- Don’t assume default settings are the same across framework upgrades.
- Build unit tests to test the assumed stuff–even the stuff controlled by the framework. Don’t assume it’s doing exactly what you want with default settings.
- Most importabtly, if your functionality depends on specific settings, then explicitly specify them–don’t ever leave them to chance.
Thankfully, these were relatively easy to diagnose and caused minimal to moderate impact.
Check out my latest book, the essential, in-depth guide to performance for all .NET developers:
Writing High-Performance.NET Code, 2nd Edition by Ben Watson. Available for pre-order: