$argv[3], 'key' => $argv[4]] : null; $server = @stream_socket_server("tcp://127.0.0.1:{$port}", $errno, $errstr); if (!$server || $log === '') { fwrite(STDOUT, "error {$errstr}\n"); exit(1); } fwrite(STDOUT, "ready\n"); fflush(STDOUT); while (true) { $c = @stream_socket_accept($server, 60); if (!$c) break; stream_set_timeout($c, 5); $first = true; $quit = false; $secure = false; fwrite($c, "220 mock ESMTP\r\n"); $auth = 0; while (($line = fgets($c)) !== false) { if ($first && str_starts_with($line, 'QUIT /__quit')) { $quit = true; break; } $first = false; file_put_contents($log, "C: {$line}", FILE_APPEND); $cmd = strtoupper(substr(trim($line), 0, 4)); if ($auth > 0) { $auth--; fwrite($c, $auth > 0 ? "334 UGFzc3dvcmQ6\r\n" : "235 2.7.0 OK\r\n"); continue; } switch (true) { case $cmd === 'EHLO': fwrite($c, "250-mock\r\n250-8BITMIME\r\n".($tls && !$secure ? "250-STARTTLS\r\n" : '')."250 AUTH LOGIN\r\n"); break; case $cmd === 'STAR' && $tls && !$secure: fwrite($c, "220 Ready to start TLS\r\n"); try { $c = Tls::accept($c, $tls); } catch (\Throwable $e) { file_put_contents($log, "TLS: {$e->getMessage()}\n", FILE_APPEND); break 2; } $secure = true; file_put_contents($log, "TLS: ".Tls::info($c)['cipher']."\n", FILE_APPEND); break; case str_starts_with(strtoupper($line), 'AUTH LOGIN'): $auth = 2; fwrite($c, "334 VXNlcm5hbWU6\r\n"); break; case $cmd === 'MAIL': fwrite($c, "250 OK\r\n"); break; case $cmd === 'RCPT': fwrite($c, str_contains($line, 'reject') ? "550 No such user\r\n" : "250 OK\r\n"); break; case $cmd === 'DATA': fwrite($c, "354 Go ahead\r\n"); $data = ''; while (($l = fgets($c)) !== false && $l !== ".\r\n") $data .= $l; file_put_contents($log, "DATA:\n{$data}END DATA\n", FILE_APPEND); fwrite($c, "250 Queued\r\n"); break; case $cmd === 'QUIT': fwrite($c, "221 Bye\r\n"); break 2; default: fwrite($c, "502 Unknown\r\n"); } } fclose($c); if ($quit) break; }