From 8813b2c066e624615d89b67e609bb66447d5d3e5 Mon Sep 17 00:00:00 2001 From: johnnyq Date: Fri, 24 Jul 2026 18:56:16 -0400 Subject: [PATCH] Use imapEngine lib for testing imap connection --- admin/post/settings_mail.php | 134 +++++++---------------------------- 1 file changed, 24 insertions(+), 110 deletions(-) diff --git a/admin/post/settings_mail.php b/admin/post/settings_mail.php index b6cd357e..17e7b651 100644 --- a/admin/post/settings_mail.php +++ b/admin/post/settings_mail.php @@ -374,121 +374,35 @@ if (isset($_POST['test_email_imap'])) { } // Build remote socket (implicit SSL vs plain TCP) - $transport = 'tcp'; - if ($encryption === 'ssl') { - $transport = 'ssl'; - } + require_once $_SERVER['DOCUMENT_ROOT'] . '/libs/vendor/autoload.php'; // ImapEngine (composer) - $remote_socket = $transport . '://' . $host . ':' . $port; - - // Stream context (you can tighten these if you want strict validation) - $context_options = []; - if (in_array($encryption, ['ssl', 'tls'], true)) { - $context_options['ssl'] = [ - 'verify_peer' => false, - 'verify_peer_name' => false, - 'allow_self_signed' => true, - ]; - } - - $context = stream_context_create($context_options); + // Map the stored encryption value to an ImapEngine transport (matches the cron sync) + $imap_transport = match ($encryption) { + 'ssl' => 'ssl', // implicit TLS (993) + 'tls' => 'starttls', // STARTTLS upgrade (143) - Webklex semantics + 'starttls' => 'starttls', + default => '', // 'none' / plain TCP + }; try { - $errno = 0; - $errstr = ''; + // Same ImapEngine client the cron sync uses, so a passing test predicts a + // working sync. Typed errors instead of raw banners; host validated at save. + $mailbox = new \DirectoryTree\ImapEngine\Mailbox([ + 'host' => $host, + 'port' => $port, + 'encryption' => $imap_transport, + 'validate_cert' => true, + 'username' => $username, + 'password' => $password, // access token when OAuth + 'authentication' => $is_oauth ? 'oauth' : 'plain', + ]); - // 10-second timeout, adjust as needed - $fp = @stream_socket_client( - $remote_socket, - $errno, - $errstr, - 10, - STREAM_CLIENT_CONNECT, - $context - ); + $mailbox->connect(); + $mailbox->inbox(); // confirm auth + mailbox access, like the sync does - if (!$fp) { - throw new Exception("Could not connect to IMAP server: [$errno] $errstr"); - } - - stream_set_timeout($fp, 10); - - // Read server greeting (IMAP servers send something like: * OK Dovecot ready) - $greeting = fgets($fp, 1024); - if ($greeting === false || strpos($greeting, '* OK') !== 0) { - fclose($fp); - throw new Exception("Invalid IMAP greeting: " . trim((string) $greeting)); - } - // If you really want STARTTLS for "tls" (port 143), you can do it here - if ($encryption === 'tls' && stripos($greeting, 'STARTTLS') !== false) { - fwrite($fp, "A0001 STARTTLS\r\n"); - $line = fgets($fp, 1024); - if ($line === false || stripos($line, 'A0001 OK') !== 0) { - fclose($fp); - throw new Exception("STARTTLS failed: " . trim((string) $line)); - } - - if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - fclose($fp); - throw new Exception("Unable to enable TLS encryption on IMAP connection."); - } - } - - $tag = 'A0002'; - - if ($is_oauth) { - $oauth_b64 = base64_encode("user={$username}\x01auth=Bearer {$password}\x01\x01"); - $auth_cmd = sprintf("%s AUTHENTICATE XOAUTH2 %s\r\n", $tag, $oauth_b64); - fwrite($fp, $auth_cmd); - } else { - $login_cmd = sprintf( - "%s LOGIN \"%s\" \"%s\"\r\n", - $tag, - addcslashes($username, "\\\""), - addcslashes($password, "\\\"") - ); - - fwrite($fp, $login_cmd); - } - - $success = false; - $error_line = ''; - - while (!feof($fp)) { - $line = fgets($fp, 2048); - if ($line === false) { - break; - } - - if (strpos($line, $tag . ' ') === 0) { - if (stripos($line, $tag . ' OK') === 0) { - $success = true; - } else { - $error_line = trim($line); - } - break; - } - } - - // Always logout / close - fwrite($fp, "A0003 LOGOUT\r\n"); - fclose($fp); - - if ($success) { - if ($is_oauth) { - flashAlert("Connected successfully using OAuth"); - } else { - flashAlert("Connected successfully"); - } - } else { - if (!$error_line) { - $error_line = 'Unknown IMAP authentication error'; - } - throw new Exception($error_line); - } - - } catch (Exception $e) { - flashAlert("IMAP connection failed: " . htmlspecialchars($e->getMessage()), 'error'); + flashAlert($is_oauth ? "Connected successfully using OAuth" : "Connected successfully"); + } catch (\Throwable $e) { + flashAlert("IMAP connection failed. Check the host, port, encryption, and credentials.", 'error'); } redirect();