Our IsWatcher method takes a ticket object as the second argument

This meant the FindRecipients function failed if any addresses were
included in the ticket update which also existed in the Users table.  A
test case is included.

Addresses which don't have an associated User record short-circuit
IsWatcher earlier enough, so the previous test didn't trigger this bug.
Return the empty string instead of undef for friendlier use in templates

Avoids warnings
Abort early if we don't have a ticket and transaction