This is a classic use case for dependency injection or a service locator. Instead of hardwiring your application to send emails, have your application get a notification service from the service locator, and have it call that. In production, configure the service locator to return an email sending service; in the test environment, configure it to return a service that does nothing, or add the notification to a list, or whatever.
You don't need to go for the full whack dependency injection here: a very simple service locator will suffice. Similarly, the injection of the test notification service can be done through test fixture code. Here's a really simple example:
public static class ServiceLocator
{
private static INotificationService _notificationService = new EmailNotificationService();
public static INotificationService NotificationService
{
get { return _notificationService; }
}
// For test use only
public static void SetNotificationService(INotificationService notificationService)
{
_notificationService = notificationService;
}
}
(A real service locator would provide a more flexible interface, along the lines of IServiceContainer/IServiceProvider, so that you could mock out multiple different services; this is just to illustrate the idea.)
Then in your test code:
[SetUp]
public void Setup()
{
ServiceLocator.NotificationService = new DiscardingService();
}
(Using NUnit terminology here for the method that gets run before each test -- not sure what the MSTest equivalent is.)
An advantage of this is that you can now test that the right notifications are being sent: have your test notification service capture the notifications in a list, and you can make assertions about that list to verify that notifications are being sent and are correct.
Again, note that this is not a full explanation of DI or service locators, and my sample code is by no means the best way to do it.