class Net::SMTP

这个库是什么?

此库提供了通过 SMTP(简单邮件传输协议)发送互联网邮件的功能。有关 SMTP 本身的详细信息,请参阅 [RFC5321]。此库还实现了 SMTP 身份验证,这对于消息编写器向其传出 SMTP 服务器提交消息通常是必要的,请参阅 [RFC6409] 和 [SMTPUTF8],这对于发送/接收包含 ASCII 范围之外字符的地址的消息是必要的。

这个库不是什么?

此库不提供编写互联网邮件的功能。您必须自己创建它们。如果您想要更好的邮件支持,请尝试 mailrmail gem,或在 RubyGems.orgThe 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.startSMTP#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.startSMTP#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 机制:PLAINLOGIN _(已弃用)_ 和 CRAM-MD5 _(已弃用)_。

要使用 SMTP 身份验证,请将额外的参数传递给 SMTP.startSMTP#start

# PLAIN
Net::SMTP.start('your.smtp.server', 25,
                user: 'Your Account', secret: 'Your Password', authtype: :plain)

对其他 SASL 机制(例如 EXTERNALOAUTHBEARERSCRAM-SHA-256XOAUTH2)的支持将在未来的版本中添加。

LOGINCRAM-MD5 机制仍然可用于向后兼容,但已弃用,应避免使用。

常量

DEFAULT_AUTH_TYPE

身份验证

VERSION

属性

address[R]

要连接的 SMTP 服务器的地址。

capabilities[R]

通过 EHLO 响应获得的服务器功能

esmtp[RW]

设置是否使用 ESMTP。这应该在调用 start 之前完成。请注意,如果在 ESMTP 模式下调用 start,并且由于 ProtocolError 导致连接失败,则 SMTP 对象将自动切换到纯 SMTP 模式并重试(但反之则不会)。

esmtp?[RW]

设置是否使用 ESMTP。这应该在调用 start 之前完成。请注意,如果在 ESMTP 模式下调用 start,并且由于 ProtocolError 导致连接失败,则 SMTP 对象将自动切换到纯 SMTP 模式并重试(但反之则不会)。

open_timeout[RW]

尝试打开连接时等待的秒数。如果在此时间内无法打开连接,则会引发 Net::OpenTimeout。默认值为 30 秒。

port[R]

要连接的 SMTP 服务器的端口号。

read_timeout[R]

在读取一个块(通过一个 read(2) 调用)时等待的秒数。如果 read(2) 调用在此时间内未完成,则会引发 Net::ReadTimeout。默认值为 60 秒。

ssl_context_params[RW]

用于其他 SSLContext 参数的哈希。

tls_hostname[RW]

用于验证服务器证书中的主机名的主机名。

tls_verify[RW]

如果为 true,则验证服务器的证书。

公共类方法

default_port() 点击以切换源代码

默认 SMTP 端口号,25。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 198
def SMTP.default_port
  25
end
default_ssl_context(ssl_context_params = nil) 点击以切换源代码
# 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
default_ssl_port()
别名为:default_tls_port
default_submission_port() 点击以切换源代码

默认邮件提交端口号,587。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 203
def SMTP.default_submission_port
  587
end
default_tls_port() 点击以切换源代码

默认 SMTPS 端口号,465。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 208
def SMTP.default_tls_port
  465
end
也别名为:default_ssl_port
new(address, port = nil, tls: false, starttls: :auto, tls_verify: true, tls_hostname: nil, ssl_context_params: nil) 点击以切换源代码

创建新的 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
start(address, port = nil, helo: 'localhost', user: nil, secret: nil, authtype: nil, tls: false, starttls: :auto, tls_verify: true, tls_hostname: nil, ssl_context_params: nil) { |smtp| ... } 点击以切换源代码
start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... }

创建新的 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.newstart

示例

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 是身份验证或授权身份。

secretpassword 是您的密码或其他身份验证令牌。

这些将作为位置参数发送到 authenticate,确切的语义取决于 authtype

请参阅概述注释中关于 Net::SMTP 的 SMTP 身份验证的讨论。

错误

此方法可能会引发

# 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

公共实例方法

auth_capable?(type) 点击以切换源代码

返回服务器是否声明支持身份验证类型。在打开 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
authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE) 点击以切换源代码

使用“AUTH”命令向服务器进行身份验证。

authtype 是 SASL 身份验证机制的名称。

除了 authtype 之外的所有参数都会被转发给身份验证器。不同的身份验证器可能会以不同的方式解释 usersecret 参数。

# 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
capable?(key) 点击切换源代码

如果 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
capable_auth_types() 点击切换源代码

返回此服务器支持的身份验证方法。在打开 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
capable_cram_md5_auth?() 点击切换源代码

如果服务器声明支持 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
capable_login_auth?() 点击切换源代码

如果服务器声明支持 AUTH LOGIN,则返回 true。在打开 SMTP 会话之前,您无法获得有效值。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 317
def capable_login_auth?
  auth_capable?('LOGIN')
end
capable_plain_auth?() 点击切换源代码

如果服务器声明支持 AUTH PLAIN,则返回 true。在打开 SMTP 会话之前,您无法获得有效值。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 311
def capable_plain_auth?
  auth_capable?('PLAIN')
end
capable_starttls?() 点击切换源代码

如果服务器声明支持 STARTTLS,则返回 true。在打开 SMTP 会话之前,您无法获得有效值。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 296
def capable_starttls?
  capable?('STARTTLS')
end
data(msgstr = nil) { |stream| ... } 点击切换源代码

此方法发送消息。如果给定 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
debug_output=(arg) 点击切换源代码

警告:此方法会导致严重的安全漏洞。仅用于调试时使用此方法。

设置用于调试日志的输出流。您必须在调用 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
别名为:set_debug_output
disable_ssl()
别名为:disable_tls
disable_starttls() 点击切换源代码

禁用此对象的 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
disable_tls() 点击切换源代码

禁用此对象的 SMTP/TLS。必须在建立连接之前调用此方法才能生效。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 364
def disable_tls
  @tls = false
  @ssl_context_tls = nil
end
别名为:disable_ssl
ehlo(domain) 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 907
def ehlo(domain)
  getok("EHLO #{domain}")
end
enable_ssl(context = nil)
别名为:enable_tls
enable_starttls(context = nil) 点击切换源代码

为此对象启用 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
enable_starttls_auto(context = nil) 点击切换源代码

如果服务器接受,则为此对象启用 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
enable_tls(context = nil) 点击切换源代码

为此对象启用 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
别名为:enable_ssl
finish() 点击切换源代码

完成 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
get_response(reqline) 点击切换源代码
# 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
helo(domain) 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 903
def helo(domain)
  getok("HELO #{domain}")
end
inspect() 点击切换源代码

提供类状态的人类可读字符串化。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 278
def inspect
  "#<#{self.class} #{@address}:#{@port} started=#{@started}>"
end
mailfrom(from_addr) 点击切换源代码

from_addrStringNet::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
open_message_stream(from_addr, *to_addrs) { |stream| ... } 点击切换源代码

打开消息写入器流并将其提供给块。该流仅在块中有效,并具有以下方法

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

错误

此方法可能会引发

# 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
别名为:ready
quit() 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 985
def quit
  getok('QUIT')
end
rcptto(to_addr) 点击切换源代码

to_addrStringNet::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
rcptto_list(to_addrs) { || ... } 点击切换源代码
# 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
read_timeout=(sec) 点击切换源代码

设置等待直到读取 (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
ready(from_addr, *to_addrs)
rset() 点击切换源代码

中止当前邮件事务

# File net-smtp-0.5.0/lib/net/smtp.rb, line 895
def rset
  getok('RSET')
end
send_mail(msgstr, from_addr, *to_addrs)
别名为:send_message
send_message(msgstr, from_addr, *to_addrs) 点击切换源代码

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

错误

此方法可能会引发

# 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
别名为:send_mail, sendmail
sendmail(msgstr, from_addr, *to_addrs)
别名为:send_message
set_debug_output(arg)
别名为:debug_output=
ssl?()
别名为:tls?
start(helo: 'localhost', user: nil, secret: nil, authtype: nil) { |smtp| ... } 点击切换源代码
start(helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... }

打开 TCP 连接并启动 SMTP 会话。

参数

helo 是您将从中发送邮件的 HELO ;请参阅概述说明中的讨论。

如果需要或期望,其余参数将用于 SMTP 身份验证。

authtype 是 SASL 身份验证机制。

user 是身份验证或授权身份。

secretpassword 是您的密码或其他身份验证令牌。

这些将作为位置参数发送到 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。

此方法可能会引发

# 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
started?() 点击切换源代码

如果已启动 SMTP 会话,则返回 true

# File net-smtp-0.5.0/lib/net/smtp.rb, line 553
def started?
  @started
end
starttls() 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 899
def starttls
  getok('STARTTLS')
end
starttls?() 点击切换源代码

如果此对象使用 STARTTLS,则返回真值。如果此对象始终使用 STARTTLS,则返回 :always。如果此对象在服务器支持 TLS 时使用 STARTTLS,则返回 :auto。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 374
def starttls?
  @starttls
end
starttls_always?() 点击切换源代码

如果此对象使用 STARTTLS,则返回 true。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 379
def starttls_always?
  @starttls == :always
end
starttls_auto?() 点击切换源代码

如果此对象在服务器声明支持 STARTTLS 时使用 STARTTLS,则返回 true。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 384
def starttls_auto?
  @starttls == :auto
end
tls?() 点击切换源代码

如果此对象使用 SMTP/TLS (SMTPS),则返回 true。

# File net-smtp-0.5.0/lib/net/smtp.rb, line 344
def tls?
  @tls
end
别名为:ssl?

私有实例方法

any_require_smtputf8(addresses) 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 748
def any_require_smtputf8(addresses)
  addresses.any?{ |a| requires_smtputf8(a) }
end
check_auth_args(type, *args, **kwargs) 点击切换源代码
# 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
check_continue(res) 点击切换源代码
# 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
check_response(res) 点击切换源代码
# 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
critical() { || ... } 点击切换源代码
# 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
do_finish() 点击切换源代码
# 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
do_helo(helo_domain) 点击切换源代码
# 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
do_start(helo_domain, user, secret, authtype) 点击切换源代码
# 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
getok(reqline) 点击切换源代码
# 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
logging(msg) 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 1125
def logging(msg)
  @debug_output << msg + "\n" if @debug_output
end
new_internet_message_io(s) 点击切换源代码
# 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
recv_response() 点击切换源代码
# 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
requires_smtputf8(address) 点击切换源代码
# 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
ssl_socket(socket, context) 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 697
def ssl_socket(socket, context)
  OpenSSL::SSL::SSLSocket.new socket, context
end
tcp_socket(address, port) 点击切换源代码
# File net-smtp-0.5.0/lib/net/smtp.rb, line 662
def tcp_socket(address, port)
  TCPSocket.open address, port
end
tlsconnect(s, context) 点击切换源代码
# 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
validate_line(line) 点击切换源代码
# 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