In addition to the fine approaches mentioned earlier, I have had success using a fake SMTP client that writes emails to a file system. Each message was written to a separate file in a
directory named after the recipient. The file system approach had the advantage of simplicity; there was no SMTP server -- fake or otherwise -- to configure.
Our product generated emails from templates. It was important to ensure that the templating system worked correctly, but it was also important to ensure that the application supplied the correct data to fill into the templates. Testing the latter became a parsing problem. I ended up replacing our standard templates with simple ones that produced property files. So for example instead of generating this:
Dear Joe Doe,
Your current account balance is $125.
JP Morgan Bank
we would generate this:
SenderBank: JP Morgan Bank
This way, it was easy to parse the generated emails.