Cette technique joint la table à elle-même dans une sous-requête, mais elle ne correspond qu'à une seule ligne (basée sur contact_id et correspondance des e-mails. L'astuce est que la sous-requête renvoie une seule des adresses e-mail en utilisant MIN, théoriquement la première par ordre alphabétique (pas fiable, mais vous avez dit que cela n'avait pas d'importance).
J'ai testé cela avec de bons résultats.
UPDATE
email
JOIN (SELECT contact_id, MIN(email) as email
FROM email GROUP BY contact_id) as singles
USING(contact_id, email)
set is_primary=1;