Co nie działało
W protokole SMTP po komendzie DATA serwer traktuje każdą kolejną linię jako treść wiadomości, aż do linii z samą kropką. Jeśli wysyłka urwała się właśnie w tym momencie, na przykład przez wyjątek albo przekroczony czas, a kod aplikacji zamykał potem połączenie przez quit(), PHPMailer wysyłał komendę QUIT. Serwer nie widział w niej końca sesji, tylko kolejną linię maila, więc nie odpowiadał, a klient czekał na odpowiedź do upływu limitu czasu. Problem opisywało zgłoszenie #2994.
Co zmieniliśmy
Poszliśmy za pomysłem z dyskusji w #3121: klasa SMTP pamięta ostatnią wysłaną komendę, a quit() sprawdza ją przed wysłaniem czegokolwiek.
Stan ustawia sendCommand() przy każdej komendzie, a close() go czyści. W opisie zmiany zaznaczyliśmy jedno ograniczenie: komenda DATA, którą serwer odrzucił, też zostawia stan DATA, i zaproponowaliśmy śledzenie tylko przyjętych komend, gdyby opiekun wolał takie zachowanie.
Jak to sprawdziliśmy
Nowy test testQuitDuringData otwiera połączenie, wysyła MAIL i RCPT, rozpoczyna DATA bez wysyłania treści, jakby wysyłka została przerwana, i wywołuje quit(). Test sprawdza w logu klienta, że QUIT nie został wysłany, oraz że połączenie jest zamknięte.
Efekt
Zmianę scalono 4 października 2026. Aplikacje, które sprzątają połączenie po nieudanej wysyłce, nie wiszą już na limicie czasu i nie dopisują QUIT do porzuconej wiadomości.