Essa técnica une a tabela contra si mesma em uma subconsulta, mas corresponde apenas a uma linha (com base em contact_id e correspondência de e-mail. O truque é que a subconsulta retorna apenas um dos endereços de e-mail usando MIN, teoricamente o primeiro em ordem alfabética (não confiável, mas você disse que não importava).
Eu testei isso com bons resultados.
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;