Class: Mailmate::SourceResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/mailmate/source_resolver.rb

Constant Summary collapse

SPECIAL_DIRS =

Standard-mailbox name patterns. Each special UUID maps to one or more ‘*.mailbox` directories per account. Gmail nests system folders under `[Gmail]/…`; iCloud is flat with different names.

{
  "INBOX"   => ["INBOX.mailbox"],
  "DRAFTS"  => ["[Gmail].mailbox/Drafts.mailbox", "Drafts.mailbox"],
  "SENT"    => ["[Gmail].mailbox/Sent Mail.mailbox", "Sent Messages.mailbox"],
  "ARCHIVE" => ["[Gmail].mailbox/Archive.mailbox", "Archive.mailbox"],
  "JUNK"    => ["[Gmail].mailbox/Spam.mailbox", "Junk.mailbox"],
  "TRASH"   => ["[Gmail].mailbox/Trash.mailbox", "Deleted Messages.mailbox"],
}.freeze
ALL_MESSAGES_EXCLUDES =

ALL_MESSAGES: union of INBOX/SENT/DRAFTS/ARCHIVE plus any custom labels. Excludes Trash/Junk (per MailMate help: “All Messages” is everything except deleted/junk).

%r{/(?:Trash|Junk|Spam|Deleted Messages)\.mailbox/Messages/?\z}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(graph) ⇒ SourceResolver

Returns a new instance of SourceResolver.



31
32
33
# File 'lib/mailmate/source_resolver.rb', line 31

def initialize(graph)
  @graph = graph
end

Instance Method Details

#all_message_dirsObject



86
87
88
89
90
# File 'lib/mailmate/source_resolver.rb', line 86

def all_message_dirs
  Dir.glob("#{Mailmate.config.imap_root}/*/**/Messages")
     .select { |p| File.directory?(p) }
     .reject { |p| p =~ ALL_MESSAGES_EXCLUDES }
end

#per_account_dirs(suffixes) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/mailmate/source_resolver.rb', line 92

def (suffixes)
  result = []
  Dir.glob("#{Mailmate.config.imap_root}/*").each do ||
    next unless File.directory?()
    suffixes.each do |suffix|
      d = "#{}/#{suffix}/Messages"
      result << d if File.directory?(d)
    end
  end
  result
end

#resolve(spec) ⇒ Object

Resolve a mailbox spec to filters:. ‘spec` may be a UUID, a name, or a special UUID literal. Returns:

:dirs    => Array<String> of absolute paths to `Messages/` directories
:filters => Array<String> of filter expressions to AND together


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
# File 'lib/mailmate/source_resolver.rb', line 40

def resolve(spec)
  filters = []
  uuid = spec
  visited = []
  loop do
    raise ArgumentError, "Cycle in mailbox resolution: #{visited.inspect}" if visited.include?(uuid)
    visited << uuid

    m = @graph.by_uuid[uuid] || @graph.by_uuid[@graph.by_name[uuid]]

    # Collect this node's filter (if it has one). The special UUIDs
    # FLAGGED / SENT / etc. can themselves be smart mailboxes (e.g.
    # Brian's "Flagged" with filter `#flags.flag = '\Flagged'`); the
    # filter has to be picked up before we resolve the special to dirs.
    filters << m[:filter] if m && m[:filter]

    next_uuid = m && m[:set]

    # If `set` points elsewhere, walk to it (handles nested smart mailboxes).
    if next_uuid && next_uuid != uuid
      uuid = next_uuid
      next
    end

    # Terminal — resolve to on-disk dirs.
    if MailboxGraph::SPECIAL_UUIDS.include?(uuid)
      return { dirs: special_dirs(uuid), filters: filters }
    end

    raise ArgumentError, "Mailbox #{spec.inspect} can't be resolved to disk paths " \
                         "(uuid=#{uuid}, name=#{m && m[:name].inspect})"
  end
end

#special_dirs(uuid) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/mailmate/source_resolver.rb', line 74

def special_dirs(uuid)
  case uuid
  when "ALL_MESSAGES"
    all_message_dirs
  when "INBOX", "DRAFTS", "SENT", "ARCHIVE", "JUNK", "TRASH"
    (SPECIAL_DIRS[uuid])
  else
    # Unknown special — return empty list and let the caller fail loudly.
    []
  end
end