18.2.4. Отправка почты по протоколу SMTP
Это понял бы и пятилетний ребенок. Дайте мне пятилетнего ребенка.
Название «простой протокол электронной почты» (Simple Mail Transfer Protocol — SMTP) не вполне правильно. Если он и «простой», то только по сравнению с более сложными протоколами.
Конечно, библиотека smtp.rb
скрывает от программиста большую часть деталей протокола. Но, на наш взгляд, эта библиотека интуитивно не вполне очевидна и, пожалуй, слишком сложна (надеемся, что в будущем это изменится). В этом разделе мы приведем несколько примеров, чтобы помочь вам освоиться.
В классе Net::SMTP
есть два метода класса: new
и start
. Метод new
принимает два параметра: имя сервера (по умолчанию localhost
) и номер порта (по умолчанию 25).
Метод start
принимает следующие параметры:
• server — доменное имя или IP-адрес SMTP-сервера; по умолчанию это 'localhost'
;
• port — номер порта, по умолчанию 25;
• domain — доменное имя отправителя, по умолчанию ENV['HOSTNAME']
;
• account — имя пользователя, по умолчанию nil
;
• password — пароль, по умолчанию nil
;
• authtype — тип авторизации, по умолчанию :cram_md5
.
Обычно большую часть этих параметров можно не задавать.
Если метод start
вызывается «нормально» (без блока), то он возвращает объект класса SMTP
. Если же блок задан, то этот объект передается прямо в блок.
У объекта SMTP
есть метод экземпляра sendmail
, который обычно и занимается всеми деталями отправки сообщения. Он принимает три параметра:
• source — строка или массив (или любой объект, у которого есть итератор each
, возвращающий на каждой итерации одну строку);
• sender — строка, записываемая в поле «from» сообщения;
• recipients — строка или массив строк, описывающие одного или нескольких получателей.
Вот пример отправки сообщения с помощью методов класса:
require 'net/smtp'
msg = <<EOF
Subject: Разное
... пришла пора
Подумать о делах:
О башмаках, о сургуче,
Капусте, королях.
И почему, как суп в котле,
Кипит вода в морях.
EOF
Net::SMTP.start('smtp-server.fake.com') do |smtp|
smtp.sendmail msg, '[email protected]', '[email protected]'
end
Поскольку в начале строки находится слово Subject:
, то получатель сообщения увидит тему Разное
.
Имеется также метод экземпляра start
, который ведет себя практически так же, как метод класса. Поскольку почтовый сервер определен в методе new
, то задавать его еще и в методе start
не нужно. Поэтому этот параметр пропускается, а остальные не отличаются от параметров, передаваемых методу класса. Следовательно, сообщение можно послать и с помощью объекта SMTP:
require 'net/smtp'
msg = <<EOF
Subject: Ясно и логично
'С другой стороны, - добавил Тарарам, -
если все так и было, то все именно так и было.
Если же все было бы так, то все не могло бы быть
не так. Но поскольку все было не совсем так, все
было совершенно не так. Ясно и логично!'
EOF
smtp = Net::SMTP.new('smtp-server.fake.com')
smtp.start
smtp.sendmail msg, '[email protected]', '[email protected]'
Если вы еще не запутались, добавим, что метод экземпляра может принимать ещё и блок:
require 'net/smtp'
msg = <<EOF
Subject: Моби Дик
Зовите меня Измаил.
EOF
addressees = ['[email protected]', '[email protected]']
smtp = Net::SMTP.new('smtp-server.fake.com')
smtp.start do |obj|
obj.sendmail msg, '[email protected]', addressees
end
Как видно из примера, объект, переданный в блок (obj
), не обязан называться так же, как объект, от имени которого вызывается метод (smtp
). Кроме того, хочу подчеркнуть: несколько получателей можно представить в виде массива строк.
Существует еще метод экземпляра со странным названием ready
. Он похож на sendmail
, но есть и важные различия. Задаются только отправитель и получатели, тело же сообщения конструируется с помощью объекта adapter
класса Net::NetPrivate::WriteAdapter
, у которого есть методы write
и append
. Адаптер передается в блок, где может использоваться произвольным образом[17]:
require 'net/smtp'
smtp = Net::SMTP.new('smtp-server.fake1.com')
smtp.start
smtp.ready('[email protected]', '[email protected]') do |obj|
obj.write 'Пошли вдвоем, пожалуй.
'