Class: Cybertrain::Test::SmtpReceiver

Inherits:
Receiver
  • Object
show all
Defined in:
cybertrain/test/smtp_receiver.rb

Overview

A receiver for e-mail in a test: start binds a port on 127.0.0.1, the application delivers to it with tls: "none", #received_message returns what arrived. It accepts max connections (1 by default), one ReceivedMessage each.

reject: makes a step fail with the reply given, to test how the application handles a refused delivery. Its keys are :greeting, :ehlo, :mail, :rcpt, :data (the reply to DATA) and :message (the reply after the message was sent).

Examples:

require "cybertrain/test/smtp_receiver"

test "the welcome mail" do
  smtp = Cybertrain::Test::SmtpReceiver.new
  port = smtp.start
  mailer = Cybertrain::Mailer.new(host: "127.0.0.1", port: port, tls: "none", from: "app@example.com")
  Welcome.deliver(mailer, "ann@example.com")   # the code under test
  mail = smtp.received_message                          # waits at most 5 s; nil if nothing came
  smtp.stop
  assert_equal ["ann@example.com"], mail.envelope_recipients
  assert_equal "Welcome", mail.message_header("Subject")
end

a refused recipient

smtp = Cybertrain::Test::SmtpReceiver.new(reject: { rcpt: "550 5.1.1 no such user" })

Instance Attribute Summary

Attributes inherited from Receiver

#port

Instance Method Summary collapse

Methods inherited from Receiver

#serving?, #start, #stop

Constructor Details

#initialize(reject: SmtpReceiver.no_rejections, eight_bit_mime: true, auth: false, max: 1, accept_window: 10.0, read_timeout: 5.0, name: "receiver.test") ⇒ SmtpReceiver

Returns a new instance of SmtpReceiver.

Parameters:

  • reject (Hash{Symbol => String}) (defaults to: SmtpReceiver.no_rejections) —

    steps to refuse, each with the whole reply line to send (“550 5.1.1 no such user”)

  • eight_bit_mime (Boolean) (defaults to: true) —

    offer 8BITMIME in the EHLO reply

  • auth (Boolean) (defaults to: false) —

    offer AUTH PLAIN and accept any credentials (the AUTH line, credentials included, is in the transcript)

  • max (Integer) (defaults to: 1) —

    how many connections (one message each) to accept

  • accept_window (Numeric) (defaults to: 10.0) —

    seconds to wait for each connection before the receiver gives up and closes its port

  • read_timeout (Numeric) (defaults to: 5.0) —

    seconds of silence that end a connection

  • name (String) (defaults to: "receiver.test") —

    the server name in the greeting and EHLO reply



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'cybertrain/test/smtp_receiver.rb', line 144

def initialize(reject: SmtpReceiver.no_rejections, eight_bit_mime: true, auth: false, max: 1,
               accept_window: 10.0, read_timeout: 5.0, name: "receiver.test")
  super(max, accept_window, read_timeout)
  @reject_greeting = reject[:greeting].to_s
  @reject_ehlo = reject[:ehlo].to_s
  @reject_mail = reject[:mail].to_s
  @reject_rcpt = reject[:rcpt].to_s
  @reject_data = reject[:data].to_s
  @reject_message = reject[:message].to_s
  @eight_bit_mime = eight_bit_mime ? true : false
  @offer_auth = auth ? true : false
  @server_name = name.to_s
  @messages = Array.new(0) { ReceivedMessage.new("", Array.new(0) { "" }, "", Array.new(0) { "" }) }
  @lock = Mutex.new
  # The connection in progress (one at a time, on the receiver's thread).
  @from = ""
  @recipients = Array.new(0) { "" }
  @data = ""
  @commands = Array.new(0) { "" }
end

Instance Method Details

#received_message(wait = 5.0) ⇒ ReceivedMessage?

The first message, waiting at most wait seconds for its connection to end (the client’s QUIT, or the connection closing).

Parameters:

  • wait (Numeric) (defaults to: 5.0)

Returns:



170
171
172
173
174
# File 'cybertrain/test/smtp_receiver.rb', line 170

def received_message(wait = 5.0)
  return nil unless await_count(1, wait)

  @messages[0]
end

#received_messages(count = 0, wait = 5.0) ⇒ Array<ReceivedMessage>

The messages that arrived, waiting at most wait seconds for count of them (0: the receiver’s max). Fewer when the time ran out.

Parameters:

  • count (Integer) (defaults to: 0)
  • wait (Numeric) (defaults to: 5.0)

Returns:



182
183
184
185
186
187
188
189
190
191
192
# File 'cybertrain/test/smtp_receiver.rb', line 182

def received_messages(count = 0, wait = 5.0)
  await_count(count > 0 ? count : @max, wait)
  out = Array.new(0) { ReceivedMessage.new("", Array.new(0) { "" }, "", Array.new(0) { "" }) }
  n = received_count
  i = 0
  while i < n
    out << @messages[i]
    i += 1
  end
  out
end