You want your function to return a value <0 if $a comes before $b, ==0 if $a is the same as $b, and >0 if $a comes after $b. strcasecmp() produces such a value.
But with that ! there all you're returning is true (if they are the same) or false (if they are different). On top of that, true is equivalent to 1 and false is equivalent to 0.
So if two emails have different last names, your function is telling usort() that they are the same; and if they're the same, you're saying that the first one is bigger.
As a result, nothing gets sorted.
Practical upshot, remove the ! and just return the results from strcasecmp (which are already of the correct form).
Oh, and incidentally, it should be usort($names, 'sort_name'); and unless you want the array to be in reverse order, sort_name($a,$b) would have a better effect.