Class: IMAPGet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/imapget.rb,
lib/imapget/cli.rb,
lib/imapget/version.rb

Defined Under Namespace

Modules: Version Classes: CLI

Constant Summary collapse

DEFAULT_BATCH_SIZE =
100
DEFAULT_STRATEGY =
:exclude
DEFAULT_LOG_LEVEL =
2
DEFAULT_DELIMITER =
'/'
FETCH_ATTR =
%w[FLAGS INTERNALDATE RFC822]
VERSION =
Version.to_s

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ IMAPGet

Returns a new instance of IMAPGet.



48
49
50
51
52
53
54
55
56
57
# File 'lib/imapget.rb', line 48

def initialize(options)
  @batch_size = options.fetch(:batch_size, DEFAULT_BATCH_SIZE)
  @log_level  = options.fetch(:log_level,  DEFAULT_LOG_LEVEL)

  @imap = Net::IMAP.new(options[:host], options)
  @imap.starttls(options[:starttls]) if options[:starttls]

  authenticate(options)
  inclexcl(options)
end

Instance Attribute Details

#batch_sizeObject

Returns the value of attribute batch_size.



46
47
48
# File 'lib/imapget.rb', line 46

def batch_size
  @batch_size
end

#exclObject (readonly)

Returns the value of attribute excl.



45
46
47
# File 'lib/imapget.rb', line 45

def excl
  @excl
end

#imapObject (readonly)

Returns the value of attribute imap.



45
46
47
# File 'lib/imapget.rb', line 45

def imap
  @imap
end

#inclObject (readonly)

Returns the value of attribute incl.



45
46
47
# File 'lib/imapget.rb', line 45

def incl
  @incl
end

#log_levelObject

Returns the value of attribute log_level.



46
47
48
# File 'lib/imapget.rb', line 46

def log_level
  @log_level
end

#strategyObject (readonly)

Returns the value of attribute strategy.



45
46
47
# File 'lib/imapget.rb', line 45

def strategy
  @strategy
end

Instance Method Details

#delete!(name, uids) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/imapget.rb', line 141

def delete!(name, uids)
  return if uids.empty?

  log "#{name}: #{uids.size}"

  yield if block_given?

  imap.select(name)

  imap.store(uids, '+FLAGS', [Net::IMAP::DELETED]).size.tap { |count|
    log "#{count} DELETED!"
  }
end

#dupes(name, quiet = false) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/imapget.rb', line 125

def dupes(name, quiet = false)
  imap.examine(name)

  hash = Hash.zipkey { |h, k| h[k] = [] }

  1.step(size(name), step = batch_size) { |i|
    fetch_batch([[i, step]]) { |mail|
      hash[mail.attr['RFC822']] << mail.attr['UID'] unless deleted?(mail)
    }
  }

  hash.flat_map { |_, uids| uids.drop(1) if uids.size > 1 }.tap { |dupes|
    dupes.compact!; log "#{name}: #{dupes.size}" unless quiet
  }
end

#eachObject



78
79
80
# File 'lib/imapget.rb', line 78

def each
  mailboxes.each { |mailbox| yield mailbox if include?(mailbox) }
end

#exclude?(mailbox) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/imapget.rb', line 86

def exclude?(mailbox)
  name = case mailbox
    when String                 then mailbox
    when Net::IMAP::MailboxList then mailbox.name
    else raise TypeError, "MailboxList or String expected, got #{mailbox.class}"
  end

  excl &&= name =~ excl
  incl &&= name =~ incl

  case strategy
    when :include then excl || !incl
    when :exclude then excl && !incl
  end
end

#get(dir) ⇒ Object Also known as: download



102
103
104
105
# File 'lib/imapget.rb', line 102

def get(dir)
  each { |mailbox| get_name(name = mailbox.name,
    File.join(dir, Net::IMAP.decode_utf7(name))) }
end

#get_name(name, dir) ⇒ Object Also known as: download_name



109
110
111
112
113
114
115
116
117
# File 'lib/imapget.rb', line 109

def get_name(name, dir)
  log "#{'=' * 10} #{name} #{'=' * 10}"

  imap.examine(name)

  imap.uid_search("SINCE #{mtime(dir)}").each_slice(batch_size) { |batch|
    fetch_batch(batch) { |mail| fetch(mail, dir, name) }
  }
end

#inclexcl(options) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/imapget.rb', line 59

def inclexcl(options)
  delim = Regexp.escape(options.fetch(:delim, DEFAULT_DELIMITER))

  %w[include exclude].each { |key|
    instance_variable_set("@#{key[0, 4]}", case value = options[key.to_sym]
      when String then Regexp.new(value)
      when Array  then Regexp.new(value.map { |v|
        "\\A#{Regexp.escape(Net::IMAP.encode_utf7(v))}(?:#{delim}|\\z)"
      }.join('|'))
    end)
  }

  @strategy = options.fetch(:strategy, DEFAULT_STRATEGY)
end

#include?(mailbox) ⇒ Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/imapget.rb', line 82

def include?(mailbox)
  !exclude?(mailbox)
end

#mailboxesObject



74
75
76
# File 'lib/imapget.rb', line 74

def mailboxes
  @mailboxes ||= imap.list('', '*').sort_by(&:name)
end

#size(name, attr = 'MESSAGES') ⇒ Object



121
122
123
# File 'lib/imapget.rb', line 121

def size(name, attr = 'MESSAGES')
  imap.status(name, [attr]).values.first
end

#uniq!(name, &block) ⇒ Object



155
156
157
# File 'lib/imapget.rb', line 155

def uniq!(name, &block)
  delete!(name, dupes(name, true), &block)
end