Spec-Zone.ru › Ruby 2.7

class Net::SMTP

Parent:
Net::Protocol

Что представляет собой эта библиотека?

Эта библиотека предоставляет функциональность для отправки почты по интернету через SMTP, протокол Simple Mail Transfer Protocol. Для получения подробной информации о самом SMTP, см. [RFC2821] (www.ietf.org/rfc/rfc2821.txt).

Что эта библиотека НЕ делает?

Эта библиотека НЕ предоставляет функции для создания почтовых сообщений. Вы должны создавать их самостоятельно. Если вам нужна лучшая поддержка почты, попробуйте RubyMail или TMail или найдите альтернативы на RubyGems.org или The Ruby Toolbox.

Для справки: официальная документация по интернету почте: [RFC2822] (www.ietf.org/rfc/rfc2822.txt).

Примеры

Отправка сообщений

Перед отправкой сообщений необходимо открыть соединение с сервером 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 <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

Закрытие сеанса

ОБЯЗАТЕЛЬНО закройте сеанс SMTP после отправки сообщений, вызвав метод finish:

# 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 определит, должен ли он отправить или отклонить сеанс SMTP, проанализировав домен HELO.

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

SMTP Аутентификация

Класс Net::SMTP поддерживает три схемы аутентификации: PLAIN, LOGIN и CRAM MD5. (SMTP Аутентификация: [RFC2554]) Для использования аутентификации SMTP, передайте дополнительные аргументы в 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
Ревизия
Версия

Атрибуты

address[R]

Адрес сервера SMTP для подключения.

esmtp[RW]

Указывает, использовать ли ESMTP. Это нужно сделать перед вызовом start. Обратите внимание, что если start вызывается в режиме ESMTP, и подключение терпит неудачу из-за ProtocolError, объект SMTP автоматически переключится на обычный режим SMTP и повторит попытку (но не наоборот).

esmtp?[RW]

Указывает, использовать ли ESMTP. Это нужно сделать перед вызовом start. Обратите внимание, что если start вызывается в режиме ESMTP, и подключение терпит неудачу из-за ProtocolError, объект SMTP автоматически переключится на обычный режим SMTP и повторит попытку (но не наоборот).

open_timeout[RW]

Секунды ожидания при попытке открытия соединения. Если соединение не может быть открыто в течение этого времени, возникает Net::OpenTimeout. Значение по умолчанию — 30 секунд.

port[R]

Порт сервера SMTP для подключения.

read_timeout[R]

Секунды ожидания при чтении блока (одним вызовом read(2)). Если вызов read(2) не завершится в течение этого времени, возникает Net::ReadTimeout. Значение по умолчанию — 60 секунд.

Методы публичного класса

default_port() Показать исходный код
# File lib/net/smtp.rb, line 175
def SMTP.default_port
  25
end

Порт по умолчанию сервера SMTP, 25.

default_ssl_context() Показать исходный код
# File lib/net/smtp.rb, line 193
def SMTP.default_ssl_context
  OpenSSL::SSL::SSLContext.new
end
default_ssl_port()
Псевдоним для: default_tls_port
default_submission_port() Показать исходный код
# File lib/net/smtp.rb, line 180
def SMTP.default_submission_port
  587
end

Порт по умолчанию для отправки почты, 587.

default_tls_port() Показать исходный код
# File lib/net/smtp.rb, line 185
def SMTP.default_tls_port
  465
end

Порт SMTPS по умолчанию, 465.

Также псевдоним для: default_ssl_port
new(address, port = nil) Показать исходный код
# File lib/net/smtp.rb, line 208
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

Создаёт новый объект Net::SMTP.

address — имя хоста или IP-адрес вашего сервера SMTP. port — порт для подключения; по умолчанию — порт 25.

Этот метод не открывает TCP-соединение. Вы можете использовать SMTP.start вместо SMTP.new, если хотите сделать всё сразу. В противном случае выполните SMTP.new с SMTP#start.

start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... } Показать исходный код
# File lib/net/smtp.rb, line 452
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

Создаёт новый объект Net::SMTP и подключается к серверу.

Этот метод эквивалентен:

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

Пример

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

Использование блока

Если вызов сопровождается блоком, вновь открытый объект Net::SMTP передаётся в блок и автоматически закрывается по завершении блока. Если вызов выполняется без блока, вновь открытый объект Net::SMTP возвращается вызывающей стороне, и ответственность за его закрытие после завершения лежит на вызывающей стороне.

Параметры

address — имя хоста или IP-адрес вашего сервера smtp.

port — порт для подключения; по умолчанию — порт 25.

helo — домен HELO, предоставляемый клиентом серверу (см. комментарии в обзоре); по умолчанию — 'localhost'.

Остальные аргументы используются для аутентификации SMTP, если она требуется или желательна. user — имя пользователя; secret — ваш пароль или другой аутентификационный токен; authtype — тип аутентификации, один из :plain, :login или :cram_md5. См. обсуждение аутентификации SMTP в примечаниях к обзору.

Ошибки

Этот метод может вызвать:

  • Net::SMTPAuthenticationError

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::OpenTimeout

  • Net::ReadTimeout

  • IOError

Методы публичного экземпляра

auth_cram_md5(user, secret) Показать исходный код
# File lib/net/smtp.rb, line 751
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) Показать исходный код
# File lib/net/smtp.rb, line 740
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) Показать исходный код
# File lib/net/smtp.rb, line 731
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) Показать исходный код
# File lib/net/smtp.rb, line 725
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() Показать исходный код
# File lib/net/smtp.rb, line 280
def capable_auth_types
  return [] unless @capabilities
  return [] unless @capabilities['AUTH']
  @capabilities['AUTH']
end

Возвращает поддерживаемые методы аутентификации на этом сервере. Вы не можете получить значение до открытия сессии SMTP.

capable_cram_md5_auth?() Показать исходный код
# File lib/net/smtp.rb, line 267
def capable_cram_md5_auth?
  auth_capable?('CRAM-MD5')
end

true, если сервер поддерживает AUTH CRAM-MD5. Вы не можете получить значение до открытия сессии SMTP.

capable_login_auth?() Показать исходный код
# File lib/net/smtp.rb, line 261
def capable_login_auth?
  auth_capable?('LOGIN')
end

true, если сервер поддерживает AUTH LOGIN. Вы не можете получить значение до открытия сессии SMTP.

capable_plain_auth?() Показать исходный код
# File lib/net/smtp.rb, line 255
def capable_plain_auth?
  auth_capable?('PLAIN')
end

true, если сервер поддерживает AUTH PLAIN. Вы не можете получить значение до открытия сессии SMTP.

capable_starttls?() Показать исходный код
# File lib/net/smtp.rb, line 243
def capable_starttls?
  capable?('STARTTLS')
end

true, если сервер поддерживает STARTTLS. Вы не можете получить значение до открытия сессии SMTP сессии.

data(msgstr = nil) { |stream| ... } Показать исходный код
# File lib/net/smtp.rb, line 885
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

Этот метод отправляет сообщение. Если msgstr задано, отправляет его как сообщение. Если задан блок, он передаёт поток записи сообщения. Вы должны записать сообщение перед закрытием блока.

# Example 1 (by string)
smtp.data(<<EndMessage)
From: john@example.com
To: betty@example.com
Subject: I found a bug

Check vm.c:58879.
EndMessage

# 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."
}
debug_output=(arg) Показать исходный код
# File lib/net/smtp.rb, line 393
def debug_output=(arg)
  @debug_output = arg
end

ПРЕДУПРЕЖДЕНИЕ: Этот метод может привести к серьёзным проблемам безопасности. Используйте этот метод только для отладки.

Устанавливает поток вывода для отладки. Вы должны вызвать его до start.

# example
smtp = Net::SMTP.new(addr, port)
smtp.set_debug_output $stderr
smtp.start do |smtp|
  ....
end
Также переименовано как: set_debug_output
disable_ssl()
Псевдоним для: disable_tls
disable_starttls() Показать исходный код
# File lib/net/smtp.rb, line 351
def disable_starttls
  @starttls = false
  @ssl_context = nil
end

Отключает SMTP/TLS (STARTTLS) для этого объекта. Должен быть вызван до установления соединения, чтобы иметь какой-либо эффект.

disable_tls() Показать исходный код
# File lib/net/smtp.rb, line 307
def disable_tls
  @tls = false
  @ssl_context = nil
end

Отключает SMTP/TLS для этого объекта. Должен быть вызван до установления соединения, чтобы иметь какой-либо эффект.

Также переименовано как: disable_ssl
ehlo(domain) Показать исходный код
# File lib/net/smtp.rb, line 829
def ehlo(domain)
  getok("EHLO #{domain}")
end
enable_ssl(context = SMTP.default_ssl_context)
Псевдоним для: enable_tls
enable_starttls(context = SMTP.default_ssl_context) Показать исходный код
# File lib/net/smtp.rb, line 333
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

Включает SMTP/TLS (STARTTLS) для этого объекта. context — это объект OpenSSL::SSL::SSLContext.

enable_starttls_auto(context = SMTP.default_ssl_context) Показать исходный код
# File lib/net/smtp.rb, line 342
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

Включает SMTP/TLS (STARTTLS) для этого объекта, если сервер его поддерживает. context — это объект OpenSSL::SSL::SSLContext.

enable_tls(context = SMTP.default_ssl_context) Показать исходный код
# File lib/net/smtp.rb, line 296
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

Включает SMTP/TLS (SMTPS: SMTP через прямое TLS-соединение) для этого объекта. Должен быть вызван до установления соединения, чтобы иметь какой-либо эффект. context — это объект OpenSSL::SSL::SSLContext.

Также переименовано как: enable_ssl
finish() Показать исходный код
# File lib/net/smtp.rb, line 531
def finish
  raise IOError, 'not yet started' unless started?
  do_finish
end

Завершает сессию SMTP и закрывает TCP-соединение. Вызывает IOError, если не начата.

helo(domain) Показать исходный код
# File lib/net/smtp.rb, line 825
def helo(domain)
  getok("HELO #{domain}")
end
inspect() Показать исходный код
# File lib/net/smtp.rb, line 225
def inspect
  "#<#{self.class} #{@address}:#{@port} started=#{@started}>"
end

Предоставляет удобочитаемую строковую интерпретацию состояния класса.

mailfrom(from_addr) Показать исходный код
# File lib/net/smtp.rb, line 833
def mailfrom(from_addr)
  getok("MAIL FROM:<#{from_addr}>")
end
END_OF_DOCUMENT_MARKER
open_message_stream(from_addr, *to_addrs) { |stream| ... } Показать исходный код
# File lib/net/smtp.rb, line 709
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

Открывает поток записи сообщения и передает его в блок. Поток действителен только в блоке и имеет следующие методы:

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, представляющий адрес источника почты.

to_addr — это String или строки или Array строк, представляющие адрес(ы) получателя почты.

Пример

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

Ошибки

Этот метод может вызвать следующие исключения:

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::ReadTimeout

  • IOError

Также алиасируется как: ready
quit() Показать исходный код
# File lib/net/smtp.rb, line 912
def quit
  getok('QUIT')
end
rcptto(to_addr) Показать исходный код
# File lib/net/smtp.rb, line 858
def rcptto(to_addr)
  getok("RCPT TO:<#{to_addr}>")
end
rcptto_list(to_addrs) { || ... } Показать исходный код
# File lib/net/smtp.rb, line 837
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) Показать исходный код
# File lib/net/smtp.rb, line 374
def read_timeout=(sec)
  @socket.read_timeout = sec if @socket
  @read_timeout = sec
end

Устанавливает количество секунд ожидания при таймауте вызова read(2).

ready(from_addr, *to_addrs)
Псевдоним для: open_message_stream
rset() Показать исходный код
# File lib/net/smtp.rb, line 817
def rset
  getok('RSET')
end

Прерывает текущую почтовую транзакцию

send_mail(msgstr, from_addr, *to_addrs)
Псевдоним для: send_message
send_message(msgstr, from_addr, *to_addrs) Показать исходный код
# File lib/net/smtp.rb, line 656
def send_message(msgstr, from_addr, *to_addrs)
  raise IOError, 'closed session' unless @socket
  mailfrom from_addr
  rcptto_list(to_addrs) {data msgstr}
end

Отправляет msgstr в качестве сообщения. Одиночные CR (“r”) и LF (“n”), найденные в msgstr, преобразуются в пару CR LF. Вы не можете отправить двоичное сообщение с помощью этого метода. msgstr должно содержать как заголовки, так и тело сообщения.

from_addr — это String, представляющий адрес источника почты.

to_addr — это String или строки или Array строк, представляющие адрес(ы) получателя почты.

Пример

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

Ошибки

Этот метод может вызвать следующие исключения:

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::ReadTimeout

  • IOError

Также алиасируется как: 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| ... } Показать исходный код
# File lib/net/smtp.rb, line 514
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

Открывает TCP-соединение и начинает сеанс SMTP.

Параметры

helo — это домен HELO, с которого будут отправляться письма; см. обсуждение в заметках об обзоре.

Если оба user и secret заданы, будет попытка аутентификации SMTP с помощью команды AUTH. authtype определяет тип аутентификации для попытки; он должен быть одним из: login, plain и cram_md5. См. заметки об аутентификации SMTP в обзоре.

Использование блока

Когда этот метод вызывается с блоком, новый запущенный объект SMTP передается в блок и автоматически закрывается после завершения вызова блока. В противном случае, ответственность за закрытие сеанса возлагается на вызывающую сторону.

Пример

Это очень похоже на метод класса SMTP.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

Основное использование этого метода (в отличие от SMTP.start) — это установка отладки (set_debug_output) или ESMTP (esmtp=), что необходимо сделать до запуска сеанса.

Ошибки

Если сеанс уже запущен, будет возбуждено исключение IOError.

Этот метод может вызвать следующие исключения:

  • Net::SMTPAuthenticationError

  • Net::SMTPServerBusy

  • Net::SMTPSyntaxError

  • Net::SMTPFatalError

  • Net::SMTPUnknownError

  • Net::OpenTimeout

  • Net::ReadTimeout

  • IOError

started?() Показать исходный код
# File lib/net/smtp.rb, line 459
def started?
  @started
end

Возвращает true, если сеанс SMTP запущен.

starttls() Показать исходный код
# File lib/net/smtp.rb, line 821
def starttls
  getok('STARTTLS')
end
starttls?() Показать исходный код
# File lib/net/smtp.rb, line 317
def starttls?
  @starttls
end

Возвращает значение true, если этот объект использует STARTTLS. Если этот объект всегда использует STARTTLS, возвращает :always. Если этот объект использует STARTTLS, когда сервер поддерживает TLS, возвращает :auto.

starttls_always?() Показать исходный код
# File lib/net/smtp.rb, line 322
def starttls_always?
  @starttls == :always
end

true, если этот объект использует STARTTLS.

starttls_auto?() Показать исходный код
# File lib/net/smtp.rb, line 327
def starttls_auto?
  @starttls == :auto
end

true, если этот объект использует STARTTLS, когда сервер рекламирует STARTTLS.

tls?() Показать исходный код
# File lib/net/smtp.rb, line 287
def tls?
  @tls
end

true, если этот объект использует SMTP/TLS (SMTPS).

Также алиасируется как: ssl?

Приватные методы экземпляра

auth_capable?(type) Показать исходный код
# File lib/net/smtp.rb, line 271
def auth_capable?(type)
  return nil unless @capabilities
  return false unless @capabilities['AUTH']
  @capabilities['AUTH'].include?(type)
end
auth_method(type) Показать исходный код
# File lib/net/smtp.rb, line 771
def auth_method(type)
  "auth_#{type.to_s.downcase}".intern
end
base64_encode(str) Показать исходный код
# File lib/net/smtp.rb, line 784
def base64_encode(str)
  # expects "str" may not become too long
  [str].pack('m0')
end
capable?(key) Показать исходный код
# File lib/net/smtp.rb, line 247
def capable?(key)
  return nil unless @capabilities
  @capabilities[key] ? true : false
end
check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE) Показать исходный код
# File lib/net/smtp.rb, line 775
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) Показать исходный код
# File lib/net/smtp.rb, line 979
def check_auth_continue(res)
  unless res.continue?
    raise res.exception_class, res.message
  end
end
check_auth_method(type) Показать исходный код
# File lib/net/smtp.rb, line 765
def check_auth_method(type)
  unless respond_to?(auth_method(type), true)
    raise ArgumentError, "wrong authentication type #{type}"
  end
end
check_auth_response(res) Показать исходный код
# File lib/net/smtp.rb, line 973
def check_auth_response(res)
  unless res.success?
    raise SMTPAuthenticationError, res.message
  end
end
check_continue(res) Показать исходный код
# File lib/net/smtp.rb, line 967
def check_continue(res)
  unless res.continue?
    raise SMTPUnknownError, "could not get 3xx (#{res.status}: #{res.string})"
  end
end
check_response(res) Показать исходный код
# File lib/net/smtp.rb, line 961
def check_response(res)
  unless res.success?
    raise res.exception_class, res.message
  end
end
cram_md5_response(secret, challenge) Показать исходный код
# File lib/net/smtp.rb, line 793
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-MD5: [RFC2195]

cram_secret(secret, mask) Показать исходный код
# File lib/net/smtp.rb, line 800
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() { || ... } Показать исходный код
# File lib/net/smtp.rb, line 951
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 lib/net/smtp.rb, line 611
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 lib/net/smtp.rb, line 599
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 lib/net/smtp.rb, line 542
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) Показать исходный код
# File lib/net/smtp.rb, line 935
def get_response(reqline)
  validate_line reqline
  @socket.writeline reqline
  recv_response()
end
getok(reqline) Показать исходный код
# File lib/net/smtp.rb, line 925
def getok(reqline)
  validate_line reqline
  res = critical {
    @socket.writeline reqline
    recv_response()
  }
  check_response res
  res
end
logging(msg) Показать исходный код
# File lib/net/smtp.rb, line 1064
def logging(msg)
  @debug_output << msg + "\n" if @debug_output
end
new_internet_message_io(s) Показать исходный код
# File lib/net/smtp.rb, line 594
def new_internet_message_io(s)
  InternetMessageIO.new(s, read_timeout: @read_timeout,
                        debug_output: @debug_output)
end
recv_response() Показать исходный код
# File lib/net/smtp.rb, line 941
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
ssl_socket(socket, context) Показать исходный код
# File lib/net/smtp.rb, line 575
def ssl_socket(socket, context)
  OpenSSL::SSL::SSLSocket.new socket, context
end
tcp_socket(address, port) Показать исходный код
# File lib/net/smtp.rb, line 538
def tcp_socket(address, port)
  TCPSocket.open address, port
end
tlsconnect(s) Показать исходный код
# File lib/net/smtp.rb, line 579
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) Показать исходный код
# File lib/net/smtp.rb, line 918
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

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API