Class: IMAPClient
- Inherits:
-
Object
- Object
- IMAPClient
- Defined in:
- lib/imap_client.rb
Overview
An IMAPClient used by IMAPFlag and IMAPCleanse.
Probably not very reusable by you, but it has lots of example code.
Direct Known Subclasses
Class Method Summary collapse
-
.process_args(args, extra_options) ⇒ Object
Handles processing of
args
. -
.run(args = ARGV) ⇒ Object
Sets up an IMAPClient options then runs.
Instance Method Summary collapse
-
#connect(host, port, ssl, username, password, auth = nil) ⇒ Object
Connects to IMAP server
host
atport
using ssl ifssl
is true then logs in asusername
withpassword
. -
#find_mailboxes ⇒ Object
Finds mailboxes with messages that were selected by the :Boxes option.
-
#initialize(options) ⇒ IMAPClient
constructor
Creates a new IMAPClient from
options
. -
#log(message) ⇒ Object
Logs
message
to $stderr if :Verbose was selected. -
#mark(messages, flags) ⇒ Object
Marks
messages
in the currently selected mailbox withflags
(see Net::IMAP#store). -
#run(message, flags) ⇒ Object
Selects messages from mailboxes then marking them with
flags
. -
#search(query, message) ⇒ Object
Searches for messages matching
query
in the selected mailbox (see Net::IMAP#select).
Constructor Details
#initialize(options) ⇒ IMAPClient
Creates a new IMAPClient from options
.
Options include:
+:Verbose+:: Verbose flag
+:Noop+:: Don't delete anything flag
+:Root+:: IMAP root path
+:Boxes+:: Comma-separated list of mailbox prefixes to search
+:Host+:: IMAP server
+:Port+:: IMAP server port
+:SSL+:: SSL flag
+:Username+:: IMAP username
+:Password+:: IMAP password
+:Auth+:: IMAP authentication type
203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/imap_client.rb', line 203 def initialize() @verbose = [:Verbose] @noop = [:Noop] @root = [:Root] root = @root root += "/" unless root.empty? boxes = [:Boxes].split(/,\s*/) @box_re = /^#{Regexp.escape root}#{Regexp.union(*boxes)}/ connect [:Host], [:Port], [:SSL], [:Username], [:Password], [:Auth] end |
Class Method Details
.process_args(args, extra_options) ⇒ Object
Handles processing of args
.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/imap_client.rb', line 16 def self.process_args(args, ) opts_file = File. '~/.imap_cleanse' = {} if File.exist? opts_file then unless File.stat(opts_file).mode & 077 == 0 then $stderr.puts "WARNING! #{opts_file} is group/other readable or writable!" $stderr.puts "WARNING! I'm not doing a thing until you fix it!" exit 1 end File.readlines(opts_file).map { |l| l.chomp.split '=', 2 }.each do |k,v| v = true if v == 'true' v = false if v == 'false' v = Integer(v) rescue v ([k.intern] = v) rescue nil end end [:SSL] ||= true [:Username] ||= ENV['USER'] [:Root] ||= 'mail' [:Noop] ||= false [:Verbose] ||= false .each do |k,(v,m)| [k] ||= v end opts = OptionParser.new do |opts| opts. = "Usage: #{File.basename $0} [options]" opts.separator '' opts.separator 'Options may also be set in the options file ~/.imap_cleanse.' opts.separator '' opts.separator 'Example ~/.imap_cleanse:' opts.separator "\tHost=mail.example.com" opts.separator "\tPassword=my password" opts.separator '' opts.separator 'Connection options:' opts.on("-H", "--host HOST", "IMAP server host", "Default: #{[:Host].inspect}", "Options file name: Host") do |host| [:Host] = host end opts.on("-P", "--port PORT", "IMAP server port", "Default: The correct port SSL/non-SSL mode", "Options file name: Port") do |port| [:Port] = port end opts.on("-s", "--[no-]ssl", "Use SSL for IMAP connection", "Default: #{[:SSL].inspect}", "Options file name: SSL") do |ssl| [:SSL] = ssl end opts.separator '' opts.separator 'Login options:' opts.on("-u", "--username USERNAME", "IMAP username", "Default: #{[:Username].inspect}", "Options file name: Username") do |username| [:Username] = username end opts.on("-p", "--password PASSWORD", "IMAP password", "Default: Read from ~/.imap_cleanse", "Options file name: Password") do |password| [:Password] = password end authenticators = Net::IMAP.send :class_variable_get, :@@authenticators auth_types = authenticators.keys.sort.join ', ' opts.on("-a", "--auth AUTH", "IMAP authentication type override", "Authentication type will be auto-", "discovered", "Default: #{[:Auth].inspect}", "Valid values: #{auth_types}", "Options file name: Auth") do |auth| [:Auth] = auth end opts.separator '' opts.separator "#{self} options:" opts.on("-r", "--root ROOT", "Root of mailbox hierarchy", "Default: #{[:Root].inspect}", "Options file name: Root") do |root| [:Root] = root end opts.on("-b", "--boxes BOXES", "Comma-separated list of mailbox name", "prefixes to search", "Default: #{[:Boxes].inspect}", "Options file name: Boxes") do |boxes| [:Boxes] = boxes end yield opts, opts.on("-n", "--noop", "Perform no destructive operations", "Best used with the verbose option", "Default: #{[:Noop].inspect}", "Options file name: Noop") do |noop| [:Noop] = noop end opts.on("-v", "--[no-]verbose", "Be verbose", "Default: #{[:Verbose].inspect}", "Options file name: Verbose") do |verbose| [:Verbose] = verbose end opts.separator '' opts.on("-h", "--help", "You're looking at it") do $stderr.puts opts exit 1 end opts.separator '' end opts.parse! args [:Port] ||= [:SSL] ? 993 : 143 if [:Host].nil? or [:Password].nil? or [:Boxes].nil? or .any? { |k,v| [k].nil? } then $stderr.puts opts $stderr.puts $stderr.puts "Host name not set" if [:Host].nil? $stderr.puts "Password not set" if [:Password].nil? $stderr.puts "Boxes option not set" if [:Boxes].nil? .each do |k,(v,msg)| $stderr.puts msg if [k].nil? end exit 1 end return end |
.run(args = ARGV) ⇒ Object
Sets up an IMAPClient options then runs.
178 179 180 181 182 183 184 185 186 |
# File 'lib/imap_client.rb', line 178 def self.run(args = ARGV) = process_args args client = new client.run rescue => e $stderr.puts "Failed to finish with exception: #{e.class}:#{e.}" $stderr.puts "\t#{e.backtrace.join "\n\t"}" exit 1 end |
Instance Method Details
#connect(host, port, ssl, username, password, auth = nil) ⇒ Object
Connects to IMAP server host
at port
using ssl if ssl
is true then logs in as username
with password
. IMAPClient will really only work with PLAIN auth on SSL sockets, sorry.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/imap_client.rb', line 262 def connect(host, port, ssl, username, password, auth = nil) @imap = Net::IMAP.new host, port, ssl log "Connected to #{host}:#{port}" if auth.nil? then auth_caps = @imap.capability.select { |c| c =~ /^AUTH/ } raise "Couldn't find a supported auth type" if auth_caps.empty? auth = auth_caps.first.sub(/AUTH=/, '') end auth = auth.upcase log "Trying #{auth} authentication" @imap.authenticate auth, username, password log "Logged in as #{username}" end |
#find_mailboxes ⇒ Object
Finds mailboxes with messages that were selected by the :Boxes option.
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/imap_client.rb', line 281 def find_mailboxes mailboxes = @imap.list(@root, "*") if mailboxes.nil? then log "Found no mailboxes, you may have an incorrect root" return [] end mailboxes.reject! { |mailbox| mailbox.attr.include? :Noselect } mailboxes.map! { |mailbox| mailbox.name } mailboxes.reject! { |mailbox| mailbox !~ @box_re } mailboxes = mailboxes.sort_by { |m| m.downcase } log "Found #{mailboxes.length} mailboxes to search:" mailboxes.each { |mailbox| log "\t#{mailbox}" } if @verbose return mailboxes end |
#log(message) ⇒ Object
Logs message
to $stderr if :Verbose was selected.
301 302 303 304 |
# File 'lib/imap_client.rb', line 301 def log() return unless @verbose $stderr.puts "# #{}" end |
#mark(messages, flags) ⇒ Object
Marks messages
in the currently selected mailbox with flags
(see Net::IMAP#store).
321 322 323 324 325 326 327 |
# File 'lib/imap_client.rb', line 321 def mark(, flags) until .empty? do chunk = .slice! 0, 500 @imap.store chunk, '+FLAGS.SILENT', flags end log "Marked messages with flags" end |
#run(message, flags) ⇒ Object
Selects messages from mailboxes then marking them with flags
. If a block is given it is run after message marking.
Unless :Noop was set, then it just prints out what it would do.
Automatically called by IMAPClient::run
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/imap_client.rb', line 226 def run(, flags) log = 0 mailboxes = find_mailboxes mailboxes.each do |mailbox| @imap.select mailbox log "Selected #{mailbox}" = next if .empty? += .length if @noop then log "Noop - doing nothing" next end mark , flags yield if block_given? end log "Done. Found #{} messages in #{mailboxes.length} mailboxes" end |
#search(query, message) ⇒ Object
Searches for messages matching query
in the selected mailbox (see Net::IMAP#select). Logs ‘Scanning for message
’ before searching.
310 311 312 313 314 315 |
# File 'lib/imap_client.rb', line 310 def search(query, ) log "Scanning for #{}" = @imap.search query log "Found #{.length} messages" return end |