module Redwood
-class Person
- @@email_map = {}
-
+class Person
attr_accessor :name, :email
def initialize name, email
raise ArgumentError, "email can't be nil" unless email
- @name =
- if name
- name.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ")
- else
- nil
+
+ if name
+ @name = name.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ")
+ if @name =~ /^(['"]\s*)(.*?)(\s*["'])$/
+ @name = $2
end
+ end
+
@email = email.gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ").downcase
- @@email_map[@email] = self
end
- def == o; o && o.email == email; end
- alias :eql? :==
+ def to_s; "#@name <#@email>" end
- def hash
- [name, email].hash
- end
+# def == o; o && o.email == email; end
+# alias :eql? :==
+# def hash; [name, email].hash; end
def shortname
case @name
when /(\S+) \S+/
$1
when nil
- @email #[0 ... 10]
+ @email
else
- @name #[0 ... 10]
+ @name
end
end
end
end
- def mediumname
- if @name
- name
- else
- @email
- end
- end
+ def mediumname; @name || @email; end
def full_address
if @name && @email
- if @name =~ /"/
- "#{@name.inspect} <#@email>"
+ if @name =~ /[",@]/
+ "#{@name.inspect} <#{@email}>" # escape quotes
else
- "#@name <#@email>"
+ "#{@name} <#{@email}>"
end
else
- @email
+ email
end
end
+ ## when sorting addresses, sort by this
def sort_by_me
case @name
when /^(\S+), \S+/
end.downcase
end
- def self.for_several s
- return [] if s.nil?
-
- begin
- s.split_on_commas.map { |ss| self.for ss }
- rescue StandardError => e
- raise "#{e.message}: for #{s.inspect}"
- end
- end
-
- def self.for s
+ def self.from_address s
return nil if s.nil?
- name, email =
- case s
+
+ ## try and parse an email address and name
+ name, email = case s
+ when /(.+?) ((\S+?)@\S+) \3/
+ ## ok, this first match cause is insane, but bear with me. email
+ ## addresses are stored in the to/from/etc fields of the index in a
+ ## weird format: "name address first-part-of-address", i.e. spaces
+ ## separating those three bits, and no <>'s. this is the output of
+ ## #indexable_content. here, we reverse-engineer that format to extract
+ ## a valid address.
+ ##
+ ## we store things this way to allow searches on a to/from/etc field to
+ ## match any of those parts. a more robust solution would be to store a
+ ## separate, non-indexed field with the proper headers. but this way we
+ ## save precious bits, and it's backwards-compatible with older indexes.
+ [$1, $2]
when /["'](.*?)["'] <(.*?)>/, /([^,]+) <(.*?)>/
a, b = $1, $2
[a.gsub('\"', '"'), b]
[nil, s]
end
- if name && (p = @@email_map[email])
- ## all else being equal, prefer longer names, unless the prior name
- ## doesn't contain any capitalization
- p.name = name if (p.name.nil? || p.name.length < name.length) unless
- p.name =~ /[A-Z]/ || (AccountManager.instantiated? && AccountManager.is_account?(p))
- p
- else
- Person.new name, email
- end
+ Person.new name, email
+ end
+
+ def self.from_address_list ss
+ return [] if ss.nil?
+ ss.split_on_commas.map { |s| self.from_address s }
end
+
+ ## see comments in self.from_address
+ def indexable_content
+ [name, email, email.split(/@/).first].join(" ")
+ end
+
+ def eql? o; email.eql? o.email end
+ def hash; email.hash end
end
end