Skip to content

Commit f09b05b

Browse files
eliashaeusslersbuerk
authored andcommitted
[TASK] Allow transport_spool_filepath outside project root
The `transport_spool_filepath` setting used for the mailer's file spool now accepts paths outside the project root. Those paths must be configured as absolute paths and added in `$GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath']`. Resolves: #103159 Releases: main, 13.4 Change-Id: I46e315148d6e50625b155678d77691430dc07e8f Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83044 Tested-by: core-ci <typo3@b13.com> Tested-by: Stefan Bürk <stefan@buerk.tech> Reviewed-by: Stephan Großberndt <stephan.grossberndt@typo3.org> Tested-by: Garvin Hicking <gh@faktor-e.de> Reviewed-by: Stefan Bürk <stefan@buerk.tech> Reviewed-by: Garvin Hicking <gh@faktor-e.de> Tested-by: Stephan Großberndt <stephan.grossberndt@typo3.org>
1 parent dbcec34 commit f09b05b

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

typo3/sysext/core/Classes/Mail/TransportFactory.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ protected function createSpool(array $mailSettings): DelayedTransportInterface
194194
$transportSpoolType = (string)($mailSettings['transport_spool_type'] ?? '');
195195
switch ($transportSpoolType) {
196196
case self::SPOOL_FILE:
197-
$path = GeneralUtility::getFileAbsFileName($mailSettings['transport_spool_filepath'] ?? '');
197+
$path = $mailSettings['transport_spool_filepath'] ?? '';
198+
if (!GeneralUtility::isAllowedAbsPath($path)) {
199+
$path = GeneralUtility::getFileAbsFileName($path);
200+
}
198201
if (empty($path)) {
199202
throw new \RuntimeException('The Spool Type filepath must be configured for TYPO3 in order to be used. Be sure that it\'s not accessible via the web.', 1518558797);
200203
}

typo3/sysext/core/Tests/Unit/Mail/TransportFactoryTest.php

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace TYPO3\CMS\Core\Tests\Unit\Mail;
1919

20+
use PHPUnit\Framework\Attributes\DataProvider;
2021
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
2122
use PHPUnit\Framework\Attributes\Test;
2223
use Psr\Log\NullLogger;
@@ -51,8 +52,22 @@ protected function getSubject(&$eventDispatcher): TransportFactory
5152
return new TransportFactory($eventDispatcher, $logManager, $logger, new FileNameValidator());
5253
}
5354

55+
/**
56+
* @return \Generator<string, array{string, string, list<string>}>
57+
*/
58+
public static function getReturnsSpoolTransportUsingFileSpoolDataProvider(): \Generator
59+
{
60+
yield 'relative path' => ['foo', Environment::getPublicPath() . '/foo', []];
61+
yield 'extension path' => ['EXT:styleguide/Resources/Private/MailQueue', Environment::getFrameworkBasePath() . '/styleguide/Resources/Private/MailQueue', []];
62+
yield 'absolute path' => ['/var/mailqueue', '/var/mailqueue', ['/var/mailqueue']];
63+
}
64+
65+
/**
66+
* @param list<string> $lockRootPath
67+
*/
68+
#[DataProvider('getReturnsSpoolTransportUsingFileSpoolDataProvider')]
5469
#[Test]
55-
public function getReturnsSpoolTransportUsingFileSpool(): void
70+
public function getReturnsSpoolTransportUsingFileSpool(string $path, string $expected, array $lockRootPath): void
5671
{
5772
$mailSettings = [
5873
'transport' => 'sendmail',
@@ -69,18 +84,62 @@ public function getReturnsSpoolTransportUsingFileSpool(): void
6984
'defaultMailFromAddress' => '',
7085
'defaultMailFromName' => '',
7186
'transport_spool_type' => 'file',
72-
'transport_spool_filepath' => '.',
87+
'transport_spool_filepath' => $path,
7388
];
7489

90+
// Register lock root path
91+
$initialLockRootPath = $GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] ?? [];
92+
$GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] = $lockRootPath;
93+
7594
// Register fixture class
7695
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][FileSpool::class]['className'] = FakeFileSpoolFixture::class;
7796

7897
$transport = $this->getSubject($eventDispatcher)->get($mailSettings);
98+
7999
self::assertInstanceOf(DelayedTransportInterface::class, $transport);
80100
self::assertInstanceOf(FakeFileSpoolFixture::class, $transport);
101+
self::assertStringContainsString($expected, $transport->getPath());
102+
103+
// Restore lock root path
104+
$GLOBALS['TYPO3_CONF_VARS']['BE']['lockRootPath'] = $initialLockRootPath;
105+
}
106+
107+
/**
108+
* @return \Generator<string, array{string}>
109+
*/
110+
public static function getThrowsExceptionOnInvalidSpoolFilePathDataProvider(): \Generator
111+
{
112+
yield 'relative path' => ['../foo'];
113+
yield 'extension path' => ['EXT:styleguide/../foo'];
114+
yield 'absolute path' => ['/foo/../baz'];
115+
}
81116

82-
$path = $transport->getPath();
83-
self::assertStringContainsString($mailSettings['transport_spool_filepath'], $path);
117+
#[DataProvider('getThrowsExceptionOnInvalidSpoolFilePathDataProvider')]
118+
#[Test]
119+
public function getThrowsExceptionOnInvalidSpoolFilePath(string $path): void
120+
{
121+
$mailSettings = [
122+
'transport' => 'sendmail',
123+
'transport_smtp_server' => 'localhost:25',
124+
'transport_smtp_encrypt' => '',
125+
'transport_smtp_username' => '',
126+
'transport_smtp_password' => '',
127+
'transport_smtp_restart_threshold' => 0,
128+
'transport_smtp_restart_threshold_sleep' => 0,
129+
'transport_smtp_ping_threshold' => 0,
130+
'transport_smtp_stream_options' => [],
131+
'transport_sendmail_command' => '',
132+
'transport_mbox_file' => '',
133+
'defaultMailFromAddress' => '',
134+
'defaultMailFromName' => '',
135+
'transport_spool_type' => 'file',
136+
'transport_spool_filepath' => $path,
137+
];
138+
139+
$this->expectException(\RuntimeException::class);
140+
$this->expectExceptionCode(1518558797);
141+
142+
$this->getSubject($eventDispatcher)->get($mailSettings);
84143
}
85144

86145
#[Test]

0 commit comments

Comments
 (0)