Module: Mailmate::EmlLookup
- Defined in:
- lib/mailmate/eml_lookup.rb
Overview
Map an ‘.eml` body-part ID to its absolute on-disk path.
Two implementations:
- The fast path uses MailMate's `#source` index
(`Database.noindex/Headers/#source.{cache,offsets}`), which carries the
`imap://account@host/path` URL for every indexed message. O(1) lookup.
- The fallback walks the IMAP tree with `Dir.glob`, the same shape as the
`find -name <id>.eml` shell-out the original scripts used. Slower
(seconds on a cold cache) but always works.
The fast path wins ~99% of the time. The fallback exists for messages MailMate hasn’t yet indexed (e.g. immediately after a fresh IMAP push) and for edge cases where ‘#source` is unreadable.
Class Method Summary collapse
-
.eml_id_for_message_id(message_id) ⇒ Object
Reverse-lookup: given an RFC Message-ID (with or without angle brackets), return the local eml-id (integer) or nil.
-
.path_for(eml_id) ⇒ Object
Returns an absolute path string, or nil if not found.
-
.resolve_id(input) ⇒ Object
Resolve an identifier that may be either an eml-id (all digits) or an RFC Message-ID (anything else) to a local eml-id.
-
.source_url_for(eml_id) ⇒ Object
Lookup the ‘imap://…` URL recorded in `#source` for this eml_id.
-
.url_to_path(url, eml_id) ⇒ Object
Convert an ‘imap://account@host/mailbox/path` URL to the on-disk absolute path of the .eml file.
-
.via_glob(eml_id) ⇒ Object
Force the glob fallback.
-
.via_index(eml_id) ⇒ Object
Force the index path (useful for tests and benchmarking).
Class Method Details
.eml_id_for_message_id(message_id) ⇒ Object
Reverse-lookup: given an RFC Message-ID (with or without angle brackets), return the local eml-id (integer) or nil. O(n) scan of the message-id index — fine for one-shot CLI lookups; cache the result if you need it repeatedly.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/mailmate/eml_lookup.rb', line 29 def self.() needle = .to_s.strip return nil if needle.empty? candidates = needle.start_with?("<") && needle.end_with?(">") ? [needle, needle[1..-2]] : [needle, "<#{needle}>"] Mailmate::IndexReader.for("message-id").each_record do |eml_id, value| return eml_id if candidates.include?(value) end nil rescue ArgumentError nil end |
.path_for(eml_id) ⇒ Object
Returns an absolute path string, or nil if not found.
21 22 23 |
# File 'lib/mailmate/eml_lookup.rb', line 21 def self.path_for(eml_id) via_index(eml_id) || via_glob(eml_id) end |
.resolve_id(input) ⇒ Object
Resolve an identifier that may be either an eml-id (all digits) or an RFC Message-ID (anything else) to a local eml-id.
47 48 49 50 51 |
# File 'lib/mailmate/eml_lookup.rb', line 47 def self.resolve_id(input) s = input.to_s.strip return s.to_i if s =~ /\A\d+\z/ (s) end |
.source_url_for(eml_id) ⇒ Object
Lookup the ‘imap://…` URL recorded in `#source` for this eml_id. Returns nil if the index doesn’t have a record for it.
68 69 70 71 72 73 |
# File 'lib/mailmate/eml_lookup.rb', line 68 def self.source_url_for(eml_id) Mailmate::IndexReader.for("#source").value_for(eml_id) rescue ArgumentError # #source index missing (non-default MailMate install? fresh sync?). nil end |
.url_to_path(url, eml_id) ⇒ Object
Convert an ‘imap://account@host/mailbox/path` URL to the on-disk absolute path of the .eml file. Internal but exposed for tests.
77 78 79 80 81 82 83 84 |
# File 'lib/mailmate/eml_lookup.rb', line 77 def self.url_to_path(url, eml_id) stripped = url.sub(%r{\Aimap://}, "") account, mailbox_path = stripped.split("/", 2) return nil if account.nil? || mailbox_path.nil? || mailbox_path.empty? mailbox_dirs = mailbox_path.split("/").map { |seg| "#{seg}.mailbox" }.join("/") File.join(Mailmate.config.imap_root, account, mailbox_dirs, "Messages", "#{eml_id}.eml") end |
.via_glob(eml_id) ⇒ Object
Force the glob fallback.
61 62 63 64 |
# File 'lib/mailmate/eml_lookup.rb', line 61 def self.via_glob(eml_id) matches = Dir.glob("#{Mailmate.config.imap_root}/*/**/Messages/#{eml_id}.eml") matches.first end |
.via_index(eml_id) ⇒ Object
Force the index path (useful for tests and benchmarking).
54 55 56 57 58 |
# File 'lib/mailmate/eml_lookup.rb', line 54 def self.via_index(eml_id) url = source_url_for(eml_id) return nil if url.nil? url_to_path(url, eml_id) end |