class Net::SMTP
这个库是什么?¶ ↑
此库提供了通过 SMTP(简单邮件传输协议)发送互联网邮件的功能。有关 SMTP 本身的详细信息,请参阅 [RFC5321]。此库还实现了 SMTP 身份验证,这对于消息编写器向其传出 SMTP 服务器提交消息通常是必要的,请参阅 [RFC6409] 和 [SMTPUTF8],这对于发送/接收包含 ASCII 范围之外字符的地址的消息是必要的。
这个库不是什么?¶ ↑
此库不提供编写互联网邮件的功能。您必须自己创建它们。如果您想要更好的邮件支持,请尝试 mail 或 rmail gem,或在 RubyGems.org 或 The Ruby Toolbox 中搜索替代方案。
仅供参考:互联网邮件的官方规范是:[RFC5322]。
示例¶ ↑
发送消息¶ ↑
在发送消息之前,必须打开与 SMTP 服务器的连接。第一个参数是您的 SMTP 服务器的地址,第二个参数是端口号。使用带有块的 SMTP.start
是执行此操作的最简单方法。这样,在执行块后会自动关闭 SMTP
连接。
require 'net/smtp' Net::SMTP.start('your.smtp.server', 25) do |smtp| # Use the SMTP object smtp only in this block. end
将“your.smtp.server”替换为您的 SMTP 服务器。通常,您的系统管理员或互联网提供商会为您提供一个服务器。
然后,您可以发送消息。
msgstr = <<END_OF_MESSAGE From: Your Name <[email protected]> To: Destination Address <[email protected]> Subject: test message Date: Sat, 23 Jun 2001 16:26:43 +0900 Message-Id: <[email protected]> This is a test message. END_OF_MESSAGE require 'net/smtp' Net::SMTP.start('your.smtp.server', 25) do |smtp| smtp.send_message msgstr, '[email protected]', '[email protected]' end
关闭会话¶ ↑
发送消息后,您必须通过调用 finish
方法来关闭 SMTP
会话
# using SMTP#finish smtp = Net::SMTP.start('your.smtp.server', 25) smtp.send_message msgstr, 'from@address', 'to@address' smtp.finish
您还可以使用 SMTP.start
或 SMTP#start
的块形式。这将自动关闭 SMTP
会话
# using block form of SMTP.start Net::SMTP.start('your.smtp.server', 25) do |smtp| smtp.send_message msgstr, 'from@address', 'to@address' end
我强烈建议使用此方案。这种形式更简单,更强大。
HELO 域名¶ ↑
在几乎所有情况下,您都必须为 SMTP.start
或 SMTP#start
提供第三个参数。这是您所在的域名(从中发送邮件的主机)。它被称为“HELO 域名”。SMTP 服务器将通过检查 HELO 域名来判断是否应发送或拒绝 SMTP
会话。
Net::SMTP.start('your.smtp.server', 25, helo: 'mail.from.domain') do |smtp| smtp.send_message msgstr, 'from@address', 'to@address' end
SMTP 身份验证¶ ↑
Net::SMTP
类支持 SASL 身份验证的 SMTP 扩展
- RFC4954
-
以及以下
SASL 机制:PLAIN
,LOGIN
_(已弃用)_ 和 CRAM-MD5
_(已弃用)_。
要使用 SMTP 身份验证,请将额外的参数传递给 SMTP.start
或 SMTP#start
。
# PLAIN Net::SMTP.start('your.smtp.server', 25, user: 'Your Account', secret: 'Your Password', authtype: :plain)
对其他 SASL 机制(例如 EXTERNAL
、OAUTHBEARER
、SCRAM-SHA-256
和 XOAUTH2
)的支持将在未来的版本中添加。
LOGIN
和 CRAM-MD5
机制仍然可用于向后兼容,但已弃用,应避免使用。
常量
- DEFAULT_AUTH_TYPE
身份验证
- VERSION
属性
要连接的 SMTP
服务器的地址。
通过 EHLO 响应获得的服务器功能
尝试打开连接时等待的秒数。如果在此时间内无法打开连接,则会引发 Net::OpenTimeout。默认值为 30 秒。
要连接的 SMTP
服务器的端口号。
在读取一个块(通过一个 read(2) 调用)时等待的秒数。如果 read(2) 调用在此时间内未完成,则会引发 Net::ReadTimeout。默认值为 60 秒。
用于其他 SSLContext 参数的哈希。
用于验证服务器证书中的主机名的主机名。
如果为 true
,则验证服务器的证书。
公共类方法
默认 SMTP
端口号,25。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 198 def SMTP.default_port 25 end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 216 def SMTP.default_ssl_context(ssl_context_params = nil) context = OpenSSL::SSL::SSLContext.new context.set_params(ssl_context_params || {}) context end
默认邮件提交端口号,587。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 203 def SMTP.default_submission_port 587 end
默认 SMTPS 端口号,465。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 208 def SMTP.default_tls_port 465 end
创建新的 Net::SMTP
对象。
address
是您的 SMTP
服务器的主机名或 IP 地址。port
是要连接的端口;它默认为端口 25。
如果 tls
为 true,则启用 TLS。默认值为 false。如果 starttls
为 :always,则启用 STARTTLS;如果为 :auto
,则在服务器支持时使用 STARTTLS;如果为 false,则禁用 STARTTLS。
如果 tls_verify
为 true,则验证服务器的证书。默认值为 true。如果服务器证书中的主机名与 address
不同,则可以使用 tls_hostname
指定。
可以将其他 SSLContext 参数添加到 ssl_context_params
哈希参数中,并将其传递给 OpenSSL::SSL::SSLContext#set_params。
tls_verify: true
等效于 ssl_context_params: { verify_mode: OpenSSL::SSL::VERIFY_PEER }
。
此方法不会打开 TCP 连接。如果想一次完成所有操作,可以使用 SMTP.start
而不是 SMTP.new
。否则,请在 SMTP.new
之后使用 SMTP#start
。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 248 def initialize(address, port = nil, tls: false, starttls: :auto, tls_verify: true, tls_hostname: nil, ssl_context_params: nil) @address = address @port = (port || SMTP.default_port) @esmtp = true @capabilities = nil @socket = nil @started = false @open_timeout = 30 @read_timeout = 60 @error_occurred = false @debug_output = nil @tls = tls @starttls = starttls @ssl_context_tls = nil @ssl_context_starttls = nil @tls_verify = tls_verify @tls_hostname = tls_hostname @ssl_context_params = ssl_context_params end
创建新的 Net::SMTP
对象并连接到服务器。
此方法等效于
Net::SMTP.new(address, port, tls_verify: flag, tls_hostname: hostname, ssl_context_params: nil) .start(helo: helo_domain, user: account, secret: password, authtype: authtype)
另请参阅:Net::SMTP.new
,start
示例¶ ↑
Net::SMTP.start('your.smtp.server') do |smtp| smtp.send_message msgstr, '[email protected]', ['[email protected]'] end
块用法¶ ↑
如果使用块调用,则会将新打开的 Net::SMTP
对象传递给该块,并在块完成时自动关闭。如果未带块调用,则会将新打开的 Net::SMTP
对象返回给调用方,并且调用方有责任在完成时将其关闭。
参数¶ ↑
address
是您的 smtp 服务器的主机名或 IP 地址。
port
是要连接的端口;它默认为端口 25。
helo
是客户端提供给服务器的 HELO 域名(请参阅概述注释);它默认为“localhost”。
如果 tls
为 true,则启用 TLS。默认值为 false。如果 starttls
为 :always,则启用 STARTTLS;如果为 :auto
,则在服务器支持时使用 STARTTLS;如果为 false,则禁用 STARTTLS。
如果 tls_verify
为 true,则验证服务器的证书。默认值为 true。如果服务器证书中的主机名与 address
不同,则可以使用 tls_hostname
指定。
可以将其他 SSLContext 参数添加到 ssl_context_params
哈希参数中,并将其传递给 OpenSSL::SSL::SSLContext#set_params。
tls_verify: true
等效于 ssl_context_params: { verify_mode: OpenSSL::SSL::VERIFY_PEER }
。
如果需要或期望,其余参数将用于 SMTP 身份验证。
authtype
是 SASL 身份验证机制。
user
是身份验证或授权身份。
secret
或 password
是您的密码或其他身份验证令牌。
这些将作为位置参数发送到 authenticate
,确切的语义取决于 authtype
。
请参阅概述注释中关于 Net::SMTP
的 SMTP 身份验证的讨论。
错误¶ ↑
此方法可能会引发
-
Net::OpenTimeout
-
Net::ReadTimeout
-
IOError
# File net-smtp-0.5.0/lib/net/smtp.rb, line 539 def SMTP.start(address, port = nil, *args, helo: nil, user: nil, secret: nil, password: nil, authtype: nil, tls: false, starttls: :auto, tls_verify: true, tls_hostname: nil, ssl_context_params: nil, &block) raise ArgumentError, "wrong number of arguments (given #{args.size + 2}, expected 1..6)" if args.size > 4 helo ||= args[0] || 'localhost' user ||= args[1] secret ||= password || args[2] authtype ||= args[3] new(address, port, tls: tls, starttls: starttls, tls_verify: tls_verify, tls_hostname: tls_hostname, ssl_context_params: ssl_context_params).start(helo: helo, user: user, secret: secret, authtype: authtype, &block) end
公共实例方法
返回服务器是否声明支持身份验证类型。在打开 SMTP
会话之前,您无法获得有效的结果。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 329 def auth_capable?(type) return nil unless @capabilities return false unless @capabilities['AUTH'] @capabilities['AUTH'].include?(type) end
使用“AUTH”命令向服务器进行身份验证。
authtype
是 SASL 身份验证机制的名称。
除了 authtype
之外的所有参数都会被转发给身份验证器。不同的身份验证器可能会以不同的方式解释 user
和 secret
参数。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 872 def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE) check_auth_args authtype, user, secret authenticator = Authenticator.auth_class(authtype).new(self) authenticator.auth(user, secret) end
如果 EHLO 响应包含 key
,则返回 true。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 301 def capable?(key) return nil unless @capabilities @capabilities[key] ? true : false end
返回此服务器支持的身份验证方法。在打开 SMTP
会话之前,您无法获得有效值。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 337 def capable_auth_types return [] unless @capabilities return [] unless @capabilities['AUTH'] @capabilities['AUTH'] end
如果服务器声明支持 AUTH CRAM-MD5,则返回 true。在打开 SMTP
会话之前,您无法获得有效值。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 323 def capable_cram_md5_auth? auth_capable?('CRAM-MD5') end
如果服务器声明支持 AUTH LOGIN,则返回 true。在打开 SMTP
会话之前,您无法获得有效值。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 317 def capable_login_auth? auth_capable?('LOGIN') end
如果服务器声明支持 AUTH PLAIN,则返回 true。在打开 SMTP
会话之前,您无法获得有效值。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 311 def capable_plain_auth? auth_capable?('PLAIN') end
如果服务器声明支持 STARTTLS,则返回 true。在打开 SMTP
会话之前,您无法获得有效值。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 296 def capable_starttls? capable?('STARTTLS') end
此方法发送消息。如果给定 msgstr
,则将其作为消息发送。如果给定块,则产生一个消息写入器流。您必须在块关闭之前写入消息。
# Example 1 (by string) smtp.data(<<EndMessage) From: [email protected] To: [email protected] Subject: I found a bug Check vm.c:58879. EndMessage # Example 2 (by block) smtp.data {|f| f.puts "From: [email protected]" f.puts "To: [email protected]" f.puts "Subject: I found a bug" f.puts "" f.puts "Check vm.c:58879." }
# File net-smtp-0.5.0/lib/net/smtp.rb, line 958 def data(msgstr = nil, &block) #:yield: stream if msgstr and block raise ArgumentError, "message and block are exclusive" end unless msgstr or block raise ArgumentError, "message or block is required" end res = critical { check_continue get_response('DATA') socket_sync_bak = @socket.io.sync begin @socket.io.sync = false if msgstr @socket.write_message msgstr else @socket.write_message_by_block(&block) end ensure @socket.io.flush @socket.io.sync = socket_sync_bak end recv_response() } check_response res res end
警告:此方法会导致严重的安全漏洞。仅用于调试时使用此方法。
设置用于调试日志的输出流。您必须在调用 start
之前调用此方法。
# example smtp = Net::SMTP.new(addr, port) smtp.set_debug_output $stderr smtp.start do |smtp| .... end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 450 def debug_output=(arg) @debug_output = arg end
禁用此对象的 SMTP/TLS (STARTTLS)。必须在建立连接之前调用此方法才能生效。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 408 def disable_starttls @starttls = false @ssl_context_starttls = nil end
禁用此对象的 SMTP/TLS。必须在建立连接之前调用此方法才能生效。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 364 def disable_tls @tls = false @ssl_context_tls = nil end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 907 def ehlo(domain) getok("EHLO #{domain}") end
为此对象启用 SMTP/TLS (STARTTLS)。context
是一个 OpenSSL::SSL::SSLContext 对象。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 390 def enable_starttls(context = nil) raise 'openssl library not installed' unless defined?(OpenSSL::VERSION) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls @starttls = :always @ssl_context_starttls = context end
如果服务器接受,则为此对象启用 SMTP/TLS (STARTTLS)。context
是一个 OpenSSL::SSL::SSLContext 对象。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 399 def enable_starttls_auto(context = nil) raise 'openssl library not installed' unless defined?(OpenSSL::VERSION) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls @starttls = :auto @ssl_context_starttls = context end
为此对象启用 SMTP/TLS (SMTPS:直接通过 TLS 连接的 SMTP)。必须在建立连接之前调用此方法才能生效。context
是一个 OpenSSL::SSL::SSLContext 对象。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 353 def enable_tls(context = nil) raise 'openssl library not installed' unless defined?(OpenSSL::VERSION) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls == :always @tls = true @ssl_context_tls = context end
完成 SMTP
会话并关闭 TCP 连接。如果未启动,则引发 IOError。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 655 def finish raise IOError, 'not yet started' unless started? do_finish end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 989 def get_response(reqline) validate_line reqline @socket.writeline reqline recv_response() end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 903 def helo(domain) getok("HELO #{domain}") end
提供类状态的人类可读字符串化。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 278 def inspect "#<#{self.class} #{@address}:#{@port} started=#{@started}>" end
from_addr
是 String
或 Net::SMTP::Address
# File net-smtp-0.5.0/lib/net/smtp.rb, line 912 def mailfrom(from_addr) addr = if requires_smtputf8(from_addr) && capable?("SMTPUTF8") Address.new(from_addr, "SMTPUTF8") else Address.new(from_addr) end getok((["MAIL FROM:<#{addr.address}>"] + addr.parameters).join(' ')) end
打开消息写入器流并将其提供给块。该流仅在块中有效,并具有以下方法
- puts(str = ”)
-
输出 STR 和 CR LF。
- print(str)
-
输出 STR。
- printf(fmt, *args)
-
输出 sprintf(fmt,*args)。
- write(str)
-
输出 STR 并返回写入的字节长度。
- <<(str)
-
输出 STR 并返回 self。
如果在消息中找到单个 CR (“r”) 或 LF (“n”),则将其转换为 CR LF 对。您不能使用此方法发送二进制消息。
参数¶ ↑
from_addr
是一个 String 或 Net::SMTP::Address
,表示源邮件地址。
to_addr
是一个 String 或 Net::SMTP::Address
或它们的数组,表示目标邮件地址或多个地址。
示例¶ ↑
Net::SMTP.start('smtp.example.com', 25) do |smtp| smtp.open_message_stream('[email protected]', ['[email protected]']) do |f| f.puts 'From: [email protected]' f.puts 'To: [email protected]' f.puts 'Subject: test message' f.puts f.puts 'This is a test message.' end end
错误¶ ↑
此方法可能会引发
-
Net::ReadTimeout
-
IOError
# File net-smtp-0.5.0/lib/net/smtp.rb, line 849 def open_message_stream(from_addr, *to_addrs, &block) # :yield: stream to_addrs.flatten! raise IOError, 'closed session' unless @socket from_addr = Address.new(from_addr, 'SMTPUTF8') if any_require_smtputf8(to_addrs) && capable?('SMTPUTF8') mailfrom from_addr rcptto_list(to_addrs) {data(&block)} end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 985 def quit getok('QUIT') end
to_addr
是 String
或 Net::SMTP::Address
# File net-smtp-0.5.0/lib/net/smtp.rb, line 930 def rcptto(to_addr) addr = Address.new(to_addr) getok((["RCPT TO:<#{addr.address}>"] + addr.parameters).join(' ')) end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 921 def rcptto_list(to_addrs) raise ArgumentError, 'mail destination not given' if to_addrs.empty? to_addrs.flatten.each do |addr| rcptto addr end yield end
设置等待直到读取 (2) 调用超时的秒数。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 431 def read_timeout=(sec) @socket.read_timeout = sec if @socket @read_timeout = sec end
中止当前邮件事务
# File net-smtp-0.5.0/lib/net/smtp.rb, line 895 def rset getok('RSET') end
将 msgstr
作为消息发送。在 msgstr
中找到的单个 CR (“r”) 和 LF (“n”) 会转换为 CR LF 对。您不能使用此方法发送二进制消息。msgstr
应包括消息头和正文。
from_addr
是一个 String 或 Net::SMTP::Address
,表示源邮件地址。
to_addr
是一个 String 或 Net::SMTP::Address
或它们的数组,表示目标邮件地址或多个地址。
示例¶ ↑
Net::SMTP.start('smtp.example.com') do |smtp| smtp.send_message msgstr, '[email protected]', ['[email protected]', '[email protected]'] end Net::SMTP.start('smtp.example.com') do |smtp| smtp.send_message msgstr, Net::SMTP::Address.new('[email protected]', size: 12345), Net::SMTP::Address.new('[email protected]', notify: :success) end
错误¶ ↑
此方法可能会引发
-
Net::ReadTimeout
-
IOError
# File net-smtp-0.5.0/lib/net/smtp.rb, line 794 def send_message(msgstr, from_addr, *to_addrs) to_addrs.flatten! raise IOError, 'closed session' unless @socket from_addr = Address.new(from_addr, 'SMTPUTF8') if any_require_smtputf8(to_addrs) && capable?('SMTPUTF8') mailfrom from_addr rcptto_list(to_addrs) {data msgstr} end
打开 TCP 连接并启动 SMTP
会话。
参数¶ ↑
helo
是您将从中发送邮件的 HELO 域;请参阅概述说明中的讨论。
如果需要或期望,其余参数将用于 SMTP 身份验证。
authtype
是 SASL 身份验证机制。
user
是身份验证或授权身份。
secret
或 password
是您的密码或其他身份验证令牌。
这些将作为位置参数发送到 authenticate
,确切的语义取决于 authtype
。
请参阅概述注释中关于 Net::SMTP
的 SMTP 身份验证的讨论。
另请参阅:Net::SMTP.start
块用法¶ ↑
当使用块调用此方法时,会将新启动的 SMTP
对象提供给块,并在块调用完成后自动关闭。否则,调用者有责任在完成后关闭会话。
示例¶ ↑
这与类方法 SMTP.start
非常相似。
require 'net/smtp' smtp = Net::SMTP.new('smtp.mail.server', 25) smtp.start(helo: helo_domain, user: account, secret: password, authtype: authtype) do |smtp| smtp.send_message msgstr, '[email protected]', ['[email protected]'] end
此方法(与 SMTP.start
相对)的主要用途可能是设置调试(set_debug_output
)或 ESMTP(esmtp=
),必须在会话启动之前完成。
错误¶ ↑
如果会话已启动,则将引发 IOError。
此方法可能会引发
-
Net::OpenTimeout
-
Net::ReadTimeout
-
IOError
# File net-smtp-0.5.0/lib/net/smtp.rb, line 622 def start(*args, helo: nil, user: nil, secret: nil, password: nil, authtype: nil) raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..4)" if args.size > 4 helo ||= args[0] || 'localhost' user ||= args[1] secret ||= password || args[2] authtype ||= args[3] if defined?(OpenSSL::VERSION) ssl_context_params = @ssl_context_params || {} unless ssl_context_params.has_key?(:verify_mode) ssl_context_params[:verify_mode] = @tls_verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE end if @tls && @ssl_context_tls.nil? @ssl_context_tls = SMTP.default_ssl_context(ssl_context_params) end if @starttls && @ssl_context_starttls.nil? @ssl_context_starttls = SMTP.default_ssl_context(ssl_context_params) end end if block_given? begin do_start helo, user, secret, authtype return yield(self) ensure do_finish end else do_start helo, user, secret, authtype return self end end
如果已启动 SMTP 会话,则返回 true
。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 553 def started? @started end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 899 def starttls getok('STARTTLS') end
如果此对象使用 STARTTLS,则返回真值。如果此对象始终使用 STARTTLS,则返回 :always。如果此对象在服务器支持 TLS 时使用 STARTTLS,则返回 :auto。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 374 def starttls? @starttls end
如果此对象使用 STARTTLS,则返回 true。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 379 def starttls_always? @starttls == :always end
如果此对象在服务器声明支持 STARTTLS 时使用 STARTTLS,则返回 true。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 384 def starttls_auto? @starttls == :auto end
如果此对象使用 SMTP/TLS (SMTPS),则返回 true。
# File net-smtp-0.5.0/lib/net/smtp.rb, line 344 def tls? @tls end
私有实例方法
# File net-smtp-0.5.0/lib/net/smtp.rb, line 748 def any_require_smtputf8(addresses) addresses.any?{ |a| requires_smtputf8(a) } end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 880 def check_auth_args(type, *args, **kwargs) type ||= DEFAULT_AUTH_TYPE klass = Authenticator.auth_class(type) or raise ArgumentError, "wrong authentication type #{type}" klass.check_args(*args, **kwargs) end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1040 def check_continue(res) unless res.continue? raise SMTPUnknownError.new(res, message: "could not get 3xx (#{res.status}: #{res.string})") end end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1034 def check_response(res) unless res.success? raise res.exception_class.new(res) end end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1024 def critical return Response.parse('200 dummy reply code') if @error_occurred begin return yield() rescue Exception @error_occurred = true raise end end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 731 def do_finish quit if @socket and not @socket.closed? and not @error_occurred ensure @started = false @error_occurred = false @socket.close if @socket @socket = nil end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 719 def do_helo(helo_domain) res = @esmtp ? ehlo(helo_domain) : helo(helo_domain) @capabilities = res.capabilities rescue SMTPError if @esmtp @esmtp = false @error_occurred = false retry end raise end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 666 def do_start(helo_domain, user, secret, authtype) raise IOError, 'SMTP session already started' if @started if user || secret || authtype check_auth_args authtype, user, secret end s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do tcp_socket(@address, @port) end logging "Connection opened: #{@address}:#{@port}" @socket = new_internet_message_io(tls? ? tlsconnect(s, @ssl_context_tls) : s) check_response critical { recv_response() } do_helo helo_domain if ! tls? and (starttls_always? or (capable_starttls? and starttls_auto?)) unless capable_starttls? raise SMTPUnsupportedCommand, "STARTTLS is not supported on this server" end starttls @socket = new_internet_message_io(tlsconnect(s, @ssl_context_starttls)) # helo response may be different after STARTTLS do_helo helo_domain end authenticate user, secret, (authtype || DEFAULT_AUTH_TYPE) if user @started = true ensure unless @started # authentication failed, cancel connection. s.close if s @socket = nil end end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1004 def getok(reqline) validate_line reqline res = critical { @socket.writeline reqline recv_response() } check_response res res end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1125 def logging(msg) @debug_output << msg + "\n" if @debug_output end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 714 def new_internet_message_io(s) InternetMessageIO.new(s, read_timeout: @read_timeout, debug_output: @debug_output) end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1014 def recv_response buf = ''.dup while true line = @socket.readline buf << line << "\n" break unless line[3,1] == '-' # "210-PIPELINING" end Response.parse(buf) end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 740 def requires_smtputf8(address) if address.kind_of? Address !address.address.ascii_only? else !address.ascii_only? end end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 697 def ssl_socket(socket, context) OpenSSL::SSL::SSLSocket.new socket, context end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 662 def tcp_socket(address, port) TCPSocket.open address, port end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 701 def tlsconnect(s, context) verified = false s = ssl_socket(s, context) logging "TLS connection started" s.sync_close = true s.hostname = @tls_hostname || @address ssl_socket_connect(s, @open_timeout) verified = true s ensure s.close unless verified end
# File net-smtp-0.5.0/lib/net/smtp.rb, line 997 def validate_line(line) # A bare CR or LF is not allowed in RFC5321. if /[\r\n]/ =~ line raise ArgumentError, "A line must not contain CR or LF" end end