Net::IMAP
class Net::IMAP
父:ObjectIncluded模块:MonitorMixin,OpenSSL,OpenSSL :: SSL
Net :: IMAP实现Internet消息访问协议(IMAP)客户端功能。该协议在IMAP中进行了描述。
IMAP概述
IMAP客户端连接到服务器,然后使用authenticate()或login()进行身份验证。通过身份验证后,可以使用一系列命令。大多数使用邮箱,可以安排在分层名称空间中,并且每个邮箱都包含零个或多个邮件。这在服务器上如何实现是依赖于实现的; 在UNIX服务器上,它经常以目录层次结构中的邮箱格式实现为文件。
要处理邮箱内的邮件,客户端必须首先使用select()或(对于只读访问)examine()来选择该邮箱。一旦客户端成功选择了一个邮箱,它们就进入选定
状态,并且该邮箱成为当前
邮箱,邮件项目相关命令将隐式操作。
消息有两种标识符:消息序列号和UID。
消息序号将邮箱中的邮件数从1增加到邮箱中的邮件数。如果新消息在会话期间到达,它会收到一个等于邮箱新大小的序列号。如果从邮箱中删除邮件,则剩余的邮件会将其序列号“乱码”以填补空白。
另一方面,UID永久保证不会在同一个邮箱中标识另一个邮件,即使现有邮件已被删除。UID需要在邮箱内以升序(但不一定是顺序)顺序进行分配; 这意味着如果非IMAP客户端重新排列邮箱中邮件项目的顺序,则必须重新分配UID。因此,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年4月的“邮件/发送邮件”从“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命令。它也可能表示发生了内部服务器故障(如磁盘崩溃)。
BYE
服务器正在说再见。这可以是正常注销序列的一部分,并且可以用作登录序列的一部分,以表明服务器(由于某种原因)不愿意接受您的连接。作为对任何其他命令的响应,它表明服务器正在关闭,或者服务器由于不活动而超时客户端连接。
这三个错误响应由错误Net :: IMAP :: NoResponseError,Net :: IMAP :: BadResponseError和Net :: IMAP :: ByeResponseError表示,所有这些都是Net :: IMAP :: ResponseError的子类。从本质上讲,所有涉及向服务器发送请求的方法都可能会产生这些错误之一。以下仅记录最相关的实例。
由于IMAP类使用套接字进行通信,因此其方法也易受使用套接字时可能发生的各种错误的影响。这些通常表示为Errno错误。例如,任何涉及向服务器发送请求和/或从其接收响应的方法都会在网络连接意外关闭时引发Errno :: EPIPE错误。请参阅套接字(7),ip(7),tcp(7),套接字(2),连接(2)以及关联的手册页。
最后,如果发现低级别数据的格式不正确(例如,在UTF-8和UTF-16之间转换时),则Net :: IMAP :: DataFormatError被抛出,并且Net :: IMAP :: ResponseParseError为如果服务器响应不可解析则抛出。
参考
IMAP
- Crispin,“INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1”,
RFC 2060,December 1996.(注:由于RFC 3501已经过时)
LANGUAGE-TAGS
Alvestrand,H.,“用于识别语言的标签”,RFC 1766,1995年3月。
MD5
Myers,J.和M. Rose,“Content-MD5 Header Field”,RFC 1864,1995年10月。
MIME-IMB
Freed,N.和N.Borenstein,“MIME(多用途因特网邮件扩展)第一部分:Internet消息体的格式”,RFC 2045,1996年11月。
RFC-822
Crocker,D.,“ARPA因特网文本消息格式标准”,STD 11,RFC 822,特拉华大学,1982年8月。
RFC-2087
Myers,J。,“IMAP4 QUOTA扩展”,RFC 2087,1997年1月。
RFC-2086
Myers,J.,“IMAP4 ACL扩展”,RFC 2086,1997年1月。
RFC-2195
Klensin,J.,Catoe,R.和Krumviede,P.,“IMAP / POP AUTHorize Extension for Simple Challenge / Response”,RFC 2195,1997年9月。
SORT-THREAD-EXT
Crispin,M.,“INTERNET MESSAGE ACCESS PROTOCOL - SORT和THREAD Extensions”,Draft-ietf-imapext-sort,2003年5月。
OSSL
RSSL
savannah.gnu.org/projects/rubypki
UTF7
Goldsmith,D。和Davis,M.,“UTF-7:Unicode的邮件安全转换格式”,RFC 2152,1997年5月。
常量
ANSWERED
指示消息的标志已被回答。
Address
Net :: IMAP :: Address表示电子邮件地址。
领域:
name
从RFC-822邮箱返回短语。
route
返回RFC-822 route-addr的路由。
mailbox
nil表示RFC-822组的结束。如果非零和主机为零,则返回RFC-822组名。否则,返回RFC-822本地部分。
host
nil表示RFC-822组语法。否则,返回RFC-822域名。
ContentDisposition
Net :: IMAP :: ContentDisposition表示Content-Disposition字段。
Fields:
dsp_type
返回处置类型。
param
返回表示Content-Disposition字段参数的散列。
ContinuationRequest
Net :: IMAP :: ContinuationRequest表示命令继续请求。
命令继续请求响应由“+”标记而不是标记指示。这种形式的响应表明服务器已准备好接受来自客户端的命令的继续。这个回应的其余部分是一行文字。
continue_req ::= "+" SPACE (resp_text / base64)
Fields:
data
返回数据(Net :: IMAP :: ResponseText)。
raw_data
返回原始数据字符串。
DATE_MONTH DELETED
指示消息的标志已被标记为删除。邮箱关闭或清除时会发生这种情况。
DRAFT
指示消息的标志只是草稿或正在进行中的版本。
Envelope
Net :: IMAP :: Envelope表示消息的信封结构。
Fields:
date
返回表示日期的字符串。
subject
返回表示主题的字符串。
from
返回表示from的Net :: IMAP :: Address数组。
sender
返回表示发件人的Net :: IMAP :: Address数组。
reply_to
返回表示答复的Net :: IMAP :: Address数组。
to
返回表示to的Net :: IMAP :: Address数组。
cc
返回表示cc的Net :: IMAP :: Address数组。
bcc
返回表示密件抄送的Net :: IMAP :: Address数组。
in_reply_to
返回一个表示in-reply-to的字符串。
message_id
返回表示消息ID的字符串。
FLAGGED
表示消息的标志已被标记为特别或紧急关注。
FetchData
Net :: IMAP :: FetchData表示FETCH响应的内容。
Fields:
seqno
返回消息序列号。(注意:即使对于UID命令响应,也不是唯一标识符。)
attr
返回一个散列。每个键都是数据项名称,每个值都是其值。
目前的数据项是:
BODY
没有扩展数据的BODYSTRUCTURE形式。
Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText, Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart. ENVELOPE
描述消息信封结构的Net :: IMAP :: Envelope对象。
FLAGS
为此消息设置的标志符号数组。标志符号大写字符串#大写。
INTERNALDATE
表示消息内部日期的字符串。
RFC822
相当于BODY []。
RFC822.HEADER
Equivalent to 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
Fields:
user
对使用getacl命令指定的邮箱具有某些权限的登录名。
rights
指定用户对邮箱的访问权限。
MailboxList
Net :: IMAP :: MailboxList表示LIST响应的内容。
mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
"\Noselect" / "\Unmarked" / flag_extension) ")"
SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
Fields:
attr
返回名称属性。每个名称属性都是由String#capitalize大写的符号,例如:Noselect(not: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
Fields:
mailbox
带有关联配额的邮箱。
usage
邮箱的当前存储使用情况。
quota
对邮箱施加配额限制。
MailboxQuotaRoot
Net :: IMAP :: MailboxQuotaRoot表示GETQUOTAROOT响应的一部分。(GETQUOTAROOT也可以返回Net :: IMAP :: MailboxQuota。)
quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)
Fields:
mailbox
带有关联配额的邮箱。
quotaroots
影响指定邮箱配额的零个或多个quotaroots。
NOINFERIORS
指示邮箱上下文名称不能包含子项的标志。
NOSELECT
表示邮箱未被选中的标志。
RECENT
表示该消息为“最近”的标志,表示该会话是客户端已收到此消息通知的第一个会话。
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 "]">]
Fields:
name
返回名称,例如“ALERT”,“PERMANENTFLAGS”或“UIDVALIDITY”。
data
返回数据(如果存在)。
ResponseText
Net :: IMAP :: ResponseText表示响应的文本。文本可能以响应代码为前缀。
resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
;; text SHOULD NOT begin with "[" or "="
Fields:
code
返回响应代码。请参阅((<Net :: IMAP :: ResponseCode>))。
text
返回文本。
SEEN
表示消息的标志已被看到。
StatusData
Net :: IMAP :: StatusData表示STATUS响应的内容。
Fields:
mailbox
返回邮箱名称。
attr
返回一个散列。每个密钥都是“消息”,“最近”,“下一个”,“无效”,“未使用”之一。每个值都是一个数字。
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
Fields:
tag
返回标签。
name
返回名称,“OK”,“NO”或“BAD”之一。
data
返回数据。请参阅((<Net :: IMAP :: ResponseText>))。
raw_data
返回原始数据字符串。
ThreadMember
Net :: IMAP :: ThreadMember表示由#thread返回的线程节点。
Fields:
seqno
此消息的序列号。
children
用于邮件项目的Net :: IMAP :: ThreadMember对象的数组,它们是线程中的子项。
UNMARKED
指示邮箱不包含新邮件的标志。
UntaggedResponse
Net :: IMAP :: UntaggedResponse表示无标记的响应。
由服务器传输到客户端的数据以及不表示命令完成的状态响应以标记“*”作为前缀,并称为未标记的响应。
response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye /
mailbox_data / message_data / capability_data)
Fields:
name
返回名称,例如“FLAGS”,“LIST”或“FETCH”。
data
返回数据,如标志符号数组,一个((<Net :: IMAP :: MailboxList>))对象。
raw_data
返回原始数据字符串。
属性
client_threadRW
接收异常的线程。
greetingR
返回来自服务器的初始问候响应。
response_handlersR
返回所有响应处理程序。
responsesR
返回未标记的响应。例如:
imap.select("inbox")
p imap.responses["EXISTS"][-1]
#=> 2
p imap.responses["UIDVALIDITY"][-1]
#=> 968263756
公共类方法
add_authenticator(auth_type,authenticator)显示源文件
为#authenticate添加一个验证器。auth_type
是此验证器支持的验证类型(例如“LOGIN”)。该authenticator
对象定义了一个process()方法来处理与服务器的身份验证。有关示例,请参阅Net :: IMAP :: LoginAuthenticator,Net :: IMAP :: CramMD5Authenticator和Net :: IMAP :: DigestMD5Authenticator。
如果auth_type
引用现有的身份验证器,它将被新的替换。
# File lib/net/imap.rb, line 294
def self.add_authenticator(auth_type, authenticator)
@@authenticators[auth_type] = authenticator
end
debug() Show source
返回调试模式。
# File lib/net/imap.rb, line 264
def self.debug
return @@debug
end
debug=(val) Show source
设置调试模式。
# File lib/net/imap.rb, line 269
def self.debug=(val)
return @@debug = val
end
decode_utf7(s) Show source
将字符串从修改的UTF-7格式解码为UTF-8。
UTF-7是Unicode UTF7的7位编码。IMAP使用稍微修改后的版本来编码包含非ASCII字符的邮箱名称; 请参阅IMAP第5.1.3节。
网:: IMAP并不会
自动编码和邮箱名称和UTF-7进行解码。
# File lib/net/imap.rb, line 991
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
default_imap_port()
别名为:default_port
default_imaps_port()
别名为:default_tls_port
default_port() Show source
IMAP连接的默认端口,端口143
# File lib/net/imap.rb, line 299
def self.default_port
return PORT
end
另外别名为:default_imap_port
default_ssl_port()
别名为:default_tls_port
default_tls_port() Show source
IMAPS连接的默认端口,端口993
# File lib/net/imap.rb, line 304
def self.default_tls_port
return SSL_PORT
end
另外别名为:default_imaps_port,default_ssl_port
encode_utf7(s) Show source
将UTF-8格式的字符串编码为修改后的UTF-7。
# File lib/net/imap.rb, line 1002
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
format_date(time) Show source
格式化time
为IMAP风格的日期。
# File lib/net/imap.rb, line 1014
def self.format_date(time)
return time.strftime('%d-%b-%Y')
end
format_datetime(time) Show source
格式化time
为IMAP风格的日期时间。
# File lib/net/imap.rb, line 1019
def self.format_datetime(time)
return time.strftime('%d-%b-%Y %H:%M %z')
end
max_flag_count() Show source
返回实现为符号的最大标志数。
# File lib/net/imap.rb, line 274
def self.max_flag_count
return @@max_flag_count
end
max_flag_count=(count) Show source
将实际标记的最大数量设置为符号。
# File lib/net/imap.rb, line 279
def self.max_flag_count=(count)
@@max_flag_count = count
end
Net::IMAP.new(host, options = {}) Show source
创建一个新的Net :: IMAP对象并将其连接到指定的对象host
。
options
是一个选项散列,其中的每个键都是一个符号。
可用的选项是:
port
端口号(imap的缺省值是143,imaps的缺省值是993)
ssl
如果选项为真,那么将尝试使用SSL(现在称为TLS)连接到服务器。为此,需要安装OpenSSL OSSL和Ruby OpenSSL RSSL扩展。如果options是一个散列,它将作为参数传递给OpenSSL :: SSL :: SSLContext#set_params。
最常见的错误是:
Errno::ECONNREFUSED
连接拒绝host
或介入防火墙。
Errno::ETIMEDOUT
连接超时(可能是由于数据包被干扰防火墙丢弃)。
Errno::ENETUNREACH
没有通往该网络的路线。
SocketError
主机名未知或其他套接字错误。
Net::IMAP::ByeResponseError
连接到主机是成功的,但它立即说再见。
调用超类方法MonitorMixin.new
# File lib/net/imap.rb, line 1061
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
公共实例方法
add_response_handler(handler = Proc.new) Show source
添加一个响应处理程序。例如,要检测服务器何时发送新的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 898
def add_response_handler(handler = Proc.new)
@response_handlers.push(handler)
end
append(mailbox, message, flags = nil, date_time = nil) Show source
发送一个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)
如果邮箱不存在(它不会自动创建),或者如果flags,date_time或message参数包含错误,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 691
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
authenticate(auth_type, *args) Show source
发送一个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
:用户名和(明文)密码。服务器可能不支持这些机制中的一种或另一种; 检查能力()的形式为“AUTH = LOGIN”或“AUTH = CRAM-MD5”的能力。
身份验证使用适当的身份验证器对象完成:有关插入自己的身份验证器的更多信息,请参阅@@ authenticators。
例如:
imap.authenticate('LOGIN', user, password)
如果身份验证失败,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 409
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
capability() Show source
发送CAPABILITY命令,并返回服务器支持的一组功能。每个功能都是一个字符串。请参阅IMAP以获取可能的功能列表。
请注意,Net :: IMAP类不会根据服务器的功能修改其行为; 在使用服务器之前,要确保服务器支持某种功能,这取决于该类的用户。
# File lib/net/imap.rb, line 351
def capability
synchronize do
send_command("CAPABILITY")
return @responses.delete("CAPABILITY")[-1]
end
end
check() Show source
发送CHECK命令以请求当前所选邮箱的检查点。这将执行特定于实施的内务管理; 例如,协调邮箱的内存和磁盘状态。
# File lib/net/imap.rb, line 705
def check
send_command("CHECK")
end
close() Show source
发送CLOSE命令关闭当前选定的邮箱。CLOSE命令将从邮箱中永久删除所有设置了“已删除”标志的邮件。
# File lib/net/imap.rb, line 712
def close
send_command("CLOSE")
end
copy(set, mailbox) Show source
发送COPY命令将指定的消息复制到指定目标的末尾mailbox
。该set
参数是一个数字,一个数字数组或一个Range对象。该号码是消息序号。
# File lib/net/imap.rb, line 845
def copy(set, mailbox)
copy_internal("COPY", set, mailbox)
end
create(mailbox) Show source
发送一个CREATE命令来创建一个新的mailbox
。
如果无法创建具有该名称的邮箱,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 472
def create(mailbox)
send_command("CREATE", mailbox)
end
delete(mailbox) Show source
发送DELETE命令以删除mailbox
。
如果具有该名称的邮箱无法删除,或者因为它不存在或者因为客户端没有删除它的权限,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 481
def delete(mailbox)
send_command("DELETE", mailbox)
end
disconnect() Show source
断开与服务器的连接。
# 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
@sock.close
end
raise e if e
end
disconnected?() Show source
如果与服务器断开连接,则返回true。
# File lib/net/imap.rb, line 337
def disconnected?
return @sock.closed?
end
examine(mailbox) Show source
发送一个EXAMINE命令来选择一个,mailbox
以便mailbox
可以访问该消息。与select()的行为相同,只是所选内容mailbox
被标识为只读。
如果邮箱不存在或出于某种原因不可检查,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 461
def examine(mailbox)
synchronize do
@responses.clear
send_command("EXAMINE", mailbox)
end
end
expunge() Show source
发送EXPUNGE命令,从当前选定的邮箱中永久删除所有设置了“已删除”标志的邮件。
# File lib/net/imap.rb, line 718
def expunge
synchronize do
send_command("EXPUNGE")
return @responses.delete("EXPUNGE")
end
end
fetch(set, attr) Show source
发送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 809
def fetch(set, attr)
return fetch_internal("FETCH", set, attr)
end
getacl(mailbox) Show source
发送GETACL命令以及指定的mailbox
。如果此邮箱存在,则会返回一个包含Net :: IMAP :: MailboxACLItem对象的数组。
# File lib/net/imap.rb, line 631
def getacl(mailbox)
synchronize do
send_command("GETACL", mailbox)
return @responses.delete("ACL")[-1]
end
end
getquota(mailbox) Show source
与指定一起发送GETQUOTA命令mailbox
。如果此邮箱存在,则返回包含Net :: IMAP :: MailboxQuota对象的数组。此命令通常仅适用于服务器管理员。
# File lib/net/imap.rb, line 595
def getquota(mailbox)
synchronize do
send_command("GETQUOTA", mailbox)
return @responses.delete("QUOTA")
end
end
getquotaroot(mailbox) Show source
发送GETQUOTAROOT命令以及指定的命令mailbox
。该命令通常对管理员和用户都可用。如果此邮箱存在,它将返回一个包含Net :: IMAP :: MailboxQuotaRoot和Net :: IMAP :: MailboxQuota类型对象的数组。
# File lib/net/imap.rb, line 581
def getquotaroot(mailbox)
synchronize do
send_command("GETQUOTAROOT", mailbox)
result = []
result.concat(@responses.delete("QUOTAROOT"))
result.concat(@responses.delete("QUOTA"))
return result
end
end
idle(timeout = nil, &response_handler) Show source
发送IDLE命令,等待新消息或已删除消息的通知。在IDLE期间从服务器收到响应。
Use idle_done() to leave IDLE.
如果timeout
给出,则此方法在timeout
秒过后返回。timeout
可以用于保持活力。例如,以下代码每60秒检查一次连接。
loop do
imap.idle(60) do |res|
...
end
end
# File lib/net/imap.rb, line 944
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 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_done() Show source
留下 IDLE.
# File lib/net/imap.rb, line 974
def idle_done
synchronize do
if @idle_done_cond.nil?
raise Net::IMAP::Error, "not during IDLE"
end
@idle_done_cond.signal
end
end
list(refname, mailbox) Show source
发送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 538
def list(refname, mailbox)
synchronize do
send_command("LIST", refname, mailbox)
return @responses.delete("LIST")
end
end
登录(用户,密码)显示源
Sends a LOGIN command to identify the client and carries the plaintext password
authenticating this user
. Note that, unlike calling authenticate() with an auth_type
of “LOGIN”, login() does not
use the login authenticator.
如果身份验证失败,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 432
def login(user, password)
send_command("LOGIN", user, password)
end
注销()显示源
发送LOGOUT命令以通知服务器客户端已完成连接。
# File lib/net/imap.rb, line 365
def logout
send_command("LOGOUT")
end
lsub(refname,mailbox)显示源文件
发送LSUB命令,并返回用户声明为“活动”或“订阅”的一组名称中的名称子集,refname
并将mailbox
其解释为list()。返回值是一个数组Net::IMAP::MailboxList
。
# File lib/net/imap.rb, line 643
def lsub(refname, mailbox)
synchronize do
send_command("LSUB", refname, mailbox)
return @responses.delete("LSUB")
end
end
移动(设置,邮箱)显示源
发送MOVE命令将指定的消息移动到指定目标的末尾mailbox
。该set
参数是一个数字,一个数字数组或一个Range对象。该号码是消息序号。RFC-6851中描述了IMAP MOVE扩展。
# File lib/net/imap.rb, line 859
def move(set, mailbox)
copy_internal("MOVE", set, mailbox)
end
noop()显示源代码
向服务器发送NOOP命令。它什么也没做。
# File lib/net/imap.rb, line 359
def noop
send_command("NOOP")
end
remove_response_handler(处理程序)显示源
删除响应处理程序。
# File lib/net/imap.rb, line 903
def remove_response_handler(handler)
@response_handlers.delete(handler)
end
重命名(邮箱,新名称)显示源
发送重命名命令来改变名称mailbox
来newname
。
如果具有名称的邮箱因任何原因mailbox
无法重命名,则会引发Net :: IMAP :: NoResponseError newname
; 例如,因为mailbox
不存在,或者因为已经有一个名称为邮箱newname
。
# File lib/net/imap.rb, line 492
def rename(mailbox, newname)
send_command("RENAME", mailbox, newname)
end
搜索(键,字符集=零)显示源
发送 SEARCH 命令在邮箱中搜索符合给定搜索条件的邮件,并返回邮件序列号。keys
可以是保存整个搜索字符串的字符串,也可以是搜索关键字和参数的单维数组。以下是一些常见的搜索标准; 有关完整列表,请参阅IMAP第6.4.4节。
<message set>
一组消息序列号。','表示间隔,':'表示范围。例如,'2,10:12,15'表示“2,10,11,12,15”。
BEFORE <date>
严格在<date>之前包含内部日期的消息。日期参数的格式类似于2002年8月8日。
BODY <string>
在其正文中包含<string>的消息。
CC <string>
在CC字段中包含<string>的消息。
FROM <string>
在其FROM字段中包含<string>的消息。
NEW
消息与最近,但不是看到,标志设置。
NOT <search-key>
否定以下搜索键。
OR <search-key> <search-key>
“或”两个搜索键在一起。
ON <date>
内部日期完全等于<date>的消息,其格式类似于2002年8月8日。
SINCE <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 765
def search(keys, charset = nil)
return search_internal("SEARCH", keys, charset)
end
选择(邮箱)显示源
发送一个SELECT命令来选择一个,mailbox
以便mailbox
可以访问该消息。
选择邮箱后,您可以从@response-1中检索该邮箱中的邮件数量,并从@response-1中检索最近邮件的数量。请注意,如果在会话期间新消息到达,这些值可能会更改; 有关检测此事件的方法,请参阅add_response_handler()。
如果邮箱不存在或出于某种原因不可选,则会引发Net :: IMAP :: NoResponseError。
# File lib/net/imap.rb, line 448
def select(mailbox)
synchronize do
@responses.clear
send_command("SELECT", mailbox)
end
end
setacl(邮箱,用户,权限)显示源
发送SETACL命令mailbox
,user
并且该rights
用户将在该邮箱中拥有该命令。如果rights
为零,则该用户将被剥夺该邮箱的任何权利。IMAP ACL命令在RFC-2086中进行了描述。
# File lib/net/imap.rb, line 620
def setacl(mailbox, user, rights)
if rights.nil?
send_command("SETACL", mailbox, user, "")
else
send_command("SETACL", mailbox, user, rights)
end
end
setquota(邮箱,配额)显示源
发送SETQUOTA命令以及指定的mailbox
和quota
。如果quota
是零,那么quota
将取消设置该邮箱。通常需要以服务器管理员身份登录才能正常工作。RFC-2087中描述了IMAP配额命令。
# File lib/net/imap.rb, line 607
def setquota(mailbox, quota)
if quota.nil?
data = '()'
else
data = '(STORAGE ' + quota.to_s + ')'
end
send_command("SETQUOTA", mailbox, RawData.new(data))
end
排序(sort_keys,search_keys,charset)显示源文件
发送一个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 877
def sort(sort_keys, search_keys, charset)
return sort_internal("SORT", sort_keys, search_keys, charset)
end
starttls(options = {},verify = true)显示源文件
发送STARTTLS命令以启动TLS会话。
# File lib/net/imap.rb, line 370
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
status(mailbox, attr) Show source
发送一个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}
如果mailbox
无法返回状态值,则会引发Net :: IMAP :: NoResponseError ; 例如,因为它不存在。
# File lib/net/imap.rb, line 666
def status(mailbox, attr)
synchronize do
send_command("STATUS", mailbox, attr)
return @responses.delete("STATUS")[-1].attr
end
end
存储(set,attr,flags)显示源文件
发送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 832
def store(set, attr, flags)
return store_internal("STORE", set, attr, flags)
end
subscribe(mailbox) Show source
发送SUBSCRIBE命令,将指定的mailbox
名称添加到由lsub()返回的服务器的“活动”或“订阅”邮箱集。
如果mailbox
无法订阅,则会引发Net :: IMAP :: NoResponseError ; 例如,因为它不存在。
# File lib/net/imap.rb, line 502
def subscribe(mailbox)
send_command("SUBSCRIBE", mailbox)
end
线程(算法,search_keys,字符集)显示源文件
与search()类似,但以线程格式返回消息序列号,作为Net :: IMAP :: ThreadMember树。支持的算法是:
ORDEREDSUBJECT
根据主题分为单层线程,按日期排序。
REFERENCES
根据哪个消息是对其的回复确定的父/子关系拆分为线程。
与search()不同,它charset
是一个必需的参数。US-ASCII和UTF-8是样本值。
有关更多详细信息,请参见SORT-THREAD-EXT。
# File lib/net/imap.rb, line 920
def thread(algorithm, search_keys, charset)
return thread_internal("THREAD", algorithm, search_keys, charset)
end
uid_copy(set,mailbox)显示源文件
与copy()类似,但set
包含唯一标识符。
# File lib/net/imap.rb, line 850
def uid_copy(set, mailbox)
copy_internal("UID COPY", set, mailbox)
end
uid_fetch(set, attr) Show source
与fetch()类似,但set
包含唯一标识符。
# File lib/net/imap.rb, line 814
def uid_fetch(set, attr)
return fetch_internal("UID FETCH", set, attr)
end
uid_move(set, mailbox) Show source
与move()类似,但set
包含唯一标识符。
# File lib/net/imap.rb, line 864
def uid_move(set, mailbox)
copy_internal("UID MOVE", set, mailbox)
end
uid_search(keys, charset = nil) Show source
与搜索()类似,但返回唯一标识符。
# File lib/net/imap.rb, line 770
def uid_search(keys, charset = nil)
return search_internal("UID SEARCH", keys, charset)
end
uid_sort(sort_keys, search_keys, charset) Show source
与sort()类似,但返回一个唯一标识符数组。
# File lib/net/imap.rb, line 882
def uid_sort(sort_keys, search_keys, charset)
return sort_internal("UID SORT", sort_keys, search_keys, charset)
end
uid_store(set, attr, flags) Show source
与store()类似,但set
包含唯一标识符。
# File lib/net/imap.rb, line 837
def uid_store(set, attr, flags)
return store_internal("UID STORE", set, attr, flags)
end
uid_thread(algorithm, search_keys, charset) Show source
与thread()类似,但返回唯一标识符而不是消息序列号。
# File lib/net/imap.rb, line 926
def uid_thread(algorithm, search_keys, charset)
return thread_internal("UID THREAD", algorithm, search_keys, charset)
end
unsubscribe(mailbox) Show source
发送UNSUBSCRIBE命令以mailbox
从服务器的“活动”或“订阅”邮箱组中删除指定的名称。
如果mailbox
无法取消订阅,则会引发Net :: IMAP :: NoResponseError ; 例如,因为客户当前没有订阅它。
# File lib/net/imap.rb, line 512
def unsubscribe(mailbox)
send_command("UNSUBSCRIBE", mailbox)
end
xlist(refname, mailbox) Show source
发送XLIST命令,并从客户端可用的全部名称集中返回一个名称的子集。refname
提供上下文(例如,基于目录的邮箱层次结构中的基本目录)。mailbox
在该上下文中指定邮箱或(通过通配符)邮箱。两个通配符可用于mailbox
:'*',它匹配包括
层次结构定界符在内
的所有字符(例如,在UNIX托管的基于目录的邮箱层次结构上的'/'); 和'%',它匹配除
层次分隔符外
的所有字符。
如果refname
为空,mailbox
则直接用于确定要匹配哪些邮箱。如果mailbox
为空,refname
则返回根名称和层次分隔符。
XLIST命令与LIST命令相似,只不过返回的标志引用了文件夹/邮箱的功能,例如:已发送
返回值是一个数组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 570
def xlist(refname, mailbox)
synchronize do
send_command("XLIST", refname, mailbox)
return @responses.delete("XLIST")
end
end
私有实例方法
copy_internal(cmd, set, mailbox) Show source
# File lib/net/imap.rb, line 1414
def copy_internal(cmd, set, mailbox)
send_command(cmd, MessageSet.new(set), mailbox)
end
create_ssl_params(certs = nil, verify = true) Show source
# File lib/net/imap.rb, line 1453
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) Show source
# File lib/net/imap.rb, line 1386
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
generate_tag() Show source
# File lib/net/imap.rb, line 1256
def generate_tag
@tagno += 1
return format("%s%04d", @tag_prefix, @tagno)
end
get_response() Show source
# File lib/net/imap.rb, line 1201
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) Show source
# File lib/net/imap.rb, line 1185
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) Show source
# File lib/net/imap.rb, line 1442
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) Show source
# File lib/net/imap.rb, line 1261
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() Show source
# File lib/net/imap.rb, line 1119
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
record_response(name, data) Show source
# File lib/net/imap.rb, line 1221
def record_response(name, data)
unless @responses.has_key?(name)
@responses[name] = []
end
@responses[name].push(data)
end
search_internal(cmd, keys, charset) Show source
# File lib/net/imap.rb, line 1370
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
send_command(cmd, *args, &block) Show source
# File lib/net/imap.rb, line 1228
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
send_data(data) Show source
# File lib/net/imap.rb, line 1293
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
send_list_data(list) Show source
# File lib/net/imap.rb, line 1342
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
send_literal(str) Show source
# File lib/net/imap.rb, line 1331
def send_literal(str)
put_string("{" + str.bytesize.to_s + "}" + CRLF)
@continuation_request_arrival.wait
raise @exception if @exception
put_string(str)
end
send_number_data(num) Show source
# File lib/net/imap.rb, line 1338
def send_number_data(num)
put_string(num.to_s)
end
send_quoted_string(str) Show source
# File lib/net/imap.rb, line 1327
def send_quoted_string(str)
put_string('"' + str.gsub(/["\]/n, "\\\\\\&") + '"')
end
send_string_data(str) Show source
# File lib/net/imap.rb, line 1312
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
send_symbol_data(symbol) Show source
# File lib/net/imap.rb, line 1366
def send_symbol_data(symbol)
put_string("\\" + symbol.to_s)
end
send_time_data(time) Show source
# File lib/net/imap.rb, line 1358
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
sort_internal(cmd, sort_keys, search_keys, charset) Show source
# File lib/net/imap.rb, line 1418
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
start_tls_session(params = {}) Show source
# File lib/net/imap.rb, line 1470
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
store_internal(cmd, set, attr, flags) Show source
# File lib/net/imap.rb, line 1403
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
thread_internal(cmd, algorithm, search_keys, charset) Show source
# File lib/net/imap.rb, line 1431
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
validate_data(data) Show source
# File lib/net/imap.rb, line 1276
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