Passed
Push — master ( 102bf2...5e6609 )
by
unknown
20:09 queued 17:40
created

EmailTest::beforeTestValidationFailed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Tests\Rule;
6
7
use Yiisoft\Validator\Rule\Email;
8
use Yiisoft\Validator\Rule\EmailHandler;
9
use Yiisoft\Validator\Tests\Rule\Base\DifferentRuleInHandlerTestTrait;
10
use Yiisoft\Validator\Tests\Rule\Base\RuleTestCase;
11
use Yiisoft\Validator\Tests\Rule\Base\RuleWithOptionsTestTrait;
12
use Yiisoft\Validator\Tests\Rule\Base\SkipOnErrorTestTrait;
13
use Yiisoft\Validator\Tests\Rule\Base\WhenTestTrait;
14
15
final class EmailTest extends RuleTestCase
16
{
17
    use DifferentRuleInHandlerTestTrait;
18
    use RuleWithOptionsTestTrait;
19
    use SkipOnErrorTestTrait;
20
    use WhenTestTrait;
21
22
    public function testGetName(): void
23
    {
24
        $rule = new Email();
25
        $this->assertSame('email', $rule->getName());
26
    }
27
28
    public function dataOptions(): array
29
    {
30
        return [
31
            [
32
                new Email(),
33
                [
34
                    'pattern' => '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/',
35
                    'fullPattern' => '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/',
36
                    'idnEmailPattern' => '/^([a-zA-Z0-9._%+-]+)@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|\d{1,3})(\]?)$/',
37
                    'allowName' => false,
38
                    'checkDNS' => false,
39
                    'enableIDN' => false,
40
                    'incorrectInputMessage' => [
41
                        'template' => 'The value must have a string type.',
42
                        'parameters' => [],
43
                    ],
44
                    'message' => [
45
                        'template' => 'This value is not a valid email address.',
46
                        'parameters' => [],
47
                    ],
48
                    'skipOnEmpty' => false,
49
                    'skipOnError' => false,
50
                ],
51
            ],
52
            [
53
                new Email(allowName: true),
54
                [
55
                    'pattern' => '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/',
56
                    'fullPattern' => '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/',
57
                    'idnEmailPattern' => '/^([a-zA-Z0-9._%+-]+)@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|\d{1,3})(\]?)$/',
58
                    'allowName' => true,
59
                    'checkDNS' => false,
60
                    'enableIDN' => false,
61
                    'incorrectInputMessage' => [
62
                        'template' => 'The value must have a string type.',
63
                        'parameters' => [],
64
                    ],
65
                    'message' => [
66
                        'template' => 'This value is not a valid email address.',
67
                        'parameters' => [],
68
                    ],
69
                    'skipOnEmpty' => false,
70
                    'skipOnError' => false,
71
                ],
72
            ],
73
            [
74
                new Email(allowName: true, checkDNS: true),
75
                [
76
                    'pattern' => '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/',
77
                    'fullPattern' => '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/',
78
                    'idnEmailPattern' => '/^([a-zA-Z0-9._%+-]+)@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|\d{1,3})(\]?)$/',
79
                    'allowName' => true,
80
                    'checkDNS' => true,
81
                    'enableIDN' => false,
82
                    'incorrectInputMessage' => [
83
                        'template' => 'The value must have a string type.',
84
                        'parameters' => [],
85
                    ],
86
                    'message' => [
87
                        'template' => 'This value is not a valid email address.',
88
                        'parameters' => [],
89
                    ],
90
                    'skipOnEmpty' => false,
91
                    'skipOnError' => false,
92
                ],
93
            ],
94
            [
95
                new Email(allowName: true, enableIDN: true),
96
                [
97
                    'pattern' => '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/',
98
                    'fullPattern' => '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/',
99
                    'idnEmailPattern' => '/^([a-zA-Z0-9._%+-]+)@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|\d{1,3})(\]?)$/',
100
                    'allowName' => true,
101
                    'checkDNS' => false,
102
                    'enableIDN' => true,
103
                    'incorrectInputMessage' => [
104
                        'template' => 'The value must have a string type.',
105
                        'parameters' => [],
106
                    ],
107
                    'message' => [
108
                        'template' => 'This value is not a valid email address.',
109
                        'parameters' => [],
110
                    ],
111
                    'skipOnEmpty' => false,
112
                    'skipOnError' => false,
113
                ],
114
            ],
115
        ];
116
    }
117
118
    public function dataValidationPassed(): array
119
    {
120
        $rule = new Email();
121
        $ruleAllowedName = new Email(allowName: true);
122
        $ruleEnabledIDN = new Email(enableIDN: true);
123
        $ruleEnabledIDNandAllowedName = new Email(allowName: true, enableIDN: true);
124
125
        return [
126
            ['[email protected]', [$rule]],
127
            ['[email protected]', [$rule]],
128
            ['[email protected]', [$rule]],
129
            ['[email protected]', [$rule]],
130
            ['user+mailbox/[email protected]', [$rule]],
131
            ['!#$%&\'*+-/=?^_`.{|}[email protected]', [$rule]],
132
            ['[email protected]', [$rule]], // checkDNS is disabled
133
            ['[email protected]', [$rule]],
134
            [str_repeat('a', 64) . '@gmail.com', [$rule]],
135
            ['name@' . str_repeat('a', 245) . '.com', [$rule]],
136
            ['[email protected]', [$rule]],
137
138
            ['[email protected]', [$ruleAllowedName]],
139
            ['[email protected]', [$ruleAllowedName]],
140
            ['[email protected]', [$ruleAllowedName]],
141
            ['Carsten Brandt <[email protected]>', [$ruleAllowedName]],
142
            ['"Carsten Brandt" <[email protected]>', [$ruleAllowedName]],
143
            ['<[email protected]>', [$ruleAllowedName]],
144
            ['[email protected]', [$ruleAllowedName]],
145
            ['John Smith <[email protected]>', [$ruleAllowedName]],
146
            [
147
                '"This name is longer than 64 characters. Blah blah blah blah blah" <[email protected]>',
148
                [$ruleAllowedName],
149
            ],
150
151
            ['[email protected]', [$ruleEnabledIDN]],
152
            ['[email protected]', [$ruleEnabledIDN]],
153
            ['example@äüößìà.de', [$ruleEnabledIDN]],
154
            ['[email protected]', [$ruleEnabledIDN]],
155
            ['info@örtliches.de', [$ruleEnabledIDN]],
156
            ['sam@рмкреатиф.ru', [$ruleEnabledIDN]],
157
            ['[email protected]', [$ruleEnabledIDN]],
158
            ['[email protected]', [$ruleEnabledIDN]],
159
            ['üñîçøðé@üñîçøðé.com', [$ruleEnabledIDN]],
160
161
            ['info@örtliches.de', [$ruleEnabledIDNandAllowedName]],
162
            ['Information <info@örtliches.de>', [$ruleEnabledIDNandAllowedName]],
163
            ['sam@рмкреатиф.ru', [$ruleEnabledIDNandAllowedName]],
164
            ['[email protected]', [$ruleEnabledIDNandAllowedName]],
165
            ['[email protected]', [$ruleEnabledIDNandAllowedName]],
166
            ['Carsten Brandt <[email protected]>', [$ruleEnabledIDNandAllowedName]],
167
            ['"Carsten Brandt" <[email protected]>', [$ruleEnabledIDNandAllowedName]],
168
            ['üñîçøðé 日本国 <üñîçøðé@üñîçøðé.com>', [$ruleEnabledIDNandAllowedName]],
169
            ['<[email protected]>', [$ruleEnabledIDNandAllowedName]],
170
            ['[email protected]', [$ruleEnabledIDNandAllowedName]],
171
            ['John Smith <[email protected]>', [$ruleEnabledIDNandAllowedName]],
172
            [
173
                '"Такое имя достаточно длинное, но оно все равно может пройти валидацию" <[email protected]>',
174
                [$ruleEnabledIDNandAllowedName],
175
            ],
176
177
            ['[email protected]', [new Email(checkDNS: true)]],
178
179
            ['[email protected]', [new Email(allowName: true, checkDNS: true)]],
180
            ['Ivan Petrov <[email protected]>', [new Email(allowName: true, checkDNS: true)]],
181
            ['name@ñandu.cl', [new Email(checkDNS: true, enableIDN: true)]],
182
        ];
183
    }
184
185
    public function dataValidationFailed(): array
186
    {
187
        $rule = new Email();
188
        $ruleAllowedName = new Email(allowName: true);
189
        $ruleEnabledIDN = new Email(enableIDN: true);
190
        $ruleEnabledIDNandAllowedName = new Email(allowName: true, enableIDN: true);
191
        $errors = ['' => ['This value is not a valid email address.']];
192
        $incorrectInputErrors = ['' => ['The value must have a string type.']];
193
194
        return [
195
            'incorrect input, integer' => [1, [$rule], $incorrectInputErrors],
196
            'incorrect input, array containing string element' => [
197
                ['[email protected]'],
198
                [$ruleAllowedName],
199
                $incorrectInputErrors,
200
            ],
201
            'custom incorrect input message' => [
202
                1,
203
                [new Email(incorrectInputMessage: 'Custom incorrect input message.')],
204
                ['' => ['Custom incorrect input message.']],
205
            ],
206
            'custom incorrect input message with parameters' => [
207
                1,
208
                [new Email(incorrectInputMessage: 'Attribute - {attribute}, type - {type}.')],
209
                ['' => ['Attribute - , type - int.']],
210
            ],
211
            'custom incorrect input message with parameters, attribute set' => [
212
                ['data' => 1],
213
                ['data' => [new Email(incorrectInputMessage: 'Attribute - {attribute}, type - {type}.')]],
214
                ['data' => ['Attribute - data, type - int.']],
215
            ],
216
217
            ['rmcreative.ru', [$rule], $errors],
218
            ['Carsten Brandt <[email protected]>', [$rule], $errors],
219
            ['"Carsten Brandt" <[email protected]>', [$rule], $errors],
220
            ['<[email protected]>', [$rule], $errors],
221
            ['info@örtliches.de', [$rule], $errors],
222
            ['sam@рмкреатиф.ru', [$rule], $errors],
223
            ['[email protected]', [$rule], $errors],
224
            [str_repeat('a', 65) . '@gmail.com', [$rule], $errors],
225
            ['name@' . str_repeat('a', 246) . '.com', [$rule], $errors],
226
227
            // Malicious email addresses that can be used to exploit SwiftMailer vulnerability CVE-2016-10074 while IDN
228
            // is disabled.
229
            // https://legalhackers.com/advisories/SwiftMailer-Exploit-Remote-Code-Exec-CVE-2016-10074-Vuln.html
230
231
            // This is the demo email used in the proof of concept of the exploit
232
            ['"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php "@email.com', [$rule], $errors],
233
234
            // Trying more addresses
235
            ['"Attacker -Param2 -Param3"@test.com', [$rule], $errors],
236
            ['\'Attacker -Param2 -Param3\'@test.com', [$rule], $errors],
237
            ['"Attacker \" -Param2 -Param3"@test.com', [$rule], $errors],
238
            ["'Attacker \\' -Param2 -Param3'@test.com", [$rule], $errors],
239
            ['"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php "@email.com', [$rule], $errors],
240
241
            // And even more variants
242
            ['"attacker\"\ -oQ/tmp/\ -X/var/www/cache/phpcode.php"@email.com', [$rule], $errors],
243
            ["\"attacker\\\"\0-oQ/tmp/\0-X/var/www/cache/phpcode.php\"@email.com", [$rule], $errors],
244
            ['"[email protected]\"-Xbeep"@email.com', [$rule], $errors],
245
            ["'attacker\\' -oQ/tmp/ -X/var/www/cache/phpcode.php'@email.com", [$rule], $errors],
246
            ["'attacker\\\\' -oQ/tmp/ -X/var/www/cache/phpcode.php'@email.com", [$rule], $errors],
247
            ["'attacker\\\\'\\ -oQ/tmp/ -X/var/www/cache/phpcode.php'@email.com", [$rule], $errors],
248
            ["'attacker\\';touch /tmp/hackme'@email.com", [$rule], $errors],
249
            ["'attacker\\\\';touch /tmp/hackme'@email.com", [$rule], $errors],
250
            ["'attacker\\';touch/tmp/hackme'@email.com", [$rule], $errors],
251
            ["'attacker\\\\';touch/tmp/hackme'@email.com", [$rule], $errors],
252
            ['"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php "@email.com', [$rule], $errors],
253
254
            ['rmcreative.ru', [$ruleAllowedName], $errors],
255
            ['info@örtliches.de', [$ruleAllowedName], $errors],
256
            ['üñîçøðé@üñîçøðé.com', [$ruleAllowedName], $errors],
257
            ['sam@рмкреатиф.ru', [$ruleAllowedName], $errors],
258
            ['Informtation [email protected]', [$ruleAllowedName], $errors],
259
            ['John Smith <example.com>', [$ruleAllowedName], $errors],
260
            [
261
                'Short Name <localPartMoreThan64Characters-blah-blah-blah-blah-blah-blah-blah-blah@example.com>',
262
                [$ruleAllowedName],
263
                $errors,
264
            ],
265
            [
266
                'Short Name <domainNameIsMoreThan254Characters@example-blah-blah-blah-blah-blah-blah-blah-blah-blah-' .
267
                'blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-' .
268
                'blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah' .
269
                '.com>',
270
                [$ruleAllowedName],
271
                $errors,
272
            ],
273
274
            ['rmcreative.ru', [$ruleEnabledIDN], $errors],
275
            ['Carsten Brandt <[email protected]>', [$ruleEnabledIDN], $errors],
276
            ['"Carsten Brandt" <[email protected]>', [$ruleEnabledIDN], $errors],
277
            ['<[email protected]>', [$ruleEnabledIDN], $errors],
278
279
            [
280
                'Короткое имя <тест@это-доменное-имя.после-преобразования-в-idn.будет-содержать-больше-254-символов.' .
281
                'бла-бла-бла-бла-бла-бла-бла-бла.бла-бла-бла-бла-бла-бла.бла-бла-бла-бла-бла-бла.бла-бла-бла-бла-бла-' .
282
                'бла.com>',
283
                [$ruleEnabledIDNandAllowedName],
284
                $errors,
285
            ],
286
            ['Information info@örtliches.de', [$ruleEnabledIDNandAllowedName], $errors],
287
            ['rmcreative.ru', [$ruleEnabledIDNandAllowedName], $errors],
288
            ['John Smith <example.com>', [$ruleEnabledIDNandAllowedName], $errors],
289
            [
290
                'Короткое имя <после-преобразования-в-idn-тут-будет-больше-чем-64-символа@пример.com>',
291
                [$ruleEnabledIDNandAllowedName],
292
                $errors,
293
            ],
294
295
            ['name@ñandu.cl', [new Email(checkDNS: true)], $errors],
296
            ['gmail.con', [new Email(checkDNS: true)], $errors],
297
            [
298
                '[email protected]',
299
                [new Email(checkDNS: true)],
300
                $errors,
301
            ],
302
303
            'custom message' => [
304
                '[email protected]',
305
                [new Email(checkDNS: true, message: 'Custom message.')],
306
                ['' => ['Custom message.']],
307
            ],
308
            'custom message with parameters' => [
309
                '[email protected]',
310
                [new Email(checkDNS: true, message: 'Attribute - {attribute}, value - {value}.')],
311
                ['' => ['Attribute - , value - [email protected].']],
312
            ],
313
            'custom message with parameters, attribute set' => [
314
                ['data' => '[email protected]'],
315
                ['data' => new Email(checkDNS: true, message: 'Attribute - {attribute}, value - {value}.')],
316
                ['data' => ['Attribute - data, value - [email protected].']],
317
            ],
318
        ];
319
    }
320
321
    public function testSkipOnError(): void
322
    {
323
        $this->testSkipOnErrorInternal(new Email(), new Email(skipOnError: true));
324
    }
325
326
    public function testWhen(): void
327
    {
328
        $when = static fn (mixed $value): bool => $value !== null;
329
        $this->testWhenInternal(new Email(), new Email(when: $when));
330
    }
331
332
    protected function getDifferentRuleInHandlerItems(): array
333
    {
334
        return [Email::class, EmailHandler::class];
335
    }
336
}
337