diff --git a/src/FileMessage.php b/src/FileMessage.php index d724e2a..570cd18 100644 --- a/src/FileMessage.php +++ b/src/FileMessage.php @@ -31,6 +31,15 @@ public function __toString(): string return $this->contents; } + /** + * Determine if this message is equal to another. + */ + public function is(MessageInterface $message): bool + { + return $message instanceof self + && $this->contents === $message->contents; + } + /** * Determine if the message is empty. */ diff --git a/src/Message.php b/src/Message.php index 8461fa9..2c9fbef 100644 --- a/src/Message.php +++ b/src/Message.php @@ -90,6 +90,18 @@ public function hasBody(): bool return ! empty($this->body); } + /** + * {@inheritDoc} + */ + public function is(MessageInterface $message): bool + { + return $message instanceof self + && $this->uid === $message->uid + && $this->head === $message->head + && $this->body === $message->body + && $this->folder->is($message->folder); + } + /** * Determine if the message is marked as seen. */ diff --git a/src/MessageInterface.php b/src/MessageInterface.php index 9fb1db0..610828f 100644 --- a/src/MessageInterface.php +++ b/src/MessageInterface.php @@ -119,6 +119,11 @@ public function header(string $name, int $offset = 0): ?IHeader; */ public function parse(): MailMimeMessage; + /** + * Determine if the message is the same as another message. + */ + public function is(MessageInterface $message): bool; + /** * Get the string representation of the message. */ diff --git a/src/Testing/FakeFolder.php b/src/Testing/FakeFolder.php index e8041ab..30b984b 100644 --- a/src/Testing/FakeFolder.php +++ b/src/Testing/FakeFolder.php @@ -83,7 +83,7 @@ public function messages(): MessageQueryInterface // Ensure the folder is selected. $this->select(true); - return new FakeMessageQuery($this, $this->messages); + return new FakeMessageQuery($this); } /** @@ -91,7 +91,9 @@ public function messages(): MessageQueryInterface */ public function idle(callable $callback, ?callable $query = null, int $timeout = 300): void { - throw new Exception('Unsupported'); + foreach ($this->messages as $message) { + $callback($message); + } } /** diff --git a/src/Testing/FakeMessage.php b/src/Testing/FakeMessage.php index dca1400..564897b 100644 --- a/src/Testing/FakeMessage.php +++ b/src/Testing/FakeMessage.php @@ -26,6 +26,17 @@ public function uid(): int return $this->uid; } + /** + * {@inheritDoc} + */ + public function is(MessageInterface $message): bool + { + return $message instanceof self + && $this->uid === $message->uid + && $this->flags === $message->flags + && $this->contents === $message->contents; + } + /** * {@inheritDoc} */ diff --git a/tests/Unit/FileMessageTest.php b/tests/Unit/FileMessageTest.php index 0ee68fe..919b145 100644 --- a/tests/Unit/FileMessageTest.php +++ b/tests/Unit/FileMessageTest.php @@ -19,7 +19,7 @@ Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" - + Hello World EOT; @@ -47,15 +47,15 @@ MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----BOUNDARY-ID----" - + ------BOUNDARY-ID---- Content-Type: text/plain; charset="UTF-8" - + Hello Plain - + ------BOUNDARY-ID---- Content-Type: text/html; charset="UTF-8" - +

Hello HTML

------BOUNDARY-ID------ EOT; @@ -77,17 +77,17 @@ MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----BOUNDARY-ID----" - + ------BOUNDARY-ID---- Content-Type: text/plain; charset="UTF-8" - + Hello with Attachment - + ------BOUNDARY-ID---- Content-Type: application/pdf; name="file.pdf" Content-Disposition: attachment; filename="file.pdf" Content-Transfer-Encoding: base64 - + JVBERi0xLjUKJeLjz9MKMyAwIG9iago8PC9MZW5ndGggNCAgIC9GaWx0ZXIvQXNjaWlIYXgg ICAgPj5zdHJlYW0Kc3R1ZmYKZW5kc3RyZWFtCmVuZG9iajAK ------BOUNDARY-ID------ @@ -114,7 +114,7 @@ Subject: No Attachments Date: Wed, 19 Feb 2025 12:34:56 -0500 Content-Type: text/plain; charset="UTF-8" - + Just a plain text email without attachments. EOT; @@ -132,7 +132,7 @@ Subject: In-Reply-To Check Date: Wed, 19 Feb 2025 12:34:56 -0500 Content-Type: text/plain; charset="UTF-8" - + Check the in-reply-to header EOT; @@ -149,7 +149,7 @@ Subject: Stringable Test Date: Wed, 19 Feb 2025 12:34:56 -0500 Content-Type: text/plain; charset="UTF-8" - + Testing __toString EOT; @@ -165,26 +165,26 @@ Subject: Test Email With Inline Image MIME-Version: 1.0 Content-Type: multipart/related; boundary="BOUNDARY_STRING" - + --BOUNDARY_STRING Content-Type: text/html; charset=UTF-8 - +

This is a test email with an inline image:

Inline Image - + --BOUNDARY_STRING Content-Type: image/png; name="inline_image.png" Content-Transfer-Encoding: base64 Content-ID: Content-Disposition: inline; filename="inline_image.png" - + iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8 z8BQDwABAgEA0xzY2QAAAABJRU5ErkJggg== - + --BOUNDARY_STRING-- EOT; @@ -197,3 +197,42 @@ expect($attachments[0]->contentId())->toBe('inline-image-id'); expect($attachments[0]->filename())->toBe('inline_image.png'); }); + +test('it can determine if two messages are the same', function () { + $contents1 = <<<'EOT' + From: "John Doe" + Subject: Test Subject + Date: Wed, 19 Feb 2025 12:34:56 -0500 + Content-Type: text/plain; charset="UTF-8" + + Test content + EOT; + + $contents2 = <<<'EOT' + From: "John Doe" + Subject: Test Subject + Date: Wed, 19 Feb 2025 12:34:56 -0500 + Content-Type: text/plain; charset="UTF-8" + + Test content + EOT; + + $contents3 = <<<'EOT' + From: "John Doe" + Subject: Different Subject + Date: Wed, 19 Feb 2025 12:34:56 -0500 + Content-Type: text/plain; charset="UTF-8" + + Different content + EOT; + + $message1 = new FileMessage($contents1); + $message2 = new FileMessage($contents2); + $message3 = new FileMessage($contents3); + + // Same content + expect($message1->is($message2))->toBeTrue(); + + // Different content + expect($message1->is($message3))->toBeFalse(); +}); diff --git a/tests/Unit/MessageTest.php b/tests/Unit/MessageTest.php index 6185e6f..4901832 100644 --- a/tests/Unit/MessageTest.php +++ b/tests/Unit/MessageTest.php @@ -107,3 +107,41 @@ expect($message->flags())->not->toContain('\\Flagged'); expect($message->hasFlag(ImapFlag::Flagged))->toBeFalse(); }); + +test('it can determine if two messages are the same', function () { + $mailbox = Mailbox::make([ + 'username' => 'foo', + 'password' => 'bar', + ]); + + $mailbox->connect(ImapConnection::fake([ + '* OK Welcome to IMAP', + 'TAG1 OK Logged in', + ])); + + $folder1 = new Folder($mailbox, 'INBOX', [], '/'); + $folder2 = new Folder($mailbox, 'INBOX.Sent', [], '/'); + + // Create messages with different properties + $message1 = new Message($folder1, 1, [], 'header1', 'body1'); + $message2 = new Message($folder1, 1, [], 'header1', 'body1'); // Same as message1 + $message3 = new Message($folder1, 2, [], 'header1', 'body1'); // Different UID + $message4 = new Message($folder2, 1, [], 'header1', 'body1'); // Different folder + $message5 = new Message($folder1, 1, [], 'header2', 'body1'); // Different header + $message6 = new Message($folder1, 1, [], 'header1', 'body2'); // Different body + + // Same message + expect($message1->is($message2))->toBeTrue(); + + // Different UID + expect($message1->is($message3))->toBeFalse(); + + // Different folder + expect($message1->is($message4))->toBeFalse(); + + // Different header + expect($message1->is($message5))->toBeFalse(); + + // Different body + expect($message1->is($message6))->toBeFalse(); +}); diff --git a/tests/Unit/Testing/FakeMessageTest.php b/tests/Unit/Testing/FakeMessageTest.php index 66cb88e..33c0e53 100644 --- a/tests/Unit/Testing/FakeMessageTest.php +++ b/tests/Unit/Testing/FakeMessageTest.php @@ -53,3 +53,23 @@ expect($message->uid())->toBe(1); expect((string) $message)->toBe(''); }); + +test('it can determine if two messages are the same', function () { + $message1 = new FakeMessage(1, ['\\Seen'], 'Test content'); + $message2 = new FakeMessage(1, ['\\Seen'], 'Test content'); + $message3 = new FakeMessage(2, ['\\Seen'], 'Test content'); + $message4 = new FakeMessage(1, ['\\Draft'], 'Test content'); + $message5 = new FakeMessage(1, ['\\Seen'], 'Different content'); + + // Same messages + expect($message1->is($message2))->toBeTrue(); + + // Different UID + expect($message1->is($message3))->toBeFalse(); + + // Different flags + expect($message1->is($message4))->toBeFalse(); + + // Different content + expect($message1->is($message5))->toBeFalse(); +});