Module: EventMachine::IMAP::Connection
- Includes:
- EM::Deferrable, CommandSender, TagSequence, DeferrableSSL, ResponseParser
- Defined in:
- lib/em-imap/connection.rb
Defined Under Namespace
Modules: Debug, TagSequence
Class Method Summary collapse
-
.connect(host, port, ssl = false) ⇒ Object
Create a new connection to an IMAP server.
- .debug! ⇒ Object
Instance Method Summary collapse
-
#add_response_handler(&block) ⇒ Object
Create a new listener for responses from the IMAP server.
- #add_to_listener_pool(listener) ⇒ Object
-
#hello_listener ⇒ Object
Returns a Listener that is active during connection setup, and which is succeeded or failed as soon as we’ve received a greeting from the server.
-
#listen_for_failure ⇒ Object
Attach life-long listeners on various conditions that we want to treat as connection errors.
-
#listen_for_greeting ⇒ Object
This listens for the IMAP connection to have been set up.
-
#listen_for_tagged_response(command) ⇒ Object
Await the response that marks the completion of this command, and succeed or fail the command as appropriate.
- #post_init ⇒ Object
-
#receive_response(response) ⇒ Object
receive_response is a higher-level receive_data provided by EM::IMAP::ResponseParser.
-
#send_command(cmd, *args) ⇒ Object
Send the command, with the given arguments, to the IMAP server.
-
#unbind ⇒ Object
Called when the connection is closed.
Methods included from TagSequence
Methods included from DeferrableSSL
#ssl_handshake_completed, #start_tls
Methods included from ResponseParser
Methods included from CommandSender
#prepare_idle_continuation, #send_authentication_data, #send_command_object, #send_literal, #send_string
Methods included from ContinuationSynchronisation
#await_continuations, #awaiting_continuation?, #listen_for_continuation, #when_not_awaiting_continuation
Methods included from EventMachine::IMAP::CommandSender::LineBuffer
Class Method Details
.connect(host, port, ssl = false) ⇒ Object
Create a new connection to an IMAP server.
23 24 25 26 27 |
# File 'lib/em-imap/connection.rb', line 23 def self.connect(host, port, ssl=false) EventMachine.connect(host, port, self).tap do |conn| conn.start_tls if ssl end end |
.debug! ⇒ Object
194 195 196 |
# File 'lib/em-imap/connection.rb', line 194 def self.debug! include IMAP::Connection::Debug end |
Instance Method Details
#add_response_handler(&block) ⇒ Object
Create a new listener for responses from the IMAP server.
98 99 100 101 102 103 |
# File 'lib/em-imap/connection.rb', line 98 def add_response_handler(&block) Listener.new(&block).tap do |listener| listener.stopback{ listener.succeed } add_to_listener_pool(listener) end end |
#add_to_listener_pool(listener) ⇒ Object
105 106 107 |
# File 'lib/em-imap/connection.rb', line 105 def add_to_listener_pool(listener) @listeners << listener.bothback{ @listeners.delete listener } end |
#hello_listener ⇒ Object
Returns a Listener that is active during connection setup, and which is succeeded or failed as soon as we’ve received a greeting from the server.
57 58 59 |
# File 'lib/em-imap/connection.rb', line 57 def hello_listener @hello_listener ||= Listener.new.errback{ |e| fail e }.bothback{ hello_listener.stop } end |
#listen_for_failure ⇒ Object
Attach life-long listeners on various conditions that we want to treat as connection errors. When such an error occurs, we want to fail all the currently pending commands so that the user of the library doesn’t have to subscribe to more than one stream of errors.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/em-imap/connection.rb', line 146 def listen_for_failure errback do |error| # NOTE: Take a shallow clone of the listeners here so that we get guaranteed # behaviour. We want to fail any listeners that may be added by the errbacks # of other listeners. @listeners.clone.each{ |listener| listener.fail error } while @listeners.size > 0 close_connection unless @unbound end # If we receive a BYE response from the server, then we're not going # to hear any more, so we fail all our listeners. add_response_handler do |response| if response.is_a?(Net::IMAP::UntaggedResponse) && response.name == "BYE" fail Net::IMAP::ByeResponseError.new((RUBY_VERSION[0,3] == "1.8" ? response.raw_data : response)) end end end |
#listen_for_greeting ⇒ Object
This listens for the IMAP connection to have been set up. This should be shortly after the TCP connection is available, once we’ve received a greeting from the server.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/em-imap/connection.rb', line 39 def listen_for_greeting add_to_listener_pool(hello_listener) hello_listener.listen do |response| # TODO: Is this the right condition? I think it can be one of several # possible answers depending on how trusted the connection is, but probably # not *anything* except BYE. if response.is_a?(Net::IMAP::UntaggedResponse) && response.name != "BYE" hello_listener.succeed response else hello_listener.fail Net::IMAP::ResponseParseError.new((RUBY_VERSION[0,3] == "1.8" ? response.raw_data : response)) end end.errback do |e| hello_listener.fail e end end |
#listen_for_tagged_response(command) ⇒ Object
Await the response that marks the completion of this command, and succeed or fail the command as appropriate.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/em-imap/connection.rb', line 120 def listen_for_tagged_response(command) command.listen do |response| if response.is_a?(Net::IMAP::TaggedResponse) && response.tag == command.tag case response.name when "NO" command.fail Net::IMAP::NoResponseError.new((RUBY_VERSION[0,3] == "1.8" ? response.data.text : response)) when "BAD" command.fail Net::IMAP::BadResponseError.new((RUBY_VERSION[0,3] == "1.8" ? response.data.text : response)) else command.succeed response end end end end |
#post_init ⇒ Object
29 30 31 32 33 34 |
# File 'lib/em-imap/connection.rb', line 29 def post_init @listeners = [] super listen_for_failure listen_for_greeting end |
#receive_response(response) ⇒ Object
receive_response is a higher-level receive_data provided by EM::IMAP::ResponseParser. Each response is a Net::IMAP response object. (FIXME)
112 113 114 115 116 |
# File 'lib/em-imap/connection.rb', line 112 def receive_response(response) # NOTE: Take a shallow clone of the listeners so that if receiving an # event causes a new listener to be added, it won't receive this response! @listeners.clone.each{ |listener| listener.receive_event response } end |
#send_command(cmd, *args) ⇒ Object
Send the command, with the given arguments, to the IMAP server.
Exceptions thrown during serialization will be thrown to the user, exceptions thrown while communicating to the socket will cause the returned command to fail.
80 81 82 83 84 85 86 |
# File 'lib/em-imap/connection.rb', line 80 def send_command(cmd, *args) Command.new(next_tag!, cmd, args).tap do |command| add_to_listener_pool(command) listen_for_tagged_response(command) send_command_object(command) end end |
#unbind ⇒ Object
Called when the connection is closed. TODO: Figure out how to send a useful error…
137 138 139 140 |
# File 'lib/em-imap/connection.rb', line 137 def unbind @unbound = true fail EOFError.new("Connection to IMAP server was unbound") end |