class GxG::Networking::ImapClient
To Generate OAuth2 Tokens, See: github.com/google/gmail-oauth2-tools IMAP Classes:
Public Class Methods
new(host=nil, port=nil, options={})
click to toggle source
# File lib/gxg/net_clients.rb, line 532 def initialize(host=nil, port=nil, options={}) if port.is_a?(::Hash) options = port port = nil end @user = nil @password = nil @client = nil @host = host unless @host raise ArgumentError, "You MUST provide a HOST String." end if options[:use_ssl] == true @port = (port || 993) else @port = (port || 143) end unless @port raise ArgumentError, "You MUST provide a valid PORT Integer." end # @capability = [] # @mounted = nil @mount_mode = :read # if options[:use_ssl] == true if options[:ignore_ssl_errors] == true @client = Net::IMAP.new(@host, @port, true, nil, false) else @client = Net::IMAP.new(@host, @port, true) end else @client = Net::IMAP.new(@host, @port) end @capability = @client.capability # self end
Public Instance Methods
add_message_flags(uid=nil, flags=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1041 def add_message_flags(uid=nil, flags=nil) result = false if @client begin unless uid.is_any?(::Integer, ::Array) raise ArgumentError, "You MUST specify a UID name to set FLAGS." end unless flags.is_a?(::Array) raise ArgumentError, "You MUST specify what FLAGS to set." end self.set_message_attributes(uid, "+FLAGS", flags) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid, :flags => flags}}) end end result end
capability()
click to toggle source
# File lib/gxg/net_clients.rb, line 576 def capability() @capability.clone end
connector()
click to toggle source
???
# File lib/gxg/net_clients.rb, line 528 def connector() @client end
copy_to_mailbox(uid=nil, mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1096 def copy_to_mailbox(uid=nil, mailbox=nil) result = false if @client begin unless uid.is_any?(::Integer, ::Array) raise ArgumentError, "You MUST specify a UID to copy the message." end unless mailbox raise ArgumentError, "You MUST specify a MAILBOX to copy the message to." end self.uid_copy(uid, mailbox) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid, :mailbox => mailbox}}) end end result end
create_mailbox(mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1253 def create_mailbox(mailbox=nil) result = [] if @client begin unless mailbox raise ArgumentError, "You MUST specify a MAILBOX name to create it." end result = @client.create(mailbox) rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox}}) end end result end
fetch_manifest(uid_set=[])
click to toggle source
# File lib/gxg/net_clients.rb, line 1134 def fetch_manifest(uid_set=[]) result = [] if @client begin unless self.mounted? raise Exception, "You MUST mount a Mailbox prior to calling this operation." end if uid_set.is_a?(::Integer) uid_set = [(uid_set)] end unless uid_set.is_a?(::Array) raise ArgumentError, "You MUST provide an Array of Message UID Integers." end # parse_header = Proc.new do |the_raw_message| header = {} parser = ::Mail.new(the_raw_message) parser.header_fields.each do |field| the_key = field.name.to_s.to_sym the_data = field.to_s.transcode({:replace => "."},::Encoding::UTF_8) the_data.gsub!(" ","") the_data.gsub!(" ","") the_data.gsub!(" ","") the_data.gsub!("\r\n","") if header[(the_key)] unless header[(the_key)].is_a?(::Array) header[(the_key)] = [(header[(the_key)])] end header[(the_key)] << the_data else header[(the_key)] = the_data end end header end # uid_set.each do |uid| record = {:uid => uid, :date => nil, :from => "", :to => "", :subject => ""} raw_response = @client.uid_fetch(uid,"BODY[HEADER]") if raw_response.is_a?(::Array) if raw_response.size > 0 header = parse_header.call(raw_response[0].attr()["BODY[HEADER]"]) record[:date] = ::DateTime.parse(header[:Date].to_s) record[:from] = header[:From] record[:to] = header[:To] record[:subject] = header[:Subject] result << record end end # end rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid_set}}) end end result end
fetch_message(uid=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 918 def fetch_message(uid=nil) result = nil if @client begin unless self.mounted? raise Exception, "You MUST mount a Mailbox prior to calling this operation." end unless uid.is_a?(::Integer) raise ArgumentError, "You MUST provide an Integer to specify the Message UID Number." end parse_message = Proc.new do |the_raw_message| header = {} body = [] attachments = [] parser = ::Mail.new(the_raw_message) parser.header_fields.each do |field| the_key = field.name.to_s.to_sym the_data = field.to_s.transcode({:replace => "."},::Encoding::UTF_8) the_data.gsub!(" ","") the_data.gsub!(" ","") the_data.gsub!(" ","") the_data.gsub!("\r\n","") if header[(the_key)] unless header[(the_key)].is_a?(::Array) header[(the_key)] = [(header[(the_key)])] end header[(the_key)] << the_data else header[(the_key)] = the_data end end if parser.multipart? link_db = [] body << {:preamble => parser.body.preamble} parser.parts.each do |part| if part.multipart? link_db << part else if part.attachment? attachments << {:content_type => {:type => part.mime_type, :parameters => part.content_type_parameters}, :filename => part.filename, :path => nil, :content => ::GxG::ByteArray.new(part.decoded)} else body << {:content_type => {:type => part.mime_type, :parameters => part.content_type_parameters}, :content => part.body.to_s.transcode({:replace => "."},::Encoding::UTF_8)} end end end while link_db.size > 0 do part = link_db.shift if part.multipart? part.parts.each do |the_sub_part| link_db << the_sub_part end else if part.attachment? attachments << {:content_type => {:type => part.mime_type, :parameters => part.content_type_parameters}, :filename => part.filename, :path => nil, :content => ::GxG::ByteArray.new(part.decoded)} else body << {:content_type => {:type => part.mime_type, :parameters => part.content_type_parameters}, :content => part.body.to_s.transcode({:replace => "."},::Encoding::UTF_8)} end end end body << {:epilogue => parser.body.epilogue} else body << {:preamble => parser.body.preamble.to_s.transcode({:replace => "."},::Encoding::UTF_8)} mime_type = "text/plain" parameters = {"charset" => "UTF-8"} body_text = parser.body.to_s.transcode({:replace => "."},::Encoding::UTF_8) if body_text.xml? mime_type = "text/xml" end if body_text.html? mime_type = "text/html" end body << {:content_type => {:type => mime_type, :parameters => parameters}, :content => body_text} body << {:epilogue => parser.body.epilogueto_s.transcode({:replace => "."},::Encoding::UTF_8)} end gxg_message = new_message gxg_message[:sender] = parser.from gxg_message[:id] = parser.message_id gxg_message[:to] = parser.to gxg_message[:cc] = parser.cc gxg_message[:bcc] = parser.bcc gxg_message[:subject] = parser.subject gxg_message[:date] = parser.date gxg_message[:header] = header gxg_message[:body] = body gxg_message[:attachments] = attachments gxg_message end # raw_response = @client.uid_fetch(uid,"BODY[]") if raw_response.is_a?(::Array) if raw_response.size > 0 result = parse_message.call(raw_response[0].attr()["BODY[]"]) end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:unique_id => uid}}) end end result end
get_quota(mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1353 def get_quota(mailbox=nil) result = nil if @client begin unless mailbox raise ArgumentError, "You MUST specify a MAILBOX name." end raw_response = @client.getquotaroot(mailbox)[1] if raw_response.is_a?(::Net::IMAP::MailboxQuota) result = {:usage => raw_response.usage.to_i, :quota => raw_response.quota.to_i} end rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox}}) end end result end
inspect()
click to toggle source
# File lib/gxg/net_clients.rb, line 572 def inspect() "<ImapClient: User: #{@user.inspect} Host: #{@host.inspect} Connected: #{! @client.disconnected?}>" end
list(reference=nil, mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 748 def list(reference=nil, mailbox=nil) result = [] if @client begin unless reference raise ArgumentError, "You MUST sepcify a REFERENCE to list." end unless mailbox raise ArgumentError, "You MUST sepcify a MAILBOX to list." end raw_list = @client.list(reference, mailbox) if raw_list raw_list.each do |entry| if entry.is_a?(::Net::IMAP::MailboxList) result << {:name => entry.name, :flags => entry.attr, :delimiter => entry.delim} end end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:reference => reference, :mailbox => mailbox}}) end end result end
list_subscriptions(reference=nil, mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1334 def list_subscriptions(reference=nil, mailbox=nil) result = [] if @client begin raw_list = @client.lsub(reference, mailbox) if raw_list raw_list.each do |entry| if entry.is_a?(::Net::IMAP::MailboxList) result << {:name => entry.name, :flags => entry.attr, :delimiter => entry.delim} end end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:reference => reference, :mailbox => mailbox}}) end end result end
login(user_id=nil, password=nil, options={:method => :auth})
click to toggle source
# File lib/gxg/net_clients.rb, line 580 def login(user_id=nil, password=nil, options={:method => :auth}) result = false begin if @client unless @client.disconnected? @user = user_id unless @user raise ArgumentError, "You MUST provide a USER id, like this: <user_id>,<password>,(<options>)" end @password = password unless @password raise ArgumentError, "You MUST provide a PASSWORD/OAUTH-TOKEN, like this: <user_id>,<password/oauth-token>,(<options>)" end case options[:method] when :auth @client.login(@user, @password) when :login @client.authenticate("LOGIN", @user, @password) when :cram_md5 @client.authenticate("CRAM-MD5", @user, @password) when :oauth2 @client.authenticate("XOAUTH2", @user, @password) else raise ArgumentError, "Authentication method #{options[:method].inspect} not supported. Choose one of these: [:auth, :login, :cram_md5, :oauth2]" end # result = true end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:user => user_id, :options => options}}) end result end
logout()
click to toggle source
# File lib/gxg/net_clients.rb, line 615 def logout() result = false if @client begin @client.logout @client.disconnect result = @client.disconnected? @client = nil rescue Exception => the_error log_error({:error => the_error, :parameters => {}}) end end result end
mount(mailbox=nil,mode=:read_write)
click to toggle source
# File lib/gxg/net_clients.rb, line 648 def mount(mailbox=nil,mode=:read_write) result = false if @client begin unless [:read, :read_write].include?(mode) raise ArgumentError, "Mode #{mode.inspect} is invalid. Choose one of these: [:read, :read_write]." end if self.mounted? if @mounted == mailbox if self.mount_mode() == :read && mode == :read_write response = @client.select(mailbox) if response.is_a?(::Net::IMAP::TaggedResponse) if response.name == "OK" @mounted = mailbox @mount_mode = :read_write result = true else raise Exception, "Failed to re-mount #{mailbox.inspect} as :read_write." end else raise Exception, "Failed to re-mount #{mailbox.inspect} as :read_write." end else result = true end else raise Exception, "You must unmount mailbox #{@mounted.inspect} first, then mount #{mailbox.inspect}." end else # mount if mode == :read_write response = @client.select(mailbox) if response.is_a?(::Net::IMAP::TaggedResponse) if response.name == "OK" @mounted = mailbox @mount_mode = :read_write result = true else raise Exception, "Failed to mount #{mailbox.inspect} as :read_write." end else raise Exception, "Failed to mount #{mailbox.inspect} as :read_write." end else # mount :read only response = @client.examine(mailbox) if response.is_a?(::Net::IMAP::TaggedResponse) if response.name == "OK" @mounted = mailbox @mount_mode = :read result = true else raise Exception, "Failed to mount #{mailbox.inspect} as :read." end else raise Exception, "Failed to mount #{mailbox.inspect} as :read." end end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox, :mode => mode}}) end end result end
mount_mode()
click to toggle source
# File lib/gxg/net_clients.rb, line 640 def mount_mode() if self.mounted? @mount_mode else :unmounted end end
mounted?()
click to toggle source
# File lib/gxg/net_clients.rb, line 630 def mounted? result = false if @client if @mounted result = true end end result end
move_to_mailbox(uid=nil, mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1115 def move_to_mailbox(uid=nil, mailbox=nil) result = false if @client begin unless uid.is_any?(::Integer, ::Array) raise ArgumentError, "You MUST specify a UID to move the message." end unless mailbox raise ArgumentError, "You MUST specify a MAILBOX to move the message to." end self.uid_move(uid, mailbox) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid, :mailbox => mailbox}}) end end result end
remove_mailbox(mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1268 def remove_mailbox(mailbox=nil) result = [] if @client begin unless mailbox raise ArgumentError, "You MUST specify a MAILBOX name to delete it." end result = @client.delete(mailbox) rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox}}) end end result end
remove_message_flags(uid=nil, flags=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1060 def remove_message_flags(uid=nil, flags=nil) result = false if @client begin unless uid.is_any?(::Integer, ::Array) raise ArgumentError, "You MUST specify a UID name to clear FLAGS." end unless flags.is_a?(::Array) raise ArgumentError, "You MUST specify what FLAGS to clear." end self.set_message_attributes(uid, "-FLAGS", flags) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid, :flags => flags}}) end end result end
remove_messages(uid=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1079 def remove_messages(uid=nil) result = false if @client begin unless uid.is_any?(::Integer, ::Array) raise ArgumentError, "You MUST specify a UID to remove." end self.add_message_flags(uid, [:Deleted]) @client.expunge result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid}}) end end result end
rename_mailbox(mailbox=nil, new_name=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1283 def rename_mailbox(mailbox=nil, new_name=nil) result = false if @client begin unless mailbox raise ArgumentError, "You MUST specify a MAILBOX name to rename it." end unless new_name raise ArgumentError, "You MUST specify a NEW_NAME name to rename the MAILBOX." end @client.rename(mailbox, new_name) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox, :new_name => new_name}}) end end result end
set_message_attributes(uid=nil, attributes=nil, flags=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1019 def set_message_attributes(uid=nil, attributes=nil, flags=nil) result = false if @client begin unless uid.is_any?(::Integer, ::Array) raise ArgumentError, "You MUST specify a UID to set an ATTRIBUTE." end unless attributes.is_a?(::String) raise ArgumentError, "You MUST specify what ATTRIBUTE to set." end unless flags.is_a?(::Array) raise ArgumentError, "You MUST specify what FLAGS to set/unset." end @client.uid_store(uid, attributes, flags) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:uid_set => uid, :attributes => attributes, :flags => flags}}) end end result end
sort(sort_keys=["DATE"], search_keys=["ALL"], charset="UTF-8")
click to toggle source
# File lib/gxg/net_clients.rb, line 1235 def sort(sort_keys=["DATE"], search_keys=["ALL"], charset="UTF-8") result = [] if @client begin unless self.mounted? raise Exception, "You MUST mount a Mailbox prior to calling this operation." end unless @mount_mode == :read_write raise Exception, "You need to re-mount #{@mounted.inspect} as :read_write to peform this operation." end result = @client.uid_sort(sort_keys, search_keys, charset) rescue Exception => the_error log_error({:error => the_error, :parameters => {:sort_keys => sort_keys, :search_keys => search_keys, :charset => charset}}) end end result end
status(mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 724 def status(mailbox=nil) result = {:connected => false, :unseen => 0, :recent => 0, :messages => 0} if @client begin result[:connected] = (! @client.disconnected?) the_mailbox = (mailbox || @mounted) unless the_mailbox raise ArgumentError, "You must either MOUNT an inbox, or specify one to get status." end if result[:connected] == true raw_response = @client.status(the_mailbox, ["UNSEEN","MESSAGES", "RECENT"]) if raw_response.is_a?(::Hash) result[:unseen] = raw_response["UNSEEN"] result[:recent] = raw_response["RECENT"] result[:messages] = raw_response["MESSAGES"] end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:reference => reference, :mailbox => mailbox}}) end end result end
subscribe(mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1302 def subscribe(mailbox=nil) result = false if @client begin unless mailbox raise ArgumentError, "You MUST specify a MAILBOX name to subscribe to." end @client.subscribe(mailbox) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox}}) end end result end
theaded_list(algorithm=nil,search_keys=nil, charset="UTF-8")
click to toggle source
# File lib/gxg/net_clients.rb, line 1210 def theaded_list(algorithm=nil,search_keys=nil, charset="UTF-8") result = [] if @client begin unless self.mounted? raise Exception, "You MUST mount a Mailbox prior to calling this operation." end unless ["orderedsubject","references"].include?(algorithm.to_s.downcase) raise ArgumentError, "The algorithm you specified is invalid. Choose one of these: ['ORDEREDSUBJECT', 'REFERENCES']" end algorithm = algorithm.to_s.upcase unless search_keys.is_a?(::Array) raise ArgumentError, "You MUST provide search keys in the form of an Array of Strings." end unless charset raise ArgumentError, "You MUST provide a CHARSET specifier. Try one of these: ['US-ASCII', 'UTF-8']" end result = @client.uid_thread(algorithm, search_keys, charset) rescue Exception => the_error log_error({:error => the_error, :parameters => {:algorithm => algorithm, :search_keys => search_keys, :charset => charset}}) end end result end
uid_list(criteria=["NEW"])
click to toggle source
# File lib/gxg/net_clients.rb, line 1192 def uid_list(criteria=["NEW"]) result = [] if @client begin unless self.mounted? raise Exception, "You MUST mount a Mailbox prior to calling this operation." end unless criteria.is_a?(::Array) raise ArgumentError, "You MUST provide a search criteria in the form of an Array of Strings." end result = @client.uid_search(criteria) rescue Exception => the_error log_error({:error => the_error, :parameters => {:criteria => criteria}}) end end result end
unmount()
click to toggle source
# File lib/gxg/net_clients.rb, line 714 def unmount() result = false if self.mounted?() @mounted = nil @mount_mode = :read result = true end result end
unsubscribe(mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 1318 def unsubscribe(mailbox=nil) result = false if @client begin unless mailbox raise ArgumentError, "You MUST specify a MAILBOX name to unsubscribe from." end @client.unsubscribe(mailbox) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox}}) end end result end
upload_message(mailbox=nil, gxg_message=nil, flags=[:Seen], timestamp=::Time.now)
click to toggle source
# File lib/gxg/net_clients.rb, line 798 def upload_message(mailbox=nil, gxg_message=nil, flags=[:Seen], timestamp=::Time.now) result = false if @client begin if mailbox.is_a?(::GxG::Events::Message) if gxg_message.is_any?(::Symbol,::Array) flags = gxg_message end gxg_message = mailbox mailbox = nil end unless mailbox mailbox = @mounted unless @mount_mode == :read_write raise Exception, "You should re-mount #{@mounted.inspect} as :read_write, or select another MAILBOX." end end unless mailbox raise ArgumentError, "You MUST sepcify a MAILBOX to append the message to." end if flags.is_a?(::Symbol) flags = [(flags)] end if flags.is_a?(::Array) unless flags.include?(:Seen) flags << :Seen end end unless gxg_message.is_a?(::GxG::Events::Message) raise ArgumentError, "You MUST provide a ::GxG::Events::Message object as the message. See: <SmtpClient>.message_template()" end # Build suitable mail message message = Mail.new the_fields = [] gxg_message[:header].each_pair do |the_key, the_value| if the_value.is_a?(::Array) the_value.each do |the_field_value| the_fields << "#{the_key.to_s}: #{the_field_value.to_s}" end else the_fields << "#{the_key.to_s}: #{the_value.to_s}" end end message.header = the_fields.join("\r\n") message.from = gxg_message[:sender] message.reply_to = gxg_message[:sender] if gxg_message[:id].to_s.include?("@") message.message_id = gxg_message[:id].to_s else message.message_id = "<#{gxg_message[:id].to_s}@#{::Socket.gethostname}.mail>" end message.to = gxg_message[:to] if gxg_message[:cc] message.cc = gxg_message[:cc] end if gxg_message[:bcc] message.bcc = gxg_message[:bcc] end message.subject = gxg_message[:subject] message.date = (gxg_message[:date].to_s || ::DateTime.now.to_s) if gxg_message[:attachments].size > 0 multipart = true else part_count = 0 gxg_message[:body].each do |part| unless part[:prologue] || part[:epilogue] part_count += 1 end end if part_count > 1 multipart = true else multipart = false end end if multipart gxg_message[:body].each do |part| unless part[:prologue] || part[:epilogue] type_info = "Content-Type: #{part[:content_type][:type]}" if part[:content_type][:parameters].keys.size > 0 part[:content_type][:parameters].each_pair do |the_key, the_value| type_info << "; '#{the_key.to_s}': '#{the_value.to_s}'" end end new_part = Mail::Part.new(type_info) new_part.body = part[:content] message.add_part(new_part) end end # Add file attachments: gxg_message[:attachments].each do |attachment| if attachment[:content].size == 0 file_size = ::File.size(attachment[:path]) file_handle = ::File.open(attachment[:path],"rb") ::GxG::apportioned_ranges(file_size,65536).each do |the_range| file_handle.seek(the_range.first) attachment[:content] << file_handle.read(the_range.size) end file_handle.close end message.add_file({:filename => attachment[:filename], :content => attachment[:content].to_s}) end else gxg_message[:body].each do |part| unless part[:prologue] || part[:epilogue] message.body = part[:content] break end end end # Send it @client.append(mailbox, message.to_s, flags, timestamp) result = true rescue Exception => the_error log_error({:error => the_error, :parameters => {:mailbox => mailbox, :message => gxg_message, :flags => flags}}) end end result end
xlist(reference=nil, mailbox=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 773 def xlist(reference=nil, mailbox=nil) result = [] if @client begin unless reference raise ArgumentError, "You MUST sepcify a REFERENCE to list." end unless mailbox raise ArgumentError, "You MUST sepcify a MAILBOX to list." end raw_list = @client.xlist(reference, mailbox) if raw_list raw_list.each do |entry| if entry.is_a?(::Net::IMAP::MailboxList) result << {:name => entry.name, :flags => entry.attr, :delimiter => entry.delim} end end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:reference => reference, :mailbox => mailbox}}) end end result end