класс Net::IMAP
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
Поток Безопасности
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 без предварительного выбора текущего почтового ящика SELECT. Это также может указывать на внутреннюю ошибку сервера (например, сбой диска).
- BYE
-
Сервер прощается. Это может быть частью обычной последовательности выхода, и может использоваться в процессе входа для указания того, что сервер (по какой-либо причине) не хочет принять ваше подключение. В ответ на любую другую команду это указывает на то, что сервер завершает работу или что сервер приостанавливает подключение клиента из-за бездействия.
Эти три ответа об ошибке представлены ошибками Net::IMAP::NoResponseError, Net::IMAP::BadResponseError и Net::IMAP::ByeResponseError, все из которых являются подклассами Net::IMAP::ResponseError. По существу, все методы, связанные с отправкой запроса на сервер, могут генерировать одну из этих ошибок. Только наиболее существенные случаи были задокументированы ниже.
Так как класс IMAP использует сокеты для связи, его методы также подвержены различным ошибкам, которые могут возникнуть при работе с сокетами. Обычно они представлены как ошибки Errno. Например, любой метод, связанный с отправкой запроса на сервер и/или получением ответа от него, может вызвать ошибку Errno::EPIPE, если сетевое соединение неожиданно прервалось. См. страницы руководств socket(7), ip(7), tcp(7), socket(2), connect(2) и связанные с ними.
Наконец, Net::IMAP::DataFormatError генерируется, если обнаружено, что низкоуровневые данные имеют неправильный формат (например, при преобразовании между UTF-8 и UTF-16), а Net::IMAP::ResponseParseError генерируется, если ответ сервера не может быть распарсен.
Ссылки
- [IMAP]
-
-
Криспин, «ПРОТОКОЛ ДОСТУПА К СООБЩЕНИЯМ INTERNET - ВЕРСИЯ 4rev1»,
RFC 2060, декабрь 1996 г. (Примечание: устарел RFC 3501)
-
- [LANGUAGE-TAGS]
-
Альвестранд, Х., «Теги для идентификации языков», RFC 1766, март 1995 г.
- [MD5]
-
Майерс, Дж., и М. Роз, «Поле заголовка Content-MD5», RFC 1864, октябрь 1995 г.
- [MIME-IMB]
-
Фрид, Н., и Н. Бореnstein, «MIME (Многоцелевые расширения электронной почты Интернет) Часть первая: Формат сообщений электронной почты Интернет», RFC 2045, ноябрь 1996 г.
- [RFC-822]
-
Крокер, Д., «Стандарт для формата текстовых сообщений ARPA Интернет», STD 11, RFC 822, Университет Делавэр, август 1982 г.
- [RFC-2087]
-
Майерс, Дж., «Расширение IMAP4 QUOTA», RFC 2087, январь 1997 г.
- [RFC-2086]
-
Майерс, Дж., «Расширение IMAP4 ACL», RFC 2086, январь 1997 г.
- [RFC-2195]
-
Кленсин, Дж., Кэто, Р., и Крумвиде, П., «Расширение IMAP/POP AUTHorize для простого запроса/ответа», RFC 2195, сентябрь 1997 г.
- [SORT-THREAD-EXT]
-
Криспин, М., «INTERNET MESSAGE ACCESS PROTOCOL - Расширения SORT и THREAD», draft-ietf-imapext-sort, май 2003 г.
- [OSSL]
- [RSSL]
- [UTF7]
-
Голдсмит, Д., и Дэвис, М., «UTF-7: Формат преобразования Unicode, безопасный для почты», RFC 2152, май 1997 г.
Константы
- 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
-
Число, выражающее уникальный идентификатор сообщения.
Флаг, указывающий, что почтовый ящик помечен сервером как «интересный»; это обычно означает, что почтовый ящик содержит новые сообщения.
Net::IMAP::MailboxACLItem представляет ответ от GETACL.
acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights) identifier ::= astring rights ::= astring
Поля:
- user
-
Имя пользователя, имеющее определенные права на указанный почтовый ящик.
- rights
-
Права доступа указанного пользователя к почтовому ящику.
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
-
Возвращает имя почтового ящика.
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
-
Лимит квоты, установленный для почтового ящика.
Net::IMAP::MailboxQuotaRoot представляет часть ответа GETQUOTAROOT. (GETQUOTAROOT также может возвращать Net::IMAP::MailboxQuota.)
quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)
Поля:
- mailbox
-
Почтовый ящик с ассоциированным лимитом.
- quotaroots
-
Ноль или более quotaroots, которые влияют на лимит квоты для указанного почтового ящика.
Флаг, указывающий, что имя контекста почтового ящика не может содержать дочерние элементы.
Флаг, указывающий, что почтовый ящик не выбран.
Флаг, указывающий, что сообщение «новое», что означает, что данный сеанс является первым сеансом, в котором клиент получил уведомление об этом сообщении.
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
-
Возвращает данные, если они существуют.
Net::IMAP::ResponseText представляет тексты ответов. Текст может быть префиксами кодом ответа.
resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
;; text SHOULD NOT begin with "[" or "=" Поля:
- code
-
Возвращает код ответа. См. ((<Net::IMAP::ResponseCode>)).
- text
-
Возвращает текст.
Флаг, указывающий, что сообщение было просмотрено.
Net::IMAP::StatusData представляет содержимое ответа STATUS.
Поля:
- mailbox
-
Возвращает имя почтового ящика.
- attr
-
Возвращает хеш. Каждый ключ — один из «MESSAGES», «RECENT», «UIDNEXT», «UIDVALIDITY», «UNSEEN». Каждое значение — число.
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
-
Возвращает строку исходных данных.
Net::IMAP::ThreadMember представляет узел потока, возвращаемый #thread.
Поля:
- seqno
-
Порядковый номер этого сообщения.
- children
-
Массив объектов Net::IMAP::ThreadMember для почтовых элементов, которые являются дочерними для этого в потоке.
Флаг, указывающий, что почтовый ящик не содержит новых сообщений.
Net::IMAP::UntaggedResponse представляет ответы без тегов.
Данные, передаваемые сервером клиенту, и ответы статуса, которые не указывают на завершение команды, предваряются маркером «*» и называются ответами без тегов.
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
-
Возвращает строку исходных данных.
Атрибуты
Поток для получения исключений.
Возвращает начальный приветственный ответ от сервера.
Возвращает все обработчики ответов.
Возвращает записанные незамеченные ответы. Например:
imap.select("inbox")
p imap.responses["EXISTS"][-1]
#=> 2
p imap.responses["UIDVALIDITY"][-1]
#=> 968263756
Методы публичного класса
# File lib/net/imap.rb, line 294 def self.add_authenticator(auth_type, authenticator) @@authenticators[auth_type] = authenticator end
Добавляет аутентификатор для #authenticate. auth_type — тип аутентификации, поддерживаемый этим аутентификатором (например, “LOGIN”). authenticator — объект, определяющий метод process() для обработки аутентификации с сервером. См. Net::IMAP::LoginAuthenticator, Net::IMAP::CramMD5Authenticator и Net::IMAP::DigestMD5Authenticator для примеров.
Если auth_type ссылается на существующий аутентификатор, он будет заменён новым.
# File lib/net/imap.rb, line 264 def self.debug return @@debug end
Возвращает режим отладки.
# File lib/net/imap.rb, line 269 def self.debug=(val) return @@debug = val end
Устанавливает режим отладки.
# File lib/net/imap.rb, line 969
def self.decode_utf7(s)
return s.gsub(/&([^-]+)?-/n) {
if $1
($1.tr(",", "/") + "===").unpack("m")[0].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.
# File lib/net/imap.rb, line 299 def self.default_port return PORT end
Порт по умолчанию для подключений IMAP, порт 143
# File lib/net/imap.rb, line 304 def self.default_tls_port return SSL_PORT end
Порт по умолчанию для подключений IMAPS, порт 993
# File lib/net/imap.rb, line 980
def self.encode_utf7(s)
return s.gsub(/(&)|[^\x20-\x7e]+/) {
if $1
"&-"
else
base64 = [$&.encode(Encoding::UTF_16BE)].pack("m")
"&" + base64.delete("=\n").tr("/", ",") + "-"
end
}.force_encoding("ASCII-8BIT")
end Кодирует строку из формата UTF-8 в модифицированный UTF-7.
# File lib/net/imap.rb, line 992
def self.format_date(time)
return time.strftime('%d-%b-%Y')
end Форматирует time как дату в стиле IMAP.
# File lib/net/imap.rb, line 997
def self.format_datetime(time)
return time.strftime('%d-%b-%Y %H:%M %z')
end Форматирует time как дату-время в стиле IMAP.
# File lib/net/imap.rb, line 274 def self.max_flag_count return @@max_flag_count end
Возвращает максимальное количество флагов, интернированных в символы.
# File lib/net/imap.rb, line 279 def self.max_flag_count=(count) @@max_flag_count = count end
Устанавливает максимальное количество флагов, интернированных в символы.
# File lib/net/imap.rb, line 1039
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
@parser = ResponseParser.new
@sock = TCPSocket.open(@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
@continuation_request_arrival = new_cond
@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 в качестве параметров.
Самые распространённые ошибки:
- Errno::ECONNREFUSED
-
Подключение отклонено
hostили промежуточным фаерволом. - Errno::ETIMEDOUT
-
Подключение истекло (возможно, из-за потери пакетов промежуточным фаерволом).
- Errno::ENETUNREACH
-
Маршрут к этой сети отсутствует.
- SocketError
-
Имя хоста не найдено или другая ошибка сокета.
- Net::IMAP::ByeResponseError
-
Подключение к хосту было успешным, но он сразу же сказал «до свидания».
Открытые методы экземпляра
# File lib/net/imap.rb, line 886 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
}
# File lib/net/imap.rb, line 693
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", "Subject: hello
From: shugo@ruby-lang.org
To: shugo@ruby-lang.org
hello world
".gsub(/\n/, "\r\n"), [:Seen], Time.now)
Возникает исключение Net::IMAP::NoResponseError, если почтовый ящик не существует (он не создается автоматически) или если аргументы flags, date_time или message содержат ошибки.
# File lib/net/imap.rb, line 411
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("m").gsub(/\n/, "")
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. Для обоих этих механизмов должно быть два args: имя пользователя и (открытый) пароль. Сервер может не поддерживать один или другой из этих механизмов; проверьте capability() для возможности в форме «AUTH=LOGIN» или «AUTH=CRAM-MD5».
Аутентификация выполняется с использованием соответствующего объекта аутентификатора: см. @@authenticators для получения дополнительной информации о подключении собственного аутентификатора.
Например:
imap.authenticate('LOGIN', user, password)
Возникает исключение Net::IMAP::NoResponseError, если аутентификация завершается неудачей.
# File lib/net/imap.rb, line 353
def capability
synchronize do
send_command("CAPABILITY")
return @responses.delete("CAPABILITY")[-1]
end
end Отправляет команду CAPABILITY и возвращает массив возможностей, поддерживаемых сервером. Каждая возможность — это строка. См. [IMAP] для списка возможных возможностей.
Обратите внимание, что класс Net::IMAP не изменяет свое поведение в соответствии с возможностями сервера; пользователь класса должен убедиться, что определенная возможность поддерживается сервером, прежде чем использовать ее.
# File lib/net/imap.rb, line 707
def check
send_command("CHECK")
end Отправляет команду CHECK для запроса контрольной точки текущего выбранного почтового ящика. Это выполняет специфичные для реализации действия по обслуживанию; например, согласование состояния почтового ящика в памяти и на диске.
# File lib/net/imap.rb, line 714
def close
send_command("CLOSE")
end Отправляет команду CLOSE для закрытия текущего выбранного почтового ящика. Команда CLOSE окончательно удаляет из почтового ящика все сообщения, у которых установлен флаг Deleted.
# File lib/net/imap.rb, line 847
def copy(set, mailbox)
copy_internal("COPY", set, mailbox)
end Отправляет команду COPY для копирования указанного сообщения (сообщений) в конец указанного почтового ящика назначения mailbox. Параметр set — это число, массив чисел или объект Range. Число — это номер последовательности сообщений.
# File lib/net/imap.rb, line 474
def create(mailbox)
send_command("CREATE", mailbox)
end Отправляет команду CREATE для создания нового mailbox.
Возникает исключение Net::IMAP::NoResponseError, если почтовый ящик с таким именем не может быть создан.
# File lib/net/imap.rb, line 483
def delete(mailbox)
send_command("DELETE", mailbox)
end Отправляет команду DELETE для удаления mailbox.
Возникает исключение Net::IMAP::NoResponseError, если почтовый ящик с таким именем не может быть удален, либо потому что он не существует, либо потому что клиент не имеет разрешения на его удаление.
# File lib/net/imap.rb, line 315
def disconnect
begin
begin
# try to call SSL::SSLSocket#io.
@sock.io.shutdown
rescue NoMethodError
# @sock is not an SSL::SSLSocket.
@sock.shutdown
end
rescue Errno::ENOTCONN
# ignore `Errno::ENOTCONN: Socket is not connected' on some platforms.
rescue Exception => e
@receiver_thread.raise(e)
end
@receiver_thread.join
synchronize do
unless @sock.closed?
@sock.close
end
end
raise e if e
end Отключается от сервера.
# File lib/net/imap.rb, line 339 def disconnected? return @sock.closed? end
Возвращает true, если отключено от сервера.
# File lib/net/imap.rb, line 463
def examine(mailbox)
synchronize do
@responses.clear
send_command("EXAMINE", mailbox)
end
end Отправляет команду EXAMINE для выбора mailbox, чтобы можно было получить доступ к сообщениям в mailbox. Ведет себя так же, как select(), за исключением того, что выбранный mailbox определяется как доступный только для чтения.
Возникает исключение Net::IMAP::NoResponseError, если почтовый ящик не существует или по какой-либо причине недоступен для проверки.
# File lib/net/imap.rb, line 720
def expunge
synchronize do
send_command("EXPUNGE")
return @responses.delete("EXPUNGE")
end
end Отправляет команду EXPUNGE для окончательного удаления из текущего выбранного почтового ящика всех сообщений, у которых установлен флаг Deleted.
# File lib/net/imap.rb, line 811
def fetch(set, attr)
return fetch_internal("FETCH", set, attr)
end Отправляет команду FETCH для получения данных, связанных с сообщением в почтовом ящике.
Параметр set — это число или диапазон между двумя числами или массив таких значений. Число — это номер последовательности сообщений, где -1 представляет '*' для использования в обозначении диапазона, например, 100..-1 интерпретируется как '100:*'. Имейте в виду, что свойство exclude_end? объекта Range игнорируется, и содержимое диапазона не зависит от порядка конечных точек диапазона в соответствии со спецификацией протокола, поэтому 1…5, 5..1 и 5…1 эквивалентны 1..5.
attr — это список атрибутов для извлечения; см. документацию для Net::IMAP::FetchData для списка допустимых атрибутов.
Возвращаемое значение — это массив Net::IMAP::FetchData или nil (вместо пустого массива), если нет совпадающих сообщений.
Например:
p imap.fetch(6..8, "UID")
#=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
#<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, \\
#<Net::IMAP::FetchData seqno=8, attr={"UID"=>100}>]
p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]")
#=> [#<Net::IMAP::FetchData seqno=6, attr={"BODY[HEADER.FIELDS (SUBJECT)]"=>"Subject: test\r\n\r\n"}>]
data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0]
p data.seqno
#=> 6
p data.attr["RFC822.SIZE"]
#=> 611
p data.attr["INTERNALDATE"]
#=> "12-Oct-2000 22:40:59 +0900"
p data.attr["UID"]
#=> 98
# File lib/net/imap.rb, line 633
def getacl(mailbox)
synchronize do
send_command("GETACL", mailbox)
return @responses.delete("ACL")[-1]
end
end Отправляет команду GETACL вместе с указанным mailbox. Если этот почтовый ящик существует, возвращается массив, содержащий объекты Net::IMAP::MailboxACLItem.
# File lib/net/imap.rb, line 597
def getquota(mailbox)
synchronize do
send_command("GETQUOTA", mailbox)
return @responses.delete("QUOTA")
end
end Отправляет команду GETQUOTA вместе с указанным mailbox. Если этот почтовый ящик существует, возвращается массив, содержащий объект Net::IMAP::MailboxQuota. Эта команда обычно доступна только администратору сервера.
# File lib/net/imap.rb, line 583
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.
# File lib/net/imap.rb, line 922
def idle(&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
@idle_done_cond = nil
if @receiver_thread_terminating
raise Net::IMAP::Error, "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.
# File lib/net/imap.rb, line 952
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.
# File lib/net/imap.rb, line 540
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">]
# File lib/net/imap.rb, line 434
def login(user, password)
send_command("LOGIN", user, password)
end Отправляет команду LOGIN для идентификации клиента и передаёт нешифрованный password для аутентификации этого user. Обратите внимание, что в отличие от вызова authenticate() с auth_type «LOGIN», login() не использует аутентификатор входа.
Возникает исключение Net::IMAP::NoResponseError, если аутентификация не удалась.
# File lib/net/imap.rb, line 367
def logout
send_command("LOGOUT")
end Отправляет команду LOGOUT, чтобы сообщить серверу, что клиент завершил работу с соединением.
# File lib/net/imap.rb, line 645
def lsub(refname, mailbox)
synchronize do
send_command("LSUB", refname, mailbox)
return @responses.delete("LSUB")
end
end Отправляет команду LSUB и возвращает подмножество имён из набора имён, которые пользователь объявил как «активные» или «подписанные». refname и mailbox интерпретируются так же, как для list(). Возвращаемое значение — это массив Net::IMAP::MailboxList.
# File lib/net/imap.rb, line 361
def noop
send_command("NOOP")
end Отправляет команду NOOP на сервер. Ничего не делает.
# File lib/net/imap.rb, line 891 def remove_response_handler(handler) @response_handlers.delete(handler) end
Удаляет обработчик ответов.
# File lib/net/imap.rb, line 494
def rename(mailbox, newname)
send_command("RENAME", mailbox, newname)
end Отправляет команду RENAME для изменения имени mailbox на newname.
Возникает исключение Net::IMAP::NoResponseError, если почтовый ящик с именем mailbox не может быть переименован в newname по какой-либо причине; например, потому что mailbox не существует или потому что уже существует почтовый ящик с именем newname.
# File lib/net/imap.rb, line 767
def search(keys, charset = nil)
return search_internal("SEARCH", keys, charset)
end Отправляет команду SEARCH для поиска в почтовом ящике сообщений, которые соответствуют заданным критериям поиска, и возвращает номера последовательности сообщений. keys может быть строкой, содержащей всю строку поиска, или одномерным массивом ключевых слов и аргументов поиска. Ниже приведены некоторые распространённые критерии поиска; см. раздел 6.4.4 [IMAP] для полного списка.
- <message set>
-
набор номеров последовательности сообщений. ',' указывает интервал, ':' указывает диапазон. Например, '2,10:12,15' означает «2,10,11,12,15».
- BEFORE <date>
-
сообщения с внутренней датой строго до <date>. Аргумент даты имеет формат, аналогичный 8-Aug-2002.
- BODY <string>
-
сообщения, которые содержат <string> в своём теле.
- CC <string>
-
сообщения, содержащие <string> в поле CC.
- FROM <string>
-
сообщения, которые содержат <string> в поле FROM.
- NEW
-
сообщения с установленным флагом Recent, но не Seen.
- NOT <search-key>
-
отрицание следующего ключа поиска.
- OR <search-key> <search-key>
-
«или» два ключа поиска вместе.
- ON <date>
-
сообщения с внутренней датой, точно равной <date>, которая имеет формат, аналогичный 8-Aug-2002.
- SINCE <date>
-
сообщения с внутренней датой в или после <date>.
- SUBJECT <string>
-
сообщения с <string> в теме.
- TO <string>
-
сообщения с <string> в поле TO.
Например:
p imap.search(["SUBJECT", "hello", "NOT", "NEW"]) #=> [1, 6, 7, 8]
# File lib/net/imap.rb, line 450
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, если почтовый ящик не существует или по какой-либо причине не может быть выбран.
# File lib/net/imap.rb, line 622
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].
# File lib/net/imap.rb, line 609
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].
# File lib/net/imap.rb, line 865
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] для получения более подробной информации.
# File lib/net/imap.rb, line 372
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.
# File lib/net/imap.rb, line 668
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 не могут быть возвращены; например, потому что он не существует.
# File lib/net/imap.rb, line 834
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]}>]
# File lib/net/imap.rb, line 504
def subscribe(mailbox)
send_command("SUBSCRIBE", mailbox)
end Отправляет команду SUBSCRIBE, чтобы добавить указанное имя mailbox в набор «активных» или «подписанных» почтовых ящиков сервера, возвращаемых функцией lsub().
Возникает исключение Net::IMAP::NoResponseError, если невозможно подписаться на mailbox; например, потому что он не существует.
# File lib/net/imap.rb, line 908
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] для получения более подробной информации.
# File lib/net/imap.rb, line 852
def uid_copy(set, mailbox)
copy_internal("UID COPY", set, mailbox)
end Аналогично copy(), но set содержит уникальные идентификаторы.
# File lib/net/imap.rb, line 816
def uid_fetch(set, attr)
return fetch_internal("UID FETCH", set, attr)
end Аналогично fetch(), но set содержит уникальные идентификаторы.
# File lib/net/imap.rb, line 772
def uid_search(keys, charset = nil)
return search_internal("UID SEARCH", keys, charset)
end Аналогично search(), но возвращает уникальные идентификаторы.
# File lib/net/imap.rb, line 870
def uid_sort(sort_keys, search_keys, charset)
return sort_internal("UID SORT", sort_keys, search_keys, charset)
end Аналогично sort(), но возвращает массив уникальных идентификаторов.
# File lib/net/imap.rb, line 839
def uid_store(set, attr, flags)
return store_internal("UID STORE", set, attr, flags)
end Аналогично store(), но set содержит уникальные идентификаторы.
# File lib/net/imap.rb, line 914
def uid_thread(algorithm, search_keys, charset)
return thread_internal("UID THREAD", algorithm, search_keys, charset)
end Аналогично thread(), но возвращает уникальные идентификаторы вместо номеров последовательностей сообщений.
# File lib/net/imap.rb, line 514
def unsubscribe(mailbox)
send_command("UNSUBSCRIBE", mailbox)
end Отправляет команду UNSUBSCRIBE, чтобы удалить указанное имя mailbox из набора «активных» или «подписанных» почтовых ящиков сервера.
Возникает исключение Net::IMAP::NoResponseError, если невозможно отписаться от mailbox; например, потому что клиент в настоящее время не подписан на него.
# File lib/net/imap.rb, line 572
def xlist(refname, mailbox)
synchronize do
send_command("XLIST", refname, mailbox)
return @responses.delete("XLIST")
end
end Отправляет команду XLIST и возвращает подмножество имен из полного набора всех имен, доступных клиенту. refname предоставляет контекст (например, базовый каталог в иерархии почтовых ящиков на основе каталогов). mailbox указывает почтовый ящик или (с помощью подстановочных знаков) почтовые ящики в этом контексте. В mailbox могут использоваться два подстановочных знака: '*', который соответствует всем символам включая разделитель иерархии (например, '/' в иерархии почтовых ящиков на основе каталогов, размещенных на UNIX); и '%', который соответствует всем символам кроме разделителя иерархии.
Если refname пуст, mailbox используется непосредственно для определения того, какие почтовые ящики необходимо сопоставить. Если mailbox пуст, возвращаются корневое имя refname и разделитель иерархии.
Команда XLIST похожа на команду LIST, за исключением того, что возвращаемые флаги относятся к функции папки/почтового ящика, например: :Sent
Возвращаемое значение — это массив Net::IMAP::MailboxList. Например:
imap.create("foo/bar")
imap.create("foo/baz")
p imap.xlist("", "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">]
Методы приватного экземпляра
# File lib/net/imap.rb, line 1392 def copy_internal(cmd, set, mailbox) send_command(cmd, MessageSet.new(set), mailbox) end
# File lib/net/imap.rb, line 1431
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 # File lib/net/imap.rb, line 1364
def fetch_internal(cmd, set, attr)
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")
send_command(cmd, MessageSet.new(set), attr)
return @responses.delete("FETCH")
end
end # File lib/net/imap.rb, line 1234
def generate_tag
@tagno += 1
return format("%s%04d", @tag_prefix, @tagno)
end # File lib/net/imap.rb, line 1179
def get_response
buff = ""
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 # File lib/net/imap.rb, line 1163
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 # File lib/net/imap.rb, line 1420
def normalize_searching_criteria(keys)
keys.collect! do |i|
case i
when -1, Range, Array
MessageSet.new(i)
else
i
end
end
end # File lib/net/imap.rb, line 1239
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 # File lib/net/imap.rb, line 1097
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
if resp.tag == @logout_command_tag
return
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 # File lib/net/imap.rb, line 1199
def record_response(name, data)
unless @responses.has_key?(name)
@responses[name] = []
end
@responses[name].push(data)
end # File lib/net/imap.rb, line 1348
def search_internal(cmd, keys, charset)
if keys.instance_of?(String)
keys = [RawData.new(keys)]
else
normalize_searching_criteria(keys)
end
synchronize do
if charset
send_command(cmd, "CHARSET", charset, *keys)
else
send_command(cmd, *keys)
end
return @responses.delete("SEARCH")[-1]
end
end # File lib/net/imap.rb, line 1206
def send_command(cmd, *args, &block)
synchronize do
args.each do |i|
validate_data(i)
end
tag = generate_tag
put_string(tag + " " + cmd)
args.each do |i|
put_string(" ")
send_data(i)
end
put_string(CRLF)
if cmd == "LOGOUT"
@logout_command_tag = tag
end
if block
add_response_handler(block)
end
begin
return get_tagged_response(tag, cmd)
ensure
if block
remove_response_handler(block)
end
end
end
end # File lib/net/imap.rb, line 1271
def send_data(data)
case data
when nil
put_string("NIL")
when String
send_string_data(data)
when Integer
send_number_data(data)
when Array
send_list_data(data)
when Time
send_time_data(data)
when Symbol
send_symbol_data(data)
else
data.send_data(self)
end
end # File lib/net/imap.rb, line 1320
def send_list_data(list)
put_string("(")
first = true
list.each do |i|
if first
first = false
else
put_string(" ")
end
send_data(i)
end
put_string(")")
end # File lib/net/imap.rb, line 1309
def send_literal(str)
put_string("{" + str.bytesize.to_s + "}" + CRLF)
@continuation_request_arrival.wait
raise @exception if @exception
put_string(str)
end # File lib/net/imap.rb, line 1316 def send_number_data(num) put_string(num.to_s) end
# File lib/net/imap.rb, line 1305
def send_quoted_string(str)
put_string('"' + str.gsub(/["\]/n, "\\\\\\&") + '"')
end # File lib/net/imap.rb, line 1290
def send_string_data(str)
case str
when ""
put_string('""')
when /[\x80-\xff\r\n]/n
# literal
send_literal(str)
when /[(){ \x00-\x1f\x7f%*"\]/n
# quoted string
send_quoted_string(str)
else
put_string(str)
end
end # File lib/net/imap.rb, line 1344
def send_symbol_data(symbol)
put_string("\\" + symbol.to_s)
end # File lib/net/imap.rb, line 1336
def send_time_data(time)
t = time.dup.gmtime
s = format('"%2d-%3s-%4d %02d:%02d:%02d +0000"',
t.day, DATE_MONTH[t.month - 1], t.year,
t.hour, t.min, t.sec)
put_string(s)
end # File lib/net/imap.rb, line 1396
def sort_internal(cmd, sort_keys, search_keys, charset)
if search_keys.instance_of?(String)
search_keys = [RawData.new(search_keys)]
else
normalize_searching_criteria(search_keys)
end
normalize_searching_criteria(search_keys)
synchronize do
send_command(cmd, sort_keys, charset, *search_keys)
return @responses.delete("SORT")[-1]
end
end # File lib/net/imap.rb, line 1448
def start_tls_session(params = {})
unless defined?(OpenSSL::SSL)
raise "SSL extension not installed"
end
if @sock.kind_of?(OpenSSL::SSL::SSLSocket)
raise RuntimeError, "already using SSL"
end
begin
params = params.to_hash
rescue NoMethodError
params = {}
end
context = SSLContext.new
context.set_params(params)
if defined?(VerifyCallbackProc)
context.verify_callback = VerifyCallbackProc
end
@sock = SSLSocket.new(@sock, context)
@sock.sync_close = true
@sock.connect
if context.verify_mode != VERIFY_NONE
@sock.post_connection_check(@host)
end
end # File lib/net/imap.rb, line 1381
def store_internal(cmd, set, attr, flags)
if attr.instance_of?(String)
attr = RawData.new(attr)
end
synchronize do
@responses.delete("FETCH")
send_command(cmd, MessageSet.new(set), attr, flags)
return @responses.delete("FETCH")
end
end # File lib/net/imap.rb, line 1409
def thread_internal(cmd, algorithm, search_keys, charset)
if search_keys.instance_of?(String)
search_keys = [RawData.new(search_keys)]
else
normalize_searching_criteria(search_keys)
end
normalize_searching_criteria(search_keys)
send_command(cmd, algorithm, charset, *search_keys)
return @responses.delete("THREAD")[-1]
end # File lib/net/imap.rb, line 1254
def validate_data(data)
case data
when nil
when String
when Integer
NumValidator.ensure_number(data)
when Array
data.each do |i|
validate_data(i)
end
when Time
when Symbol
else
data.validate
end
end
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.