Ваша задача — заставить Invision Community (IPS4) корректно работать с SMTPS (TLS на порту 465, implicit TLS), а не только с SMTP+STARTTLS (обычно порт 587). Из того, что вы описали:
- Вы успешно «пропатчили» механизм авторизации SMTP, заменив LOGIN на PLAIN — это решило вопрос аутентификации.
- Теперь вы хотите перейти на SMTPS (implicit TLS) на порту 465.
- При попытке отправки через SMTPS происходит зависание и таймаут.
---
### Почему возникает проблема?
Большинство современных PHP-библиотек и реализаций SMTP-клиентов (включая стандартный stream_socket_client и частично PHPMailer, которые может использовать IPS4) по умолчанию поддерживают STARTTLS, но implicit TLS (где TLS начинается сразу при подключении) требует особой настройки соединения.
Если пытаться подключаться к SMTPS на 465 порт без правильного указания SSL-контекста в stream_socket_client, то соединение либо не устанавливается, либо "зависает".
---
### Что проверить и как решить
1. Проверка способа соединения
Убедитесь, что в IPS4 при использовании порта 465 действительно используется SSL/TLS-соединение с самого начала, а не plain TCP, и не пытается запускать STARTTLS.
2. Настройка параметров соединения
В IPS4 (его классе SMTP отправки), скорее всего, используется stream_socket_client(). Для implicit SSL вам нужно использовать транспорт ssl:// или tls:// в URL подключения.
Например:
$transport = ($this->smtpPort == 465) ? 'ssl://' : 'tcp://';
$connection = stream_socket_client($transport . $this->smtpHost . ':' . $this->smtpPort, $errno, $errstr, $timeout);Часто ssl:// используется для implicit TLS (порт 465), а tcp:// — для обычного TCP (порт 587 с STARTTLS).
3. Патчинг IPS4
Возможно, в исходном коде IPS4 в классе SMTP нет поддержки ssl:// транспорта, или она автоматически не выбирается по порту.
Попробуйте поискать и изменить логику открытия соединения так, чтобы для порта 465 использовать ssl://.
Обычно в IPS4 путь к классу — IPS\Email\Outgoing\Smtp или похожий.
4. Пример патча для подключения:
Найдите метод, который открывает сокет, может называться _openSocket() или что-то подобное. Добавьте условие:
$transport = 'tcp://';
if ( $this->smtpPort == 465 )
{
$transport = 'ssl://';
}
$this->_socket = stream_socket_client(
$transport . $this->smtpHost . ':' . $this->smtpPort,
$errno,
$errstr,
$timeout
);5. Выключите STARTTLS
При использовании SMTPS на 465 не нужно запускать команду STARTTLS — TLS уже активен. Проверьте, что IPS4 не пытается выполнить STARTTLS после подключения, иначе возникнет конфликт.
6. Проверка настроек почтового сервера
Убедитесь, что ваш SMTP сервер корректно слушает 465 порт с implicit TLS.
7. Логирование и отладка
Включите расширенное логирование SMTP соединения в IPS4, чтобы увидеть, на каком этапе происходит зависание.
8. Альтернативы
Если IPS4 не поддерживает implicit TLS из коробки, можно:
- Использовать порт 587 с STARTTLS (если это возможно).
- Проксировать SMTP через stunnel на сервере, переводя plain 587 в 465 SSL.
- Использовать внешний SMTP-клиент/шлюз.
---
### Краткое резюме
- SMTPS (порт 465) требует подключения с ssl:// transport в PHP.
- Нужно исправить код создания сокета, чтобы для порта 465 использовать ssl://.
- Убедиться, что не запускается STARTTLS, когда используешь implicit TLS.
- Проверьте, что аутентификацию и отправку сообщений IPS4 выполняет после установления TLS.
- Логируйте SMTP-сессию для диагностики.
---
Если хотите, могу помочь более конкретно с кодом, если вы предоставите исходный код класса, где открывается SMTP-соединение у вас в IPS4.
Ваш GPT-5
Спасибо за предоставленный код класса SMTP. Теперь гораздо яснее, как идёт подключение и какая логика используется.
---
### Ваша задача — заставить Invision Community корректно работать с implicit TLS (SMTPS на порту 465).
---
## Анализ текущей реализации подключения
В методе connect() есть эта строка:
$connection = @fsockopen( ( ( $this->smtpProtocol == 'ssl' ) ? 'ssl://' : '' ) . $this->smtpHost, $this->smtpPort, $errno, $errstr );То есть протокол ssl:// добавляется к хосту только, если $this->smtpProtocol == 'ssl'. Это позволяет открывать implicit TLS соединение, которое как раз используется на порту 465.
Если $this->smtpProtocol == 'tls', то соединение открывается как plain TCP, и затем вызывается команда STARTTLS.
Всё выглядит правильно, но:
- Вы должны убедиться, что в конфигурации IPS4 при использовании порта 465 указано $smtpProtocol = 'ssl'.
- Если у вас $smtpProtocol == 'tls' на 465 порту — соединение зависнет, так как сервер ожидает TLS с самого начала, а клиент пытается сделать plain connection.
---
## Рекомендации и исправления
1. **Проверьте значение $smtpProtocol в вашей конфигурации.**
Для implicit TLS (порт 465) оно должно быть точно 'ssl', а не 'tls'!
2. **Убедитесь, что вы не запускаете STARTTLS при $smtpProtocol == 'ssl'.**
В вашем методе connect() есть такой код:
if( $this->smtpProtocol == 'tls' )
{
// starttls и активация шифрования
} Следовательно при 'ssl' этот блок пропускается, что правильно.
3. **Ваш патч с AUTH PLAIN**
Ваш код авторизации должен выглядеть примерно так, чтобы включать поддержку PLAIN, например заменить этот участок:
/* Authenticate */
if ( $this->smtpUser )
{
// вместо AUTH LOGIN, сделать:
$responseCode = $this->_sendCommand( 'AUTH PLAIN', 334 );
$responseCode = $this->_sendCommand( base64_encode("\0" . $this->smtpUser . "\0" . $this->smtpPass), 235 );
}4. **Добавьте логирование**
Метод getLog() есть, так что вызовите его после неудачных попыток, чтобы получить подробный лог SMTP сессии. Это поможет отловить, на каком этапе подвисает.
5. **Пример конфигурации для port 465**
В конфиге форума/почты должно быть так:
- SMTP host: ваш сервер
- SMTP port: 465
- SMTP protocol: ssl
- SMTP user/pass: ваши данные
---
## Можно протестировать -- пример быстрого скрипта для проверки соединения (outside IPS4)
<?php
$host = 'ssl://smtp.yourserver.com';
$port = 465;
$user = 'username';
$pass = 'password';
$fp = fsockopen($host, $port, $errno, $errstr, 10);
if (!$fp) {
die("Ошибка подключения: $errstr ($errno)\n");
}
echo fgets($fp, 515); // ждем готовности сервера
fputs($fp, "EHLO yourdomain.com\r\n");
echo fgets($fp, 515);
fputs($fp, "AUTH PLAIN " . base64_encode("\0$user\0$pass") . "\r\n");
echo fgets($fp, 515);
// Далее команда MAIL, RCPT и DATA ...
Если тестовый скрипт работает, а IPS4 нет — проблема в настройках (smtpProtocol) или нюансах работы класса.
---
## Резюме
- В IPS4 для implicit TLS на 465 порт должно быть $smtpProtocol = 'ssl'
- В этом случае fsockopen() использует ssl:// префикс, TLS устанавливается сразу
- STARTTLS в этом случае не вызывается
- Используйте AUTH PLAIN вместо AUTH LOGIN для аутентификации
- Проверьте лог сессии для диагностики проблем
- Убедитесь, что порт 465 на сервере корректно работает с implicit TLS
---
Если будете испытывать проблемы — пришлите лог из $smtp->getLog() после неудачной попытки. Помогу проанализировать дальше.