Well this is quite nice solution, a working one. I've seen much worst around.
Only a few notes.
- it has some unnecessary validations, say
contains_bad_str(body); is useless. And whole "bad words" approach at all. Newline test is enough
- just a rule:
DO NOT TALK TO STRANGERS. Never talk to possible attacker, providing them with any feedback. All these "Suspected injection attempt" are childish and more of it - it supply an attacker with information they can use. Always send just 500 HTTP error in all these cases and nothing else.
- you're using pretty unusual way of error handling. I can't understand the difference between these code snippets
why the first one just sets a variable
if(trim($_POST['emailTo']) == '') {
$hasError = true;
and second one prints an error and exits?
if (!is_valid_email($email)) {
echo 'Invalid email submitted - mail not being sent.';
exit;
}
Will you provide a fair user with any feedback on error occurred? Something like "Please fill all required fields"?
I wouldn't make user supplied e-mail subject but rather some hardcoded sentence, like Feedback from ".$_SERVER['HTTP_HOST']. I'd like to distinguish feedback messages in my mailbox from the regular ones. (I wouldn't make that fancy reply-to feature either, but it's my own preference)
stripslashes thing. Why only message? Aren't other fields behave the same? And at least you have check get_magic_quotes_gpc() before applying. I'd make it automated, at hte top of the script, both stripslashes and trim, just in the loop over $_POST array.