|
| 1 | +WITH normalized AS ( |
| 2 | + SELECT "id", "email", lower(btrim("email")) AS "normalized" FROM "core_users" |
| 3 | +), split AS ( |
| 4 | + SELECT |
| 5 | + "id", |
| 6 | + "email", |
| 7 | + "normalized", |
| 8 | + CASE WHEN length("normalized") - length(replace("normalized", '@', '')) = 1 |
| 9 | + THEN split_part("normalized", '@', 1) END AS "localPart", |
| 10 | + CASE WHEN length("normalized") - length(replace("normalized", '@', '')) = 1 |
| 11 | + THEN split_part("normalized", '@', 2) END AS "domain" |
| 12 | + FROM normalized |
| 13 | +), canonical AS ( |
| 14 | + SELECT |
| 15 | + "id", |
| 16 | + "email", |
| 17 | + CASE |
| 18 | + WHEN "localPart" IS NULL OR "localPart" = '' OR "domain" = '' OR left("localPart", 1) = '"' |
| 19 | + THEN "normalized" |
| 20 | + WHEN "domain" IN ('gmail.com', 'googlemail.com') |
| 21 | + THEN CASE |
| 22 | + WHEN replace(split_part("localPart", '+', 1), '.', '') = '' THEN "normalized" |
| 23 | + ELSE replace(split_part("localPart", '+', 1), '.', '') || '@gmail.com' |
| 24 | + END |
| 25 | + WHEN "domain" IN ( |
| 26 | + 'fastmail.com', 'fastmail.fm', 'gmx.com', 'gmx.de', 'gmx.net', |
| 27 | + 'icloud.com', 'mac.com', 'me.com', 'pm.me', 'proton.me', |
| 28 | + 'protonmail.com', 'yandex.com', 'yandex.ru', 'zoho.com' |
| 29 | + ) OR "domain" ~ '^(outlook|hotmail|live|msn)\.[a-z]{2,}(\.[a-z]{2,})?$' |
| 30 | + THEN CASE |
| 31 | + WHEN split_part("localPart", '+', 1) = '' THEN "normalized" |
| 32 | + ELSE split_part("localPart", '+', 1) || '@' || "domain" |
| 33 | + END |
| 34 | + ELSE "normalized" |
| 35 | + END AS "canonical" |
| 36 | + FROM split |
| 37 | +) |
| 38 | +UPDATE "core_users" AS u SET "email" = c."canonical" |
| 39 | +FROM canonical c |
| 40 | +WHERE c."id" = u."id" |
| 41 | + AND c."canonical" <> u."email" |
| 42 | + AND NOT EXISTS ( |
| 43 | + SELECT 1 FROM "core_users" taken |
| 44 | + WHERE taken."email" = c."canonical" AND taken."id" <> c."id" |
| 45 | + ) |
| 46 | + AND NOT EXISTS ( |
| 47 | + SELECT 1 FROM canonical rival |
| 48 | + WHERE rival."canonical" = c."canonical" AND rival."id" < c."id" |
| 49 | + ); |
0 commit comments