Skip to content
8 changes: 6 additions & 2 deletions src/PhpImap/Imap.php
Original file line number Diff line number Diff line change
Expand Up @@ -813,12 +813,16 @@ public static function search(
$imap_stream,
string $criteria,
int $options = SE_FREE,
string $charset = null
string $charset = null,
bool $encodeCriteriaAsUtf7Imap = false
): array {
\imap_errors(); // flush errors

$imap_stream = static::EnsureConnection($imap_stream, __METHOD__, 1);
$criteria = static::encodeStringToUtf7Imap($criteria);

if ($encodeCriteriaAsUtf7Imap) {
$criteria = static::encodeStringToUtf7Imap($criteria);
}

if (\is_string($charset)) {
$result = \imap_search(
Expand Down
158 changes: 158 additions & 0 deletions tests/unit/AbstractLiveMailboxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@

namespace PhpImap;

use Generator;
use ParagonIE\HiddenString\HiddenString;
use PHPUnit\Framework\TestCase;
use Throwable;

/**
* @psalm-type MAILBOX_ARGS = array{
Expand All @@ -21,6 +23,17 @@
* 3:string,
* 4?:string
* }
* @psalm-type COMPOSE_ENVELOPE = array{
* subject?:string
* }
* @psalm-type COMPOSE_BODY = list<array{
* type?:int,
* encoding?:int,
* charset?:string,
* subtype?:string,
* description?:string,
* disposition?:array{filename:string}
* }>
*/
abstract class AbstractLiveMailboxTest extends TestCase
{
Expand All @@ -44,6 +57,138 @@ public function MailBoxProvider(): array
return $sets;
}

/**
* @psalm-return Generator<int, array{0:COMPOSE_ENVELOPE, 1:COMPOSE_BODY, 2:string}, mixed, void>
*/
public function ComposeProvider(): Generator
{
yield from [];
}

/**
* @psalm-return Generator<int, array{
* 0:MAILBOX_ARGS,
* 1:COMPOSE_ENVELOPE,
* 2:COMPOSE_BODY,
* 3:string,
* 4:bool
* }, mixed, void>
*/
public function AppendProvider(): Generator
{
foreach ($this->MailBoxProvider() as $mailbox_args) {
foreach ($this->ComposeProvider() as $compose_args) {
[$envelope, $body, $expected_compose_result] = $compose_args;

yield [$mailbox_args, $envelope, $body, $expected_compose_result, false];
}

foreach ($this->ComposeProvider() as $compose_args) {
[$envelope, $body, $expected_compose_result] = $compose_args;

yield [$mailbox_args, $envelope, $body, $expected_compose_result, true];
}
}
}

/**
* @dataProvider AppendProvider
*
* @group live
*
* @depends testGetImapStream
* @depends testMailCompose
*
* @psalm-param MAILBOX_ARGS $mailbox_args
* @psalm-param COMPOSE_ENVELOPE $envelope
* @psalm-param COMPOSE_BODY $body
*/
public function testAppend(
array $mailbox_args,
array $envelope,
array $body,
string $_expected_compose_result,
bool $pre_compose
): void {
if ($this->MaybeSkipAppendTest($envelope)) {
return;
}

list($search_criteria) = $this->SubjectSearchCriteriaAndSubject($envelope);

list($mailbox, $remove_mailbox, $path) = $this->getMailboxFromArgs(
$mailbox_args
);

/** @var Throwable|null */
$exception = null;

$mailboxDeleted = false;

try {
$search = $mailbox->searchMailbox($search_criteria);

$this->assertCount(
0,
$search,
(
'If a subject was found,'.
' then the message is insufficiently unique to assert that'.
' a newly-appended message was actually created.'
)
);

$message = [$envelope, $body];

if ($pre_compose) {
$message = Imap::mail_compose($envelope, $body);
}

$mailbox->appendMessageToMailbox($message);

$search = $mailbox->searchMailbox($search_criteria);

$this->assertCount(
1,
$search,
(
'If a subject was not found, '.
' then Mailbox::appendMessageToMailbox() failed'.
' despite not throwing an exception.'
)
);

$mailbox->deleteMail($search[0]);

$mailbox->expungeDeletedMails();

$mailbox->switchMailbox($path->getString());
$mailbox->deleteMailbox($remove_mailbox);
$mailboxDeleted = true;

$this->assertCount(
0,
$mailbox->searchMailbox($search_criteria),
(
'If a subject was found,'.
' then the message is was not expunged as requested.'
)
);
} catch (Throwable $ex) {
$exception = $ex;
} finally {
$mailbox->switchMailbox($path->getString());
if (!$mailboxDeleted) {
$mailbox->deleteMailbox($remove_mailbox);
}
$mailbox->disconnect();
}

if (null !== $exception) {
throw $exception;
}
}

/**
* Get instance of Mailbox, pre-set to a random mailbox.
*
Expand Down Expand Up @@ -106,4 +251,17 @@ protected function SubjectSearchCriteriaAndSubject(array $envelope): array
/** @psalm-var array{0:string, 1:string} */
return [$search_criteria, (string) $subject];
}

protected function MaybeSkipAppendTest(array $envelope): bool
{
if (!isset($envelope['subject'])) {
$this->markTestSkipped(
'Cannot search for message by subject, no subject specified!'
);

return true;
}

return false;
}
}
89 changes: 89 additions & 0 deletions tests/unit/LiveMailboxIssue250Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* Live Mailbox - PHPUnit tests.
*
* Runs tests on a live mailbox
*
* @author BAPCLTD-Marv
*/
declare(strict_types=1);

namespace PhpImap;

use Generator;
use ParagonIE\HiddenString\HiddenString;
use const TYPETEXT;

/**
* @psalm-type MAILBOX_ARGS = array{
* 0:HiddenString,
* 1:HiddenString,
* 2:HiddenString,
* 3:string,
* 4?:string
* }
* @psalm-type COMPOSE_ENVELOPE = array{
* subject?:string
* }
* @psalm-type COMPOSE_BODY = list<array{
* type?:int,
* encoding?:int,
* charset?:string,
* subtype?:string,
* description?:string,
* disposition?:array{filename:string}
* }>
*/
class LiveMailboxIssue250Test extends AbstractLiveMailboxTest
{
/**
* @psalm-return Generator<int, array{0:COMPOSE_ENVELOPE, 1:COMPOSE_BODY, 2:string}, mixed, void>
*/
public function ComposeProvider(): Generator
{
$random_subject = 'barbushin/php-imap#250 测试: '.\bin2hex(\random_bytes(16));

yield [
['subject' => $random_subject],
[
[
'type' => TYPETEXT,
'contents.data' => 'test',
],
],
(
'Subject: '.$random_subject."\r\n".
'MIME-Version: 1.0'."\r\n".
'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII'."\r\n".
"\r\n".
'test'."\r\n"
),
];
}

/**
* @dataProvider AppendProvider
*
* @group live
* @group live-issue-250
*
* @psalm-param MAILBOX_ARGS $mailbox_args
* @psalm-param COMPOSE_ENVELOPE $envelope
* @psalm-param COMPOSE_BODY $body
*/
public function testAppend(
array $mailbox_args,
array $envelope,
array $body,
string $expected_compose_result,
bool $pre_compose
): void {
parent::testAppend(
$mailbox_args,
$envelope,
$body,
$expected_compose_result,
$pre_compose
);
}
}
Loading