mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
smtp-test: bypass DB, use POST fields directly for credentials
This commit is contained in:
10
TODO.md
10
TODO.md
@@ -6,6 +6,16 @@
|
|||||||
- [x] Exclude `cover` file_type from public files loop (covers are banners, not content)
|
- [x] Exclude `cover` file_type from public files loop (covers are banners, not content)
|
||||||
- [x] Move `App::boot()` in Dispatcher to after direct-response matching (no session on media requests)
|
- [x] Move `App::boot()` in Dispatcher to after direct-response matching (no session on media requests)
|
||||||
|
|
||||||
|
## SMTP Relay — bad greeting fix
|
||||||
|
|
||||||
|
- [x] Fix `$read()` loop: use `!== false` so empty lines don't terminate early; check `timed_out` meta
|
||||||
|
- [x] Add SSL stream context (`verify_peer=false`) to `stream_socket_client` to avoid CA bundle failures
|
||||||
|
- [x] Improve "bad greeting" error: distinguish timeout vs garbage response in log message
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
- [x] Fix `RateLimit::check()` called statically in `request-access.php` — replaced with `(new RateLimit(3, 600))->checkKey($rateLimitKey)`
|
||||||
|
|
||||||
## Dev / Debug Fixes
|
## Dev / Debug Fixes
|
||||||
|
|
||||||
- [x] Fix `serve` recipe: show all PHP output (errors, logs) except static assets/connection noise
|
- [x] Fix `serve` recipe: show all PHP output (errors, logs) except static assets/connection noise
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class SmtpRelay {
|
|||||||
// Build MIME message
|
// Build MIME message
|
||||||
$boundary = 'posterg_' . bin2hex(random_bytes(8));
|
$boundary = 'posterg_' . bin2hex(random_bytes(8));
|
||||||
$date = date('r');
|
$date = date('r');
|
||||||
$fromHdr = $s['from_name'] !== ''
|
$fromHdr = ($s['from_name'] ?? '') !== ''
|
||||||
? "=?UTF-8?B?" . base64_encode($s['from_name']) . "?= <{$s['from_email']}>"
|
? "=?UTF-8?B?" . base64_encode($s['from_name']) . "?= <{$s['from_email']}>"
|
||||||
: $s['from_email'];
|
: $s['from_email'];
|
||||||
$subjectHdr = '=?UTF-8?B?' . base64_encode($subject) . '?=';
|
$subjectHdr = '=?UTF-8?B?' . base64_encode($subject) . '?=';
|
||||||
@@ -179,8 +179,16 @@ class SmtpRelay {
|
|||||||
$connectHost = ($encryption === 'ssl') ? "ssl://{$host}" : $host;
|
$connectHost = ($encryption === 'ssl') ? "ssl://{$host}" : $host;
|
||||||
|
|
||||||
$errno = 0; $errstr = '';
|
$errno = 0; $errstr = '';
|
||||||
|
$ctx = stream_context_create([
|
||||||
|
'ssl' => [
|
||||||
|
'verify_peer' => false,
|
||||||
|
'verify_peer_name' => false,
|
||||||
|
'allow_self_signed' => true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
$sock = @stream_socket_client(
|
$sock = @stream_socket_client(
|
||||||
"{$connectHost}:{$port}", $errno, $errstr, $timeout
|
"{$connectHost}:{$port}", $errno, $errstr, $timeout,
|
||||||
|
STREAM_CLIENT_CONNECT, $ctx
|
||||||
);
|
);
|
||||||
if ($sock === false) {
|
if ($sock === false) {
|
||||||
throw new \RuntimeException("SMTP connect failed ({$connectHost}:{$port}): {$errstr} [{$errno}]");
|
throw new \RuntimeException("SMTP connect failed ({$connectHost}:{$port}): {$errstr} [{$errno}]");
|
||||||
@@ -189,10 +197,12 @@ class SmtpRelay {
|
|||||||
|
|
||||||
$read = function () use ($sock): string {
|
$read = function () use ($sock): string {
|
||||||
$buf = '';
|
$buf = '';
|
||||||
while ($line = fgets($sock, 512)) {
|
while (($line = fgets($sock, 512)) !== false) {
|
||||||
$buf .= $line;
|
$buf .= $line;
|
||||||
// 4th char is ' ' when it's the last line of a multi-line reply
|
// 4th char is ' ' when it's the last line of a multi-line reply
|
||||||
if (isset($line[3]) && $line[3] === ' ') break;
|
if (isset($line[3]) && $line[3] === ' ') break;
|
||||||
|
$meta = stream_get_meta_data($sock);
|
||||||
|
if ($meta['timed_out']) break;
|
||||||
}
|
}
|
||||||
return $buf;
|
return $buf;
|
||||||
};
|
};
|
||||||
@@ -211,7 +221,9 @@ class SmtpRelay {
|
|||||||
// Greeting
|
// Greeting
|
||||||
$greeting = $read();
|
$greeting = $read();
|
||||||
if (strncmp($greeting, '220', 3) !== 0) {
|
if (strncmp($greeting, '220', 3) !== 0) {
|
||||||
throw new \RuntimeException("SMTP bad greeting: {$greeting}");
|
$meta = stream_get_meta_data($sock);
|
||||||
|
$detail = $meta['timed_out'] ? '(socket timed out — no data received)' : '(received: ' . json_encode($greeting) . ')';
|
||||||
|
throw new \RuntimeException("SMTP bad greeting {$detail}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseEhlo = function (string $resp): array {
|
$parseEhlo = function (string $resp): array {
|
||||||
@@ -237,7 +249,7 @@ class SmtpRelay {
|
|||||||
if ($encryption === 'tls') {
|
if ($encryption === 'tls') {
|
||||||
$expect('STARTTLS', '220');
|
$expect('STARTTLS', '220');
|
||||||
if (!stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
|
if (!stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
|
||||||
throw new \RuntimeException('SMTP STARTTLS crypto negotiation failed');
|
throw new \RuntimeException('SMTP STARTTLS crypto negotiation failed (check server cert / CA bundle)');
|
||||||
}
|
}
|
||||||
// Re-EHLO after TLS — refresh capabilities
|
// Re-EHLO after TLS — refresh capabilities
|
||||||
$ehloResp = $send('EHLO ' . gethostname());
|
$ehloResp = $send('EHLO ' . gethostname());
|
||||||
|
|||||||
Reference in New Issue
Block a user