buildMessage($email, $subject, $body); $this->client->send( $this->host, $this->port, $this->user, $this->password, $this->fromEmail, $email, $message, ); } /** Assemble en-tetes + corps en CRLF, avec dot-stuffing pour la phase DATA. */ private function buildMessage(string $to, string $subject, string $body): string { $headers = [ 'From: ' . $this->encodeHeader($this->fromName) . ' <' . $this->fromEmail . '>', 'To: <' . $to . '>', 'Subject: ' . $this->encodeHeader($subject), 'MIME-Version: 1.0', 'Content-Type: text/plain; charset=UTF-8', 'Content-Transfer-Encoding: 8bit', ]; $raw = implode("\r\n", $headers) . "\r\n\r\n" . $this->normalizeEol($body); return $this->dotStuff($raw); } /** RFC 2047 (encoded-word base64) si la valeur sort de l'ASCII imprimable. */ private function encodeHeader(string $value): string { if (preg_match('/^[\x20-\x7E]*$/', $value) === 1) { return $value; } return '=?UTF-8?B?' . base64_encode($value) . '?='; } /** Normalise toutes les fins de ligne en CRLF (LF ou CR isoles -> CRLF). */ private function normalizeEol(string $text): string { return (string) preg_replace('/\r\n|\r|\n/', "\r\n", $text); } /** Double un point en debut de ligne (RFC 5321 transparency). */ private function dotStuff(string $message): string { $lines = explode("\r\n", $message); foreach ($lines as $i => $line) { if (isset($line[0]) && $line[0] === '.') { $lines[$i] = '.' . $line; } } return implode("\r\n", $lines); } }