Протокол IMAP нельзя назвать вершиной совершенства, но во многих отношениях он превосходит POP3. Сообщения могут храниться на сервере сколь угодно долго (с индивидуальными пометками «прочитано» и «не прочитано»). Для хранения сообщений можно организовать иерархию папок. Этих возможностей уже достаточно для того, чтобы считать протокол IMAP более развитым, чем POP3.
Для взаимодействия с IMAP-сервером предназначена стандартная библиотека
net/imap
. Естественно, вы должны сначала установить соединение с сервером, а затем идентифицировать
себя с помощью имени и пароля:
require 'net/imap'
host = "imap.hogwarts.edu"
user, pass = "lupin", "riddikulus"
imap = Net::IMAP.new(host)
begin
imap.login(user, pass)
# Или иначе:
# imap.authenticate("LOGIN", user, pass)
rescue Net::IMAP::NoResponseError
abort "He удалось аутентифицировать пользователя #{user}"
end
# Продолжаем работу...
imap.logout # Разорвать соединение.
Установив соединение, можно проверить почтовый ящик методом examine; по умолчанию почтовый ящик в IMAP называется INBOX. Метод responses возвращает информацию из почтового ящика в виде хэша массивов (наиболее интересные данные находятся в последнем элементе массива). Показанный ниже код показывает общее число сообщений в почтовом ящике (
"EXISTS"
) и число непрочитанных сообщений (
"RESENT"
):
imap.examine("INBOX")
total = imap.responses["EXISTS"].last # Всего сообщений.
в предыдущем примере выглядит так сложно, потому что возвращает массив хэшей. Сам конверт тоже представляет собой сложную структуру; некоторые методы доступа к нему возвращают составные объекты, другие — просто строки.
В протоколе IMAP есть понятия UID (уникального идентификатора) и порядкового номера сообщения. Обычно методы типа
fetch
обращаются к сообщениям по номерам, но есть и варианты (например,
uid_fetch
) для обращения по UID. У нас нет места объяснять, почему нужны обе системы идентификации, но если вы собираетесь серьезно работать с IMAP, то должны понимать различие между ними (и никогда не путать одну с другой).
Библиотека
net/imap
располагает разнообразными средствами для работы с почтовыми ящиками, сообщениями, вложениями и т.д. Дополнительную информацию поищите в онлайновой документации на сайте ruby-doc.org.
18.2.6. Кодирование и декодирование вложений
Для вложения в почтовое сообщение или в сообщение, отправляемое в конференцию, файл обычно кодируется. Как правило, применяется кодировка
base64
, для работы с которой служит метод
pack
с аргументом
m
:
bin = File.read("new.gif")
str = [bin].pack("m") # str закодирована.
orig = str.unpack("m")[0] # orig == bin
Старые почтовые клиенты работали с кодировкой uuencode/uudecode. В этом случае вложение просто добавляется в конец текста сообщения и ограничивается строками
begin
и
end
, причем в строке
begin
указываются также разрешения на доступ к файлу (которые можно и проигнорировать) и имя файла. Аргумент u метода
pack
позволяет представить строку в кодировке
uuencode
. Пример:
# Предположим, что mailtext содержит текст сообщения.
filename = "new.gif"
bin = File.read(filename)
encoded = [bin].pack("u")
mailtext << "begin 644 #{filename}"
mailtext << encoded
mailtext << "end"
# ...
На принимающей стороне мы должны извлечь закодированную информацию и декодировать ее методом