ronin-support 0.3.0 → 0.4.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/ChangeLog.md +77 -7
  2. data/README.md +19 -3
  3. data/gemspec.yml +2 -2
  4. data/lib/ronin/extensions/regexp.rb +50 -2
  5. data/lib/ronin/extensions/string.rb +1 -0
  6. data/lib/ronin/formatting.rb +1 -0
  7. data/lib/ronin/formatting/extensions.rb +1 -0
  8. data/lib/ronin/formatting/extensions/binary/string.rb +56 -5
  9. data/lib/ronin/formatting/extensions/html/string.rb +6 -7
  10. data/lib/ronin/formatting/extensions/sql/string.rb +34 -0
  11. data/lib/ronin/formatting/extensions/text/string.rb +0 -180
  12. data/lib/ronin/fuzzing.rb +21 -0
  13. data/lib/ronin/fuzzing/extensions.rb +20 -0
  14. data/lib/ronin/fuzzing/extensions/string.rb +380 -0
  15. data/lib/ronin/fuzzing/fuzzing.rb +191 -0
  16. data/lib/ronin/network/esmtp.rb +94 -1
  17. data/lib/ronin/network/extensions/esmtp/net.rb +2 -82
  18. data/lib/ronin/network/extensions/http/net.rb +1 -736
  19. data/lib/ronin/network/extensions/imap/net.rb +1 -103
  20. data/lib/ronin/network/extensions/pop3/net.rb +1 -71
  21. data/lib/ronin/network/extensions/smtp/net.rb +2 -157
  22. data/lib/ronin/network/extensions/ssl/net.rb +1 -132
  23. data/lib/ronin/network/extensions/tcp/net.rb +2 -296
  24. data/lib/ronin/network/extensions/telnet/net.rb +1 -135
  25. data/lib/ronin/network/extensions/udp/net.rb +2 -214
  26. data/lib/ronin/network/http/http.rb +750 -5
  27. data/lib/ronin/network/imap.rb +105 -2
  28. data/lib/ronin/network/mixins.rb +1 -1
  29. data/lib/ronin/network/mixins/esmtp.rb +49 -52
  30. data/lib/ronin/network/mixins/http.rb +49 -53
  31. data/lib/ronin/network/mixins/imap.rb +47 -44
  32. data/lib/ronin/network/mixins/mixin.rb +58 -0
  33. data/lib/ronin/network/mixins/pop3.rb +44 -38
  34. data/lib/ronin/network/mixins/smtp.rb +49 -51
  35. data/lib/ronin/network/mixins/tcp.rb +56 -69
  36. data/lib/ronin/network/mixins/telnet.rb +57 -50
  37. data/lib/ronin/network/mixins/udp.rb +48 -52
  38. data/lib/ronin/network/network.rb +1 -0
  39. data/lib/ronin/network/pop3.rb +72 -2
  40. data/lib/ronin/network/smtp/email.rb +1 -0
  41. data/lib/ronin/network/smtp/smtp.rb +159 -3
  42. data/lib/ronin/network/ssl.rb +131 -2
  43. data/lib/ronin/network/tcp.rb +306 -1
  44. data/lib/ronin/network/telnet.rb +136 -2
  45. data/lib/ronin/network/udp.rb +229 -1
  46. data/lib/ronin/support.rb +2 -3
  47. data/lib/ronin/support/support.rb +38 -0
  48. data/lib/ronin/support/version.rb +1 -1
  49. data/lib/ronin/templates/erb.rb +2 -1
  50. data/lib/ronin/ui/output/helpers.rb +35 -1
  51. data/lib/ronin/ui/shell.rb +12 -2
  52. data/lib/ronin/wordlist.rb +157 -0
  53. data/spec/extensions/regexp_spec.rb +38 -0
  54. data/spec/formatting/html/string_spec.rb +1 -1
  55. data/spec/formatting/sql/string_spec.rb +23 -3
  56. data/spec/formatting/text/string_spec.rb +0 -110
  57. data/spec/fuzzing/string_spec.rb +158 -0
  58. data/spec/wordlist_spec.rb +65 -0
  59. metadata +35 -27
@@ -17,11 +17,8 @@
17
17
  # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
+ require 'ronin/network/mixins/mixin'
20
21
  require 'ronin/network/telnet'
21
- require 'ronin/ui/output/helpers'
22
- require 'ronin/mixin'
23
-
24
- require 'parameters'
25
22
 
26
23
  module Ronin
27
24
  module Network
@@ -40,34 +37,30 @@ module Ronin
40
37
  # * `telnet_ssl` (`Boolean`) - Enable Telnet over SSL. Defaults to `true`.
41
38
  #
42
39
  module Telnet
43
- include Mixin
44
-
45
- mixin UI::Output::Helpers, Parameters
40
+ include Mixin, Network::Telnet
46
41
 
47
- mixin do
48
- # Telnet host
49
- parameter :host, :type => String,
50
- :description => 'Telnet host'
42
+ # Telnet host
43
+ parameter :host, :type => String,
44
+ :description => 'Telnet host'
51
45
 
52
- # Telnet port
53
- parameter :port, :type => Integer,
54
- :description => 'Telnet port'
46
+ # Telnet port
47
+ parameter :port, :type => Integer,
48
+ :description => 'Telnet port'
55
49
 
56
- # Telnet user
57
- parameter :telnet_user, :type => String,
58
- :description => 'Telnet user to login as'
50
+ # Telnet user
51
+ parameter :telnet_user, :type => String,
52
+ :description => 'Telnet user to login as'
59
53
 
60
- # Telnet password
61
- parameter :telnet_password, :type => String,
62
- :description => 'Telnet password to login with'
54
+ # Telnet password
55
+ parameter :telnet_password, :type => String,
56
+ :description => 'Telnet password to login with'
63
57
 
64
- # Telnet proxy
65
- parameter :telnet_proxy, :description => 'Telnet proxy'
58
+ # Telnet proxy
59
+ parameter :telnet_proxy, :description => 'Telnet proxy'
66
60
 
67
- # Enable Telnet SSL
68
- parameter :telnet_ssl, :type => true,
69
- :description => 'Enable Telnet over SSL'
70
- end
61
+ # Enable Telnet SSL
62
+ parameter :telnet_ssl, :type => true,
63
+ :description => 'Enable Telnet over SSL'
71
64
 
72
65
  protected
73
66
 
@@ -80,7 +73,7 @@ module Ronin
80
73
  # @param [Hash] options
81
74
  # Additional options.
82
75
  #
83
- # @option options [Integer] :port (Ronin::Network::Telnet.default_port)
76
+ # @option options [Integer] :port (Network::Telnet.default_port)
84
77
  # The port to connect to.
85
78
  #
86
79
  # @option options [Boolean] :binmode
@@ -94,7 +87,7 @@ module Ronin
94
87
  # Similar to the `:output_log` option, but connection output
95
88
  # is also written in hexdump format.
96
89
  #
97
- # @option options [Regexp] :prompt (Ronin::Network::Telnet.default_prompt)
90
+ # @option options [Regexp] :prompt (Network::Telnet.default_prompt)
98
91
  # A regular expression matching the host command-line prompt
99
92
  # sequence, used to determine when a command has finished.
100
93
  #
@@ -106,7 +99,7 @@ module Ronin
106
99
  # Indicates that the connection shall behave as a normal TCP
107
100
  # connection.
108
101
  #
109
- # @option options [Integer] :timeout (Ronin::Network::Telnet.default_timeout)
102
+ # @option options [Integer] :timeout (Network::Telnet.default_timeout)
110
103
  # The number of seconds to wait before timing out both the
111
104
  # initial attempt to connect to host, and all attempts to read
112
105
  # data from the host.
@@ -115,7 +108,7 @@ module Ronin
115
108
  # The amount of time to wait after seeing what looks like
116
109
  # a prompt.
117
110
  #
118
- # @option options [Net::Telnet, IO] :proxy (Ronin::Network::Telnet.proxy)
111
+ # @option options [Net::Telnet, IO] :proxy (Network::Telnet.proxy)
119
112
  # A proxy object to used instead of opening a direct connection
120
113
  # to the host.
121
114
  #
@@ -142,20 +135,9 @@ module Ronin
142
135
  # @api public
143
136
  #
144
137
  def telnet_connect(options={},&block)
145
- options[:port] ||= self.port
146
- options[:user] ||= self.telnet_user
147
- options[:password] ||= self.telnet_password
148
-
149
- options[:proxy] ||= self.telnet_proxy
150
- options[:ssl] ||= self.telnet_ssl
138
+ print_info "Connecting to #{host_port} ..."
151
139
 
152
- if self.port
153
- print_info "Connecting to #{self.host}:#{self.port} ..."
154
- else
155
- print_info "Connecting to #{self.host} ..."
156
- end
157
-
158
- return ::Net.telnet_connect(self.host,options,&block)
140
+ return super(self.host,telnet_merge_options(options),&block)
159
141
  end
160
142
 
161
143
  #
@@ -182,16 +164,41 @@ module Ronin
182
164
  # @api public
183
165
  #
184
166
  def telnet_session(options={},&block)
185
- return telnet_connect(options) do |sess|
167
+ super(telnet_merge_options(options)) do |sess|
186
168
  yield sess if block_given?
187
- sess.close
188
169
 
189
- if self.port
190
- print_info "Disconnecting to #{self.host}:#{self.port}"
191
- else
192
- print_info "Disconnecting to #{self.host}"
193
- end
170
+ print "Logging out ..."
194
171
  end
172
+
173
+ print_info "Disconnected to #{host_port}"
174
+ return nil
175
+ end
176
+
177
+ private
178
+
179
+ #
180
+ # Merges the Telnet parameters into the options for {Network::Telnet}
181
+ # methods.
182
+ #
183
+ # @param [Hash] options
184
+ # The original options.
185
+ #
186
+ # @return [Hash]
187
+ # The merged options.
188
+ #
189
+ # @since 0.4.0
190
+ #
191
+ # @api private
192
+ #
193
+ def telnet_merge_options(options={})
194
+ options[:port] ||= self.port
195
+ options[:user] ||= self.telnet_user
196
+ options[:password] ||= self.telnet_password
197
+
198
+ options[:proxy] ||= self.telnet_proxy
199
+ options[:ssl] ||= self.telnet_ssl
200
+
201
+ return options
195
202
  end
196
203
  end
197
204
  end
@@ -17,11 +17,8 @@
17
17
  # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
+ require 'ronin/network/mixins/mixin'
20
21
  require 'ronin/network/udp'
21
- require 'ronin/ui/output/helpers'
22
- require 'ronin/mixin'
23
-
24
- require 'parameters'
25
22
 
26
23
  module Ronin
27
24
  module Network
@@ -39,35 +36,31 @@ module Ronin
39
36
  # * `server_port` (`Integer`) - UDP server port.
40
37
  #
41
38
  module UDP
42
- include Mixin
43
-
44
- mixin UI::Output::Helpers, Parameters
39
+ include Mixin, Network::UDP
45
40
 
46
- mixin do
47
- # UDP host
48
- parameter :host, :type => String,
49
- :description => 'UDP host'
41
+ # UDP host
42
+ parameter :host, :type => String,
43
+ :description => 'UDP host'
50
44
 
51
- # UDP port
52
- parameter :port, :type => Integer,
53
- :description => 'UDP port'
45
+ # UDP port
46
+ parameter :port, :type => Integer,
47
+ :description => 'UDP port'
54
48
 
55
- # UDP local host
56
- parameter :local_host, :type => String,
57
- :description => 'UDP local host'
49
+ # UDP local host
50
+ parameter :local_host, :type => String,
51
+ :description => 'UDP local host'
58
52
 
59
- # UDP local port
60
- parameter :local_port, :type => Integer,
61
- :description => 'UDP local port'
53
+ # UDP local port
54
+ parameter :local_port, :type => Integer,
55
+ :description => 'UDP local port'
62
56
 
63
- # UDP server host
64
- parameter :server_host, :type => String,
65
- :description => 'UDP server host'
57
+ # UDP server host
58
+ parameter :server_host, :type => String,
59
+ :description => 'UDP server host'
66
60
 
67
- # UDP server port
68
- parameter :server_port, :type => Integer,
69
- :description => 'UDP server port'
70
- end
61
+ # UDP server port
62
+ parameter :server_port, :type => Integer,
63
+ :description => 'UDP server port'
71
64
 
72
65
  protected
73
66
 
@@ -98,9 +91,9 @@ module Ronin
98
91
  # @api public
99
92
  #
100
93
  def udp_connect(&block)
101
- print_info "Connecting to #{self.host}:#{self.port} ..."
94
+ print_info "Connecting to #{host_port} ..."
102
95
 
103
- return ::Net.udp_connect(self.host,self.port,self.local_host,self.local_port,&block)
96
+ return super(self.host,self.port,self.local_host,self.local_port,&block)
104
97
  end
105
98
 
106
99
  #
@@ -124,10 +117,10 @@ module Ronin
124
117
  # @api public
125
118
  #
126
119
  def udp_connect_and_send(data,&block)
127
- print_info "Connecting to #{self.host}:#{self.port} ..."
120
+ print_info "Connecting to #{host_port} ..."
128
121
  print_debug "Sending data: #{data.inspect}"
129
122
 
130
- return ::Net.udp_connect_and_send(data,self.host,self.port,self.local_host,self.local_port,&block)
123
+ return super(data,self.host,self.port,self.local_host,self.local_port,&block)
131
124
  end
132
125
 
133
126
  #
@@ -148,11 +141,11 @@ module Ronin
148
141
  # @api public
149
142
  #
150
143
  def udp_session(&block)
151
- print_info "Connecting to #{self.host}:#{self.port} ..."
144
+ print_info "Connecting to #{host_port} ..."
152
145
 
153
- ::Net.udp_session(self.host,self.port,self.local_host,self.local_port,&block)
146
+ super(self.host,self.port,self.local_host,self.local_port,&block)
154
147
 
155
- print_info "Disconnected from #{self.host}:#{self.port}"
148
+ print_info "Disconnected from #{host_port}"
156
149
  return nil
157
150
  end
158
151
 
@@ -175,13 +168,9 @@ module Ronin
175
168
  # @api public
176
169
  #
177
170
  def udp_server(&block)
178
- if self.server_host
179
- print_info "Listening on #{self.server_host}:#{self.server_port} ..."
180
- else
181
- print_info "Listening on #{self.server_port} ..."
182
- end
171
+ print_info "Listening on #{server_host_port} ..."
183
172
 
184
- return ::Net.udp_server(self.server_port,self.server_host,&block)
173
+ return super(self.server_port,self.server_host,&block)
185
174
  end
186
175
 
187
176
  #
@@ -205,22 +194,29 @@ module Ronin
205
194
  # @api public
206
195
  #
207
196
  def udp_server_session(&block)
208
- if self.server_host
209
- print_info "Listening on #{self.server_host}:#{self.server_port} ..."
210
- else
211
- print_info "Listening on #{self.server_port} ..."
212
- end
197
+ print_info "Listening on #{self.server_host_port} ..."
213
198
 
214
- ::Net.udp_server_session(&block)
215
-
216
- if self.server_host
217
- print_info "Closed #{self.server_host}:#{self.server_port}"
218
- else
219
- print_info "Closed #{self.server_port}"
220
- end
199
+ super(self.server_port,self.server_host,&block)
221
200
 
201
+ print_info "Closed #{self.server_host_port}"
222
202
  return nil
223
203
  end
204
+
205
+ private
206
+
207
+ #
208
+ # The server host/port parameters.
209
+ #
210
+ # @return [String]
211
+ # The server host/port parameters in String form.
212
+ #
213
+ # @since 0.4.0
214
+ #
215
+ # @api private
216
+ #
217
+ def server_host_port
218
+ "#{self.server_host}:#{self.server_port}"
219
+ end
224
220
  end
225
221
  end
226
222
  end
@@ -27,6 +27,7 @@ module Ronin
27
27
  # Network helper methods.
28
28
  #
29
29
  module Network
30
+ # The URL used for determining the external IP Address.
30
31
  IP_URL = URI.parse('http://checkip.dyndns.org/')
31
32
 
32
33
  #
@@ -17,12 +17,12 @@
17
17
  # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
- require 'ronin/network/extensions/pop3'
20
+ require 'net/pop'
21
21
 
22
22
  module Ronin
23
23
  module Network
24
24
  #
25
- # Global settings for accessing POP3.
25
+ # Provides helper methods for communicating with POP3 services.
26
26
  #
27
27
  module POP3
28
28
  # Default POP3 port
@@ -49,6 +49,76 @@ module Ronin
49
49
  def POP3.default_port=(port)
50
50
  @default_port = port
51
51
  end
52
+
53
+ #
54
+ # Creates a connection to the POP3 server.
55
+ #
56
+ # @param [String] host
57
+ # The host to connect to.
58
+ #
59
+ # @param [Hash] options
60
+ # Additional options.
61
+ #
62
+ # @option options [Integer] :port (POP3.default_port)
63
+ # The port the POP3 server is running on.
64
+ #
65
+ # @option options [String] :user
66
+ # The user to authenticate with when connecting to the POP3 server.
67
+ #
68
+ # @option options [String] :password
69
+ # The password to authenticate with when connecting to the POP3 server.
70
+ #
71
+ # @yield [session]
72
+ # If a block is given, it will be passed the newly created POP3 session.
73
+ #
74
+ # @yieldparam [Net::POP3] session
75
+ # The newly created POP3 session.
76
+ #
77
+ # @return [Net::POP3]
78
+ # The newly created POP3 session.
79
+ #
80
+ # @api public
81
+ #
82
+ def pop3_connect(host,options={})
83
+ host = host.to_s
84
+ port = (options[:port] || POP3.default_port)
85
+ user = options[:user]
86
+ password = options[:password]
87
+
88
+ session = Net::POP3.start(host,port,user,password)
89
+
90
+ yield session if block_given?
91
+ return session
92
+ end
93
+
94
+ #
95
+ # Starts a session with the POP3 server.
96
+ #
97
+ # @param [String] host
98
+ # The host to connect to.
99
+ #
100
+ # @param [Hash] options
101
+ # Additional options.
102
+ #
103
+ # @yield [session]
104
+ # If a block is given, it will be passed the newly created POP3 session.
105
+ # After the block has returned, the session will be closed.
106
+ #
107
+ # @yieldparam [Net::POP3] session
108
+ # The newly created POP3 session.
109
+ #
110
+ # @return [nil]
111
+ #
112
+ # @api public
113
+ #
114
+ def pop3_session(host,options={})
115
+ session = pop3_connect(host,options)
116
+
117
+ yield session if block_given?
118
+
119
+ session.finish
120
+ return nil
121
+ end
52
122
  end
53
123
  end
54
124
  end
@@ -25,6 +25,7 @@ module Ronin
25
25
  #
26
26
  class Email
27
27
 
28
+ # The CR-LF String
28
29
  CRLF = "\n\r"
29
30
 
30
31
  # Sender of the email
@@ -19,10 +19,12 @@
19
19
 
20
20
  require 'ronin/network/smtp/email'
21
21
 
22
+ require 'net/smtp'
23
+
22
24
  module Ronin
23
25
  module Network
24
26
  #
25
- # Global settings for accessing STMP.
27
+ # Provides helper methods for communicating with SMTP services.
26
28
  #
27
29
  module SMTP
28
30
  # Default SMTP port
@@ -57,19 +59,173 @@ module Ronin
57
59
  # If a block is given, it will be passed the newly created Email
58
60
  # object.
59
61
  #
60
- # @yieldparam [Ronin::Network::Email::SMTP] email
62
+ # @yieldparam [Email] email
61
63
  # The new Email object.
62
64
  #
63
65
  # @return [String]
64
66
  # Formatted SMTP email.
65
67
  #
66
- # @see Ronin::Network::SMTP::Email
68
+ # @see SMTP::Email
67
69
  #
68
70
  # @api public
69
71
  #
70
72
  def SMTP.message(options={},&block)
71
73
  Email.new(options,&block).to_s
72
74
  end
75
+
76
+ #
77
+ # Creates a new email message.
78
+ #
79
+ # @param [Hash] options
80
+ # Additional options for the email.
81
+ #
82
+ # @yield [email]
83
+ # The given block will be passed the new email.
84
+ #
85
+ # @yieldparam [Email] email
86
+ # The new email.
87
+ #
88
+ # @see Email.new
89
+ #
90
+ # @api public
91
+ #
92
+ def smtp_message(options={},&block)
93
+ Email.new(options,&block)
94
+ end
95
+
96
+ #
97
+ # Creates a connection to the SMTP server.
98
+ #
99
+ # @param [String] host
100
+ # The host to connect to.
101
+ #
102
+ # @param [Hash] options
103
+ # Additional options.
104
+ #
105
+ # @option options [Integer] :port (SMTP.default_port)
106
+ # The port to connect to.
107
+ #
108
+ # @option options [String] :helo
109
+ # The HELO domain.
110
+ #
111
+ # @option options [Symbol] :auth
112
+ # The type of authentication to use. Can be either `:login`, `:plain`,
113
+ # or `:cram_md5`.
114
+ #
115
+ # @option options [String] :user
116
+ # The user-name to authenticate with.
117
+ #
118
+ # @option options [String] :password
119
+ # The password to authenticate with.
120
+ #
121
+ # @yield [session]
122
+ # If a block is given, it will be passed an SMTP session object.
123
+ #
124
+ # @yieldparam [Net::SMTP] session
125
+ # The SMTP session.
126
+ #
127
+ # @return [Net::SMTP]
128
+ # The SMTP session.
129
+ #
130
+ # @example
131
+ # smtp_connect('www.example.com', :user => 'joe')
132
+ #
133
+ # @api public
134
+ #
135
+ def smtp_connect(host,options={})
136
+ host = host.to_s
137
+ port = (options[:port] || SMTP.default_port)
138
+
139
+ helo = options[:helo]
140
+
141
+ auth = options[:auth]
142
+ user = options[:user]
143
+ password = options[:password]
144
+
145
+ session = Net::SMTP.start(host,port,helo,user,password,auth)
146
+
147
+ yield session if block_given?
148
+ return session
149
+ end
150
+
151
+ #
152
+ # Starts a session with the SMTP server.
153
+ #
154
+ # @param [String] host
155
+ # The host to connect to.
156
+ #
157
+ # @param [Hash] options
158
+ # Additional options.
159
+ #
160
+ # @yield [session]
161
+ # If a block is given, it will be passed an SMTP session object.
162
+ # After the block has returned, the session will be closed.
163
+ #
164
+ # @yieldparam [Net::SMTP] session
165
+ # The SMTP session.
166
+ #
167
+ # @example
168
+ # smtp_session('www.example.com', :user => 'joe') do |smtp|
169
+ # # ...
170
+ # end
171
+ #
172
+ # @see smtp_connect
173
+ #
174
+ # @api public
175
+ #
176
+ def smtp_session(host,options={})
177
+ session = smtp_connect(host,options)
178
+
179
+ yield session if block_given?
180
+
181
+ session.finish
182
+ return nil
183
+ end
184
+
185
+ #
186
+ # @since 0.2.0
187
+ #
188
+ # @param [String] host
189
+ # The host to connect to.
190
+ #
191
+ # @param [Hash] options
192
+ # Additional SMTP and Email options.
193
+ #
194
+ # @yield [email]
195
+ # The given block will be passed the new email to be sent.
196
+ #
197
+ # @yieldparam [SMTP::Email] email
198
+ # The new email to be sent.
199
+ #
200
+ # @see smtp_session
201
+ #
202
+ # @example
203
+ # smtp_send_message 'www.example.com', :to => 'joe@example.com',
204
+ # :from => 'eve@example.com',
205
+ # :subject => 'Hello',
206
+ # :message_id => 'XXXX',
207
+ # :body => 'Hello'
208
+ #
209
+ # @example Using the block.
210
+ # smtp_send_message('www.example.com') do |email|
211
+ # email.to = 'joe@example.com'
212
+ # email.from 'eve@example.com'
213
+ # email.subject = 'Hello'
214
+ # email.message_id = 'XXXXXXXXXX'
215
+ # email.body << 'Hello!'
216
+ # end
217
+ #
218
+ # @since 0.2.0
219
+ #
220
+ # @api public
221
+ #
222
+ def smtp_send_message(host,options={},&block)
223
+ email = smtp_message(options,&block)
224
+
225
+ smtp_session(host,options) do |smtp|
226
+ smtp.send_message(email.to_s, email.from, email.to)
227
+ end
228
+ end
73
229
  end
74
230
  end
75
231
  end