class ASF::Mail
Public Class Methods
Source
# File lib/whimsy/asf/mail.rb, line 231 def self._autosubid(dom, list) return "#{list}@#{dom}" end
Convert dom, list to form used in mail_list_autosub.yml This changed in March 2022 from dom-list format
Source
# File lib/whimsy/asf/mail.rb, line 52 def self._cannot_sub self._load_auto() @auto[:disallowed] + @auto[:intrinsic] end
Source
# File lib/whimsy/asf/mail.rb, line 57 def self._cannot_unsub self._load_auto() @auto[:intrinsic] end
Source
# File lib/whimsy/asf/mail.rb, line 67 def self._chairs_allowed self._load_auto() @auto[:chairs] end
Source
# File lib/whimsy/asf/mail.rb, line 62 def self._committers_allowed self._load_auto() @auto[:committers] end
Source
# File lib/whimsy/asf/mail.rb, line 47 def self._deprecated self._load_auto() @auto[:deprecated] end
list of mailing lists that aren’t actively seeking new subscribers
Source
# File lib/whimsy/asf/mail.rb, line 268 def self._load_auto apmail_bin = File.join(ASF::Config[:puppet_data], 'apmail_bin') # Loaded by puppet auto_file = File.join(apmail_bin, 'mail_list_autosub.yml') auto_mtime = File.mtime(auto_file) # fetch this up front in case file updated during loading if not @auto or auto_mtime != @auto_mtime @auto = YAML.load_file(auto_file) @auto_mtime = auto_mtime end end
Load the auto-subscription file
Source
# File lib/whimsy/asf/mail.rb, line 279 def self._load_flags # flags for each mailing list @list_flags ||= File.join(ASF::Config[:subscriptions], 'list-flags') if not @flags or File.mtime(@list_flags) != @flags_mtime lists = [] File.open(@list_flags).each do |line| if line.match(/(?:^F:-([a-zA-Z]{26}) )?(\S+) (\S+)/) flags, dom, list = $1, $2, $3 next if list =~ /^infra-[a-z]$/ or (dom == 'incubator' and list == 'infra-dev') lists << [dom, list, flags || ''] else raise "Unexpected flags: #{line}" end end @flags = lists @flags_hash = lists.map{|d,l,f| ["#{l}@#{d}",f]}.to_h @flags_mtime = File.mtime(@list_flags) end end
Load the flags file
Source
# File lib/whimsy/asf/mail.rb, line 72 def self._members_allowed self._load_auto() @auto[:members] + @auto[:chairs] end
Source
# File lib/whimsy/asf/mail.rb, line 222 def self.archivelistid(dom, list) return "apachecon-#{list}" if dom == 'apachecon.com' return list if dom == 'apache.org' dom.sub('.apache.org', '-') + list end
Convert dom, list to form currently used in subreq.py
Source
# File lib/whimsy/asf/mail.rb, line 156 def self.canmod(ldap_pmcs, lidonly = true) allowed = [] parse_flags do |dom, list, _| autoid = _autosubid(dom, list) next if self._deprecated.include? autoid next if self._cannot_sub.include? autoid lid = archivelistid(dom, list) if ldap_pmcs.include? dom.sub('.apache.org', '') if lidonly allowed << lid else allowed << [dom, list, lid] end end end allowed end
which lists are available for automatic moderation via Whimsy? Params: ldap_pmcs: list of (P)PMC mail_list names to which the user belongs (as owner) lid_only: return lid instead of [dom,list,lid] Return: an array of entries: lid or [dom,list,lid]
Source
# File lib/whimsy/asf/mail.rb, line 95 def self.canread(listid, member=false, pmc_chair=false, ldap_pmcs=[]) flags = getflags(listid) return nil if flags.nil? # Not a known list return true unless isModSub?(flags) # subscription not needed return true if self._cannot_unsub.include? listid # must be system maintained, so assume OK return true if self._committers_allowed().include?(listid) return true if member # They can read anything return true if pmc_chair and self._chairs_allowed.include? listid return true if ldap_pmcs and ldap_pmcs.include? listid.split('@')[-1].sub('.apache.org', '') false end
Can a list be read by the person with the specified attributes? Note: this is different from cansub - not all readable lists can be self-subscribed
Params: listid: list@domain member: true if member pmc_chair: true if pmc_chair ldap_pmcs: list of (P)PMC mail_list names to which the user belongs Return true if person is allowed to read the list nil if the list is not known otherwise true
Source
# File lib/whimsy/asf/mail.rb, line 114 def self.cansub(member, pmc_chair, ldap_pmcs, lidonly = true) allowed = [] parse_flags do |dom, list, f| autoid = _autosubid(dom, list) next if self._deprecated.include? autoid next if self._cannot_sub.include? autoid lid = archivelistid(dom, list) cansub = false modsub = isModSub?(f) if not modsub # subs not moderated; allow all cansub = true elsif self._committers_allowed().include?(autoid) # always allowed cansub = true else # subs are moderated if member if list == 'private' or self._members_allowed.include?(autoid) cansub = true end elsif ldap_pmcs and list == 'private' and ldap_pmcs.include? dom.sub('.apache.org', '') cansub = true end if pmc_chair and self._chairs_allowed.include? autoid cansub = true end end if cansub if lidonly allowed << lid else allowed << [dom, list, lid] end end end allowed end
which lists are available for subscription via Whimsy? Params: member: true if member pmc_chair: true if pmc_chair ldap_pmcs: list of (P)PMC mail_list names to which the user belongs lid_only: return lid instead of [dom,list,lid] Return: an array of entries: lid or [dom,list,lid]
Source
# File lib/whimsy/asf/mail.rb, line 179 def self.configure # fetch overrides sendmail = ASF::Config.get(:sendmail) if sendmail # convert string keys to symbols options = Hash[sendmail.map {|key, value| [key.to_sym, value]}] # extract delivery method method = options.delete(:delivery_method).to_sym else # provide defaults that work on whimsy-vm* infrastructure. Since # procmail is configured with a self-signed certificate, verification # isn't a possibility method = :smtp options = {openssl_verify_mode: 'none'} end ::Mail.defaults do delivery_method method, options end end
common configuration for sending mail; loads :sendmail
configuration from ~/.whimsy
if available; otherwise default to disable openssl verification as that is what it required in order to work on the infrastructure provided whimsy-vm.
Source
# File lib/whimsy/asf/mail.rb, line 316 def self.getflags(listid) self._load_flags() @flags_hash[listid] end
get flags for list@domain; nil if not found
Source
# File lib/whimsy/asf/mail.rb, line 322 def self.isModSub?(flags) flags.include? 's' end
Do the flags indicate subscription moderation?
Source
# File lib/whimsy/asf/mail.rb, line 8 def self.list begin return @list.to_h if @list rescue NoMethodError, WeakRef::RefError end list = {} # load info from LDAP people = ASF::Person.preload(['mail', 'asf-altEmail']) people.each do |person| (person.mail + person.alt_email).each do |mail| list[mail.downcase] = person end end # load all member emails in one pass ASF::Member.each do |id, text| Member.emails(text).each do |mail| list[mail.downcase] ||= Person.find(id) end end # load all ICLA emails in one pass ASF::ICLA.each do |icla| person = Person.find(icla.id) icla.emails.each do |email| list[email.downcase] ||= person end next if icla.noId? list["#{icla.id.downcase}@apache.org"] ||= person end @list = WeakRef.new(list) list end
return a Hash containing complete list of all known emails, and the ASF::Person
that is associated with that email.
Source
# File lib/whimsy/asf/mail.rb, line 216 def self.listdom2listkey(listdom) list, dom = listdom.split('@') self.archivelistid(dom, list) end
Convert list@host.apache.org to host-list (listkey) style
Source
# File lib/whimsy/asf/mail.rb, line 306 def self.parse_flags(filter=nil) self._load_flags() @flags.each do |d, l, f| next if filter and f !~ filter yield [d, l, f] end end
parse the flags F:-aBcdeFgHiJklMnOpqrSTUVWXYz domain list Input: filter = RE to match against the flags, e.g. /s/ for subsmod Output: yields: domain, list, flags
Source
# File lib/whimsy/asf/mail.rb, line 203 def self.qmail_ids return [] unless File.exist? '/srv/subscriptions/qmail.ids' File.read('/srv/subscriptions/qmail.ids').split end
List of .qmail files that could clash with user ids (See: INFRA-14566)
Source
# File lib/whimsy/asf/mail.rb, line 211 def self.taken?(id) self.qmail_ids.include? id end
Is the id used by qmail? See also ASF::ICLA.taken?
Source
# File lib/whimsy/asf/mail.rb, line 244 def self.to_canonical(email) parts = email.split('@') if parts.length == 2 name, dom = parts return email if name.empty? || dom.empty? dom.downcase! dom = 'gmail.com' if dom == 'googlemail.com' # same mailbox if dom == 'gmail.com' return name.sub(/\+.*/, '').gsub('.', '').downcase + '@' + dom else # Effectively the same: dom = 'apache.org' if dom == 'minotaur.apache.org' # only downcase the domain (done above) return name + '@' + dom end end # Invalid; return input rather than failing return email end
Canonicalise an email address, removing aliases and ignored punctuation and downcasing the name if safe to do so
Currently only handles aliases for @gmail.com and @googlemail.com
All domains are converted to lower-case
The case of the name part is preserved since some providers may be case-sensitive Almost all providers ignore case in names, however that is not guaranteed
Source
# File lib/whimsy/asf/mail.rb, line 80 def self.unsubbable?(listid) !self._cannot_unsub.include? listid end
Is a list available for unsubscription via Whimsy? Params: listid (a@b) Return: true or false