module Mailmate::EmlLookup
def self.eml_id_for_message_id(message_id)
index — fine for one-shot CLI lookups; cache the result if you need it
return the local eml-id (integer) or nil. O(n) scan of the message-id
Reverse-lookup: given an RFC Message-ID (with or without angle brackets),
def self.eml_id_for_message_id(message_id) needle = message_id.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
def self.path_for(eml_id)
def self.path_for(eml_id) via_index(eml_id) || via_glob(eml_id) end
def self.resolve_id(input)
Resolve an identifier that may be either an eml-id (all digits) or an
def self.resolve_id(input) s = input.to_s.strip return s.to_i if s =~ /\A\d+\z/ eml_id_for_message_id(s) end
def self.source_url_for(eml_id)
Lookup the `imap://...` URL recorded in `#source` for this eml_id.
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
def self.url_to_path(url, eml_id)
Convert an `imap://account@host/mailbox/path` URL to the on-disk
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
def self.via_glob(eml_id)
def self.via_glob(eml_id) matches = Dir.glob("#{Mailmate.config.imap_root}/*/**/Messages/#{eml_id}.eml") matches.first end
def self.via_index(eml_id)
def self.via_index(eml_id) url = source_url_for(eml_id) return nil if url.nil? url_to_path(url, eml_id) end