This problem is known, AFAIK, as "partitioning a set into equivalence classes", but I could not find ad hoc a good web resource for it, so I try give a general outline of an efficient algorithm:
The outer part is straightforward:
Start with an empty set of buckets. Each bucket will hold a list of persons, and, for any pair of different buckets, the joint email adresses of the associated persons of each bucket will be disjoint at any time.
iterate over all persons P
For each email adress of P: determine if there is already a related bucket -> gives you a list B of buckets (which might be empty)
if B is empty (none of the email addresses of P matches any of the previous buckets), create a new bucket containing only this person
if B contains exactly one element, put P into that bucket (and extend the email adress list of the bucket accordingly)
if B contains 2 or more buckets, merge these buckets into one (and extend the email adress list of this new bucket accordingly)
So what remains is to pick some efficient data structures which support the required operations:
each bucket needs to hold a set of persons -> a list of persons for each bucket will do it
efficient adding of persons to a bucket and merging of buckets -> a list is still fine
efficient lookup of buckets by email: that means you need an additional dictionary D which maps
email -> bucket.
The latter one can be efficiently updated when a new bucket is added, when a bucket gets additional email addresses or when two buckets will be merged (which means the email adresses in the dictionary will need to be remapped to the newly created merged bucket).
To finally retrieve all the found buckets, you can either do some bookkeeping during the process about the newly created buckets and the ones which were deleted during a merge (some additional hashset for all valid buckets will do the trick), or you can iterate over all values of that dictionary and remove the duplicate buckets (see some standard Java solutions here).
The above sketch can be made even more efficient by utilizing a so-called "disjoint-set data structure" instead of a list of persons for each bucket, but to my experience for many practical applications a list is sufficient.