Skip to content

Commit b5e4cda

Browse files
authored
Merge pull request #508 from bapcltd/issue/250
Disable utf7 imap encoding of search criteria by default
2 parents 8598f85 + 01e4302 commit b5e4cda

File tree

4 files changed

+256
-122
lines changed

4 files changed

+256
-122
lines changed

src/PhpImap/Imap.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,12 +813,16 @@ public static function search(
813813
$imap_stream,
814814
string $criteria,
815815
int $options = SE_FREE,
816-
string $charset = null
816+
string $charset = null,
817+
bool $encodeCriteriaAsUtf7Imap = false
817818
): array {
818819
\imap_errors(); // flush errors
819820

820821
$imap_stream = static::EnsureConnection($imap_stream, __METHOD__, 1);
821-
$criteria = static::encodeStringToUtf7Imap($criteria);
822+
823+
if ($encodeCriteriaAsUtf7Imap) {
824+
$criteria = static::encodeStringToUtf7Imap($criteria);
825+
}
822826

823827
if (\is_string($charset)) {
824828
$result = \imap_search(

tests/unit/AbstractLiveMailboxTest.php

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111
namespace PhpImap;
1212

13+
use Generator;
1314
use ParagonIE\HiddenString\HiddenString;
1415
use PHPUnit\Framework\TestCase;
16+
use Throwable;
1517

1618
/**
1719
* @psalm-type MAILBOX_ARGS = array{
@@ -21,6 +23,17 @@
2123
* 3:string,
2224
* 4?:string
2325
* }
26+
* @psalm-type COMPOSE_ENVELOPE = array{
27+
* subject?:string
28+
* }
29+
* @psalm-type COMPOSE_BODY = list<array{
30+
* type?:int,
31+
* encoding?:int,
32+
* charset?:string,
33+
* subtype?:string,
34+
* description?:string,
35+
* disposition?:array{filename:string}
36+
* }>
2437
*/
2538
abstract class AbstractLiveMailboxTest extends TestCase
2639
{
@@ -44,6 +57,138 @@ public function MailBoxProvider(): array
4457
return $sets;
4558
}
4659

60+
/**
61+
* @psalm-return Generator<int, array{0:COMPOSE_ENVELOPE, 1:COMPOSE_BODY, 2:string}, mixed, void>
62+
*/
63+
public function ComposeProvider(): Generator
64+
{
65+
yield from [];
66+
}
67+
68+
/**
69+
* @psalm-return Generator<int, array{
70+
* 0:MAILBOX_ARGS,
71+
* 1:COMPOSE_ENVELOPE,
72+
* 2:COMPOSE_BODY,
73+
* 3:string,
74+
* 4:bool
75+
* }, mixed, void>
76+
*/
77+
public function AppendProvider(): Generator
78+
{
79+
foreach ($this->MailBoxProvider() as $mailbox_args) {
80+
foreach ($this->ComposeProvider() as $compose_args) {
81+
[$envelope, $body, $expected_compose_result] = $compose_args;
82+
83+
yield [$mailbox_args, $envelope, $body, $expected_compose_result, false];
84+
}
85+
86+
foreach ($this->ComposeProvider() as $compose_args) {
87+
[$envelope, $body, $expected_compose_result] = $compose_args;
88+
89+
yield [$mailbox_args, $envelope, $body, $expected_compose_result, true];
90+
}
91+
}
92+
}
93+
94+
/**
95+
* @dataProvider AppendProvider
96+
*
97+
* @group live
98+
*
99+
* @depends testGetImapStream
100+
* @depends testMailCompose
101+
*
102+
* @psalm-param MAILBOX_ARGS $mailbox_args
103+
* @psalm-param COMPOSE_ENVELOPE $envelope
104+
* @psalm-param COMPOSE_BODY $body
105+
*/
106+
public function testAppend(
107+
array $mailbox_args,
108+
array $envelope,
109+
array $body,
110+
string $_expected_compose_result,
111+
bool $pre_compose
112+
): void {
113+
if ($this->MaybeSkipAppendTest($envelope)) {
114+
return;
115+
}
116+
117+
list($search_criteria) = $this->SubjectSearchCriteriaAndSubject($envelope);
118+
119+
list($mailbox, $remove_mailbox, $path) = $this->getMailboxFromArgs(
120+
$mailbox_args
121+
);
122+
123+
/** @var Throwable|null */
124+
$exception = null;
125+
126+
$mailboxDeleted = false;
127+
128+
try {
129+
$search = $mailbox->searchMailbox($search_criteria);
130+
131+
$this->assertCount(
132+
0,
133+
$search,
134+
(
135+
'If a subject was found,'.
136+
' then the message is insufficiently unique to assert that'.
137+
' a newly-appended message was actually created.'
138+
)
139+
);
140+
141+
$message = [$envelope, $body];
142+
143+
if ($pre_compose) {
144+
$message = Imap::mail_compose($envelope, $body);
145+
}
146+
147+
$mailbox->appendMessageToMailbox($message);
148+
149+
$search = $mailbox->searchMailbox($search_criteria);
150+
151+
$this->assertCount(
152+
1,
153+
$search,
154+
(
155+
'If a subject was not found, '.
156+
' then Mailbox::appendMessageToMailbox() failed'.
157+
' despite not throwing an exception.'
158+
)
159+
);
160+
161+
$mailbox->deleteMail($search[0]);
162+
163+
$mailbox->expungeDeletedMails();
164+
165+
$mailbox->switchMailbox($path->getString());
166+
$mailbox->deleteMailbox($remove_mailbox);
167+
$mailboxDeleted = true;
168+
169+
$this->assertCount(
170+
0,
171+
$mailbox->searchMailbox($search_criteria),
172+
(
173+
'If a subject was found,'.
174+
' then the message is was not expunged as requested.'
175+
)
176+
);
177+
} catch (Throwable $ex) {
178+
$exception = $ex;
179+
} finally {
180+
$mailbox->switchMailbox($path->getString());
181+
if (!$mailboxDeleted) {
182+
$mailbox->deleteMailbox($remove_mailbox);
183+
}
184+
$mailbox->disconnect();
185+
}
186+
187+
if (null !== $exception) {
188+
throw $exception;
189+
}
190+
}
191+
47192
/**
48193
* Get instance of Mailbox, pre-set to a random mailbox.
49194
*
@@ -106,4 +251,17 @@ protected function SubjectSearchCriteriaAndSubject(array $envelope): array
106251
/** @psalm-var array{0:string, 1:string} */
107252
return [$search_criteria, (string) $subject];
108253
}
254+
255+
protected function MaybeSkipAppendTest(array $envelope): bool
256+
{
257+
if (!isset($envelope['subject'])) {
258+
$this->markTestSkipped(
259+
'Cannot search for message by subject, no subject specified!'
260+
);
261+
262+
return true;
263+
}
264+
265+
return false;
266+
}
109267
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
/**
3+
* Live Mailbox - PHPUnit tests.
4+
*
5+
* Runs tests on a live mailbox
6+
*
7+
* @author BAPCLTD-Marv
8+
*/
9+
declare(strict_types=1);
10+
11+
namespace PhpImap;
12+
13+
use Generator;
14+
use ParagonIE\HiddenString\HiddenString;
15+
use const TYPETEXT;
16+
17+
/**
18+
* @psalm-type MAILBOX_ARGS = array{
19+
* 0:HiddenString,
20+
* 1:HiddenString,
21+
* 2:HiddenString,
22+
* 3:string,
23+
* 4?:string
24+
* }
25+
* @psalm-type COMPOSE_ENVELOPE = array{
26+
* subject?:string
27+
* }
28+
* @psalm-type COMPOSE_BODY = list<array{
29+
* type?:int,
30+
* encoding?:int,
31+
* charset?:string,
32+
* subtype?:string,
33+
* description?:string,
34+
* disposition?:array{filename:string}
35+
* }>
36+
*/
37+
class LiveMailboxIssue250Test extends AbstractLiveMailboxTest
38+
{
39+
/**
40+
* @psalm-return Generator<int, array{0:COMPOSE_ENVELOPE, 1:COMPOSE_BODY, 2:string}, mixed, void>
41+
*/
42+
public function ComposeProvider(): Generator
43+
{
44+
$random_subject = 'barbushin/php-imap#250 测试: '.\bin2hex(\random_bytes(16));
45+
46+
yield [
47+
['subject' => $random_subject],
48+
[
49+
[
50+
'type' => TYPETEXT,
51+
'contents.data' => 'test',
52+
],
53+
],
54+
(
55+
'Subject: '.$random_subject."\r\n".
56+
'MIME-Version: 1.0'."\r\n".
57+
'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII'."\r\n".
58+
"\r\n".
59+
'test'."\r\n"
60+
),
61+
];
62+
}
63+
64+
/**
65+
* @dataProvider AppendProvider
66+
*
67+
* @group live
68+
* @group live-issue-250
69+
*
70+
* @psalm-param MAILBOX_ARGS $mailbox_args
71+
* @psalm-param COMPOSE_ENVELOPE $envelope
72+
* @psalm-param COMPOSE_BODY $body
73+
*/
74+
public function testAppend(
75+
array $mailbox_args,
76+
array $envelope,
77+
array $body,
78+
string $expected_compose_result,
79+
bool $pre_compose
80+
): void {
81+
parent::testAppend(
82+
$mailbox_args,
83+
$envelope,
84+
$body,
85+
$expected_compose_result,
86+
$pre_compose
87+
);
88+
}
89+
}

0 commit comments

Comments
 (0)