Книга: Программирование на языке Ruby

18.2.4. Отправка почты по протоколу SMTP

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 "Пошли вдвоем, пожалуй.rn"
 obj.write "Уж вечер небо навзничью распялоrn"
 obj.write "Как пациента под ножом наркоз... rn"
end

Отметим, что пары символов «возврат каретки», «перевод строки» обязательны (если вы хотите разбить сообщение на строчки). Читатели, знакомые с деталями протокола, обратят внимание на то, что сообщение «завершается» (добавляется точка и слово «QUIT») без нашего участия.

Можно вместо метода write воспользоваться оператором конкатенации:

smtp.ready("[email protected]", "[email protected]") do |obj|
 obj << "В гостиной разговаривают тетиrn"
 obj << "О Микеланджело Буонаротти.rn"
end

И еще одно небольшое усовершенствование: мы добавим метод puts, который вставит в сообщение символы перехода на новую строку:

class Net::NetPrivate::WriteAdapter
 def puts(args)
  args << "rn"
  self.write(*args)
 end
end

Новый метод позволяет формировать сообщение и так:

smtp.ready("[email protected]", "[email protected]") do |obj|
 obj.puts "Мы были призваны в глухую глубину,"
 obj.puts "В мир дев морских, в волшебную страну,"
 obj.puts "Но нас окликнули - и мы пошли ко дну."
end

Если всего изложенного вам не хватает, поэкспериментируйте самостоятельно. А если соберетесь написать новый интерфейс к протоколу SMTP, не стесняйтесь.

Оглавление книги


Генерация: 1.348. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз