8000 [Mailer] Add NativeTransportFactory · symfony/symfony@04de561 · GitHub
[go: up one dir, main page]

Skip to content

Commit 04de561

Browse files
committed
[Mailer] Add NativeTransportFactory
1 parent d555112 commit 04de561

File tree

6 files changed

+204
-1
lines changed

6 files changed

+204
-1
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer_transports.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
1919
use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory;
2020
use Symfony\Component\Mailer\Transport\AbstractTransportFactory;
21+
use Symfony\Component\Mailer\Transport\NativeTransportFactory;
2122
use Symfony\Component\Mailer\Transport\NullTransportFactory;
2223
use Symfony\Component\Mailer\Transport\SendmailTransportFactory;
2324
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory;
@@ -67,5 +68,8 @@
6768
->set('mailer.transport_factory.smtp', EsmtpTransportFactory::class)
6869
->parent('mailer.transport_factory.abstract')
6970
->tag('mailer.transport_factory', ['priority' => -100])
70-
;
71+
72+
->set('mailer.transport_factory.native', NativeTransportFactory::class)
73+
->parent('mailer.transport_factory.abstract')
74+
->tag('mailer.transport_factory');
7175
};

src/Symfony/Component/Mailer/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.2.0
5+
-----
6+
7+
* added `NativeTransportFactory` to configure a transport based on php.ini settings
8+
49
4.4.0
510
-----
611

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
namespace Symfony\Component\Mailer\Tests\Transport;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
7+
use Symfony\Component\Mailer\Transport\Dsn;
8+
use Symfony\Component\Mailer\Transport\NativeTransportFactory;
9+
use Symfony\Component\Mailer\Transport\SendmailTransport;
10+
use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
11+
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
12+
use Symfony\Component\Mailer\Transport\TransportInterface;
13+
14+
final class NativeTransportFactoryTest extends TestCase
15+
{
16+
public static $fakeConfiguration = [];
17+
18+
public static function setUpBeforeClass(): void
19+
{
20+
parent::setUpBeforeClass();
21+
22+
$namespace = str_replace('\\Tests\\', '\\', __NAMESPACE__);
23+
24+
$current = static::class;
25+
26+
$eval = <<<EOT
27+
namespace $namespace;
28+
29+
function ini_get(\$key)
30+
{
31+
\$vals = \\$current::\$fakeConfiguration;
32+
return \$vals[\$key] ?? '';
33+
}
34+
EOT;
35+
eval($eval);
36+
}
37+
38+
public function testCreateWithNotSupportedScheme()
39+
{
40+
$this->expectException(UnsupportedSchemeException::class);
41+
$this->expectExceptionMessageRegExp('#The ".*" scheme is not supported#');
42+
43+
$sut = new NativeTransportFactory();
44+
$sut->create(Dsn::fromString('sendmail://default'));
45+
}
46+
47+
public function testCreateSendmailWithNoSendmailPath()
48+
{
49+
if ('\\' === \DIRECTORY_SEPARATOR) {
50+
$this->markTestSkipped('This test cannot run on Windows.');
51+
}
52+
53+
$this->expectException(\Exception::class);
54+
$this->expectExceptionMessage('sendmail_path is not configured');
55+
56+
$sut = new NativeTransportFactory();
57+
$sut->create(Dsn::fromString('native://default'));
58+
}
59+
60+
public function provideCreateSendmailWithNoHostOrNoPort(): \Generator
61+
{
62+
yield ['native://default', '', '', ''];
63+
yield ['native://default', '', 'localhost', ''];
64+
yield ['native://default', '', '', '25'];
65+
}
66+
67+
/**
68+
* @dataProvider provideCreateSendmailWithNoHostOrNoPort
69+
*/
70+
public function testCreateSendmailWithNoHostOrNoPort(string $dsn, string $sendmaiPath, string $smtp, string $smtpPort)
71+
{
72+
if ('\\' !== \DIRECTORY_SEPARATOR) {
73+
$this->markTestSkipped('This test only run on Windows.');
74+
}
75+
76+
$this->expectException(\Exception::class);
77+
$this->expectExceptionMessage('smtp or smtp_port is not configured');
78+
79+
self::$fakeConfiguration = [
80+
'sendmail_path' => $sendmaiPath,
81+
'smtp' => $smtp,
82+
'smtp_port' => $smtpPort,
83+
];
84+
85+
$sut = new NativeTransportFactory();
86+
$sut->create(Dsn::fromString($dsn));
87+
}
88+
89+
public function provideCreate(): \Generator
90+
{
91+
yield ['native://default', '/usr/sbin/sendmail -t -i', '', '', new SendmailTransport('/usr/sbin/sendmail -t -i')];
92+
93+
if ('\\' === \DIRECTORY_SEPARATOR) {
94+
$socketStream = new SocketStream();
95+
$socketStream->setHost('myhost.tld');
96+
$socketStream->setPort(25);
97+
$socketStream->disableTls();
98+
yield ['native://default', '', 'myhost.tld', '25', new SmtpTransport($socketStream)];
99+
100+
$socketStreamTls = new SocketStream();
101+
$socketStreamTls->setHost('myhost.tld');
102+
$socketStreamTls->setPort(465);
103+
yield ['native://default', '', 'myhost.tld', '465', new SmtpTransport($socketStreamTls)];
104+
}
105+
}
106+
107+
/**
108+
* @dataProvider provideCreate
109+
*/
110+
public function testCreate(string $dsn, string $sendmailPath, string $smtp, string $smtpPort, TransportInterface $expectedTransport)
111+
{
112+
self::$fakeConfiguration = [
113+
'sendmail_path' => $sendmailPath,
114+
'smtp' => $smtp,
115+
'smtp_port' => $smtpPort,
116+
];
117+
118+
$sut = new NativeTransportFactory();
119+
$transport = $sut->create(Dsn::fromString($dsn));
120+
121+
$this->assertEquals($expectedTransport, $transport);
122+
}
123+
}

src/Symfony/Component/Mailer/Transport.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
2323
use Symfony\Component\Mailer\Transport\Dsn;
2424
use Symfony\Component\Mailer\Transport\FailoverTransport;
25+
use Symfony\Component\Mailer\Transport\NativeTransportFactory;
2526
use Symfony\Component\Mailer\Transport\NullTransportFactory;
2627
use Symfony\Component\Mailer\Transport\RoundRobinTransport;
2728
use Symfony\Component\Mailer\Transport\SendmailTransportFactory;
@@ -162,5 +163,7 @@ public static function getDefaultFactories(EventDispatcherInterface $dispatcher
162163
yield new SendmailTransportFactory($dispatcher, $client, $logger);
163164

164165
yield new EsmtpTransportFactory($dispatcher, $client, $logger);
166+
167+
yield new NativeTransportFactory($dispatcher, $client, $logger);
165168
}
166169
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Transport;
13+
14+
use Symfony\Component\Mailer\Exception\TransportException;
15+
use Symfony\Component\Mailer\Exception\UnsupportedSchemeException;
16+
use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
17+
use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
18+
19+
/**
20+
* Factory that configures a transport (sendmail or SMTP) based on php.ini settings.
21+
*
22+
* @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
23+
*/
24+
final class NativeTransportFactory extends AbstractTransportFactory
25+
{
26+
public function create(Dsn $dsn): TransportInterface
27+
{
28+
if (!\in_array($dsn->getScheme(), $this->getSupportedSchemes(), true)) {
29+
throw new UnsupportedSchemeException($dsn, 'native', $this->getSupportedSchemes());
30+
}
31+
32+
if ($sendMailPath = ini_get('sendmail_path')) {
33+
return new SendmailTransport($sendMailPath, $this->dispatcher, $this->logger);
34+
}
35+
36+
if ('\\' !== \DIRECTORY_SEPARATOR) {
37+
throw new TransportException('sendmail_path is not configured in php.ini.');
38+
}
39+
40+
// Only for windows hosts; at this point non-windows
41+
// host have already thrown an exception or returned a transport
42+
$host = ini_get('smtp');
43+
$port = (int) ini_get('smtp_port');
44+
45+
if (!$host || !$port) {
46+
throw new TransportException('smtp or smtp_port is not configured in php.ini.');
47+
}
48+
49+
$socketStream = new SocketStream();
50+
$socketStream->setHost($host);
51+
$socketStream->setPort($port);
52+
if (465 !== $port) {
53+
$socketStream->disableTls();
54+
}
55+
56+
return new SmtpTransport($socketStream, $this->dispatcher, $this->logger);
57+
}
58+
59+
protected function getSupportedSchemes(): array
60+
{
61+
return ['native'];
62+
}
63+
}

src/Symfony/Component/Mailer/Transport/SendmailTransport.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
* It is advised to use -bs mode since error reporting with -t mode is not
2828
* possible.
2929
*
30+
* Transport can be instanciated through SendmailTransportFactory or NativeTransportFactory:
31+
*
32+
* - SendmailTransportFactory to use most common sendmail path and recommanded options
33+
* - NativeTransportFactory when configuration is set via php.ini
34+
*
3035
* @author Fabien Potencier <fabien@symfony.com>
3136
* @author Chris Corbyn
3237
*/

0 commit comments

Comments
 (0)
0