The bash exec function has an underutilized feature allowing you to redirect stdin or stderr for the entire script, avoiding the need to make sure that the user always runs
myscript.sh > output.log:
exec > example.`date +%Y-%m-%d`.log
Unfortunately, when the documentation says "If FILE is not specified, the redirections take effect in this shell" there's a key omission: you can't simply use a normal pipe to have your output go to mail, logger, etc. or in non-interactive environments like grid / batch schedulers which don't allow you to specify a pipe for job output.
Googling won't turn up much useful other than some hacks which redirect to a temporary file/pipe or re-exec the script and I wanted something cleaner. The solution is to use the bash process substitution feature which allows you to create a file handle for a given command and use that where you might normally use a filename. This is normally demoed for cool input hacks such as diff-ing the output of two commands but it's also useful for our purposes:
#!/bin/bash exec > >(mail -s "$0: normal job output" email@example.com) exec 2> >(mail -s "$0: error job output" firstname.lastname@example.org) ... commands which will be executed normally ...