Spec-Zone.ru › Ruby 2.6

класс Net::IMAP

Родитель:
Protocol
Включенные модули:
MonitorMixin, OpenSSL, OpenSSL::SSL

Net::IMAP реализует функциональность клиента протокола Internet Message Access Protocol (IMAP). Протокол описан в [IMAP].

IMAP Обзор

Клиент IMAP подключается к серверу и затем выполняет аутентификацию, используя либо authenticate(), либо login(). После аутентификации доступны различные команды. Большинство из них работают с почтовыми ящиками, которые могут быть организованы в иерархическом пространстве имен, и каждый из которых содержит ноль или более сообщений. Реализация на сервере зависит от конкретной реализации; на сервере UNIX часто реализуется как файлы в формате почтового ящика в иерархии каталогов.

Для работы с сообщениями в почтовом ящике клиент должен сначала выбрать этот почтовый ящик, используя либо select(), либо (для чтения только для просмотра) examine(). После успешного выбора почтового ящика клиент переходит в состояние «выбран» и этот почтовый ящик становится «текущим», для которого неявно применяются команды, связанные с элементами почты.

Сообщения имеют два типа идентификаторов: последовательные номера сообщений и UIDs.

Последовательные номера сообщений нумеруют сообщения в почтовом ящике от 1 до количества элементов в почтовом ящике. Если во время сессии приходит новое сообщение, ему присваивается последовательный номер, равный новому размеру почтового ящика. Если сообщения удаляются из почтового ящика, оставшиеся сообщения изменяют свои последовательные номера, «сдвигая» их вниз, чтобы заполнить пробелы.

С другой стороны, UIDs гарантированно не идентифицируют другое сообщение в том же почтовом ящике, даже если существующее сообщение удалено. UIDs должны назначаться в порядке возрастания (но необязательно последовательно) в пределах почтового ящика; это означает, что если клиент, не поддерживающий IMAP, изменяет порядок элементов почты в почтовом ящике, UIDs должны быть переназначены. Клиент IMAP поэтому не может изменять порядок сообщений.

Примеры использования

Вывод отправителя и темы всех последних сообщений в стандартном почтовом ящике

imap = Net::IMAP.new('mail.example.com')
imap.authenticate('LOGIN', 'joe_user', 'joes_password')
imap.examine('INBOX')
imap.search(["RECENT"]).each do |message_id|
  envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
  puts "#{envelope.from[0].name}: \t#{envelope.subject}"
end

Перемещение всех сообщений из апреля 2003 года из «Mail/sent-mail» в «Mail/sent-apr03»

imap = Net::IMAP.new('mail.example.com')
imap.authenticate('LOGIN', 'joe_user', 'joes_password')
imap.select('Mail/sent-mail')
if not imap.list('Mail/', 'sent-apr03')
  imap.create('Mail/sent-apr03')
end
imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id|
  imap.copy(message_id, "Mail/sent-apr03")
  imap.store(message_id, "+FLAGS", [:Deleted])
end
imap.expunge

Thread Безопасность многопоточности

Net::IMAP поддерживает одновременную работу нескольких потоков. Например,

imap = Net::IMAP.new("imap.foo.net", "imap2")
imap.authenticate("cram-md5", "bar", "password")
imap.select("inbox")
fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
search_result = imap.search(["BODY", "hello"])
fetch_result = fetch_thread.value
imap.disconnect

Этот скрипт вызывает команды FETCH и SEARCH одновременно.

Ошибки

Сервер IMAP может отправлять три разных типа ответов, чтобы указать на ошибку:

NO

попытка выполнить команду не удалась. Например, имя пользователя/пароль, используемые для входа, неверны; выбранный почтовый ящик не существует и т.д.

BAD

запрос от клиента не соответствует пониманию сервером протокола IMAP. Это включает попытку команд из неправильного состояния клиента; например, попытка выполнить команду SEARCH без выбора текущего почтового ящика. Также может указывать на внутреннюю ошибку сервера (например, сбой диска).

BYE

сервер завершает работу. Это может быть частью обычной последовательности выхода, и может использоваться в процессе входа для указания того, что сервер (по какой-либо причине) не хочет принимать ваше подключение. В ответ на любую другую команду, это указывает либо на то, что сервер выключается, либо на то, что сервер отключает подключение клиента из-за бездействия.

Эти три ответа об ошибках представлены ошибками Net::IMAP::NoResponseError, Net::IMAP::BadResponseError и Net::IMAP::ByeResponseError, которые являются подклассами Net::IMAP::ResponseError. По существу, все методы, которые подразумевают отправку запроса на сервер, могут генерировать одну из этих ошибок. Только наиболее важные случаи описаны ниже.

Поскольку класс IMAP использует сокеты для связи, его методы также подвержены различным ошибкам, которые могут возникнуть при работе с сокетами. Они обычно представлены как ошибки Errno. Например, любой метод, который подразумевает отправку запроса на сервер и/или получение ответа от него, может вызвать ошибку Errno::EPIPE, если сетевое соединение неожиданно прервётся. Обратитесь к руководствам man по сокетам(7), ip(7), tcp(7), socket(2), connect(2) и связанным с ними.

Наконец, Net::IMAP::DataFormatError выбрасывается, если обнаружено, что данные низкого уровня имеют неправильный формат (например, при преобразовании между UTF-8 и UTF-16), и Net::IMAP::ResponseParseError выбрасывается, если ответ сервера не может быть проанализирован.

Ссылки

[IMAP]
  1. Crispin, «INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1»,

RFC 2060, декабрь 1996 года. (Примечание: устарел RFC 3501)

[LANGUAGE-TAGS]

Alvestrand, H., «Метки для идентификации языков», RFC 1766, март 1995 года.

[MD5]

Myers, J., и M. Rose, «Поле заголовка Content-MD5», RFC 1864, октябрь 1995 года.

[MIME-IMB]

Freed, N., и N. Borenstein, «MIME (Multipurpose Internet Mail Extensions) Часть первая: Формат тел сообщений в Интернете», RFC 2045, ноябрь 1996 года.

[RFC-822]

Crocker, D., «Стандарт для формата текстовых сообщений ARPA Internet», STD 11, RFC 822, Университет Делавэра, август 1982 года.

[RFC-2087]

Myers, J., «Расширение IMAP4 QUOTA», RFC 2087, январь 1997 года.

[RFC-2086]

Myers, J., «Расширение IMAP4 ACL», RFC 2086, январь 1997 года.

[RFC-2195]

Klensin, J., Catoe, R., и Krumviede, P., «Расширение IMAP/POP AUTHorize для простого вызова/ответа», RFC 2195, сентябрь 1997 года.

[SORT-THREAD-EXT]

Crispin, M., «INTERNET MESSAGE ACCESS PROTOCOL - Расширения SORT и THREAD», draft-ietf-imapext-sort, май 2003 года.

[OSSL]

www.openssl.org

[RSSL]

savannah.gnu.org/projects/rubypki

[UTF7]

Goldsmith, D. и Davis, M., «UTF-7: Формат преобразования Unicode, безопасный для почты», RFC 2152, май 1997 года.

END_OF_DOCUMENT_MARKER

Константы

ANSWERED

Флаг, указывающий, что сообщение было обработано.

Address

Net::IMAP::Address представляет электронные адреса почты.

Поля:

name

Возвращает фразу из [RFC-822] почтового ящика.

route

Возвращает маршрут из [RFC-822] route-addr.

mailbox

nil указывает конец группы [RFC-822]. Если не nil и host — nil, возвращает имя группы [RFC-822]. В противном случае возвращает локальную часть [RFC-822].

host

nil указывает синтаксис группы [RFC-822]. В противном случае возвращает доменное имя [RFC-822].

ContentDisposition

Net::IMAP::ContentDisposition представляет поля Content-Disposition.

Поля:

dsp_type

Возвращает тип расположения.

param

Возвращает хеш, представляющий параметры поля Content-Disposition.

ContinuationRequest

Net::IMAP::ContinuationRequest представляет запросы продолжения команды.

Ответ на запрос продолжения команды обозначается маркером “+” вместо тега. Эта форма ответа указывает, что сервер готов принять продолжение команды от клиента. Остальная часть этого ответа — строка текста.

continue_req    ::= "+" SPACE (resp_text / base64)

Поля:

data

Возвращает данные (Net::IMAP::ResponseText).

raw_data

Возвращает строку исходных данных.

DATE_MONTH
DELETED

Флаг, указывающий, что сообщение помечено для удаления. Это произойдёт при закрытии или очистке почтового ящика.

DRAFT

Флаг, указывающий, что сообщение является черновиком или промежуточной версией.

Envelope

Net::IMAP::Envelope представляет структуры конвертов сообщений.

Поля:

date

Возвращает строку, представляющую дату.

subject

Возвращает строку, представляющую тему.

from

Возвращает массив Net::IMAP::Address, представляющий отправителя.

sender

Возвращает массив Net::IMAP::Address, представляющий отправителя.

reply_to

Возвращает массив Net::IMAP::Address, представляющий ответ.

to

Возвращает массив Net::IMAP::Address, представляющий получателей.

cc

Возвращает массив Net::IMAP::Address, представляющий список копий.

bcc

Возвращает массив Net::IMAP::Address, представляющий скрытые копии.

in_reply_to

Возвращает строку, представляющую in-reply-to.

message_id

Возвращает строку, представляющую message-id.

FLAGGED

Флаг, указывающий, что сообщение помечено для особого или срочного внимания.

FetchData

Net::IMAP::FetchData представляет содержимое ответа FETCH.

Поля:

seqno

Возвращает порядковый номер сообщения. (Примечание: не уникальный идентификатор, даже для ответа команды UID.)

attr

Возвращает хеш. Каждый ключ — имя элемента данных, а каждое значение — его значение.

Текущие элементы данных:

BODY

Форма BODYSTRUCTURE без расширенных данных.

Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText, Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart.
ENVELOPE

Объект Net::IMAP::Envelope, описывающий структуру конверта сообщения.

FLAGS

Массив символов флагов, установленных для данного сообщения. Символы флагов капитализируются с помощью String#capitalize.

INTERNALDATE

Строка, представляющая внутреннюю дату сообщения.

RFC822

Эквивалентно BODY[].

RFC822.HEADER

Эквивалентно BODY.PEEK.

RFC822.SIZE

Число, выражающее размер сообщения [RFC-822].

RFC822.TEXT

Эквивалентно BODY.

UID

Число, выражающее уникальный идентификатор сообщения.

MARKED

Флаг, указывающий, что почтовый ящик был помечен сервером как «интересный»; это обычно означает, что почтовый ящик содержит новые сообщения.

MailboxACLItem

Net::IMAP::MailboxACLItem представляет ответ от GETACL.

acl_data        ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights)

identifier      ::= astring

rights          ::= astring

Поля:

user

Имя пользователя, имеющее определенные права доступа к почтовому ящику, указанному в команде getacl.

rights

Права доступа указанного пользователя к почтовому ящику.

MailboxList

Net::IMAP::MailboxList представляет содержимое ответа LIST.

mailbox_list    ::= "(" #("\Marked" / "\Noinferiors" /
                    "\Noselect" / "\Unmarked" / flag_extension) ")"
                    SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox

Поля:

attr

Возвращает атрибуты имени. Каждый атрибут имени — символ, приведенный к верхнему регистру с помощью String#capitalize, например :Noselect (а не :NoSelect).

delim

Возвращает разделитель иерархии.

name

Возвращает имя почтового ящика.

MailboxQuota

Net::IMAP::MailboxQuota представляет содержимое ответа GETQUOTA. Этот объект также может быть ответом на GETQUOTAROOT. В синтаксическом определении ниже разделитель, используемый в конструкции «#», — одиночное пробельное пространство (SPACE).

quota_list      ::= "(" #quota_resource ")"

quota_resource  ::= atom SPACE number SPACE number

quota_response  ::= "QUOTA" SPACE astring SPACE quota_list

Поля:

mailbox

Почтовый ящик с соответствующим квотой.

usage

Текущее использование памяти почтового ящика.

quota

Предел квоты, установленный для почтового ящика.

MailboxQuotaRoot

Net::IMAP::MailboxQuotaRoot представляет часть ответа GETQUOTAROOT. (GETQUOTAROOT также может возвращать Net::IMAP::MailboxQuota.)

quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)

Поля:

mailbox

Почтовый ящик с соответствующим квотой.

quotaroots

Ноль или более quotaroots, которые влияют на квоту указанного почтового ящика.

NOINFERIORS

Флаг, указывающий, что имя контекста почтового ящика не может содержать дочерние элементы.

NOSELECT

Флаг, указывающий, что почтовый ящик не выбран.

RECENT

Флаг, указывающий, что сообщение «недавнее», то есть в этом сеансе клиент впервые уведомлен об этом сообщении.

RESPONSE_ERRORS
ResponseCode

Net::IMAP::ResponseCode представляет коды ответов.

resp_text_code  ::= "ALERT" / "PARSE" /
                    "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
                    "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
                    "UIDVALIDITY" SPACE nz_number /
                    "UNSEEN" SPACE nz_number /
                    atom [SPACE 1*<any TEXT_CHAR except "]">]

Поля:

name

Возвращает имя, например «ALERT», «PERMANENTFLAGS» или «UIDVALIDITY».

data

Возвращает данные, если они существуют.

ResponseText

Net::IMAP::ResponseText представляет тексты ответов. Текст может быть префиксным кодом ответа.

resp_text       ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
                    ;; text SHOULD NOT begin with "[" or "="

Поля:

code

Возвращает код ответа. См. ((<Net::IMAP::ResponseCode>)).

text

Возвращает текст.

SEEN

Флаг, указывающий, что сообщение просмотрено.

StatusData

Net::IMAP::StatusData представляет содержимое ответа STATUS.

Поля:

mailbox

Возвращает имя почтового ящика.

attr

Возвращает хеш. Каждый ключ — один из «MESSAGES», «RECENT», «UIDNEXT», «UIDVALIDITY», «UNSEEN». Каждое значение — число.

TaggedResponse

Net::IMAP::TaggedResponse представляет помеченные ответы.

Ответ сервера о результате завершения операции указывает на успех или неудачу операции. Он помечен тем же тегом, что и команда клиента, которая начала операцию.

response_tagged ::= tag SPACE resp_cond_state CRLF

tag             ::= 1*<any ATOM_CHAR except "+">

resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text

Поля:

tag

Возвращает тег.

name

Возвращает имя, одно из «OK», «NO» или «BAD».

data

Возвращает данные. См. ((<Net::IMAP::ResponseText>)).

raw_data

Возвращает строку исходных данных.

ThreadMember

Net::IMAP::ThreadMember представляет узел потока, возвращаемый Net::IMAP#thread.

Поля:

seqno

Порядковый номер этого сообщения.

children

Массив объектов Net::IMAP::ThreadMember для элементов почтовых сообщений, которые являются дочерними элементами этого в потоке.

UNMARKED

Флаг, указывающий, что почтовый ящик не содержит новых сообщений.

UntaggedResponse

Net::IMAP::UntaggedResponse представляет непомеченные ответы.

Data передаются сервером клиенту, а ответы статуса, которые не указывают на завершение команды, имеют префикс «*» и называются непомеченными ответами.

response_data   ::= "*" SPACE (resp_cond_state / resp_cond_bye /
                    mailbox_data / message_data / capability_data)

Поля:

name

Возвращает имя, например «FLAGS», «LIST» или «FETCH».

data

Возвращает данные, такие как массив символов флагов, объект ((<Net::IMAP::MailboxList>)).

raw_data

Возвращает строку исходных данных.

END_OF_DOCUMENT_MARKER

Атрибуты

client_thread[RW]

Поток для обработки исключений.

greeting[R]

Возвращает начальное приветственное сообщение от сервера.

open_timeout[R]

Секунды ожидания открытия соединения. Если объект IMAP не может открыть соединение в течение этого времени, он генерирует исключение Net::OpenTimeout. Значение по умолчанию — 30 секунд.

response_handlers[R]

Возвращает все обработчики ответов.

responses[R]

Возвращает записанные немаркированные ответы. Например:

imap.select("inbox")
p imap.responses["EXISTS"][-1]
#=> 2
p imap.responses["UIDVALIDITY"][-1]
#=> 968263756

Методы публичного класса

add_authenticator(auth_type, authenticator) Показать исходный код
# File lib/net/imap.rb, line 301
def self.add_authenticator(auth_type, authenticator)
  @@authenticators[auth_type] = authenticator
end

Добавляет аутентификатор для Net::IMAP#authenticate. auth_type — тип аутентификации, поддерживаемый этим аутентификатором (например, “LOGIN”). authenticator — объект, определяющий метод process() для обработки аутентификации с сервером. См. Net::IMAP::LoginAuthenticator, Net::IMAP::CramMD5Authenticator и Net::IMAP::DigestMD5Authenticator для примеров.

Если auth_type относится к существующему аутентификатору, он будет заменён новым.

debug() Показать исходный код
# File lib/net/imap.rb, line 271
def self.debug
  return @@debug
end

Возвращает режим отладки.

debug=(val) Показать исходный код
# File lib/net/imap.rb, line 276
def self.debug=(val)
  return @@debug = val
end

Устанавливает режим отладки.

decode_utf7(s) Показать исходный код
# File lib/net/imap.rb, line 999
def self.decode_utf7(s)
  return s.gsub(/&([^-]+)?-/n) {
    if $1
      ($1.tr(",", "/") + "===").unpack1("m").encode(Encoding::UTF_8, Encoding::UTF_16BE)
    else
      "&"
    end
  }
end

Декодирование строки из модифицированного формата UTF-7 в UTF-8.

UTF-7 — это 7-битовое кодирование Unicode [UTF7]. IMAP использует слегка модифицированную версию для кодирования имён почтовых ящиков, содержащих символы, не входящие в ASCII; см. раздел 5.1.3 [IMAP].

Net::IMAP не кодирует и не декодирует имена почтовых ящиков в UTF-7 автоматически.

default_imap_port()
Псевдоним для: default_port
default_imaps_port()
Псевдоним для: default_tls_port
default_port() Показать исходный код
# File lib/net/imap.rb, line 306
def self.default_port
  return PORT
end

Порт по умолчанию для подключений IMAP, порт 143

Также псевдоним: default_imap_port
default_ssl_port()
Псевдоним для: default_tls_port
default_tls_port() Показать исходный код
# File lib/net/imap.rb, line 311
def self.default_tls_port
  return SSL_PORT
end

Порт по умолчанию для подключений IMAPS, порт 993

Также псевдоним: default_imaps_port, default_ssl_port
encode_utf7(s) Показать исходный код
# File lib/net/imap.rb, line 1010
def self.encode_utf7(s)
  return s.gsub(/(&)|[^\x20-\x7e]+/) {
    if $1
      "&-"
    else
      base64 = [$&.encode(Encoding::UTF_16BE)].pack("m0")
      "&" + base64.delete("=").tr("/", ",") + "-"
    end
  }.force_encoding("ASCII-8BIT")
end

Кодирование строки из формата UTF-8 в модифицированный UTF-7.

format_date(time) Показать исходный код
# File lib/net/imap.rb, line 1022
def self.format_date(time)
  return time.strftime('%d-%b-%Y')
end

Форматирование time как даты в формате IMAP.

format_datetime(time) Показать исходный код
# File lib/net/imap.rb, line 1027
def self.format_datetime(time)
  return time.strftime('%d-%b-%Y %H:%M %z')
end

Форматирование time как даты и времени в формате IMAP.

max_flag_count() Показать исходный код
# File lib/net/imap.rb, line 281
def self.max_flag_count
  return @@max_flag_count
end

Возвращает максимальное количество флагов, интернированных в символы.

max_flag_count=(count) Показать исходный код
# File lib/net/imap.rb, line 286
def self.max_flag_count=(count)
  @@max_flag_count = count
end

Устанавливает максимальное количество флагов, интернированных в символы.

Net::IMAP.new(host, options = {}) Показать исходный код
# File lib/net/imap.rb, line 1070
def initialize(host, port_or_options = {},
               usessl = false, certs = nil, verify = true)
  super()
  @host = host
  begin
    options = port_or_options.to_hash
  rescue NoMethodError
    # for backward compatibility
    options = {}
    options[:port] = port_or_options
    if usessl
      options[:ssl] = create_ssl_params(certs, verify)
    end
  end
  @port = options[:port] || (options[:ssl] ? SSL_PORT : PORT)
  @tag_prefix = "RUBY"
  @tagno = 0
  @open_timeout = options[:open_timeout] || 30
  @parser = ResponseParser.new
  @sock = tcp_socket(@host, @port)
  begin
    if options[:ssl]
      start_tls_session(options[:ssl])
      @usessl = true
    else
      @usessl = false
    end
    @responses = Hash.new([].freeze)
    @tagged_responses = {}
    @response_handlers = []
    @tagged_response_arrival = new_cond
    @continued_command_tag = nil
    @continuation_request_arrival = new_cond
    @continuation_request_exception = nil
    @idle_done_cond = nil
    @logout_command_tag = nil
    @debug_output_bol = true
    @exception = nil

    @greeting = get_response
    if @greeting.nil?
      raise Error, "connection closed"
    end
    if @greeting.name == "BYE"
      raise ByeResponseError, @greeting
    end

    @client_thread = Thread.current
    @receiver_thread = Thread.start {
      begin
        receive_responses
      rescue Exception
      end
    }
    @receiver_thread_terminating = false
  rescue Exception
    @sock.close
    raise
  end
end

Создаёт новый объект Net::IMAP и подключает его к указанному host.

options — хеш-таблица опций, ключи которой — символы.

Доступные опции:

port

Номер порта (значение по умолчанию — 143 для imap или 993 для imaps)

ssl

Если options истинно, будет попытка подключения по SSL (теперь TLS) к серверу. Для этого должны быть установлены расширения OpenSSL [OSSL] и Ruby OpenSSL [RSSL]. Если options — хеш, он передаётся в OpenSSL::SSL::SSLContext#set_params в качестве параметров.

open_timeout

Секунды ожидания открытия соединения

Наиболее распространённые ошибки:

Errno::ECONNREFUSED

Подключение отклонено сервером или межсетевым экраном.

Errno::ETIMEDOUT

Подключение истекло (возможно, из-за потери пакетов межсетевым экраном).

Errno::ENETUNREACH

Нет маршрута к сети.

SocketError

Хост неизвестен или ошибка сокета.

Net::IMAP::ByeResponseError

Подключение к хосту выполнено успешно, но он сразу же отключился.

Вызывает метод суперкласса MonitorMixin::new

Методы публичного экземпляра

add_response_handler(handler = Proc.new) Показать исходный код
# File lib/net/imap.rb, line 906
def add_response_handler(handler = Proc.new)
  @response_handlers.push(handler)
end

Добавляет обработчик ответов. Например, чтобы обнаружить, когда сервер отправляет новый ответ EXISTS (который обычно указывает на добавление новых сообщений в почтовый ящик), добавьте следующий обработчик после выбора почтового ящика:

imap.add_response_handler { |resp|
  if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
    puts "Mailbox now has #{resp.data} messages"
  end
}
append(mailbox, message, flags = nil, date_time = nil) Показать исходный код
# File lib/net/imap.rb, line 699
def append(mailbox, message, flags = nil, date_time = nil)
  args = []
  if flags
    args.push(flags)
  end
  args.push(date_time) if date_time
  args.push(Literal.new(message))
  send_command("APPEND", mailbox, *args)
end

Отправляет команду APPEND для добавления message в конец mailbox. Необязательный параметр flags — массив флагов, изначально передаваемых новому сообщению. Необязательный параметр date_time задаёт время создания нового сообщения; по умолчанию используется текущее время. Например:

imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
Subject: hello
From: shugo@ruby-lang.org
To: shugo@ruby-lang.org

hello world
EOF

Исключение Net::IMAP::NoResponseError генерируется, если почтовый ящик не существует (он не создаётся автоматически) или если в аргументах flags, date_time или message содержатся ошибки.

authenticate(auth_type, *args) Показать исходный код
# File lib/net/imap.rb, line 417
def authenticate(auth_type, *args)
  auth_type = auth_type.upcase
  unless @@authenticators.has_key?(auth_type)
    raise ArgumentError,
      format('unknown auth type - "%s"', auth_type)
  end
  authenticator = @@authenticators[auth_type].new(*args)
  send_command("AUTHENTICATE", auth_type) do |resp|
    if resp.instance_of?(ContinuationRequest)
      data = authenticator.process(resp.data.text.unpack("m")[0])
      s = [data].pack("m0")
      send_string_data(s)
      put_string(CRLF)
    end
  end
end

Отправляет команду AUTHENTICATE для аутентификации клиента. Параметр auth_type — строка, представляющая используемый механизм аутентификации. В настоящее время Net::IMAP поддерживает следующие механизмы аутентификации:

LOGIN:: login using cleartext user and password.
CRAM-MD5:: login with cleartext user and encrypted password
           (see [RFC-2195] for a full description).  This
           mechanism requires that the server have the user's
           password stored in clear-text password.

Для обоих механизмов требуется два параметра: имя пользователя и (в открытом виде) пароль. Сервер может не поддерживать один или другой из этих механизмов; проверьте capability() на наличие возможности вида “AUTH=LOGIN” или “AUTH=CRAM-MD5”.

Аутентификация выполняется с помощью соответствующего объекта аутентификатора: см. @@authenticators для получения дополнительной информации о подключении собственного аутентификатора.

Например:

imap.authenticate('LOGIN', user, password)

Исключение Net::IMAP::NoResponseError генерируется, если аутентификация не удалась.

capability() Показать исходный код
# File lib/net/imap.rb, line 359
def capability
  synchronize do
    send_command("CAPABILITY")
    return @responses.delete("CAPABILITY")[-1]
  end
end

Отправляет команду CAPABILITY и возвращает массив поддерживаемых сервером возможностей. Каждая возможность — строка. См. [IMAP] для списка возможных возможностей.

Обратите внимание, что класс Net::IMAP не изменяет своего поведения в зависимости от возможностей сервера; пользователю класса необходимо убедиться, что определённая возможность поддерживается сервером перед её использованием.

check() Показать исходный код
# File lib/net/imap.rb, line 713
def check
  send_command("CHECK")
end

Отправляет команду CHECK для запроса контрольной точки текущего выбранного почтового ящика. Это выполняет специфичные для реализации задачи по уходу; например, согласование состояния почтового ящика в памяти и на диске.

close() Показать исходный код
# File lib/net/imap.rb, line 720
def close
  send_command("CLOSE")
end

Отправляет команду CLOSE для закрытия текущего выбранного почтового ящика. Команда CLOSE постоянно удаляет из почтового ящика все сообщения, у которых установлен флаг Удалено.

getquotaroot(mailbox) Показать исходный код
# File lib/net/imap.rb, line 589
def getquotaroot(mailbox)
  synchronize do
    send_command("GETQUOTAROOT", mailbox)
    result = []
    result.concat(@responses.delete("QUOTAROOT"))
    result.concat(@responses.delete("QUOTA"))
    return result
  end
end

Отправляет команду GETQUOTAROOT вместе с указанным mailbox. Эта команда, как правило, доступна как администраторам, так и пользователям. Если почтовый ящик существует, возвращает массив, содержащий объекты типа Net::IMAP::MailboxQuotaRoot и Net::IMAP::MailboxQuota.

idle(timeout = nil, &response_handler) Показать исходный код
# File lib/net/imap.rb, line 952
def idle(timeout = nil, &response_handler)
  raise LocalJumpError, "no block given" unless response_handler

  response = nil

  synchronize do
    tag = Thread.current[:net_imap_tag] = generate_tag
    put_string("#{tag} IDLE#{CRLF}")

    begin
      add_response_handler(response_handler)
      @idle_done_cond = new_cond
      @idle_done_cond.wait(timeout)
      @idle_done_cond = nil
      if @receiver_thread_terminating
        raise @exception || Net::IMAP::Error.new("connection closed")
      end
    ensure
      unless @receiver_thread_terminating
        remove_response_handler(response_handler)
        put_string("DONE#{CRLF}")
        response = get_tagged_response(tag, "IDLE")
      end
    end
  end

  return response
end

Отправляет команду IDLE, которая ожидает уведомлений о новых или удалённых сообщениях. Выводит ответы сервера во время IDLE.

Используйте idle_done(), чтобы выйти из режима IDLE.

Если timeout задано, этот метод возвращает значение после того, как пройдёт timeout секунд. timeout может использоваться для поддержания соединения. Например, следующий код проверяет соединение каждые 60 секунд.

loop do
  imap.idle(60) do |res|
    ...
  end
end
idle_done() Показать исходный код
# File lib/net/imap.rb, line 982
def idle_done
  synchronize do
    if @idle_done_cond.nil?
      raise Net::IMAP::Error, "not during IDLE"
    end
    @idle_done_cond.signal
  end
end

Выходит из режима IDLE.

list(refname, mailbox) Показать исходный код
# File lib/net/imap.rb, line 546
def list(refname, mailbox)
  synchronize do
    send_command("LIST", refname, mailbox)
    return @responses.delete("LIST")
  end
end

Отправляет команду LIST и возвращает подмножество имён из полного набора всех имён, доступных клиенту. refname предоставляет контекст (например, базовый каталог в иерархии почтовых ящиков на основе каталогов). mailbox указывает почтовый ящик или (с помощью подстановочных символов) почтовые ящики в этом контексте. В mailbox могут использоваться два подстановочных знака: «*», который соответствует всем символам, **включая** разделитель иерархии (например, «/» в иерархии почтовых ящиков на основе каталогов на сервере Unix); и «%», который соответствует всем символам, **кроме** разделителя иерархии.

Если refname пусто, mailbox используется напрямую для определения, какие почтовые ящики подходят. Если mailbox пусто, возвращается корневое имя refname и разделитель иерархии.

Возвращаемое значение — массив Net::IMAP::MailboxList. Например:

imap.create("foo/bar")
imap.create("foo/baz")
p imap.list("", "foo/%")
#=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
     #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
     #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
login(user, password) Показать исходный код
# File lib/net/imap.rb, line 440
def login(user, password)
  send_command("LOGIN", user, password)
end

Отправляет команду LOGIN для идентификации клиента и содержит текстовое password для аутентификации этого user. Обратите внимание, что в отличие от вызова authenticate() с auth_type «LOGIN», login() **не** использует аутентификатор входа.

Если аутентификация завершится неудачей, возникает ошибка Net::IMAP::NoResponseError.

logout() Показать исходный код
# File lib/net/imap.rb, line 373
def logout
  send_command("LOGOUT")
end

Отправляет команду LOGOUT, чтобы сообщить серверу, что клиент завершил работу с соединением.

lsub(refname, mailbox) Показать исходный код
# File lib/net/imap.rb, line 651
def lsub(refname, mailbox)
  synchronize do
    send_command("LSUB", refname, mailbox)
    return @responses.delete("LSUB")
  end
end

Отправляет команду LSUB и возвращает подмножество имён из набора имён, которые пользователь объявил «активными» или «подписанными». refname и mailbox интерпретируются так же, как для list(). Возвращаемое значение — массив Net::IMAP::MailboxList.

move(set, mailbox) Показать исходный код
# File lib/net/imap.rb, line 867
def move(set, mailbox)
  copy_internal("MOVE", set, mailbox)
end

Отправляет команду MOVE для перемещения указанных сообщений в конец указанного целевого mailbox. Параметр set — число, массив чисел или объект Range. Число — порядковый номер сообщения. Расширение MOVE протокола IMAP описано в [RFC-6851].

noop() Показать исходный код
# File lib/net/imap.rb, line 367
def noop
  send_command("NOOP")
end

Отправляет команду NOOP на сервер. Она ничего не делает.

remove_response_handler(handler) Показать исходный код
# File lib/net/imap.rb, line 911
def remove_response_handler(handler)
  @response_handlers.delete(handler)
end

Удаляет обработчик ответов.

rename(mailbox, newname) Показать исходный код
# File lib/net/imap.rb, line 500
def rename(mailbox, newname)
  send_command("RENAME", mailbox, newname)
end

Отправляет команду RENAME для изменения имени mailbox на newname.

Ошибка Net::IMAP::NoResponseError возникает, если почтовый ящик с именем mailbox не может быть переименован в newname по какой-либо причине; например, потому что mailbox не существует или потому, что уже существует почтовый ящик с именем newname.

search(keys, charset = nil) Показать исходный код
# File lib/net/imap.rb, line 773
def search(keys, charset = nil)
  return search_internal("SEARCH", keys, charset)
end

Отправляет команду SEARCH для поиска сообщений в почтовом ящике, которые соответствуют заданным критериям поиска, и возвращает порядковые номера сообщений. keys может быть либо строкой, содержащей всю строку поиска, либо одномерным массивом поисковых ключевых слов и аргументов. Ниже приведены некоторые распространённые критерии поиска; полный список см. в разделе [IMAP] 6.4.4.

<набор сообщений>

набор порядковых номеров сообщений. «,» обозначает интервал, «:» обозначает диапазон. Например, «2,10:12,15» означает «2,10,11,12,15».

BEFORE <дата>

сообщения с внутренней датой строго до <дата>. Аргумент даты имеет формат, аналогичный 8-авг-2002.

BODY <строка>

сообщения, содержащие <строка> в своём теле.

CC <строка>

сообщения, содержащие <строка> в поле CC.

FROM <строка>

сообщения, содержащие <строка> в поле FROM.

NEW

сообщения со флагом Recent, но не флагом Seen.

NOT <ключ-поиска>

отменить следующий ключ поиска.

OR <ключ-поиска> <ключ-поиска>

соединить два ключа поиска по принципу «или».

ON <дата>

сообщения с внутренней датой, точно равной <дата>, которая имеет формат, аналогичный 8-авг-2002.

SINCE <дата>

сообщения с внутренней датой на или после <дата>.

SUBJECT <строка>

сообщения с <строка> в теме.

TO <строка>

сообщения с <строка> в поле TO.

Например:

p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
#=> [1, 6, 7, 8]
select(mailbox) Показать исходный код
# File lib/net/imap.rb, line 456
def select(mailbox)
  synchronize do
    @responses.clear
    send_command("SELECT", mailbox)
  end
end

Отправляет команду SELECT для выбора mailbox, чтобы можно было получить доступ к сообщениям в этом mailbox.

После выбора почтового ящика вы можете получить количество элементов в этом почтовом ящике из @responses[-1] и количество последних сообщений из @responses[-1]. Обратите внимание, что эти значения могут измениться, если во время сессии придут новые сообщения; см. add_response_handler() для способа обнаружения этого события.

Если почтовый ящик не существует или по какой-либо причине недоступен для выбора, возникает ошибка Net::IMAP::NoResponseError.

setacl(mailbox, user, rights) Показать исходный код
# File lib/net/imap.rb, line 628
def setacl(mailbox, user, rights)
  if rights.nil?
    send_command("SETACL", mailbox, user, "")
  else
    send_command("SETACL", mailbox, user, rights)
  end
end

Отправляет команду SETACL вместе с mailbox, user и rights для пользователя в данном почтовом ящике. Если rights равно nil, права этого пользователя для данного почтового ящика будут удалены. Команды IMAP ACL описаны в [RFC-2086].

END_OF_DOCUMENT_MARKER
setquota(mailbox, quota) Показать исходный код
# File lib/net/imap.rb, line 615
def setquota(mailbox, quota)
  if quota.nil?
    data = '()'
  else
    data = '(STORAGE ' + quota.to_s + ')'
  end
  send_command("SETQUOTA", mailbox, RawData.new(data))
end

Отправляет команду SETQUOTA вместе с указанными mailbox и quota. Если quota равно nil, то quota будет снято для этой почтовой папки. Обычно для этого требуется вход под учетной записью администратора сервера. Команды квоты IMAP описаны в [RFC-2087].

sort(sort_keys, search_keys, charset) Показать исходный код
# File lib/net/imap.rb, line 885
def sort(sort_keys, search_keys, charset)
  return sort_internal("SORT", sort_keys, search_keys, charset)
end

Отправляет команду SORT для сортировки сообщений в почтовой папке. Возвращает массив номеров последовательности сообщений. Например:

p imap.sort(["FROM"], ["ALL"], "US-ASCII")
#=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
#=> [6, 7, 8, 1]

Дополнительные сведения см. в [SORT-THREAD-EXT].

starttls(options = {}, verify = true) Показать исходный код
# File lib/net/imap.rb, line 378
def starttls(options = {}, verify = true)
  send_command("STARTTLS") do |resp|
    if resp.kind_of?(TaggedResponse) && resp.name == "OK"
      begin
        # for backward compatibility
        certs = options.to_str
        options = create_ssl_params(certs, verify)
      rescue NoMethodError
      end
      start_tls_session(options)
    end
  end
end

Отправляет команду STARTTLS для начала TLS-сессии.

status(mailbox, attr) Показать исходный код
# File lib/net/imap.rb, line 674
def status(mailbox, attr)
  synchronize do
    send_command("STATUS", mailbox, attr)
    return @responses.delete("STATUS")[-1].attr
  end
end

Отправляет команду STATUS и возвращает состояние указанной mailbox. attr — список одной или нескольких характеристик, статус которых необходимо запросить. Поддерживаемые характеристики включают:

MESSAGES:: the number of messages in the mailbox.
RECENT:: the number of recent messages in the mailbox.
UNSEEN:: the number of unseen messages in the mailbox.

Возвращаемое значение — хеш характеристик. Например:

p imap.status("inbox", ["MESSAGES", "RECENT"])
#=> {"RECENT"=>0, "MESSAGES"=>44}

Исключение Net::IMAP::NoResponseError генерируется, если значения статуса для mailbox не могут быть возвращены; например, потому что они не существуют.

store(set, attr, flags) Показать исходный код
# File lib/net/imap.rb, line 840
def store(set, attr, flags)
  return store_internal("STORE", set, attr, flags)
end

Отправляет команду STORE для изменения данных, связанных с сообщениями в почтовой папке, в частности, их флагов. Параметр set — число, массив чисел или объект Range. Каждое число — номер последовательности сообщения. attr — имя элемента данных для сохранения: 'FLAGS' заменит список флагов сообщения предоставленным, '+FLAGS' добавит предоставленные флаги, а '-FLAGS' удалит их. flags — список флагов.

Возвращаемое значение — массив Net::IMAP::FetchData. Например:

p imap.store(6..8, "+FLAGS", [:Deleted])
#=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
     #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
     #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
subscribe(mailbox) Показать исходный код
# File lib/net/imap.rb, line 510
def subscribe(mailbox)
  send_command("SUBSCRIBE", mailbox)
end

Отправляет команду SUBSCRIBE для добавления указанного mailbox имени в набор «активных» или «подписанных» почтовых папок сервера, возвращаемых функцией lsub().

Исключение Net::IMAP::NoResponseError генерируется, если к mailbox невозможно подключиться; например, потому что оно не существует.

thread(algorithm, search_keys, charset) Показать исходный код
# File lib/net/imap.rb, line 928
def thread(algorithm, search_keys, charset)
  return thread_internal("THREAD", algorithm, search_keys, charset)
end

Аналогично search(), но возвращает номера последовательности сообщений в формате потоков в виде дерева Net::IMAP::ThreadMember. Поддерживаемые алгоритмы:

ORDEREDSUBJECT

разбивает на потоки по одному уровню в соответствии с темой, отсортированные по дате.

REFERENCES

разбивает на потоки по отношениям родитель/дочерний, определяющим, какое сообщение является ответом на какое.

В отличие от search(), charset является обязательным аргументом. Примеры значений — US-ASCII и UTF-8.

Дополнительные сведения см. в [SORT-THREAD-EXT].

END_OF_DOCUMENT_MARKER

Методы частного экземпляра

copy_internal(cmd, set, mailbox) Показать исходный код
# File lib/net/imap.rb, line 1458
def copy_internal(cmd, set, mailbox)
  send_command(cmd, MessageSet.new(set), mailbox)
end
create_ssl_params(certs = nil, verify = true) Показать исходный код
# File lib/net/imap.rb, line 1497
def create_ssl_params(certs = nil, verify = true)
  params = {}
  if certs
    if File.file?(certs)
      params[:ca_file] = certs
    elsif File.directory?(certs)
      params[:ca_path] = certs
    end
  end
  if verify
    params[:verify_mode] = VERIFY_PEER
  else
    params[:verify_mode] = VERIFY_NONE
  end
  return params
end
fetch_internal(cmd, set, attr, mod = nil) Показать исходный код
# File lib/net/imap.rb, line 1426
def fetch_internal(cmd, set, attr, mod = nil)
  case attr
  when String then
    attr = RawData.new(attr)
  when Array then
    attr = attr.map { |arg|
      arg.is_a?(String) ? RawData.new(arg) : arg
    }
  end

  synchronize do
    @responses.delete("FETCH")
    if mod
      send_command(cmd, MessageSet.new(set), attr, mod)
    else
      send_command(cmd, MessageSet.new(set), attr)
    end
    return @responses.delete("FETCH")
  end
end
generate_tag() Показать исходный код
# File lib/net/imap.rb, line 1282
def generate_tag
  @tagno += 1
  return format("%s%04d", @tag_prefix, @tagno)
end
get_response() Показать исходный код
# File lib/net/imap.rb, line 1227
def get_response
  buff = String.new
  while true
    s = @sock.gets(CRLF)
    break unless s
    buff.concat(s)
    if /\{(\d+)\}\r\n/n =~ s
      s = @sock.read($1.to_i)
      buff.concat(s)
    else
      break
    end
  end
  return nil if buff.length == 0
  if @@debug
    $stderr.print(buff.gsub(/^/n, "S: "))
  end
  return @parser.parse(buff)
end
get_tagged_response(tag, cmd) Показать исходный код
# File lib/net/imap.rb, line 1211
def get_tagged_response(tag, cmd)
  until @tagged_responses.key?(tag)
    raise @exception if @exception
    @tagged_response_arrival.wait
  end
  resp = @tagged_responses.delete(tag)
  case resp.name
  when /\A(?:NO)\z/ni
    raise NoResponseError, resp
  when /\A(?:BAD)\z/ni
    raise BadResponseError, resp
  else
    return resp
  end
end
normalize_searching_criteria(keys) Показать исходный код
# File lib/net/imap.rb, line 1486
def normalize_searching_criteria(keys)
  keys.collect! do |i|
    case i
    when -1, Range, Array
      MessageSet.new(i)
    else
      i
    end
  end
end
put_string(str) Показать исходный код
# File lib/net/imap.rb, line 1287
def put_string(str)
  @sock.print(str)
  if @@debug
    if @debug_output_bol
      $stderr.print("C: ")
    end
    $stderr.print(str.gsub(/\n(?!\z)/n, "\nC: "))
    if /\r\n\z/n.match(str)
      @debug_output_bol = true
    else
      @debug_output_bol = false
    end
  end
end
receive_responses() Показать исходный код
# File lib/net/imap.rb, line 1140
def receive_responses
  connection_closed = false
  until connection_closed
    synchronize do
      @exception = nil
    end
    begin
      resp = get_response
    rescue Exception => e
      synchronize do
        @sock.close
        @exception = e
      end
      break
    end
    unless resp
      synchronize do
        @exception = EOFError.new("end of file reached")
      end
      break
    end
    begin
      synchronize do
        case resp
        when TaggedResponse
          @tagged_responses[resp.tag] = resp
          @tagged_response_arrival.broadcast
          case resp.tag
          when @logout_command_tag
            return
          when @continued_command_tag
            @continuation_request_exception =
              RESPONSE_ERRORS[resp.name].new(resp)
            @continuation_request_arrival.signal
          end
        when UntaggedResponse
          record_response(resp.name, resp.data)
          if resp.data.instance_of?(ResponseText) &&
              (code = resp.data.code)
            record_response(code.name, code.data)
          end
          if resp.name == "BYE" && @logout_command_tag.nil?
            @sock.close
            @exception = ByeResponseError.new(resp)
            connection_closed = true
          end
        when ContinuationRequest
          @continuation_request_arrival.signal
        end
        @response_handlers.each do |handler|
          handler.call(resp)
        end
      end
    rescue Exception => e
      @exception = e
      synchronize do
        @tagged_response_arrival.broadcast
        @continuation_request_arrival.broadcast
      end
    end
  end
  synchronize do
    @receiver_thread_terminating = true
    @tagged_response_arrival.broadcast
    @continuation_request_arrival.broadcast
    if @idle_done_cond
      @idle_done_cond.signal
    end
  end
end

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API