Skip to content

Commit 54bd5b1

Browse files
update
1 parent 54e3db9 commit 54bd5b1

File tree

4 files changed

+198
-31
lines changed

4 files changed

+198
-31
lines changed

src/Traits/EmailUtilityTrait.php

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
use Tamedevelopers\Support\Str;
88
use Tamedevelopers\Support\Tame;
99
use Tamedevelopers\Support\Capsule\File;
10+
use Tamedevelopers\Support\Collections\Collection;
1011

1112

1213
/**
1314
* @property array $providers
15+
* @property array $providersChildren
1416
*/
1517
trait EmailUtilityTrait{
1618

@@ -88,10 +90,11 @@ public static function normalizeEmail(string $email, bool $lowercaseLocal = fals
8890
[$local, $domain] = explode('@', $email, 2);
8991
$domain = mb_strtolower($domain);
9092

91-
self::loadProviders();
93+
// load children data
94+
self::loadProvidersChildren();
9295

93-
if (isset(self::$providers[$domain])) {
94-
$rules = self::$providers[$domain];
96+
if (isset(self::$providersChildren[$domain])) {
97+
$rules = self::$providersChildren[$domain];
9598

9699
if (!empty($rules['strip_plus'])) {
97100
$plusPos = strpos($local, '+');
@@ -131,6 +134,107 @@ public static function equalsEmail(string $email, string $second_email, bool $lo
131134
return self::normalizeEmail($email, $lowercaseLocal) === self::normalizeEmail($second_email, $lowercaseLocal);
132135
}
133136

137+
// --- Specific provider families ---
138+
public static function isGmail(string $email): bool
139+
{
140+
self::loadProviders();
141+
return self::isDomainIn($email, array_keys(self::$providers['gmail']));
142+
}
143+
144+
public static function isOutlook(string $email): bool
145+
{
146+
self::loadProviders();
147+
return self::isDomainIn($email, array_keys(self::$providers['outlook']));
148+
}
149+
150+
public static function isIcloud(string $email): bool
151+
{
152+
self::loadProviders();
153+
return self::isDomainIn($email, array_keys(self::$providers['icloud']));
154+
}
155+
156+
public static function isFastmail(string $email): bool
157+
{
158+
self::loadProviders();
159+
return self::isDomainIn($email, array_keys(self::$providers['fastmail']));
160+
}
161+
162+
public static function isProtonmail(string $email): bool
163+
{
164+
self::loadProviders();
165+
return self::isDomainIn($email, array_keys(self::$providers['protonmail']));
166+
}
167+
168+
public static function isZoho(string $email): bool
169+
{
170+
self::loadProviders();
171+
return self::isDomainIn($email, array_keys(self::$providers['zohomail']));
172+
}
173+
174+
public static function isYandex(string $email): bool
175+
{
176+
self::loadProviders();
177+
return self::isDomainIn($email, array_keys(self::$providers['yandex']));
178+
}
179+
180+
public static function isGmx(string $email): bool
181+
{
182+
self::loadProviders();
183+
return self::isDomainIn($email, array_keys(self::$providers['gmx']));
184+
}
185+
186+
public static function isMailCom(string $email): bool
187+
{
188+
self::loadProviders();
189+
return self::isDomainIn($email, array_keys(self::$providers['gmx']));
190+
}
191+
192+
public static function isMailboxOrg(string $email): bool
193+
{
194+
self::loadProviders();
195+
return self::isDomainIn($email, array_keys(self::$providers['focused']));
196+
}
197+
198+
public static function isPosteo(string $email): bool
199+
{
200+
self::loadProviders();
201+
return self::isDomainIn($email, array_keys(self::$providers['focused']));
202+
}
203+
204+
public static function isRunbox(string $email): bool
205+
{
206+
self::loadProviders();
207+
return self::isDomainIn($email, array_keys(self::$providers['focused']));
208+
}
209+
210+
public static function isStartmail(string $email): bool
211+
{
212+
self::loadProviders();
213+
return self::isDomainIn($email, array_keys(self::$providers['focused']));
214+
}
215+
216+
/**
217+
* Load providers data child elements
218+
* @return void
219+
*/
220+
protected static function loadProvidersChildren()
221+
{
222+
self::loadProviders();
223+
224+
if (!empty(self::$providersChildren)) {
225+
return; // already loaded
226+
}
227+
228+
$collection = new Collection(self::$providers);
229+
230+
$data = [];
231+
$collection->each(function($item) use (&$data) {
232+
$data = array_merge($data, $item);
233+
});
234+
235+
self::$providersChildren = $data;
236+
}
237+
134238
/**
135239
* Load providers config from `emailProviders` file.
136240
* @return void
@@ -146,5 +250,42 @@ protected static function loadProviders()
146250
self::$providers = require $file; // this directly returns the array
147251
}
148252
}
149-
253+
254+
/**
255+
* Extract and normalize the domain part of an email.
256+
*/
257+
protected static function extractDomain(?string $email): ?string
258+
{
259+
if (!is_string($email)) {
260+
return null;
261+
}
262+
$email = trim($email);
263+
$at = strrpos($email, '@');
264+
if ($at === false) {
265+
return null;
266+
}
267+
$domain = substr($email, $at + 1);
268+
if ($domain === '') {
269+
return null;
270+
}
271+
272+
return mb_strtolower($domain);
273+
}
274+
275+
/**
276+
* Check if email belongs to any of the given domains.
277+
*
278+
* @param string $email
279+
* @param string[] $domains
280+
*/
281+
protected static function isDomainIn(string $email, array $domains): bool
282+
{
283+
$domain = self::extractDomain($email);
284+
if ($domain === null) {
285+
return false;
286+
}
287+
288+
return in_array($domain, $domains, true);
289+
}
290+
150291
}

src/Utility.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,18 @@ class Utility
3030
{
3131
use TextUtilityTrait,
3232
EmailUtilityTrait;
33-
33+
34+
/**
35+
* Providers rules cache loaded from stubs/emailProviders.php
36+
* @var array<string, array{strip_plus: bool, strip_dots: bool}>
37+
*/
38+
protected static $providers = [];
39+
3440
/**
35-
* Email Providers
41+
* Providers rules children data loaded from <$providers>
3642
* @var array
3743
*/
38-
protected static array $providers = [];
44+
protected static $providersChildren = [];
3945

4046
/**
4147
* Text to analyze/manipulate.

src/stubs/emailProviders.php

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,63 @@
1414
*/
1515

1616
// Gmail ignores dots and supports plus|but we can't confirm this with confidence
17-
"gmail.com" => ["strip_plus" => true, "strip_dots" => false],
18-
"googlemail.com" => ["strip_plus" => true, "strip_dots" => false],
17+
"gmail" => [
18+
"gmail.com" => ["strip_plus" => true, "strip_dots" => false],
19+
"googlemail.com" => ["strip_plus" => true, "strip_dots" => false],
20+
],
1921

2022
// Microsoft (Outlook/Hotmail/Live/MSN) supports plus, but NOT dot collapsing
21-
"outlook.com" => ["strip_plus" => true, "strip_dots" => false],
22-
"hotmail.com" => ["strip_plus" => true, "strip_dots" => false],
23-
"live.com" => ["strip_plus" => true, "strip_dots" => false],
24-
"msn.com" => ["strip_plus" => true, "strip_dots" => false],
23+
"outlook" => [
24+
"outlook.com" => ["strip_plus" => true, "strip_dots" => false],
25+
"hotmail.com" => ["strip_plus" => true, "strip_dots" => false],
26+
"live.com" => ["strip_plus" => true, "strip_dots" => false],
27+
"msn.com" => ["strip_plus" => true, "strip_dots" => false],
28+
],
2529

2630
// Apple (iCloud/Me/Mac) supports plus, no dot collapsing
27-
"icloud.com" => ["strip_plus" => true, "strip_dots" => false],
28-
"me.com" => ["strip_plus" => true, "strip_dots" => false],
29-
"mac.com" => ["strip_plus" => true, "strip_dots" => false],
31+
"icloud" => [
32+
"icloud.com" => ["strip_plus" => true, "strip_dots" => false],
33+
"me.com" => ["strip_plus" => true, "strip_dots" => false],
34+
"mac.com" => ["strip_plus" => true, "strip_dots" => false],
35+
36+
],
3037

3138
// Fastmail supports plus, no dot collapsing
32-
"fastmail.com" => ["strip_plus" => true, "strip_dots" => false],
39+
"fastmail" => [
40+
"fastmail.com" => ["strip_plus" => true, "strip_dots" => false],
41+
],
3342

3443
// ProtonMail supports plus, no dot collapsing
35-
"protonmail.com" => ["strip_plus" => true, "strip_dots" => false],
36-
"proton.me" => ["strip_plus" => true, "strip_dots" => false],
37-
"pm.me" => ["strip_plus" => true, "strip_dots" => false],
44+
"protonmail" => [
45+
"protonmail.com" => ["strip_plus" => true, "strip_dots" => false],
46+
"proton.me" => ["strip_plus" => true, "strip_dots" => false],
47+
"pm.me" => ["strip_plus" => true, "strip_dots" => false],
48+
],
3849

3950
// Zoho supports plus, no dot collapsing
40-
"zoho.com" => ["strip_plus" => true, "strip_dots" => false],
41-
"zohomail.com" => ["strip_plus" => true, "strip_dots" => false],
51+
"zohomail" => [
52+
"zoho.com" => ["strip_plus" => true, "strip_dots" => false],
53+
"zohomail.com" => ["strip_plus" => true, "strip_dots" => false],
54+
],
4255

4356
// Yandex supports plus, no dot collapsing
44-
"yandex.com" => ["strip_plus" => true, "strip_dots" => false],
45-
"yandex.ru" => ["strip_plus" => true, "strip_dots" => false],
57+
"yandex" => [
58+
"yandex.com" => ["strip_plus" => true, "strip_dots" => false],
59+
"yandex.ru" => ["strip_plus" => true, "strip_dots" => false],
60+
],
4661

4762
// GMX and Mail.com support plus, no dot collapsing
48-
"gmx.com" => ["strip_plus" => true, "strip_dots" => false],
49-
"gmx.de" => ["strip_plus" => true, "strip_dots" => false],
50-
"mail.com" => ["strip_plus" => true, "strip_dots" => false],
63+
"gmx" => [
64+
"gmx.com" => ["strip_plus" => true, "strip_dots" => false],
65+
"gmx.de" => ["strip_plus" => true, "strip_dots" => false],
66+
"mail.com" => ["strip_plus" => true, "strip_dots" => false],
67+
],
5168

5269
// Privacy-focused providers (Mailbox.org, Posteo, Runbox, StartMail) support plus
53-
"mailbox.org" => ["strip_plus" => true, "strip_dots" => false],
54-
"posteo.de" => ["strip_plus" => true, "strip_dots" => false],
55-
"runbox.com" => ["strip_plus" => true, "strip_dots" => false],
56-
"startmail.com" => ["strip_plus" => true, "strip_dots" => false]
70+
"focused" => [
71+
"mailbox.org" => ["strip_plus" => true, "strip_dots" => false],
72+
"posteo.de" => ["strip_plus" => true, "strip_dots" => false],
73+
"runbox.com" => ["strip_plus" => true, "strip_dots" => false],
74+
"startmail.com" => ["strip_plus" => true, "strip_dots" => false]
75+
],
5776
];

tests/utility.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
Utility::normalizeEmail($email),
3737
Utility::normalizeEmail($email2),
3838
Utility::normalizeEmail($email3),
39+
"isGmail: " . (Utility::isGmail($email2) ? 'yes' : 'no'),
3940
],
4041
Utility::equalsEmail($email, $email, true),
4142
// Utility::validateEmail($email, true, true),

0 commit comments

Comments
 (0)