I have been thinking about this recently, too.
I decided to
- completely avoid using user-generated in any of the mail functions arguments that go into the mail header, i.e. 1st, 2nd and 4th
- if necessary carefully validating user-generated content used in the header, rather by restricting allowed characters then by allowing everything but certain characters, as you can always miss something.
I would probably validate email addresses with regex. For content that is supposed to be used in the subject line, the easiest way seems to have certain subjects for the user to choose from, and set it to "other" or something if the submitted data does not match any of these (maybe putting the original into the body to see what it looked like).
I just felt I'd share these thought, as I would definitely like to know if I missed something.