Задать вопрос
@KitOsorgin

Как реализовать SMTP отправку почты PHP?

Хотел реализовать свою функцию для отправки SMTP почты на PHP, без модулей вроде Mailer и т.д. Столкнулся с тем, что ничего не происходит в результате последовательности, она просто не работает:

$socket = fsockopen($this->smtp_host, $this->smtp_port, $errorNumber, $errorDescription, 30);
$server_name = filter_input(INPUT_SERVER, 'NAME');
fputs($socket, "EHLO $server_name\r\n");
fputs($socket, "AUTH LOGIN\r\n");
fputs($socket, base64_encode($this->smtp_username) . "\r\n");
fputs($socket, base64_encode($this->smtp_password) . "\r\n");
fputs($socket, "MAIL FROM: <" . $this->smtp_username . ">\r\n");
fputs($socket, "RCPT TO: <{$mailTo}>\r\n");
fputs($socket, "DATA\r\n");
fputs($socket, $contentMail . "\r\n.\r\n");
fputs($socket, "QUIT\r\n");
fclose($socket);


При этом код, который я нашел на просторах интернета в виде класса с проверкой через try - catch работает замечательно:

function send($mailTo, $subject, $message, $smtp_from) {

        $contentMail = $this->getContentMail($subject, $message, $smtp_from);

        try {
            if (!$socket = @fsockopen($this->smtp_host, $this->smtp_port, $errorNumber, $errorDescription, 30)) {
                throw new Exception($errorNumber . "." . $errorDescription);
            }
            if (!$this->_parseServer($socket, "220")) {
                throw new Exception('Connection error');
            }

            $server_name = $_SERVER["SERVER_NAME"];
            fputs($socket, "EHLO $server_name\r\n");
            if (!$this->_parseServer($socket, "250")) {
                // если сервер не ответил на EHLO, то отправляем HELO
                fputs($socket, "HELO $server_name\r\n");
                if (!$this->_parseServer($socket, "250")) {
                    fclose($socket);
                    throw new Exception('Error of command sending: HELO');
                }
            }

            fputs($socket, "AUTH LOGIN\r\n");
            if (!$this->_parseServer($socket, "334")) {
                fclose($socket);
                throw new Exception('Autorization error');
            }

            fputs($socket, base64_encode($this->smtp_username) . "\r\n");
            if (!$this->_parseServer($socket, "334")) {
                fclose($socket);
                throw new Exception('Autorization error');
            }

            fputs($socket, base64_encode($this->smtp_password) . "\r\n");
            if (!$this->_parseServer($socket, "235")) {
                fclose($socket);
                throw new Exception('Autorization error');
            }

            fputs($socket, "MAIL FROM: <" . $this->smtp_username . ">\r\n");
            if (!$this->_parseServer($socket, "250")) {
                fclose($socket);
                throw new Exception('Error of command sending: MAIL FROM');
            }

            $mailTo = str_replace(" ", "", $mailTo);
            $emails_to_array = explode(',', $mailTo);
            foreach ($emails_to_array as $email) {
                fputs($socket, "RCPT TO: <{$email}>\r\n");
                if (!$this->_parseServer($socket, "250")) {
                    fclose($socket);
                    throw new Exception('Error of command sending: RCPT TO');
                }
            }

            fputs($socket, "DATA\r\n");
            if (!$this->_parseServer($socket, "354")) {
                fclose($socket);
                throw new Exception('Error of command sending: DATA');
            }

            fputs($socket, $contentMail . "\r\n.\r\n");
            if (!$this->_parseServer($socket, "250")) {
                fclose($socket);
                throw new Exception("E-mail didn't sent");
            }

            fputs($socket, "QUIT\r\n");
            fclose($socket);
        } catch (Exception $e) {
            return $e->getMessage();
        }
        return true;
    }

    private function _parseServer($socket, $response) {
        while (@substr($responseServer, 3, 1) != ' ') {
            if (!($responseServer = fgets($socket, 256))) {
                return false;
            }
        }
        if (!(substr($responseServer, 0, 3) == $response)) {
            return false;
        }
        return true;
    }


Как только я избавляю код от элементов дебага и функции _parseServer - почта перестает отправляться:
function send($mailTo, $subject, $message, $smtp_from) {

        $contentMail = $this->getContentMail($subject, $message, $smtp_from);


        $socket = fsockopen($this->smtp_host, $this->smtp_port, $errorNumber, $errorDescription, 30);

        $server_name = $_SERVER["SERVER_NAME"];
        fputs($socket, "EHLO $server_name\r\n");
        fputs($socket, "AUTH LOGIN\r\n");
        fputs($socket, base64_encode($this->smtp_username) . "\r\n");
        fputs($socket, base64_encode($this->smtp_password) . "\r\n");
        fputs($socket, "MAIL FROM: <" . $this->smtp_username . ">\r\n");
        fputs($socket, "RCPT TO: <{$mailTo}>\r\n");
        fputs($socket, "DATA\r\n");
        fputs($socket, $contentMail . "\r\n.\r\n");
        fputs($socket, "QUIT\r\n");
        fclose($socket);

        return true;
    }


Я понимаю, что раз есть работающий вариант - можно не трогать его и работать с ним, но не могу делать это спокойно, не разобравшись в причинах проблемы при упрощении кода.
  • Вопрос задан
  • 287 просмотров
Подписаться 2 Средний Комментировать
Решения вопроса 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Поскольку вы не дожидаетесь ответа сервера, то ваши команды уходят на сервер до того, как он будет готов их принять.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
rpsv
@rpsv
делай либо хорошо, либо никак
Хотел реализовать свою функцию для отправки SMTP почты на PHP, без модулей вроде Mailer

Ну собственно вопрос зачем, а главное нах опустим, но если уж вы в целом знаете о существовании PHPMailer и Swiftmailer, то почему бы не посмотреть на их код, а не код интернета?

_parseServer у вас читает сокет, наверное выкидывать его не стоит, как считаете?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы