diff --git a/src/Configuration/EmailConfiguration.php b/src/Configuration/EmailConfiguration.php index 639fa99..8ee4671 100644 --- a/src/Configuration/EmailConfiguration.php +++ b/src/Configuration/EmailConfiguration.php @@ -32,7 +32,7 @@ public function modify(Container $container) return new SesClient($container['ymir_http_client'], $container['cloud_provider_key'], $container['cloud_provider_region'], $container['cloud_provider_secret']); }); $container['email'] = function (Container $container) { - return new Email($container['event_manager'], $container['default_email_from'], $container['phpmailer'], $container['blog_charset']); + return new Email($container['event_manager'], $container['default_email_from'], $container['file_manager'], $container['phpmailer'], $container['blog_charset']); }; } } diff --git a/src/Email/Email.php b/src/Email/Email.php index c1450fb..61cbfc7 100644 --- a/src/Email/Email.php +++ b/src/Email/Email.php @@ -13,7 +13,9 @@ namespace Ymir\Plugin\Email; +use Ymir\Plugin\Attachment\AttachmentFileManager; use Ymir\Plugin\EventManagement\EventManager; +use Ymir\Plugin\Support\Collection; class Email { @@ -45,6 +47,13 @@ class Email */ private $eventManager; + /** + * The attachment file manager. + * + * @var AttachmentFileManager + */ + private $fileManager; + /** * WordPress PHPMailer object. * @@ -55,12 +64,13 @@ class Email /** * Constructor. */ - public function __construct(EventManager $eventManager, string $defaultFromAddress, \PHPMailer $mailer, string $defaultCharset = 'UTF-8', string $defaultContentType = 'text/plain') + public function __construct(EventManager $eventManager, string $defaultFromAddress, AttachmentFileManager $fileManager, \PHPMailer $mailer, string $defaultCharset = 'UTF-8', string $defaultContentType = 'text/plain') { $this->defaultCharset = $defaultCharset; $this->defaultContentType = $defaultContentType; $this->defaultFromAddress = $defaultFromAddress; $this->eventManager = $eventManager; + $this->fileManager = $fileManager; $this->mailer = $mailer; // Remove some of the default values so we can check if they were set and passed through the WordPress filters @@ -80,9 +90,15 @@ public function attachments($attachments) throw new \InvalidArgumentException('"attachments" argument must be an array or a string'); } - foreach ($attachments as $attachment) { + (new Collection($attachments))->map(function (string $attachment) { + if ($this->fileManager->isInUploadsDirectory($attachment)) { + $attachment = $this->fileManager->copyToTempDirectory($attachment); + } + + return $attachment; + })->each(function (string $attachment) { $this->mailer->addAttachment($attachment); - } + }); } /** diff --git a/tests/Unit/Email/EmailTest.php b/tests/Unit/Email/EmailTest.php index 2f28ef7..654c9bf 100644 --- a/tests/Unit/Email/EmailTest.php +++ b/tests/Unit/Email/EmailTest.php @@ -14,6 +14,7 @@ namespace Ymir\Plugin\Tests\Unit\Email; use Ymir\Plugin\Email\Email; +use Ymir\Plugin\Tests\Mock\AttachmentFileManagerMockTrait; use Ymir\Plugin\Tests\Mock\EventManagerMockTrait; use Ymir\Plugin\Tests\Mock\PHPMailerMockTrait; use Ymir\Plugin\Tests\Unit\TestCase; @@ -23,9 +24,40 @@ */ class EmailTest extends TestCase { + use AttachmentFileManagerMockTrait; use EventManagerMockTrait; use PHPMailerMockTrait; + public function testAttachmentsCopiesUploadFilesToTmpDirectory() + { + $fileManager = $this->getAttachmentFileManagerMock(); + $phpmailer = $this->getPHPMailerMock(); + + $fileManager->expects($this->exactly(2)) + ->method('isInUploadsDirectory') + ->withConsecutive( + [$this->identicalTo('attachment1')], + [$this->identicalTo('attachment2')] + ) + ->willReturnOnConsecutiveCalls(false, true); + + $fileManager->expects($this->once()) + ->method('copyToTempDirectory') + ->with($this->identicalTo('attachment2')) + ->willReturn('/tmp/attachment2'); + + $phpmailer->expects($this->exactly(2)) + ->method('addAttachment') + ->withConsecutive( + [$this->identicalTo('attachment1')], + [$this->identicalTo('/tmp/attachment2')] + ); + + $email = new Email($this->getEventManagerMock(), 'from_address', $fileManager, $phpmailer); + + $email->attachments(['attachment1', 'attachment2']); + } + public function testAttachmentsWithArray() { $phpmailer = $this->getPHPMailerMock(); @@ -37,7 +69,7 @@ public function testAttachmentsWithArray() [$this->identicalTo('attachment2')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->attachments(['attachment1', 'attachment2']); } @@ -47,7 +79,7 @@ public function testAttachmentsWithInvalidArgument() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('"attachments" argument must be an array or a string'); - $email = new Email($this->getEventManagerMock(), 'from_address', $this->getPHPMailerMock()); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $this->getPHPMailerMock()); $email->attachments(new \stdClass()); } @@ -63,7 +95,7 @@ public function testAttachmentsWithString() [$this->identicalTo('attachment2')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->attachments("attachment1\r\nattachment2"); } @@ -79,7 +111,7 @@ public function testBccWithArray() [$this->identicalTo('foo@bar.com'), $this->identicalTo('Foo')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->bcc(['test@test.com', 'Foo ']); } @@ -89,7 +121,7 @@ public function testBccWithInvalidArgument() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('"addresses" argument must be an array or a string'); - $email = new Email($this->getEventManagerMock(), 'from_address', $this->getPHPMailerMock()); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $this->getPHPMailerMock()); $email->bcc(new \stdClass()); } @@ -105,7 +137,7 @@ public function testBccWithString() [$this->identicalTo('foo@bar.com'), $this->identicalTo('Foo')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->bcc('test@test.com, Foo '); } @@ -120,7 +152,7 @@ public function testCharset() ->with($this->identicalTo('wp_mail_charset'), $this->identicalTo('UTF-8')) ->willReturn('filtered_UTF-8'); - (new Email($eventManager, 'from_address', $phpmailer))->charset('UTF-8'); + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->charset('UTF-8'); $this->assertSame('filtered_UTF-8', $phpmailer->CharSet); } @@ -132,7 +164,7 @@ public function testConstructorRemovesValues() $this->assertNotSame('', $phpmailer->CharSet); $this->assertNotSame('', $phpmailer->ContentType); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $this->assertSame('', $phpmailer->CharSet); $this->assertSame('', $phpmailer->ContentType); @@ -152,7 +184,7 @@ public function testContentTypeHtml() ->with($this->identicalTo('wp_mail_content_type'), $this->identicalTo('text/html')) ->willReturn('text/html'); - (new Email($eventManager, 'from_address', $phpmailer))->contentType('text/html'); + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->contentType('text/html'); $this->assertSame('text/html', $phpmailer->ContentType); } @@ -171,7 +203,7 @@ public function testContentTypeNotHtml() ->with($this->identicalTo('wp_mail_content_type'), $this->identicalTo('content_type')) ->willReturn('filtered_content_type'); - (new Email($eventManager, 'from_address', $phpmailer))->contentType('content_type'); + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->contentType('content_type'); $this->assertSame('filtered_content_type', $phpmailer->ContentType); } @@ -193,7 +225,7 @@ public function testFromWithDefaultNAme() ->method('setFrom') ->with($this->identicalTo('filtered_foo@bar.com'), $this->identicalTo('filtered_WordPress'), $this->identicalTo(false)); - (new Email($eventManager, 'from_address', $phpmailer))->from('foo@bar.com'); + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->from('foo@bar.com'); } public function testHeadersWithArray() @@ -222,7 +254,7 @@ public function testHeadersWithArray() ->method('isHtml') ->with($this->identicalTo(false)); - (new Email($eventManager, 'from_address', $phpmailer))->headers([ + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->headers([ 'From: test@test.com', 'Cc: Foo ', 'Content-Type: content_type', @@ -248,7 +280,7 @@ public function testHeadersWithContentTypeAndCharset() ->method('isHtml') ->with($this->identicalTo(false)); - (new Email($eventManager, 'from_address', $phpmailer))->headers([ + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->headers([ 'Content-Type: content_type;charset=foo_charset', ]); } @@ -258,7 +290,7 @@ public function testHeadersWithInvalidArgument() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('"headers" argument must be an array or a string'); - $email = new Email($this->getEventManagerMock(), 'from_address', $this->getPHPMailerMock()); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $this->getPHPMailerMock()); $email->headers(new \stdClass()); } @@ -280,7 +312,7 @@ public function testHeadersWithMultipartContentType() ->method('isHtml') ->with($this->identicalTo(false)); - (new Email($eventManager, 'from_address', $phpmailer))->headers([ + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->headers([ 'Content-Type: multipart/mixed; boundary="----=_Part_4892_25692638.1192452070893"', ]); } @@ -311,7 +343,7 @@ public function testHeadersWithString() ->method('isHtml') ->with($this->identicalTo(false)); - (new Email($eventManager, 'from_address', $phpmailer))->headers("From: test@test.com\r\nCc: Foo \r\nContent-Type: content_type\r\nHeader: Value\r\nX-Mailer: foo"); + (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->headers("From: test@test.com\r\nCc: Foo \r\nContent-Type: content_type\r\nHeader: Value\r\nX-Mailer: foo"); } public function testReplyToWithArray() @@ -325,7 +357,7 @@ public function testReplyToWithArray() [$this->identicalTo('foo@bar.com'), $this->identicalTo('Foo')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->replyTo(['test@test.com', 'Foo ']); } @@ -335,7 +367,7 @@ public function testReplyToWithInvalidArgument() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('"addresses" argument must be an array or a string'); - $email = new Email($this->getEventManagerMock(), 'from_address', $this->getPHPMailerMock()); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $this->getPHPMailerMock()); $email->replyTo(new \stdClass()); } @@ -351,7 +383,7 @@ public function testReplyToWithString() [$this->identicalTo('foo@bar.com'), $this->identicalTo('Foo')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->replyTo('test@test.com, Foo '); } @@ -360,7 +392,7 @@ public function testSubject() { $phpmailer = $this->getPHPMailerMock(); - (new Email($this->getEventManagerMock(), 'from_address', $phpmailer))->subject('Foo subject'); + (new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->subject('Foo subject'); $this->assertSame('Foo subject', $phpmailer->Subject); } @@ -390,7 +422,7 @@ public function testToStringSetsDefaultValues() ->method('getSentMIMEMessage') ->willReturn('email'); - $this->assertSame('email', (new Email($eventManager, 'from_address', $phpmailer))->toString()); + $this->assertSame('email', (new Email($eventManager, 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer))->toString()); } public function testToWithArray() @@ -404,7 +436,7 @@ public function testToWithArray() [$this->identicalTo('foo@bar.com'), $this->identicalTo('Foo')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->to(['test@test.com', 'Foo ']); } @@ -414,7 +446,7 @@ public function testToWithInvalidArgument() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('"addresses" argument must be an array or a string'); - $email = new Email($this->getEventManagerMock(), 'from_address', $this->getPHPMailerMock()); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $this->getPHPMailerMock()); $email->to(new \stdClass()); } @@ -430,7 +462,7 @@ public function testToWithString() [$this->identicalTo('foo@bar.com'), $this->identicalTo('Foo')] ); - $email = new Email($this->getEventManagerMock(), 'from_address', $phpmailer); + $email = new Email($this->getEventManagerMock(), 'from_address', $this->getAttachmentFileManagerMock(), $phpmailer); $email->to('test@test.com, Foo '); }