* SPDX-License-Identifier: AGPL-3.0-or-later */ namespace KTXM\ProviderImap\Smtp\Protocol; use KTXM\ProviderImap\Smtp\Transport\ConnectionInterface; use Psr\Log\LoggerInterface; final class ProtocolWriter { public function __construct( private readonly ConnectionInterface $connection, private readonly ?LoggerInterface $logger = null, ) {} /** * Write a single command line, appending the CRLF terminator. * * @param bool $sensitive when true the payload is redacted from logs * (used for AUTH credential exchanges) */ public function writeLine(string $line, bool $sensitive = false): void { $this->logger?->debug('SMTP command sent: {command}', [ 'command' => $sensitive ? $this->redact($line) : $line, ]); $this->connection->write($line . "\r\n"); } /** * Write raw bytes verbatim (e.g. the DATA payload). Never logged. */ public function writeRaw(string $payload): void { $this->connection->write($payload); } private function redact(string $line): string { if (preg_match('/^(AUTH\s+\S+)(\s+.*)?$/i', $line, $matches) === 1) { return $matches[1] . (isset($matches[2]) ? ' [REDACTED]' : ''); } return '[REDACTED]'; } }