Class: Remailer::SMTP::Client
- Inherits:
-
AbstractConnection
- Object
- EventMachine::Connection
- AbstractConnection
- Remailer::SMTP::Client
- Includes:
- EventMachine::Deferrable, Constants
- Defined in:
- lib/remailer/smtp/client.rb
Defined Under Namespace
Classes: Interpreter
Constant Summary collapse
- DEFAULT_TIMEOUT =
5
Constants included from Constants
Constants::CRLF, Constants::IMAPS_PORT, Constants::LINE_REGEXP, Constants::SMTP_PORT, Constants::SOCKS5_PORT
Constants inherited from AbstractConnection
AbstractConnection::NOTIFICATIONS
Instance Attribute Summary collapse
-
#active_message ⇒ Object
Properties ===========================================================.
-
#auth_support ⇒ Object
Returns the value of attribute auth_support.
-
#error ⇒ Object
readonly
Returns the value of attribute error.
-
#error_message ⇒ Object
readonly
Returns the value of attribute error_message.
-
#hostname ⇒ Object
Returns the value of attribute hostname.
-
#max_size ⇒ Object
Returns the value of attribute max_size.
-
#options ⇒ Object
Returns the value of attribute options.
-
#pipelining ⇒ Object
Returns the value of attribute pipelining.
-
#protocol ⇒ Object
Returns the value of attribute protocol.
-
#remote ⇒ Object
Returns the value of attribute remote.
-
#timeout ⇒ Object
Returns the value of attribute timeout.
-
#tls_support ⇒ Object
Returns the value of attribute tls_support.
Class Method Summary collapse
- .default_port ⇒ Object
-
.default_timeout ⇒ Object
Class Methods ========================================================.
-
.open(smtp_server, options = nil, &block) ⇒ Object
Opens a connection to a specific SMTP server.
Instance Method Summary collapse
-
#after_initialize ⇒ Object
Called by AbstractConnection at the end of the initialize procedure.
- #after_message_sent(reply_code, reply_message) ⇒ Object
-
#after_proxy_connected ⇒ Object
Callback receiver for when the proxy connection has been completed.
- #after_ready ⇒ Object
- #after_unbind ⇒ Object
-
#close_when_complete! ⇒ Object
Closes the connection after all of the queued messages have been sent.
-
#closed? ⇒ Boolean
Returns true if the connection has been closed, false otherwise.
-
#error? ⇒ Boolean
Returns true if an error has occurred, false otherwise.
-
#pipelining? ⇒ Boolean
Returns true if pipelining support has been detected on the connection, false otherwise.
- #resolve_hostname(hostname) ⇒ Object
-
#send_email(from, to, data, &block) ⇒ Object
Sends an email message through the connection at the earliest opportunity.
-
#send_line(line = '') ⇒ Object
Sends a single line to the remote host with the appropriate CR+LF delmiter at the end.
-
#state ⇒ Object
Returns the current state of the active interpreter, or nil if no state is assigned.
-
#test_email(from, to, &block) ⇒ Object
Tests the validity of an email address through the connection at the earliest opportunity.
-
#tls_support? ⇒ Boolean
Returns true if pipelining support has been detected on the connection, false otherwise.
-
#unbound? ⇒ Boolean
Returns true if the connection has been unbound by EventMachine, false otherwise.
-
#use_smtp_interpreter! ⇒ Object
Switches to use the SMTP interpreter for all subsequent communication.
-
#use_socks5_interpreter! ⇒ Object
Switches to use the SOCKS5 interpreter for all subsequent communication.
Methods inherited from AbstractConnection
#after_complete, #auth_support?, #cancel_timer!, #check_for_timeouts!, #close_connection, #connect_notification, #connected?, #connection_completed, #debug_notification, #error_notification, establish!, #initialize, #interpreter_entered_state, #message_callback, #post_init, #proxy_connection_initiated!, #proxy_connection_initiated?, #receive_data, report_exception, #requires_authentication?, #reset_timeout!, #send_callback, #send_notification, #set_timer!, #start_tls, #time_remaning, #unbind, #use_tls?, #using_proxy?, warn_about_arguments
Constructor Details
This class inherits a constructor from Remailer::AbstractConnection
Instance Attribute Details
#active_message ⇒ Object
Properties ===========================================================
17 18 19 |
# File 'lib/remailer/smtp/client.rb', line 17 def @active_message end |
#auth_support ⇒ Object
Returns the value of attribute auth_support.
19 20 21 |
# File 'lib/remailer/smtp/client.rb', line 19 def auth_support @auth_support end |
#error ⇒ Object (readonly)
Returns the value of attribute error.
22 23 24 |
# File 'lib/remailer/smtp/client.rb', line 22 def error @error end |
#error_message ⇒ Object (readonly)
Returns the value of attribute error_message.
22 23 24 |
# File 'lib/remailer/smtp/client.rb', line 22 def @error_message end |
#hostname ⇒ Object
Returns the value of attribute hostname.
18 19 20 |
# File 'lib/remailer/smtp/client.rb', line 18 def hostname @hostname end |
#max_size ⇒ Object
Returns the value of attribute max_size.
18 19 20 |
# File 'lib/remailer/smtp/client.rb', line 18 def max_size @max_size end |
#options ⇒ Object
Returns the value of attribute options.
21 22 23 |
# File 'lib/remailer/smtp/client.rb', line 21 def @options end |
#pipelining ⇒ Object
Returns the value of attribute pipelining.
19 20 21 |
# File 'lib/remailer/smtp/client.rb', line 19 def pipelining @pipelining end |
#protocol ⇒ Object
Returns the value of attribute protocol.
18 19 20 |
# File 'lib/remailer/smtp/client.rb', line 18 def protocol @protocol end |
#remote ⇒ Object
Returns the value of attribute remote.
18 19 20 |
# File 'lib/remailer/smtp/client.rb', line 18 def remote @remote end |
#timeout ⇒ Object
Returns the value of attribute timeout.
20 21 22 |
# File 'lib/remailer/smtp/client.rb', line 20 def timeout @timeout end |
#tls_support ⇒ Object
Returns the value of attribute tls_support.
19 20 21 |
# File 'lib/remailer/smtp/client.rb', line 19 def tls_support @tls_support end |
Class Method Details
.default_port ⇒ Object
34 35 36 |
# File 'lib/remailer/smtp/client.rb', line 34 def self.default_port SMTP_PORT end |
.default_timeout ⇒ Object
Class Methods ========================================================
30 31 32 |
# File 'lib/remailer/smtp/client.rb', line 30 def self.default_timeout DEFAULT_TIMEOUT end |
.open(smtp_server, options = nil, &block) ⇒ Object
Opens a connection to a specific SMTP server. Options can be specified:
-
port => Numerical port number (default is 25)
-
require_tls => If true will fail connections to non-TLS capable servers (default is false)
-
username => Username to authenticate with the SMTP server (optional)
-
password => Password to authenticate with the SMTP server (optional)
-
use_tls => Will use TLS if availble (default is true)
-
debug => Where to send debugging output (IO or Proc)
-
connect => Where to send a connection notification (IO or Proc)
-
error => Where to send errors (IO or Proc)
-
on_connect => Called upon successful connection (Proc)
-
on_error => Called upon connection error (Proc)
-
on_disconnect => Called when connection is closed (Proc)
A block can be supplied in which case it will stand in as the :connect option. The block will recieve a first argument that is the status of the connection, and an optional second that is a diagnostic message.
54 55 56 |
# File 'lib/remailer/smtp/client.rb', line 54 def self.open(smtp_server, = nil, &block) super(smtp_server, , &block) end |
Instance Method Details
#after_initialize ⇒ Object
Called by AbstractConnection at the end of the initialize procedure
61 62 63 64 65 66 67 68 69 70 |
# File 'lib/remailer/smtp/client.rb', line 61 def after_initialize @protocol = :smtp if (using_proxy?) proxy_connection_initiated! use_socks5_interpreter! else use_smtp_interpreter! end end |
#after_message_sent(reply_code, reply_message) ⇒ Object
248 249 250 251 252 |
# File 'lib/remailer/smtp/client.rb', line 248 def (reply_code, ) (reply_code, ) @active_message = nil end |
#after_proxy_connected ⇒ Object
Callback receiver for when the proxy connection has been completed.
226 227 228 |
# File 'lib/remailer/smtp/client.rb', line 226 def after_proxy_connected use_smtp_interpreter! end |
#after_ready ⇒ Object
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/remailer/smtp/client.rb', line 230 def after_ready super return if (@active_message) if (@active_message = @messages.shift) if (@interpreter.state == :ready) @interpreter.enter_state(:send) end elsif (@options[:close]) if (callback = @options[:after_complete]) callback.call end @interpreter.enter_state(:quit) end end |
#after_unbind ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/remailer/smtp/client.rb', line 131 def after_unbind if (@active_message) debug_notification(:disconnect, "Disconnected by remote before transaction could be completed.") if (callback = @active_message[:callback]) callback.call(nil) @active_message = nil end elsif (@closed) debug_notification(:disconnect, "Disconnected from remote.") elsif (!@established) error_notification(:hangup, "Disconnected from remote before fully established.") else debug_notification(:disconnect, "Disconnected by remote while connection was idle.") end end |
#close_when_complete! ⇒ Object
Closes the connection after all of the queued messages have been sent.
78 79 80 |
# File 'lib/remailer/smtp/client.rb', line 78 def close_when_complete! @options[:close] = true end |
#closed? ⇒ Boolean
Returns true if the connection has been closed, false otherwise.
207 208 209 |
# File 'lib/remailer/smtp/client.rb', line 207 def closed? !!@closed end |
#error? ⇒ Boolean
Returns true if an error has occurred, false otherwise.
212 213 214 |
# File 'lib/remailer/smtp/client.rb', line 212 def error? !!@error end |
#pipelining? ⇒ Boolean
Returns true if pipelining support has been detected on the connection, false otherwise.
196 197 198 |
# File 'lib/remailer/smtp/client.rb', line 196 def pipelining? !!@pipelining end |
#resolve_hostname(hostname) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/remailer/smtp/client.rb', line 175 def resolve_hostname(hostname) record = Socket.gethostbyname(hostname) # FIXME: IPv6 Support here address = (record and record[3]) if (address) debug_notification(:resolver, "Address #{hostname} resolved as #{address.unpack('CCCC').join('.')}") else debug_notification(:resolver, "Address #{hostname} could not be resolved") end yield(address) if (block_given?) address rescue nil end |
#send_email(from, to, data, &block) ⇒ Object
Sends an email message through the connection at the earliest opportunity. A callback block can be supplied that will be executed when the message has been sent, an unexpected result occurred, or the send timed out.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/remailer/smtp/client.rb', line 85 def send_email(from, to, data, &block) if (block_given?) self.class.warn_about_arguments(block, 1..2) end = { from: from, to: to, data: data, callback: block } @messages << # If the connection is ready to send... if (@interpreter and @interpreter.state == :ready) # ...send the message right away. after_ready end end |
#send_line(line = '') ⇒ Object
Sends a single line to the remote host with the appropriate CR+LF delmiter at the end.
167 168 169 170 171 172 173 |
# File 'lib/remailer/smtp/client.rb', line 167 def send_line(line = '') reset_timeout! send_data(line + CRLF) debug_notification(:send, line.inspect) end |
#state ⇒ Object
Returns the current state of the active interpreter, or nil if no state is assigned.
157 158 159 160 161 162 163 |
# File 'lib/remailer/smtp/client.rb', line 157 def state if (interpreter = @interpreter) @interpreter.state else nil end end |
#test_email(from, to, &block) ⇒ Object
Tests the validity of an email address through the connection at the earliest opportunity. A callback block can be supplied that will be executed when the address has been tested, an unexpected result occurred, or the request timed out.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/remailer/smtp/client.rb', line 110 def test_email(from, to, &block) if (block_given?) self.class.warn_about_arguments(block, 1..2) end = { from: from, to: to, test: true, callback: block } @messages << # If the connection is ready to send... if (@interpreter and @interpreter.state == :ready) # ...send the message right away. after_ready end end |
#tls_support? ⇒ Boolean
Returns true if pipelining support has been detected on the connection, false otherwise.
202 203 204 |
# File 'lib/remailer/smtp/client.rb', line 202 def tls_support? !!@tls_support end |
#unbound? ⇒ Boolean
Returns true if the connection has been unbound by EventMachine, false otherwise.
151 152 153 |
# File 'lib/remailer/smtp/client.rb', line 151 def unbound? !!@unbound end |
#use_smtp_interpreter! ⇒ Object
Switches to use the SMTP interpreter for all subsequent communication
217 218 219 220 221 222 223 |
# File 'lib/remailer/smtp/client.rb', line 217 def use_smtp_interpreter! @interpreter = Interpreter.new(delegate: self) # Trigger processing using the new interpreter as some SMTP data might # already be buffered by this point. receive_data end |
#use_socks5_interpreter! ⇒ Object
Switches to use the SOCKS5 interpreter for all subsequent communication
73 74 75 |
# File 'lib/remailer/smtp/client.rb', line 73 def use_socks5_interpreter! @interpreter = Remailer::SOCKS5::Client::Interpreter.new(delegate: self) end |