Skip to content

bug(timeout): No stream timeout set after connection — fgets() can block indefinitely #50

Description

@usernane

Bug Description

SMTPServer::$responseTimeout is only used during the initial stream_socket_client() call. After the connection is established, no stream_set_timeout() is called on the stream resource. The read() method calls fgets() which will block indefinitely if the server stops responding mid-session.

// In _tryConnect() — timeout only applies to connection establishment
$conn = @stream_socket_client($protocol.$host.':'.portNum, $err, $errStr, $timeout * 60, ...);

// In read() — no timeout protection
public function read() : string {
    while (!feof($this->serverCon)) {
        $str = fgets($this->serverCon);  // blocks forever if server hangs
        // ...
    }
}

Steps to Reproduce

  1. Connect to an SMTP server
  2. Start sending a message
  3. Server becomes unresponsive mid-session (network issue, server crash, firewall drops packets silently)
  4. fgets() blocks indefinitely — PHP process hangs

Expected Behavior

  • stream_set_timeout() should be called on the connection after it's established
  • read() should detect timeouts via stream_get_meta_data() and throw an exception
  • The $responseTimeout property should apply to all read operations, not just the initial connection

Actual Behavior

The PHP process hangs forever with no way to recover. In web contexts this eventually hits PHP's max_execution_time, but in CLI/queue workers it blocks the process permanently.

WebFiori Version

v2.1.1

PHP Version

8.1+

Operating System

Linux

Additional Context

Suggested fix — after successful connection in _tryConnect() or connect():

stream_set_timeout($this->serverCon, $this->responseTimeout * 60);

And in read(), detect timeout:

$str = fgets($this->serverCon);
$meta = stream_get_meta_data($this->serverCon);

if ($meta['timed_out']) {
    throw new SMTPException('Connection timed out waiting for server response.', 0, $this->getLog());
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions