Skip to content

Commit

Permalink
Use fgets and detect partial line reads
Browse files Browse the repository at this point in the history
Signed-off-by: Elan Ruusamäe <[email protected]>
  • Loading branch information
glensc committed Feb 27, 2021
1 parent dec6db4 commit d9156cc
Showing 1 changed file with 25 additions and 4 deletions.
29 changes: 25 additions & 4 deletions src/Protocol/Smtp.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,21 +326,42 @@ public function data($data)
unset($data);
rewind($fp);

// max line length is 998 char + \r\n = 1000
// read the line up to PHP_SOCK_CHUNK_SIZE
while (($line = stream_get_line($fp, 0, "\n")) !== false) {
$line = rtrim($line, "\r");
$chunkSize = 4096;
$line = '';
while (($buffer = fgets($fp, $chunkSize)) !== false) {
$line .= $buffer;

// partial read, continue loop to read again to complete the line
if (strlen($buffer) === $chunkSize - 1 && $buffer[$chunkSize - 2] !== "\n") {
continue;
}

$line = rtrim($line, "\r\n");
if (isset($line[0]) && $line[0] === '.') {
// Escape lines prefixed with a '.'
$line = '.' . $line;
}

// max line length is 998 char + \r\n = 1000
if (strlen($line) > 998) {
// Long lines are "folded" by inserting "<CR><LF><SPACE>"
// https://tools.ietf.org/html/rfc5322#section-2.2.3
$line = substr(chunk_split($line, 998, Headers::FOLDING), 0, -strlen(Headers::FOLDING));
}
$this->_send($line);
$line = '';
}
if ($line) {
// max line length is 998 char + \r\n = 1000
if (strlen($line) > 998) {
// Long lines are "folded" by inserting "<CR><LF><SPACE>"
// https://tools.ietf.org/html/rfc5322#section-2.2.3
$line = substr(chunk_split($line, 998, Headers::FOLDING), 0, -strlen(Headers::FOLDING));
}

$this->_send($line);
}

fclose($fp);

$this->_send('.');
Expand Down

0 comments on commit d9156cc

Please sign in to comment.