This repository has been archived by the owner on Dec 5, 2023. It is now read-only.
forked from ConradIrwin/em-imap
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2cf31f4
commit a2cbccf
Showing
7 changed files
with
262 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,22 @@ | ||
module EventMachine | ||
class Imap | ||
def self.connect(host, port, ssl=false) | ||
conn = EventMachine.connect(host, port, EventMachine::ImapConnection) | ||
conn.start_tls if ssl | ||
new(conn) | ||
end | ||
|
||
def initialize(connection) | ||
@connection = connection | ||
end | ||
require 'net/imap' | ||
|
||
def disconnect | ||
@connection.close_connection | ||
end | ||
|
||
## 6.1 Client commands - any state. | ||
|
||
def capability | ||
one_data_response("CAPABILITY") | ||
end | ||
|
||
def noop | ||
tagged_response("NOOP") | ||
end | ||
require 'rubygems' | ||
require 'eventmachine' | ||
require 'deferrable_gratification' | ||
|
||
# Logout and close the connection. | ||
def logout | ||
tagged_response("LOGOUT").errback do |e| | ||
if e.is_a? Net::IMAP::ByeResponseError | ||
# RFC 3501 says the server MUST send a BYE response and then close the connection. | ||
disconnect | ||
succeed | ||
end | ||
end.callback do |response| | ||
fail Net::IMAP::ResponseParseError.new("Received the wrong response to LOGOUT: #{response}") | ||
end | ||
end | ||
|
||
## 6.2 Client commands - "Not authenticated" state | ||
|
||
def starttls | ||
raise NotImplementedError | ||
end | ||
|
||
def authenticate(auth_type, *args) | ||
auth_type = auth_type.upcase | ||
raise "bleargh" | ||
end | ||
|
||
|
||
def create(mailbox) | ||
tagged_response("CREATE") | ||
end | ||
|
||
def delete(mailbox) | ||
tagged_response("DELETE") | ||
end | ||
$:.unshift File.dirname( __FILE__ ) | ||
require 'imap/command_sender' | ||
require 'imap/response_parser' | ||
require 'imap/connection' | ||
require 'imap/client' | ||
$:.shift | ||
|
||
def examine(mailbox) | ||
tagged_response("EXAMINE") | ||
end | ||
|
||
def login(username, password) | ||
tagged_response("LOGIN", username, password) | ||
end | ||
|
||
def logout | ||
tagged_response("LOGOUT") | ||
end | ||
|
||
def select(mailbox) | ||
tagged_response("SELECT", mailbox) | ||
end | ||
|
||
def subscribe(mailbox) | ||
send_command("SUBSCRIBE", mailbox) | ||
end | ||
|
||
def rename(mailbox, newname) | ||
tagged_response("RENAME", mailbox, newname) | ||
end | ||
|
||
private | ||
|
||
# The callback of a Command returns both a tagged response, | ||
# and optionally a list of untagged responses that were | ||
# generated at the same time. | ||
def tagged_response(*command) | ||
send_command(*command).transform{ |response, data| response } | ||
end | ||
|
||
def one_data_response(*command) | ||
send_command(*command).transform{ |response, data| data.last } | ||
end | ||
|
||
def multi_data_response(*command) | ||
send_command(*command).transform{ |response, data| data } | ||
end | ||
|
||
def send_command(cmd, *args) | ||
connection.send_command(cmd, *args) | ||
module EventMachine | ||
module Imap | ||
def self.connect(host, port, ssl=false) | ||
conn = EventMachine.connect(host, port, EventMachine::Imap::Connection) | ||
conn.start_tls if ssl | ||
Client.new(conn) | ||
end | ||
|
||
attr_reader :connection | ||
private :connection | ||
end | ||
end |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
module EventMachine | ||
module Imap | ||
class Client | ||
def initialize(connection) | ||
@connection = connection | ||
end | ||
|
||
def disconnect | ||
@connection.close_connection | ||
end | ||
|
||
## 6.1 Client commands - any state. | ||
|
||
def capability | ||
one_data_response("CAPABILITY") | ||
end | ||
|
||
def noop | ||
tagged_response("NOOP") | ||
end | ||
|
||
# Logout and close the connection. | ||
def logout | ||
tagged_response("LOGOUT").errback do |e| | ||
if e.is_a? Net::IMAP::ByeResponseError | ||
# RFC 3501 says the server MUST send a BYE response and then close the connection. | ||
disconnect | ||
succeed | ||
end | ||
end.callback do |response| | ||
fail Net::IMAP::ResponseParseError.new("Received the wrong response to LOGOUT: #{response}") | ||
end | ||
end | ||
|
||
## 6.2 Client commands - "Not authenticated" state | ||
|
||
def starttls | ||
raise NotImplementedError | ||
end | ||
|
||
def authenticate(auth_type, *args) | ||
auth_type = auth_type.upcase | ||
raise "bleargh" | ||
end | ||
|
||
|
||
def create(mailbox) | ||
tagged_response("CREATE") | ||
end | ||
|
||
def delete(mailbox) | ||
tagged_response("DELETE") | ||
end | ||
|
||
def examine(mailbox) | ||
tagged_response("EXAMINE") | ||
end | ||
|
||
def login(username, password) | ||
tagged_response("LOGIN", username, password) | ||
end | ||
|
||
def logout | ||
tagged_response("LOGOUT") | ||
end | ||
|
||
def select(mailbox) | ||
tagged_response("SELECT", mailbox) | ||
end | ||
|
||
def subscribe(mailbox) | ||
send_command("SUBSCRIBE", mailbox) | ||
end | ||
|
||
def rename(mailbox, newname) | ||
tagged_response("RENAME", mailbox, newname) | ||
end | ||
|
||
private | ||
|
||
# The callback of a Command returns both a tagged response, | ||
# and optionally a list of untagged responses that were | ||
# generated at the same time. | ||
def tagged_response(*command) | ||
send_command(*command).transform{ |response, data| response } | ||
end | ||
|
||
def one_data_response(*command) | ||
send_command(*command).transform{ |response, data| data.last } | ||
end | ||
|
||
def multi_data_response(*command) | ||
send_command(*command).transform{ |response, data| data } | ||
end | ||
|
||
def send_command(cmd, *args) | ||
@connection.send_command(cmd, *args) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
require 'net/imap' | ||
require File.dirname( __FILE__ ) + '/response_parser.rb' | ||
require File.dirname( __FILE__ ) + '/command_sender.rb' | ||
module EventMachine | ||
module Imap | ||
CRLF = "\r\n" | ||
module Connection | ||
attr_reader :waiting | ||
|
||
def self.connect(host, port, ssl=false) | ||
EventMachine.connect(host, port, self).tap do |conn| | ||
conn.start_tls if ssl | ||
end | ||
end | ||
|
||
def post_init | ||
super | ||
@tagged_commands = {} | ||
@named_responses = {} | ||
end | ||
|
||
def send_command(cmd, *args) | ||
Command.new(next_tag!, cmd, args).tap do |command| | ||
|
||
add_to_listener_pool(command) | ||
command.bothback do | ||
remove_from_listener_pool(command) | ||
end | ||
|
||
send_command_object(command) | ||
end | ||
rescue => e | ||
fail_all e | ||
end | ||
|
||
# See also Net::IMAP#receive_responses | ||
def receive_response(response) | ||
case response | ||
when Net::IMAP::TaggedResponse | ||
|
||
if @tagged_commands[response.tag] | ||
complete_response @tagged_commands[response.tag], response | ||
else | ||
# The server has responded to a request we didn't make, let's bail. | ||
fail_all Net::IMAP::ResponseParseError.new(response.raw_data) | ||
end | ||
|
||
when Net::IMAP::UntaggedResponse | ||
if response.name == "BYE" # && @logout_command_tag.nil? | ||
fail_all Net::IMAP::ByeResponseError.new(response.raw_data) | ||
else | ||
record_response(response.name, response.data) | ||
end | ||
|
||
when Net::IMAP::ContinuationRequest | ||
# TODO | ||
|
||
end | ||
rescue => e | ||
fail_all e | ||
end | ||
|
||
# Net::IMAP#pick_up_tagged_response | ||
def complete_response(command, response) | ||
case response.name | ||
when "NO" | ||
command.fail Net::IMAP::NoResponseError.new(response.data.text) | ||
when "BAD" | ||
command.fail Net::IMAP::BadResponseError.new(response.data.text) | ||
else | ||
command.succeed response, @named_responses.delete(command.cmd) | ||
end | ||
end | ||
|
||
# NOTE: This is a pretty horrible way to do things. | ||
def record_response(name, response) | ||
@named_responses[name] ||= [] | ||
@named_responses[name] << response | ||
end | ||
|
||
def add_to_listener_pool(command) | ||
@tagged_commands[command.tag] = command | ||
end | ||
|
||
def remove_from_listener_pool(command) | ||
@tagged_commands.delete command.tag | ||
end | ||
|
||
def fail_all(error) | ||
@tagged_commands.values.each do |command| | ||
command.fail error | ||
end | ||
raise error | ||
end | ||
|
||
def unbind | ||
unless @tagged_commands.empty? | ||
fail_all EOFError.new("end of file reached") | ||
end | ||
end | ||
|
||
# Provides a next_tag! method to generate unique tags | ||
# for an Imap session. | ||
module TagSequence | ||
def post_init | ||
super | ||
# Copying Net::IMAP | ||
@tag_prefix = "RUBY" | ||
@tagno = 0 | ||
end | ||
|
||
def next_tag! | ||
@tagno += 1 | ||
"%s%04d" % [@tag_prefix, @tagno] | ||
end | ||
end | ||
|
||
# Intercepts send_data and receive_data and logs them to STDOUT, | ||
# this should be the last module included. | ||
module Debug | ||
def send_data(data) | ||
puts "C: #{data.inspect}" | ||
super | ||
end | ||
|
||
def receive_data(data) | ||
puts "S: #{data.inspect}" | ||
super | ||
end | ||
end | ||
|
||
class Command < Struct.new(:tag, :cmd, :args) | ||
include EventMachine::Deferrable | ||
end | ||
DG.enhance! Command | ||
|
||
include Imap::CommandSender | ||
include Imap::ResponseParser | ||
include Imap::Connection::TagSequence | ||
include Imap::Connection::Debug | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.