Module: Mailmate::CLI::Mailboxes Private

Extended by:
Mailboxes
Included in:
Mailboxes
Defined in:
lib/mailmate/cli/mailboxes.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

‘mm-mailboxes` — enumerate accounts, their IMAP mailboxes, and the smart mailboxes MailMate has defined. Read-side (no UI activation), but uses the `mm-` prefix anyway so it doesn’t shadow ‘mmmessage` in tab-completion: `mmm<tab>` keeps resolving to `mmmessage`.

Instance Method Summary collapse

Instance Method Details

#collect_mailboxes(account_dir, count:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/mailmate/cli/mailboxes.rb', line 64

def collect_mailboxes(, count:)
  prefix = "#{}/"
  Dir.glob("#{}/**/Messages").sort.filter_map do |messages_dir|
    next unless File.directory?(messages_dir)
    rel = messages_dir.sub(prefix, "").sub(%r{/Messages\z}, "")
    # Strip the .mailbox suffix from each segment for display.
    mailbox_name = rel.split("/").map { |s| s.sub(/\.mailbox\z/, "") }.join("/")
    row = { mailbox: mailbox_name }
    row[:count] = count ? Dir.children(messages_dir).count { |f| f.end_with?(".eml") } : nil
    row
  end
end

#decode_account(dirname) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

MailMate’s account dirs encode ‘@` as `%40` (they’re literally IMAP URL fragments). Decode for display so users see real addresses.



92
93
94
# File 'lib/mailmate/cli/mailboxes.rb', line 92

def (dirname)
  URI.decode_www_form_component(dirname)
end

#emit_csv(accounts, smart, opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/mailmate/cli/mailboxes.rb', line 113

def emit_csv(accounts, smart, opts)
  rows = []
  accounts.each do |, mailboxes|
    mailboxes.each do |m|
      rows << [, m[:mailbox], "imap", opts[:count] ? format_count(m[:count]) : ""]
    end
  end
  smart.each { |name| rows << ["(smart)", name, "smart", "-"] }

  header = %w[account mailbox type count]
  if opts[:align]
    display = ([header] + rows)
    widths  = Array.new(header.size, 0)
    display.each { |r| r.each_with_index { |c, i| widths[i] = c.to_s.length if c.to_s.length > widths[i] } }
    display.each do |r|
      $stdout.puts r.each_with_index.map { |c, i| i == r.size - 1 ? c.to_s : c.to_s.ljust(widths[i]) }.join(",")
    end
  else
    require "csv"
    $stdout.puts CSV.generate_line(header)
    rows.each { |r| $stdout.puts CSV.generate_line(r) }
  end
end

#emit_grouped(accounts, smart, opts) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

—- output ————————————————————-



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/mailmate/cli/mailboxes.rb', line 98

def emit_grouped(accounts, smart, opts)
  accounts.each do |, mailboxes|
    $stdout.puts 
    mailboxes.each do |m|
      count_str = opts[:count] ? format_count(m[:count]) : ""
      $stdout.puts "  #{m[:mailbox].ljust(50)}imap   #{count_str}"
    end
  end
  unless smart.empty?
    $stdout.puts
    $stdout.puts "Smart Mailboxes"
    smart.each { |name| $stdout.puts "  #{name.ljust(50)}smart  -" }
  end
end

#enumerate_imap_accounts(count: true) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns [[account_display, [‘INBOX’, count: 127, …]], …] Account names are pulled from on-disk dir names under imap_root, with MailMate’s URL-encoding decoded for display (‘%40` → `@`).



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/mailmate/cli/mailboxes.rb', line 49

def enumerate_imap_accounts(count: true)
  root = Mailmate.config.imap_root
  return [] unless File.directory?(root)

  Dir.children(root).sort.filter_map do |dirname|
     = File.join(root, dirname)
    next unless File.directory?()

    mailboxes = collect_mailboxes(, count: count)
    next if mailboxes.empty?

    [(dirname), mailboxes]
  end
end

#enumerate_smart_mailboxesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns array of smart-mailbox names (sorted).



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/mailmate/cli/mailboxes.rb', line 78

def enumerate_smart_mailboxes
  graph = Mailmate::MailboxGraph.load
  graph.by_uuid.values
       .select { |m| m[:filter] }
       .map    { |m| m[:name] }
       .compact
       .uniq
       .sort
rescue StandardError
  []
end

#format_count(n) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



137
138
139
# File 'lib/mailmate/cli/mailboxes.rb', line 137

def format_count(n)
  n.nil? ? "-" : n.to_s
end

#parse_options(argv) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/mailmate/cli/mailboxes.rb', line 30

def parse_options(argv)
  opts = { count: true, csv: false, align: true }
  OptionParser.new do |o|
    o.banner = "Usage: mm-mailboxes [options]"
    o.separator ""
    o.separator "List MailMate accounts, their IMAP mailboxes, and smart mailboxes."
    o.separator "Default output groups by account with a section header per account."
    o.on("--no-count",  "Skip .eml counts (faster on large stores)") { opts[:count] = false }
    o.on("--csv",       "Flat CSV output (one row per mailbox, account repeated)") { opts[:csv] = true }
    o.on("--no-align",  "Plain CSV (no column padding) — implies --csv") { opts[:csv] = true; opts[:align] = false }
  end.parse!(argv)
  opts
end

#run(argv) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/mailmate/cli/mailboxes.rb', line 16

def run(argv)
  opts = parse_options(argv)

  accounts = enumerate_imap_accounts(count: opts[:count])
  smart    = enumerate_smart_mailboxes

  if opts[:csv]
    emit_csv(accounts, smart, opts)
  else
    emit_grouped(accounts, smart, opts)
  end
  0
end