sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

lib/sup/person.rb (3184B) - raw

      1 module Redwood
      2 
      3 class Person
      4   attr_accessor :name, :email
      5 
      6   def initialize name, email
      7     raise ArgumentError, "email can't be nil" unless email
      8 
      9     email.fix_encoding!
     10 
     11     @name = if name
     12       name.fix_encoding!
     13       name = name.strip.gsub(/\s+/, " ")
     14       name =~ /^(['"]\s*)(.*?)(\s*["'])$/ ? $2 : name
     15       name.gsub('\\\\', '\\')
     16     end
     17 
     18     @email = email.strip.gsub(/\s+/, " ")
     19   end
     20 
     21   def to_s
     22     if @name
     23       "#@name <#@email>"
     24     else
     25       @email
     26     end
     27   end
     28 
     29 #   def == o; o && o.email == email; end
     30 #   alias :eql? :==
     31 
     32   def shortname
     33     case @name
     34     when /\S+, (\S+)/
     35       $1
     36     when /(\S+) \S+/
     37       $1
     38     when nil
     39       @email
     40     else
     41       @name
     42     end
     43   end
     44 
     45   def mediumname; @name || @email; end
     46 
     47   def longname
     48     to_s
     49   end
     50 
     51   def full_address
     52     Person.full_address @name, @email
     53   end
     54 
     55   ## when sorting addresses, sort by this
     56   def sort_by_me
     57     case @name
     58     when /^(\S+), \S+/
     59       $1
     60     when /^\S+ \S+ (\S+)/
     61       $1
     62     when /^\S+ (\S+)/
     63       $1
     64     when nil
     65       @email
     66     else
     67       @name
     68     end.downcase
     69   end
     70 
     71   def eql? o; email.eql? o.email end
     72   def hash; email.hash end
     73 
     74 
     75   ## see comments in self.from_address
     76   def indexable_content
     77     [name, email, email.split(/@/).first].join(" ")
     78   end
     79 
     80   class << self
     81 
     82     def full_address name, email
     83       if name && email
     84         if name =~ /[",@]/
     85           "#{name.inspect} <#{email}>" # escape quotes
     86         else
     87           "#{name} <#{email}>"
     88         end
     89       else
     90         email
     91       end
     92     end
     93 
     94     ## return "canonical" person using contact manager or create one if
     95     ## not found or contact manager not available
     96     def from_name_and_email name, email
     97       ContactManager.instantiated? && ContactManager.person_for(email) || Person.new(name, email)
     98     end
     99 
    100     def from_address s
    101       return nil if s.nil?
    102 
    103       ## try and parse an email address and name
    104       name, email = case s
    105         when /(.+?) ((\S+?)@\S+) \3/
    106           ## ok, this first match cause is insane, but bear with me.  email
    107           ## addresses are stored in the to/from/etc fields of the index in a
    108           ## weird format: "name address first-part-of-address", i.e.  spaces
    109           ## separating those three bits, and no <>'s. this is the output of
    110           ## #indexable_content. here, we reverse-engineer that format to extract
    111           ## a valid address.
    112           ##
    113           ## we store things this way to allow searches on a to/from/etc field to
    114           ## match any of those parts. a more robust solution would be to store a
    115           ## separate, non-indexed field with the proper headers. but this way we
    116           ## save precious bits, and it's backwards-compatible with older indexes.
    117           [$1, $2]
    118         when /["'](.*?)["'] <(.*?)>/, /([^,]+) <(.*?)>/
    119           a, b = $1, $2
    120           [a.gsub('\"', '"'), b]
    121         when /<((\S+?)@\S+?)>/
    122           [$2, $1]
    123         when /((\S+?)@\S+)/
    124           [$2, $1]
    125         else
    126           [nil, s]
    127         end
    128 
    129       from_name_and_email name, email
    130     end
    131 
    132     def from_address_list ss
    133       return [] if ss.nil?
    134       ss.dup.split_on_commas.map { |s| self.from_address s }
    135     end
    136 
    137   end
    138 
    139 end
    140 
    141 end