diff --git a/README.md b/README.md index ba20d26..670d16b 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,14 @@ return [ 'dot_mail' => [ 'default' => [ //... - 'transport' => Symfony\Component\Mailer\Transport\Smtp\SmtpTransport::class, + 'transport' => 'sendmail', //... ] ] ] ``` -### Mail - SMTP +### Mail - ESMTP If you want your application to send mails on e.g. registration, contact, then edit the file `config/autoload/mail.local.php`. Set the `transport`, `message_options` and `smtp_options` keys like below. @@ -55,7 +55,8 @@ Under `smtp_options` key: - `host` - the mail server's hostname or IP address - `port` - the mail server's port -- `connection_config` - fill in the `username`, `password` and `ssl` keys with the login details of the email used in `from` above +- `connection_config` - fill in the `username` and `password` keys with the login details of the email used in `from` above +- if you want to disable auto_tls set `tls` key to false Note: all other keys can be left as is. @@ -65,7 +66,7 @@ return [ 'dot_mail' => [ 'default' => [ //... - 'transport' => Symfony\Component\Mailer\Transport\Smtp\SmtpTransport::class, + 'transport' => 'esmtp' 'message_options' => [ 'from' => '', //... @@ -76,7 +77,7 @@ return [ 'connection_config' => [ 'username' => '', 'password' => '', - 'ssl' => '', + 'tls' => null, ] ] //... diff --git a/config/mail.global.php b/config/mail.global.php new file mode 100644 index 0000000..10308ca --- /dev/null +++ b/config/mail.global.php @@ -0,0 +1,81 @@ + [ + //the key is the mail service name, this is the default one, which does not extends any configuration + 'default' => [ + //message configuration + 'message_options' => [ + //from email address of the email + 'from' => '', + //from name to be displayed instead of from address + 'from_name' => '', + //reply-to email address of the email + 'reply_to' => '', + //replyTo name to be displayed instead of the address + 'reply_to_name' => '', + //destination email address as string or a list of email addresses + 'to' => [], + //copy destination addresses + 'cc' => [], + //hidden copy destination addresses + 'bcc' => [], + //email subject + 'subject' => '', + //body options - content can be plain text, HTML + 'body' => [ + 'content' => '', + 'charset' => 'utf-8', + ], + //attachments config + 'attachments' => [ + 'files' => [], + 'dir' => [ + 'iterate' => false, + 'path' => 'data/mail/attachments', + 'recursive' => false, + ], + ], + ], + /** + * the mail transport to use + * can be any class implementing Symfony\Component\Mailer\Transport\TransportInterface + * + * for standard mail transports, you can use these aliases + * - sendmail => Symfony\Component\Mailer\Transport\SendmailTransport + * - esmtp => Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport + * + * defaults to sendmail + **/ + 'transport' => 'sendmail', + //options that will be used only if esmtp adapter is used + 'smtp_options' => [ + //hostname or IP address of the mail server + 'host' => '', + //port of the mail server - 587 or 465 for secure connections + 'port' => 587, + 'connection_config' => [ + //the smtp authentication identity + 'username' => '', + //the smtp authentication credential + 'password' => '', + //to disable auto_tls set tls key to false + //it's not recommended to disable TLS while connecting to an SMTP server over the Internet + 'tls' => null, + ], + ], + ], + // option to log the SENT emails + 'log' => [ + 'sent' => getcwd() . '/log/mail/sent.log', + ], + ], +]; diff --git a/config/mail.global.php.dist b/config/mail.global.php.dist index 5ed3c08..10308ca 100644 --- a/config/mail.global.php.dist +++ b/config/mail.global.php.dist @@ -2,8 +2,6 @@ declare(strict_types=1); -use Symfony\Component\Mailer\Transport\SendmailTransport; - return [ /** @@ -14,17 +12,6 @@ return [ 'dot_mail' => [ //the key is the mail service name, this is the default one, which does not extends any configuration 'default' => [ - /** - * the mail transport to use - * can be any class implementing Symfony\Component\Mailer\Transport\TransportInterface - * - * for standard mail transports, you can use these aliases - * - sendmail => Symfony\Component\Mailer\Transport\SendmailTransport - * - smtp => Symfony\Component\Mailer\Transport\Smtp\SmtpTransport - * - * defaults to sendmail - **/ - 'transport' => SendmailTransport::class, //message configuration 'message_options' => [ //from email address of the email @@ -58,7 +45,18 @@ return [ ], ], ], - //options that will be used only if Symfony\Component\Mailer\Transport\Smtp\SmtpTransport adapter is used + /** + * the mail transport to use + * can be any class implementing Symfony\Component\Mailer\Transport\TransportInterface + * + * for standard mail transports, you can use these aliases + * - sendmail => Symfony\Component\Mailer\Transport\SendmailTransport + * - esmtp => Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport + * + * defaults to sendmail + **/ + 'transport' => 'sendmail', + //options that will be used only if esmtp adapter is used 'smtp_options' => [ //hostname or IP address of the mail server 'host' => '', @@ -69,6 +67,9 @@ return [ 'username' => '', //the smtp authentication credential 'password' => '', + //to disable auto_tls set tls key to false + //it's not recommended to disable TLS while connecting to an SMTP server over the Internet + 'tls' => null, ], ], ], diff --git a/docs/book/v5/configuration.md b/docs/book/v5/configuration.md index 7316366..35faeeb 100644 --- a/docs/book/v5/configuration.md +++ b/docs/book/v5/configuration.md @@ -21,9 +21,9 @@ $this->mailService->getMessage()->addTo("receiver@email.com"); ## Transport configuration `dot-mail` uses the `transport` key under the main `dot_mail` configuration key to select the email transport. -It has four email transport classes available by default (`SmtpTransport`), one of which is to be added under the `dot_mail.transport` key for use. +It has two email transport classes available (by default `sendmail`), one of which is to be added under the `dot_mail.transport` key for use. -Sending email with the `Smtp` transport requires valid data for the values under `dot-mail.default.smtp_options`, which is only used in this case. +Sending email with the `Esmtp` transport requires valid data for the values under `dot-mail.default.smtp_options`, which is only used in this case. > The configured path must be a writable directory diff --git a/docs/book/v5/transports.md b/docs/book/v5/transports.md index e6301eb..3a0d586 100644 --- a/docs/book/v5/transports.md +++ b/docs/book/v5/transports.md @@ -2,8 +2,8 @@ `dot-mail` can use any transport class that implements `Symfony\Component\Mailer\Transport\TransportInterface`, with the standard transport available being: -- `Symfony\Component\Mailer\Transport\Smtp\SmtpTransport,` -- `Symfony\Component\Mailer\Transport\SendmailTransport,` +- `esmtp,` +- `sendmail,` > Feel free to use any custom transport you desire, provided it implements the mentioned `TransportInterface`. @@ -11,4 +11,4 @@ PHP's `mail()` function is a wrapper over `Sendmail`, and as such has a differen - Note: emails sent using the sendmail transport will be more often delivered to SPAM. -`Smtp` connects to the configured SMTP host in order to handle sending emails. +`Esmtp` connects to the configured SMTP host in order to handle sending emails. diff --git a/src/Factory/MailServiceAbstractFactory.php b/src/Factory/MailServiceAbstractFactory.php index b3507fd..b03a8d5 100644 --- a/src/Factory/MailServiceAbstractFactory.php +++ b/src/Factory/MailServiceAbstractFactory.php @@ -21,7 +21,7 @@ use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use Symfony\Component\Mailer\Transport; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; use Symfony\Component\Mailer\Transport\TransportInterface; use function explode; @@ -177,13 +177,14 @@ protected function createTransport(ContainerInterface $container): TransportInte protected function setupTransportConfig(TransportInterface $transport): TransportInterface { - if ($transport instanceof SmtpTransport) { - $user = $this->mailOptions->getSmtpOptions()->getConnectionConfig()['username']; - $pass = $this->mailOptions->getSmtpOptions()->getConnectionConfig()['password']; - $port = $this->mailOptions->getSmtpOptions()->getPort(); - $host = $this->mailOptions->getSmtpOptions()->getHost(); - - $transport = Transport::fromDsn('smtp://' . $user . ':' . $pass . '@' . $host . ':' . $port); + if ($transport instanceof EsmtpTransport) { + $user = $this->mailOptions->getSmtpOptions()->getConnectionConfig()['username']; + $pass = $this->mailOptions->getSmtpOptions()->getConnectionConfig()['password']; + $tls = $this->mailOptions->getSmtpOptions()->getConnectionConfig()['tls'] === false ? 'false' : null; + $port = $this->mailOptions->getSmtpOptions()->getPort(); + $host = $this->mailOptions->getSmtpOptions()->getHost(); + $transport = Transport::fromDsn('smtp://' . $user . ':' . $pass . '@' . $host . ':' . $port + . '?auto_tls=' . $tls); } return $transport; diff --git a/src/Options/MailOptions.php b/src/Options/MailOptions.php index cac4935..10153ce 100644 --- a/src/Options/MailOptions.php +++ b/src/Options/MailOptions.php @@ -6,7 +6,7 @@ use Laminas\Stdlib\AbstractOptions; use Symfony\Component\Mailer\Transport\SendmailTransport; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; use Symfony\Component\Mailer\Transport\TransportInterface; use function array_key_exists; @@ -21,9 +21,9 @@ class MailOptions extends AbstractOptions { protected array $eventListeners = []; - protected TransportInterface|string $transport = SmtpTransport::class; + protected TransportInterface|string $transport = EsmtpTransport::class; protected array $transportMap = [ - 'smtp' => [SmtpTransport::class], + 'esmtp' => [EsmtpTransport::class], 'sendmail' => [SendmailTransport::class], ]; protected MessageOptions $messageOptions; diff --git a/test/CommonTrait.php b/test/CommonTrait.php index 09fda28..f74833e 100644 --- a/test/CommonTrait.php +++ b/test/CommonTrait.php @@ -6,7 +6,6 @@ use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamDirectory; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; trait CommonTrait { @@ -46,17 +45,6 @@ private function generateConfig(): array return [ 'dot_mail' => [ 'default' => [ - /** - * the mail transport to use - * can be any class implementing Symfony\Component\Mailer\Transport\TransportInterface - * - * for standard mail transports, you can use these aliases - * - sendmail => Symfony\Component\Mailer\Transport\SendmailTransport - * - smtp => Symfony\Component\Mailer\Transport\Smtp\SmtpTransport - * - * defaults to sendmail - **/ - 'transport' => SmtpTransport::class, 'message_options' => [ 'from' => '', 'from_name' => '', @@ -79,7 +67,18 @@ private function generateConfig(): array ], ], ], - //options that will be used only if Symfony\Component\Mailer\Transport\Smtp\SmtpTransport + /** + * the mail transport to use + * can be any class implementing Symfony\Component\Mailer\Transport\TransportInterface + * + * for standard mail transports, you can use these aliases + * - sendmail => Symfony\Component\Mailer\Transport\SendmailTransport + * - esmtp => Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport + * + * defaults to sendmail + **/ + 'transport' => 'esmtp', + //options that will be used only if Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport // adapter is used 'smtp_options' => [ 'host' => 'testHost', @@ -89,11 +88,11 @@ private function generateConfig(): array 'username' => 'test', //the smtp authentication credential 'password' => 'testPassword', + 'tsl' => null, ], ], ], 'test' => 'string test', - // option to log the SENT emails 'log' => [ 'sent' => $this->fileSystem->url() . '/log/mail/sent.log', diff --git a/test/Factory/MailServiceAbstractFactoryTest.php b/test/Factory/MailServiceAbstractFactoryTest.php index 13565e8..a926bba 100644 --- a/test/Factory/MailServiceAbstractFactoryTest.php +++ b/test/Factory/MailServiceAbstractFactoryTest.php @@ -23,7 +23,7 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; class MailServiceAbstractFactoryTest extends TestCase { @@ -91,7 +91,7 @@ public function testGenerateServiceWithProvidedAdapter(): void ->willReturn($this->messageOptions); $this->mailOptions->expects($this->any()) ->method('getTransport') - ->willReturn($this->createMock(SmtpTransport::class)); + ->willReturn($this->createMock(EsmtpTransport::class)); $this->mailOptions->expects($this->any()) ->method('getEventListeners') ->willReturn([AbstractMailEventListener::class]); @@ -116,7 +116,7 @@ public function testGenerateServiceWithProvidedAdapter(): void ->willReturn([ 'username' => 'test', 'password' => 'testPassword', - 'port' => 587, + 'tls' => null, ]); $this->smtpOptions->expects($this->once()) @@ -129,7 +129,7 @@ public function testGenerateServiceWithProvidedAdapter(): void $mailService = (new Subject())($this->container, $requestedName); $this->assertInstanceOf(MailService::class, $mailService); - $this->assertInstanceOf(SmtpTransport::class, $mailService->getTransport()); + $this->assertInstanceOf(EsmtpTransport::class, $mailService->getTransport()); } /** @@ -159,7 +159,7 @@ public function testGenerateServiceWithoutProvidedAdapter(): void ->willReturn($this->messageOptions); $this->mailOptions->expects($this->any()) ->method('getTransport') - ->willReturn(SmtpTransport::class); + ->willReturn(EsmtpTransport::class); $this->mailOptions->expects($this->any()) ->method('getEventListeners') ->willReturn(['Invalid Listener Test']); @@ -169,13 +169,13 @@ public function testGenerateServiceWithoutProvidedAdapter(): void ->willReturnMap([ ['dot-mail.options.default', $this->mailOptions], [LogServiceInterface::class, $this->createMock(LogService::class)], - [SmtpTransport::class, new SmtpTransport()], + [EsmtpTransport::class, new EsmtpTransport()], ['Invalid Listener Test', 'Invalid Listener provided'], ]); $this->container->expects($this->any()) ->method('has') ->willReturnMap([ - [SmtpTransport::class, true], + [EsmtpTransport::class, true], ['Invalid Listener Test', true], ]); @@ -184,7 +184,7 @@ public function testGenerateServiceWithoutProvidedAdapter(): void ->willReturn([ 'username' => 'test', 'password' => 'testPassword', - 'port' => 587, + 'tls' => false, ]); $this->smtpOptions->expects($this->once()) @@ -200,7 +200,7 @@ public function testGenerateServiceWithoutProvidedAdapter(): void $mailService = (new Subject())($this->container, $requestedName); $this->assertInstanceOf(MailService::class, $mailService); - $this->assertInstanceOf(SmtpTransport::class, $mailService->getTransport()); + $this->assertInstanceOf(EsmtpTransport::class, $mailService->getTransport()); $this->assertCount(2, $mailService->getAttachments()); } @@ -247,7 +247,7 @@ public function testGenerateServiceThrowException(): void ->willReturnMap([ ['dot-mail.options.default', $this->mailOptions], [LogServiceInterface::class, $this->createMock(LogService::class)], - [SmtpTransport::class, new SmtpTransport()], + [EsmtpTransport::class, new EsmtpTransport()], ['Invalid Listener Test', 'Invalid Listener provided'], ]); $this->container->expects($this->any()) diff --git a/test/Options/MailOptionsTest.php b/test/Options/MailOptionsTest.php index bb5d983..5e78703 100644 --- a/test/Options/MailOptionsTest.php +++ b/test/Options/MailOptionsTest.php @@ -9,7 +9,7 @@ use Dot\Mail\Options\MessageOptions; use Dot\Mail\Options\SmtpOptions; use PHPUnit\Framework\TestCase; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; class MailOptionsTest extends TestCase { @@ -17,7 +17,7 @@ public function testGettersAndSetters(): void { $subject = new MailOptions(); - $transport = 'smtp'; + $transport = 'esmtp'; $transportMap = ['test' => 'array']; $messageOptions = ['from' => '', 'to' => []]; $smtpOptions = ['host' => '', 'port' => 587]; @@ -29,7 +29,7 @@ public function testGettersAndSetters(): void $subject->setSmtpOptions($smtpOptions); $subject->setEventListeners($eventListeners); - $this->assertSame(SmtpTransport::class, $subject->getTransport()); + $this->assertSame(EsmtpTransport::class, $subject->getTransport()); $this->assertSame($transportMap, $subject->getTransportMap()); $this->assertInstanceOf(MessageOptions::class, $subject->getMessageOptions()); $this->assertInstanceOf(SmtpOptions::class, $subject->getSmtpOptions()); diff --git a/test/Service/MailServiceTest.php b/test/Service/MailServiceTest.php index 02bae60..b87c78a 100644 --- a/test/Service/MailServiceTest.php +++ b/test/Service/MailServiceTest.php @@ -17,7 +17,7 @@ use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; +use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Mime\Part\TextPart; @@ -68,7 +68,7 @@ public function setUp(): void public function testGettersAndSetters(): void { $attachments = ['/testAttachment.pdf', '/testDirectory/testAttachment2.xls']; - $transport = $this->createMock(SmtpTransport::class); + $transport = $this->createMock(EsmtpTransport::class); $this->mailService->setAttachments($attachments); $this->mailService->setTransport($transport);