Отправка писем с использованием сокетовВ этой статье я рассматриваю вопрос отсылки письма с web-формы. Я понимаю, что на эту статью может наткнуться человек с любыми знаниями, но если вы не знаете хотя бы чуть-чуть основы синтаксиса PHP - думаю, вам это не подойдёт. Хотя, постараюсь ответить на любые ваши вопросы. Вообще говоря, есть несколько способов отправки письма с формы, простых и не очень. Начнём с самого простого (и обычно не работающего). PHP функция mail()Описание функции следующее: bool mail (string to, string subject, string message) т.е. она для работы требует несколько параметров (они подробно рассматриваются в мануале), в том числе строка с адресом почты "кому". А вообще-то для отправки письма нам необходимо:
А у нас имеется только последние два, где же прячется ещё один параметр? А прячется он в конфигурационном файле
Для *nix систем параметры php.ini следующие:
Так вот мы нашли "точку входа" нашего письма. Под Windows это обязательно некий почтовый сервер, который, словно металический почтовый ящик, что стоит на почте, умеет принимать письма и отправлять их адресату. Под юникс это программа sendmail, которая сама, без помощи сторонних серверов, умеет доставлять сообщения до сервера "B".
Тут немного разгребли, теперь составлю общий план:
Тогда начинаем работать по плану, для начала накидаем форму в каком-нибудь редакторе визуальном или не очень: <FORM METHOD="POST" ACTION="mail.php"> <INPUT NAME="to" TYPE="text"> Адрес получателя<BR> <INPUT NAME="subj" TYPE="text"> Тема сообщения<BR> <TEXTAREA NAME="mess" ROWS="3" COLS="20">Сообщение</TEXTAREA><BR> <INPUT TYPE="submit" NAME="send"> </FORM> Пишем скрипт:
<?php
Вот и весь скрипт. Один только минус. Пока каждый может беспрепятственно отправить с сервера сколько угодно и куда угодно писем - сервер является находкой для спаммеров. Потому на всех мало-мальски крупных серверах вводят обязательную авторизацию на исходящие сообщения. А функция Warning: mail(): SMTP server response: 575 login@zelnet.ru sender requires authentication in test_mail.php on line 9 Более чем уверен, что это не совсем то, что требовалось.
Используем сокеты
Вопрос: как обойти проблемы с обязательной smtp авторизацией (на исходящие сообщения)? Решение: если функция О том, что такое сокеты чуть позже, а пока жмите: Пуск->Выполнить->cmd, пишем: telnet smtp.zelnet.ru 25 Подождём с ответа и что видим? 220 mail.zelnet.ru ESMTP CommuniGate Pro 4.3.4 SMTP-сервер нам что-то ответил. А ну-ка напишем мы ему следующую команду: HELO 127.0.0.1 Вместо 127.0.0.1 подставите свой IP адрес, на что нам ответят: 250 mail.zelnet.ru is pleased to meet you Вот ведь... Рады видеть они нас... Закрываем телнет. В общем, суть в том, что можно посылая команды SMTP-серверу (сервер исходящих сообщений) заставить его что-либо делать. Собственно функция mail() тоже так же команды посылала, но что плохо для нас, посылала не те что нужны. Для начала стоит рассказать, что собственно этому серверу посылать-то, какие команды... Набросаю кратко план действий.
После соединения необходимо забрать строку приветствия сервера, в нашем случае " Далее отправляем: HELO hostгде вместо host ваш IP-адрес. После нужно уведомить smtp-сервер о том, что мы хотим авторизоваться. Делается это командой: AUTH LOGINдалее последовательно посылаются логин и пароль (тут есть тонкость, о ней чуть позже). И если сервер ответил что, вы авторизованы, уведомляем сервер от кого письмо: MAIL FROM:vasya_pupkin@mail.ruИ кому: RCPT TO:vasha_masha@gmail.comДалее необходимо уведомить сервер о том, что сейчас будем посылать данные: DATAИ если сервер готов принять посылается сам текст письма: Приветсвую, Маня! Как у тебя дела? Ну и надо уведомить сервер о том, что письмо закончилось. Для этого посылаем всего одну точку . Всё собственно. Больше нам сервер не нужен (мы же пока не собираемся ещё и принимать письма, ведь так?), так что закрываем соединение: QUIT Это и есть план подключения. Заметьте, после каждой команды сервер вернёт некую строчку - она начинается с трёхзначного кода и строки пояснения после пробела. Какой код означает удачу/неудачу, какой код после какой команды вообще может быть возвращён - смотрите в RFC821. Вопрос ещё не родился у вас в светлых головах? А как эти команды посылать с помощью PHP? СОКЕТЫ!!! Так, сейчас расскажу. Для начала: сокеты - это некий программный интерфейс над реализацией стека TCP/IP. По сути это функции с помощью которых можно работать с сетью на низком уровне: соединиться с каким-то адрессом:портом, послать байт, принять байт и т.п. А ещё сокет - это связка адрес-порт. Например, файловый сервер городской сети открыт по адресу ftp1.zelnet.ru и порту 21. Так вот связка ftp1.zelnet.ru:21 будет точно указывать именно на этот файловый сервер (можно на ftp1.zelnet.ru открыть ещё один файловый сервер просто на другом порту и это будет уже другой сервер), её и можно назвать сокетом. Чтобы открыть соединение используем функцию fsockopen(): resource fsockopen ( string target, int port ) Здесь
Чтение/запись через сокет, открытый этой функцией, производится с помощью fgets() и fputs() соответственно. Для простоты дальнейшей работы напишем функцию, отправляющую команду и возвращающую код ответа:
<?php
Каждая команда SMTP-серверу должна завершаться символом перевода строки Всё собственно, можно писать код (пояснения в комментариях и ниже):
<?php
Теперь немного пояснений. Почему логин и пароль кодируются с помощью base64_encode() не знаю. Мне это не интересно, для результата знание этого не важно - так что примите на веру. Вот переменные которые должны быть определены до того как вызовётся этот кусок кода: $localhost $smtp_user $smtp_pass $to $data $smtp_host $smtp_port и вроде бы имена говорящие. Единственное с чем есть загвоздка это $data. Эта строковая переменная должна содержать письмо, в определённом формате. В примитивном случаем это примерно вот так: заголовки\r\n заголовки\r\n заголовки\r\n \r\n само послание Как пример: From: vasya@nc.ru To: masha@mail.ru Subject: Вот такое хреновое лето Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: 8bit Привет. Как ваша жизнь? Какие бывают заголовки можно посмотреть, открыв в почтовом клиенте любое письмо и в менюшках щёлкнув "Показать заголовки RFC822" или что-нибудь вроде того, либо проштудировав данный RFC. Кому-то то, что я написал, может не понравится, потому что сочтут что воспользоваться веб-интерфейсом какого-нить mail.ru проще. А вообще, именно так, в абсолютном большинстве случаев, и отправляют почту, используя PHP. |
||