Ruby 2.4

Net::SMTP

class Net::SMTP

Parent:Net::Protocol

What is This Library?

此库提供了通过SMTP(简单邮件传输协议)发送Internet邮件的功能。有关SMTP本身的详细信息,请参阅RFC2821。

What is This Library NOT?

这个库不提供编写网络邮件的功能。你必须自己创建它们。如果您想要更好的邮件支持,请尝试RubyMail或TMail或在RubyGems.orgRuby工具箱中搜索替代方案。

FYI:Internet邮件的官方文档是:RFC2822。

Examples

Sending Messages

在发送消息之前,您必须打开与SMTP服务器的连接。第一个参数是您的SMTP服务器的地址,第二个参数是端口号。使用::开始一个块是最简单的方法。这样,在执行该块后,SMTP连接会自动关闭。

require 'net/smtp' Net::SMTP.start('your.smtp.server', 25) do |smtp| # Use the SMTP object smtp only in this block. end

用你的SMTP服务器替换'your.smtp.server'。通常您的系统管理员或互联网提供商为您提供服务器。

然后你可以发送消息。

msgstr = <<END_OF_MESSAGE From: Your Name <your@mail.address> To: Destination Address <someone@example.com> Subject: test message Date: Sat, 23 Jun 2001 16:26:43 +0900 Message-Id: <unique.message.id.string@example.com> This is a test message. END_OF_MESSAGE require 'net/smtp' Net::SMTP.start('your.smtp.server', 25) do |smtp| smtp.send_message msgstr, 'your@mail.address', 'his_address@example.com' end

Closing the Session

您必须在发送消息后通过调用finish方法关闭SMTP会话:

# using SMTP#finish smtp = Net::SMTP.start('your.smtp.server', 25) smtp.send_message msgstr, 'from@address', 'to@address' smtp.finish

您还可以使用:: 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 domain

在几乎所有情况下,您必须提供第三个参数:: start / SMTP#start。这是您所在的域名(主机发送邮件)。它被称为“HELO域”。SMTP服务器将通过检查HELO域来判断它是否应发送或拒绝SMTP会话。

Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain') { |smtp| ... }

SMTP Authentication

Net :: SMTP类支持三种认证方案; PLAIN,LOGIN和CRAM MD5。(SMTP验证:RFC2554)要使用SMTP验证,请将额外参数传递给:: start / SMTP#start。

# PLAIN Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', 'Your Account', 'Your Password', :plain) # LOGIN Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', 'Your Account', 'Your Password', :login) # CRAM MD5 Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', 'Your Account', 'Your Password', :cram_md5)

常量

CRAM_BUFSIZE DEFAULT_AUTH_TYPE

认证

IMASK OMASK Revision

Attributes

addressR

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

esmtpRW

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

esmtp?RW

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

open_timeoutRW

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

portR

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

read_timeoutR

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

Public Class Methods

default_port() Show source

默认的SMTP端口号,25。

# File lib/net/smtp.rb, line 174 def SMTP.default_port 25 end

default_ssl_context()显示源文件

# File lib/net/smtp.rb, line 192 def SMTP.default_ssl_context OpenSSL::SSL::SSLContext.new end

default_ssl_port()

别名为:default_tls_port

default_submission_port() Show source

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

# File lib/net/smtp.rb, line 179 def SMTP.default_submission_port 587 end

default_tls_port() Show source

默认的SMTPS端口号,465。

# File lib/net/smtp.rb, line 184 def SMTP.default_tls_port 465 end

另外别名为:default_ssl_port

new(address, port = nil) Show source

创建一个新的Net :: SMTP对象。

address是您的SMTP服务器的主机名或IP地址。port是连接的端口; 它默认为端口25。

此方法不会打开TCP连接。如果你想一次做所有事情,你可以使用:: start而不是:: new。否则,请使用#start追踪:: new。

# File lib/net/smtp.rb, line 207 def initialize(address, port = 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 = false @starttls = false @ssl_context = nil end

start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... } Show source

创建一个新的Net :: SMTP对象并连接到服务器。

这种方法相当于:

Net::SMTP.new(address, port).start(helo_domain, account, password, authtype)

Example

Net::SMTP.start('your.smtp.server') do |smtp| smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] end

Block Usage

如果使用块调用,则新打开的Net :: SMTP对象被赋予块,并在块完成时自动关闭。如果在没有阻止的情况下调用,则新打开的Net :: SMTP对象将返回给调用者,并且调用者有责任在完成时关闭它。

Parameters

address 是您的smtp服务器的主机名或IP地址。

port是连接的端口; 它默认为端口25。

helo是客户端提供给服务器的HELO (请参阅概述注释); 它默认为'localhost'。

如果需要或需要,其余参数用于SMTP验证。user是帐户名称; secret是您的密码或其他身份验证令牌; 并且authtype是身份验证类型,其中包括:plain,:login或:cram_md5。请参阅概述说明中有关SMTP身份验证的讨论。

Errors

这种方法可能会引起:

  • Net::SMTPAuthenticationError

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::OpenTimeout

  • Net::ReadTimeout

  • IOError

# File lib/net/smtp.rb, line 451 def SMTP.start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil, &block) # :yield: smtp new(address, port).start(helo, user, secret, authtype, &block) end

公共实例方法

auth_cram_md5(user, secret) Show source

# File lib/net/smtp.rb, line 750 def auth_cram_md5(user, secret) check_auth_args user, secret res = critical { res0 = get_response('AUTH CRAM-MD5') check_auth_continue res0 crammed = cram_md5_response(secret, res0.cram_md5_challenge) get_response(base64_encode("#{user} #{crammed}")) } check_auth_response res res end

auth_login(user, secret) Show source

# File lib/net/smtp.rb, line 739 def auth_login(user, secret) check_auth_args user, secret res = critical { check_auth_continue get_response('AUTH LOGIN') check_auth_continue get_response(base64_encode(user)) get_response(base64_encode(secret)) } check_auth_response res res end

auth_plain(user, secret) Show source

# File lib/net/smtp.rb, line 730 def auth_plain(user, secret) check_auth_args user, secret res = critical { get_response('AUTH PLAIN ' + base64_encode("\0#{user}\0#{secret}")) } check_auth_response res res end

authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE) Show source

# File lib/net/smtp.rb, line 724 def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE) check_auth_method authtype check_auth_args user, secret send auth_method(authtype), user, secret end

capable_auth_types() Show source

返回此服务器上支持的身份验证方法 在打开SMTP会话之前,您无法获得有效的值。

# File lib/net/smtp.rb, line 279 def capable_auth_types return [] unless @capabilities return [] unless @capabilities['AUTH'] @capabilities['AUTH'] end

capable_cram_md5_auth?() Show source

如果服务器通告AUTH CRAM-MD5,则为true。在打开SMTP会话之前,您无法获得有效的值。

# File lib/net/smtp.rb, line 266 def capable_cram_md5_auth? auth_capable?('CRAM-MD5') end

capable_login_auth?() Show source

如果服务器通告AUTH LOGIN,则为true。在打开SMTP会话之前,您无法获得有效的值。

# File lib/net/smtp.rb, line 260 def capable_login_auth? auth_capable?('LOGIN') end

capable_plain_auth?() Show source

如果服务器通告AUTH PLAIN,则为true。在打开SMTP会话之前,您无法获得有效的值。

# File lib/net/smtp.rb, line 254 def capable_plain_auth? auth_capable?('PLAIN') end

capable_starttls?() Show source

如果服务器宣传STARTTLS,则为true。在打开SMTP会话之前,您无法获得有效的值。

# File lib/net/smtp.rb, line 242 def capable_starttls? capable?('STARTTLS') end

data(msgstr = nil) { |stream| ... } Show source

此方法发送消息。如果msgstr给出,则将其作为消息发送。如果给出块,则产生消息编写器流。您必须在该块关闭前写入消息。

# Example 1 (by string) smtp.data("From: john@example.com To: betty@example.com Subject: I found a bug Check vm.c:58879. ") # Example 2 (by block) smtp.data {|f| f.puts "From: john@example.com" f.puts "To: betty@example.com" f.puts "Subject: I found a bug" f.puts "" f.puts "Check vm.c:58879." }

# File lib/net/smtp.rb, line 890 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) Show source

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

设置输出流以进行调试日志记录。你必须在开始之前调用它。

# example smtp = Net::SMTP.new(addr, port) smtp.set_debug_output $stderr smtp.start do |smtp| .... end

# File lib/net/smtp.rb, line 392 def debug_output=(arg) @debug_output = arg end

Also aliased as: set_debug_output

disable_ssl()

Alias for: disable_tls

disable_starttls() Show source

禁用此对象的SMTP / TLS(STARTTLS)。必须在建立连接之前调用才能起作用。

# File lib/net/smtp.rb, line 350 def disable_starttls @starttls = false @ssl_context = nil end

disable_tls() Show source

禁用此对象的SMTP / TLS。必须在建立连接之前调用才能起作用。

# File lib/net/smtp.rb, line 306 def disable_tls @tls = false @ssl_context = nil end

Also aliased as: disable_ssl

ehlo(domain) Show source

# File lib/net/smtp.rb, line 828 def ehlo(domain) getok("EHLO #{domain}") end

enable_ssl(context = SMTP.default_ssl_context)

Alias for: enable_tls

enable_starttls(context = SMTP.default_ssl_context) Show source

为此对象启用SMTP / TLS(STARTTLS)。context是一个OpenSSL :: SSL :: SSLContext对象。

# File lib/net/smtp.rb, line 332 def enable_starttls(context = SMTP.default_ssl_context) raise 'openssl library not installed' unless defined?(OpenSSL) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls @starttls = :always @ssl_context = context end

enable_starttls_auto(context = SMTP.default_ssl_context) Show source

如果服务器接受,则为此对象启用SMTP / TLS(STARTTLS)。context是一个OpenSSL :: SSL :: SSLContext对象。

# File lib/net/smtp.rb, line 341 def enable_starttls_auto(context = SMTP.default_ssl_context) raise 'openssl library not installed' unless defined?(OpenSSL) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls @starttls = :auto @ssl_context = context end

enable_tls(context = SMTP.default_ssl_context) Show source

为此对象启用SMTP / TLS(SMTPS:通过直接TLS连接的SMTP)。必须在建立连接之前调用才能起作用。context是一个OpenSSL :: SSL :: SSLContext对象。

# File lib/net/smtp.rb, line 295 def enable_tls(context = SMTP.default_ssl_context) raise 'openssl library not installed' unless defined?(OpenSSL) raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls @tls = true @ssl_context = context end

Also aliased as: enable_ssl

finish() Show source

完成SMTP会话并关闭TCP连接。如果未启动,则引发IOError。

# File lib/net/smtp.rb, line 530 def finish raise IOError, 'not yet started' unless started? do_finish end

helo(domain) Show source

# File lib/net/smtp.rb, line 824 def helo(domain) getok("HELO #{domain}") end

inspect() Show source

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

# File lib/net/smtp.rb, line 224 def inspect "#<#{self.class} #{@address}:#{@port} started=#{@started}>" end

mailfrom(from_addr) Show source

# File lib/net/smtp.rb, line 832 def mailfrom(from_addr) if $SAFE > 0 raise SecurityError, 'tainted from_addr' if from_addr.tainted? end getok("MAIL FROM:<#{from_addr}>") end

open_message_stream(from_addr, *to_addrs) { |stream| ... } Show source

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

puts(str = '')

outputs STR and CR LF.

print(str)

outputs STR.

printf(fmt, *args)

outputs sprintf(fmt,*args).

write(str)

输出STR并返回写入字节的长度。

<<(str)

输出STR并返回自我。

如果在消息中找到单个CR(“r”)或LF(“n”),它将转换为CR LF对。您无法使用此方法发送二进制消息。

参数

from_addr 是表示源邮件地址的字符串。

to_addr 是一个字符串或字符串或字符串数​​组,表示目标邮件地址或地址。

Example

Net::SMTP.start('smtp.example.com', 25) do |smtp| smtp.open_message_stream('from@example.com', ['dest@example.com']) do |f| f.puts 'From: from@example.com' f.puts 'To: dest@example.com' f.puts 'Subject: test message' f.puts f.puts 'This is a test message.' end end

Errors

这种方法可能会引起:

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::ReadTimeout

  • IOError

# File lib/net/smtp.rb, line 708 def open_message_stream(from_addr, *to_addrs, &block) # :yield: stream raise IOError, 'closed session' unless @socket mailfrom from_addr rcptto_list(to_addrs) {data(&block)} end

还有别名:ready

quit() Show source

# File lib/net/smtp.rb, line 917 def quit getok('QUIT') end

rcptto(to_addr) Show source

# File lib/net/smtp.rb, line 860 def rcptto(to_addr) if $SAFE > 0 raise SecurityError, 'tainted to_addr' if to_addr.tainted? end getok("RCPT TO:<#{to_addr}>") end

rcptto_list(to_addrs) { || ... } Show source

# File lib/net/smtp.rb, line 839 def rcptto_list(to_addrs) raise ArgumentError, 'mail destination not given' if to_addrs.empty? ok_users = [] unknown_users = [] to_addrs.flatten.each do |addr| begin rcptto addr rescue SMTPAuthenticationError unknown_users << addr.dump else ok_users << addr end end raise ArgumentError, 'mail destination not given' if ok_users.empty? ret = yield unless unknown_users.empty? raise SMTPAuthenticationError, "failed to deliver for #{unknown_users.join(', ')}" end ret end

read_timeout=(sec) Show source

设置要等到读取(2)调用超时的秒数。

# File lib/net/smtp.rb, line 373 def read_timeout=(sec) @socket.read_timeout = sec if @socket @read_timeout = sec end

ready(from_addr, *to_addrs)

别名为:open_message_stream

rset() Show source

中止当前的邮件交易

# File lib/net/smtp.rb, line 816 def rset getok('RSET') end

send_mail(msgstr, from_addr, *to_addrs)

别名为:send_message

send_message(msgstr, from_addr, *to_addrs) Show source

发送msgstr作为消息。找到的单个CR(“r”)和LF(“n”)msgstr被转换为CR LF对。您无法使用此方法发送二进制消息。msgstr应该包含消息标题和正文。

from_addr 是表示源邮件地址的字符串。

to_addr 是一个字符串或字符串或字符串数​​组,表示目标邮件地址或地址。

Example

Net::SMTP.start('smtp.example.com') do |smtp| smtp.send_message msgstr, 'from@example.com', ['dest@example.com', 'dest2@example.com'] end

Errors

这种方法可能会引起:

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::ReadTimeout

  • IOError

# File lib/net/smtp.rb, line 655 def send_message(msgstr, from_addr, *to_addrs) raise IOError, 'closed session' unless @socket 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 | ...}显示源文件

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

Parameters

helo是您将派遣邮件的HELO 域名 ; 请参阅概述说明中的讨论。

如果这两个usersecret给出,SMTP身份验证将使用AUTH命令进行尝试。authtype指定要尝试的认证类型; 它必须是以下之一:login,:plain和:cram_md5。请参阅概述中有关SMTP身份验证的注意事项。

Block Usage

当使用块调用此方法时,新启动的SMTP对象被赋予块,并在块调用完成后自动关闭。否则,完成后关闭会话是主叫方的责任。

Example

这与类方法:: start非常相似。

require 'net/smtp' smtp = Net::SMTP.new('smtp.mail.server', 25) smtp.start(helo_domain, account, password, authtype) do |smtp| smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] end

此方法(与:: start相反)的主要用途可能是设置调试(#set_debug_output)或ESMTP(#esmtp =),这必须在会话启动之前完成。

Errors

如果会话已经启动,则会引发IOError。

这种方法可能会引起:

  • Net::SMTPAuthenticationError

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::OpenTimeout

  • Net::ReadTimeout

  • IOError

# File lib/net/smtp.rb, line 513 def start(helo = 'localhost', user = nil, secret = nil, authtype = nil) # :yield: smtp 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?() Show source

true 如果SMTP会话已启动。

# File lib/net/smtp.rb, line 458 def started? @started end

starttls() Show source

# File lib/net/smtp.rb, line 820 def starttls getok('STARTTLS') end

starttls?() Show source

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

# File lib/net/smtp.rb, line 316 def starttls? @starttls end

starttls_always?() Show source

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

# File lib/net/smtp.rb, line 321 def starttls_always? @starttls == :always end

starttls_auto?() Show source

如果此对象在服务器通告STARTTLS时使用STARTTLS,则为true。

# File lib/net/smtp.rb, line 326 def starttls_auto? @starttls == :auto end

tls?() Show source

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

# File lib/net/smtp.rb, line 286 def tls? @tls end

Also aliased as: ssl?

私有实例方法

auth_capable?(type) Show source

# File lib/net/smtp.rb, line 270 def auth_capable?(type) return nil unless @capabilities return false unless @capabilities['AUTH'] @capabilities['AUTH'].include?(type) end

auth_method(type) Show source

# File lib/net/smtp.rb, line 770 def auth_method(type) "auth_#{type.to_s.downcase}".intern end

base64_encode(str) Show source

# File lib/net/smtp.rb, line 783 def base64_encode(str) # expects "str" may not become too long [str].pack('m0') end

capable?(key) Show source

# File lib/net/smtp.rb, line 246 def capable?(key) return nil unless @capabilities @capabilities[key] ? true : false end

check_auth_args(用户,秘密,authtype = DEFAULT_AUTH_TYPE)显示源

# File lib/net/smtp.rb, line 774 def check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE) unless user raise ArgumentError, 'SMTP-AUTH requested but missing user name' end unless secret raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase' end end

check_auth_continue(res) Show source

# File lib/net/smtp.rb, line 984 def check_auth_continue(res) unless res.continue? raise res.exception_class, res.message end end

check_auth_method(type) Show source

# File lib/net/smtp.rb, line 764 def check_auth_method(type) unless respond_to?(auth_method(type), true) raise ArgumentError, "wrong authentication type #{type}" end end

check_auth_response(res) Show source

# File lib/net/smtp.rb, line 978 def check_auth_response(res) unless res.success? raise SMTPAuthenticationError, res.message end end

check_continue(res) Show source

# File lib/net/smtp.rb, line 972 def check_continue(res) unless res.continue? raise SMTPUnknownError, "could not get 3xx (#{res.status}: #{res.string})" end end

check_response(res) Show source

# File lib/net/smtp.rb, line 966 def check_response(res) unless res.success? raise res.exception_class, res.message end end

cram_md5_response(secret, challenge) Show source

CRAM-MD5: RFC2195

# File lib/net/smtp.rb, line 792 def cram_md5_response(secret, challenge) tmp = Digest::MD5.digest(cram_secret(secret, IMASK) + challenge) Digest::MD5.hexdigest(cram_secret(secret, OMASK) + tmp) end

cram_secret(secret, mask) Show source

# File lib/net/smtp.rb, line 799 def cram_secret(secret, mask) secret = Digest::MD5.digest(secret) if secret.size > CRAM_BUFSIZE buf = secret.ljust(CRAM_BUFSIZE, "\0") 0.upto(buf.size - 1) do |i| buf[i] = (buf[i].ord ^ mask).chr end buf end

critical() { || ... } Show source

# File lib/net/smtp.rb, line 956 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() Show source

# File lib/net/smtp.rb, line 610 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) Show source

# File lib/net/smtp.rb, line 598 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) Show source

# File lib/net/smtp.rb, line 541 def do_start(helo_domain, user, secret, authtype) raise IOError, 'SMTP session already started' if @started if user or secret check_auth_method(authtype || DEFAULT_AUTH_TYPE) check_auth_args 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) : s) check_response critical { recv_response() } do_helo helo_domain if 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)) # 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

get_response(reqline) Show source

# File lib/net/smtp.rb, line 940 def get_response(reqline) validate_line reqline @socket.writeline reqline recv_response() end

getok(reqline) Show source

# File lib/net/smtp.rb, line 930 def getok(reqline) validate_line reqline res = critical { @socket.writeline reqline recv_response() } check_response res res end

logging(msg) Show source

# File lib/net/smtp.rb, line 1069 def logging(msg) @debug_output << msg + "\n" if @debug_output end

new_internet_message_io(s) Show source

# File lib/net/smtp.rb, line 593 def new_internet_message_io(s) InternetMessageIO.new(s, read_timeout: @read_timeout, debug_output: @debug_output) end

recv_response() Show source

# File lib/net/smtp.rb, line 946 def recv_response buf = '' while true line = @socket.readline buf << line << "\n" break unless line[3,1] == '-' # "210-PIPELINING" end Response.parse(buf) end

ssl_socket(socket, context) Show source

# File lib/net/smtp.rb, line 574 def ssl_socket(socket, context) OpenSSL::SSL::SSLSocket.new socket, context end

tcp_socket(address, port) Show source

# File lib/net/smtp.rb, line 537 def tcp_socket(address, port) TCPSocket.open address, port end

tlsconnect(s) Show source

# File lib/net/smtp.rb, line 578 def tlsconnect(s) verified = false s = ssl_socket(s, @ssl_context) logging "TLS connection started" s.sync_close = true ssl_socket_connect(s, @open_timeout) if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE s.post_connection_check(@address) end verified = true s ensure s.close unless verified end

validate_line(line) Show source

# File lib/net/smtp.rb, line 923 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