class QuickML::Group
Attributes
address[R]
charset[R]
count[R]
name[R]
return_address[R]
Public Class Methods
exclude?(address, config_domain)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 35 def self.exclude?(address, config_domain) name, domain = address.split('@') return true if domain.nil? return Mail.address_of_domain?(address, config_domain) end
new(config, address, creator = nil, message_charset = nil)
click to toggle source
initialize¶ ↑
# File vendor/qwik/lib/qwik/group.rb, line 37 def initialize (config, address, creator = nil, message_charset = nil) @config = config @address = address @name, domain = Group.get_name(@address) @return_address = Group.generate_return_address(@address, @config.use_qmail_verp) # init_db @db = GroupDB.new(@config.sites_dir, @name) init_site # initialize for GroupSite @db.set_site(@site) @added_members = [] @logger = @config.logger @catalog = @config.catalog init_group_config init_members init_count init_charset @message_charset = message_charset || @charset @logger.log "[#{@name}]: New ML by #{creator}" if newly_created? end
Private Class Methods
generate_return_address(address, use_qmail_verp = false)
click to toggle source
# File vendor/qwik/lib/qwik/group.rb, line 98 def self.generate_return_address(address, use_qmail_verp = false) name, domain = Group.get_name(address) # e.g. <foo=return=@quickml.com-@[]> return "#{name}=return=@#{domain}-@[]" if use_qmail_verp # e.g. <foo=return@quickml.com> return "#{name}=return@#{domain}" end
get_name(address)
click to toggle source
# File vendor/qwik/lib/qwik/group.rb, line 86 def self.get_name(address) raise InvalidMLName if /@.*@/ =~ address name, host = address.split('@') raise InvalidMLName if ! valid_name?(name) return name, host end
load_charset(db)
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 43 def self.load_charset(db) return nil if ! db.exist?(:Charset) return parse_charset(db.get(:Charset)) end
load_count(db)
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 27 def self.load_count(db) return 0 if ! db.exist?(:Count) content = db.get(:Count) return (content.to_a.first || '1').chomp.to_i end
parse_charset(content)
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 48 def self.parse_charset(content) return (content.to_a.first || '').chomp end
valid_name?(name)
click to toggle source
# File vendor/qwik/lib/qwik/group.rb, line 93 def self.valid_name? (name) # Do not allow '_' and '.' for the name. return /\A[0-9a-zA-Z-]+\z/ =~ name end
Public Instance Methods
accept_confirmation()
click to toggle source
ml-processor.rb:98: ml.accept_confirmation
# File vendor/qwik/lib/qwik/group-confirm.rb, line 37 def accept_confirmation # Add suspended members. waiting_members = (waiting_members_get || '').to_a.map {|line| line.chomp } waiting_members.each {|address| begin add_member(address) rescue TooManyMembers end } # Read suspended message. waiting_message = waiting_message_get || '' mail = Mail.create { waiting_message } submit(mail) # Send it. waiting_members_delete waiting_message_delete @logger.log "[#{@name}]: Accept confirmation: #{@address}" end
active_members_include?(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 16 def active_members_include?(address) return @members.active_include?(address) end
add_error_member(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 48 def add_error_member (address) return if ! @members.active_include?(address) prev_count = @members.error_count(address) count = @members.inc_error_count(address) if prev_count == count @logger.log "[#{@name}]: AddError: #{address} (not counted)" else @logger.log "[#{@name}]: AddError: #{address} #{count}" end @members.save if @group_config[:auto_unsubscribe_count] <= @members.error_count(address) remove_member(address) report_removed_member(address) end end
add_member(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 24 def add_member (address) if Group.exclude?(address, @config.ml_domain) @logger.vlog "Excluded: #{address}" return end return if @members.active_include?(address) # Already included. @members.add_member(address) @added_members.push(address) @logger.log "[#{@name}]: Add: #{address}" end
close()
click to toggle source
# File vendor/qwik/lib/qwik/group.rb, line 73 def close @db.delete(:Members) @db.delete(:Count) @db.delete(:Alerted) @db.delete(:Charset) @db.delete(:Config) @db.delete(:WaitingMembers) @db.delete(:WaitingMessage) @logger.log("[#{@name}]: ML Closed") end
close_dummy()
click to toggle source
# File vendor/qwik/lib/qwik/group.rb, line 69 def close_dummy @logger.log("[#{@name}]: ML will be closed") end
former_members_include?(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 20 def former_members_include?(address) return @members.former_include?(address) end
forward?()
click to toggle source
# File vendor/qwik/lib/qwik/group-config.rb, line 16 def forward? return @group_config.forward? end
get_max_members()
click to toggle source
# File vendor/qwik/lib/qwik/group-config.rb, line 24 def get_max_members return @group_config[:max_members] end
group_config_check_exist()
click to toggle source
# File vendor/qwik/lib/qwik/group-config.rb, line 20 def group_config_check_exist @group_config.check_exist end
inactive?(now = Time.now)
click to toggle source
# File vendor/qwik/lib/qwik/group-sweep.rb, line 21 def inactive?(now = Time.now) return false if forward? || @group_config.permanent? return @db.last_article_time + @group_config[:ml_life_time] < now end
need_alert?(now = Time.now)
click to toggle source
# File vendor/qwik/lib/qwik/group-sweep.rb, line 16 def need_alert?(now = Time.now) return false if forward? || @group_config.permanent? || alerted? return @db.last_article_time + @group_config[:ml_alert_time] <= now end
newly_created?()
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 16 def newly_created? return ! @db.exist?(:Members) end
prepare_confirmation(mail)
click to toggle source
ml-processor.rb:115: ml.prepare_confirmation(@mail)
# File vendor/qwik/lib/qwik/group-confirm.rb, line 18 def prepare_confirmation (mail) # Create empty ML files. @members.save waiting_message_put(mail.bare) str = waiting_message_get # FIXME: Why? add_waiting_member(mail.from) mail.collect_cc.each {|address| add_waiting_member(address) } send_confirmation(mail.from) end
remove_member(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 41 def remove_member (address) return if ! @members.active_include?(address) @members.remove_member(address) @logger.log "[#{@name}]: Remove: #{address}" close if @members.active_empty? end
report_ml_close_soon()
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 18 def report_ml_close_soon return if @members.active_empty? name = @name subject = Mail.encode_field(_("[%s] ML will be closed soon", name)) header = [ ['To', @address], ['From', @address], ['Subject', subject], ['Reply-To', @address], ['Content-Type', content_type] ] header.concat(quickml_fields) time_to_close = @db.last_article_time + @group_config[:ml_life_time] ndays = ((time_to_close - Time.now) / 86400.0).ceil datefmt = __('%Y-%m-%d %H:%M') body = _("ML will be closed if no article is posted for %d days.\n\n", ndays) body << _("Time to close: %s.\n\n", time_to_close.strftime(datefmt)) body << generate_footer(true) mail = { :mail_from => '', :recipient => get_active_members, :header => header, :body => body, } Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail) @logger.log "[#{@name}]: Alert: ML will be closed soon" close_alertedp_file end
setup_test_config()
click to toggle source
# File vendor/qwik/lib/qwik/test-module-ml.rb, line 22 def setup_test_config # setup config raise 'config not defined' if !defined?($test_config) @qwikconfig = $test_config # setup memory raise 'memory not defined' if !defined?($test_memory) @qwikmemory = $test_memory end
submit(mail)
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 54 def submit (mail) #p 'ml.submit ' if $ml_debug return if @members.active_empty? if @group_config[:max_mail_length] < mail.body.length report_too_large_mail(mail) @logger.log "[#{@name}]: Too Large Mail: #{mail.from}" return end reset_error_member(mail.from) start_time = Time.now _submit(mail) elapsed = Time.now - start_time msg = "[#{@name}:#{@count}]: Send:" msg += " #{@config.smtp_host} #{elapsed} sec." if ! $test @logger.log msg end
validate_confirmation(time)
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 32 def validate_confirmation(time) return waiting_message_exist? && waiting_message_mtime.to_i == time.to_i end
Private Instance Methods
_org_submit(mail)
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 81 def _org_submit (mail) inc_count save_charset(@message_charset) remove_alertedp_file subject = Mail.rewrite_subject(mail['Subject'], @name, @count) body = rewrite_body(mail) header = [] mail.each_field {|key, value| k = key.downcase next if k == 'subject' or k == 'reply-to' header.push([key, value]) } header.push(['Subject', subject], ['Reply-To', @address], ['X-Mail-Count',@count]) header.concat(quickml_fields) mail = { :mail_from => @return_address, :recipient => get_active_members, :header => header, :body => body } Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail) end
_submit(mail)
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 76 def _submit(mail) site_post(mail) _org_submit(mail) end
add_waiting_member(address)
click to toggle source
waiting_member
# File vendor/qwik/lib/qwik/group-confirm.rb, line 85 def add_waiting_member (address) waiting_members_add(address+"\n") end
alerted?()
click to toggle source
close_alertedp_file()
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 62 def close_alertedp_file @db.put(:Alerted, '') end
confirmation_address()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 62 def confirmation_address t = waiting_message_mtime.to_i return "confirm+#{t}+#{@address}" end
confirmation_message(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 195 def confirmation_message(address) body = '' body += _("First, please read the agreement of this service.\n") #body += _("http://example.com/qwikjpAgreementE.html\n") body += _("http://qwik.jp/qwikjpAgreementE.html\n") #body += "http://#{@cnfig.domain}/"+_('AgreementE.html')+"\n" body += _("You must agree with this agreement to use the service.\n") body += _("If you agree, then,\n") body += _("Please simply reply to this mail to create ML <%s>.\n", address) body end
content_type()
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 181 def content_type return Mail.content_type(@config.content_type, @message_charset) end
generate_header(address, added_members)
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 49 def generate_header(address, added_members) header = "ML: #{address}\n" header << generate_new_member_list(added_members) header << "\n" return header end
generate_member_list(address, list)
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 96 def generate_member_list(address, list) return _("Members of <%s>:\n", address) + list + "\n" end
generate_new_member_list(added_members)
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 56 def generate_new_member_list(added_members) return added_members.map {|address| _("New Member: %s\n", MailAddress.obfuscate(address)) }.join end
generate_total_file_size_exceeded_info()
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 100 def generate_total_file_size_exceeded_info return "\n" + _('WARNING: Total attached file size exceeded.') + " " + _('Files are not attached on the web.') + "\n" end
generate_total_file_size_reaching_info()
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 106 def generate_total_file_size_reaching_info return "\n" + _("WARNING: Total attached file size is reaching to the limit.") + " " + _("%s left", (@config[:max_total_file_size] - @site.files_total).byte_format) + "\n" end
generate_unsubscribe_info(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 87 def generate_unsubscribe_info(address) return "\n" + _("How to unsubscribe from the ML:\n") + _("- Just send an empty message to <%s>.\n", address) + _("- Alternatively, if you cannot send an empty message for some reason,\n") + _(" please send a message just saying 'unsubscribe' to <%s>.\n", address) + _(" (e.g., hotmail's advertisement, signature, etc.)\n") #' end
get_active_members()
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 82 def get_active_members return @members.get_active end
inc_count()
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 33 def inc_count @count += 1 @db.put(:Count, @count) end
init_charset()
click to toggle source
init_count()
click to toggle source
init_group_config()
click to toggle source
# File vendor/qwik/lib/qwik/group-config.rb, line 30 def init_group_config @group_config = GroupConfig.new(@db) group_config = GroupConfig.get_group_config(@config) @group_config.set_default(group_config) @group_config.write end
init_members()
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 74 def init_members @members = GroupMembers.new(@config, self, @db, @group_config) end
init_site()
click to toggle source
# File vendor/qwik/lib/qwik/group-site.rb, line 20 def init_site @groupsite = GroupSite.new(@config, @name) @site = @groupsite.site end
member_added?()
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 78 def member_added? return ! @added_members.empty? end
page_url()
click to toggle source
# File vendor/qwik/lib/qwik/group-site.rb, line 34 def page_url key = @groupsite.key base = '' base = "#{key}.html" if key #return "http://#{@config.ml_domain}/#{@name}/#{base}" return "#{@config.public_url}#{@name}/#{base}" end
quickml_fields()
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 185 def quickml_fields return [ ['Precedence', 'bulk'], ['X-ML-Address', @address], ['X-ML-Name', @name], ['X-ML-Info', @config.public_url], ['X-QuickML', 'true'] ] end
remove_alertedp_file()
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 66 def remove_alertedp_file @db.delete(:Alerted) end
report_removed_member(error_address)
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 154 def report_removed_member (error_address) return if @members.active_empty? subject = Mail.encode_field(_("[%s] Removed: <%s>", @name, error_address)) header = [ ['To', @address], ['From', @address], ['Subject', subject], ['Reply-To', @address], ['Content-Type', content_type] ] header.concat(quickml_fields) body = _("<%s> was removed from the mailing list:\n<%s>\n", error_address, @address) body << _("because the address was unreachable.\n") body << generate_footer(true) mail = { :mail_from => '', :recipient => get_active_members, :header => header, :body => body, } Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail) @logger.log "[#{@name}]: Notify: Remove #{error_address}" end
report_too_large_mail(mail)
click to toggle source
FIXME: too similar to report_too_large_mail
in ml-session.rb
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 129 def report_too_large_mail (mail) header = [] subject = Mail.encode_field(_("[QuickML] Error: %s", mail['Subject'])) header.push(['To', mail.from], ['From', @address], ['Subject', subject], ['Content-Type', content_type]) max = @group_config[:max_mail_length].commify body = _("Sorry, your mail exceeds the length limitation.\n") body << _("The max length is %s bytes.\n\n", max) orig_subject = codeconv(Mail.decode_subject(mail['Subject'])) body << "Subject: #{orig_subject}\n" body << "To: #{mail['To']}\n" body << "From: #{mail['From']}\n" body << "Date: #{mail['Date']}\n" mail = { :mail_from => '', :recipient => mail.from, :header => header, :body => body, } Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail) end
reset_error_member(address)
click to toggle source
# File vendor/qwik/lib/qwik/group-member.rb, line 67 def reset_error_member (address) return unless @members.error_include?(address) @members.error_delete(address) @logger.log "[#{@name}]: ResetError: #{address}" @members.save end
rewrite_body(mail)
click to toggle source
# File vendor/qwik/lib/qwik/group-mail.rb, line 18 def rewrite_body (mail) # body header header = generate_header(@address, @added_members) if member_added? # body footer footer = generate_footer if mail.multipart? parts = mail.parts sub_mail = Mail.new sub_mail.read(parts.first) cte = sub_mail['Content-Transfer-Encoding'] if sub_mail.content_type == 'text/plain' and cte.nil? or cte.empty? or cte =~ /^[78]bit$/ sub_mail.body = header + sub_mail.body if header sub_mail.body += footer end parts[0] = sub_mail.to_s mail.body = Mail.join_parts(parts, mail.boundary) return mail.body end cte = mail['Content-Transfer-Encoding'] if mail.plain_text_body? and cte.nil? or cte.empty? or cte =~ /^[78]bit$/ mail.body = header + mail.body if header mail.body += footer return mail.body end return mail.body # abandon end
save_charset(charset)
click to toggle source
# File vendor/qwik/lib/qwik/group-cond.rb, line 52 def save_charset(charset) return if charset.nil? @db.put(:Charset, charset+"\n") end
send_confirmation(creator_address)
click to toggle source
# File vendor/qwik/lib/qwik/group-sendmail.rb, line 110 def send_confirmation (creator_address) header = [] subject = Mail.encode_field(_("[%s] Confirmation: %s", @name, @address)) header.push(['To', creator_address], ['From', confirmation_address], ['Subject', subject], ['Content-Type', content_type]) body = confirmation_message(@address) mail = { :mail_from => '', :recipient => creator_address, :header => header, :body => body, } Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail) @logger.log "[#{@name}]: Send confirmation: #{confirmation_address} #{creator_address}" end
site_post(mail, test=false)
click to toggle source
# File vendor/qwik/lib/qwik/group-site.rb, line 25 def site_post(mail, test=false) begin # Do not raise exception when posting a message. @groupsite.post(mail) @logger.log("[#{@name}]: QwikPost: #{@groupsite.key}") rescue @logger.log("[#{@name}]: QwikPostError: "+$!.to_s+$!.backtrace.to_s) end end
total_file_size_exceeded?()
click to toggle source
# File vendor/qwik/lib/qwik/group-site.rb, line 55 def total_file_size_exceeded? @groupsite.total_file_size_exceeded end
total_file_size_reaching?()
click to toggle source
# File vendor/qwik/lib/qwik/group-site.rb, line 59 def total_file_size_reaching? @groupsite.total_file_size_reaching end
waiting_members_add(content)
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 94 def waiting_members_add(content) @db.add(:WaitingMembers, content) end
waiting_members_delete()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 97 def waiting_members_delete @db.delete(:WaitingMembers) end
waiting_members_exist?()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 88 def waiting_members_exist? return @db.exist?(:WaitingMembers) end
waiting_members_get()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 91 def waiting_members_get return @db.get(:WaitingMembers) end
waiting_message_delete()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 80 def waiting_message_delete @db.delete(:WaitingMessage) end
waiting_message_exist?()
click to toggle source
waiting_message
# File vendor/qwik/lib/qwik/group-confirm.rb, line 68 def waiting_message_exist? return @db.exist?(:WaitingMessage) end
waiting_message_get()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 77 def waiting_message_get return @db.get(:WaitingMessage) end
waiting_message_mtime()
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 71 def waiting_message_mtime return @db.mtime(:WaitingMessage) end
waiting_message_put(content)
click to toggle source
# File vendor/qwik/lib/qwik/group-confirm.rb, line 74 def waiting_message_put(content) @db.put(:WaitingMessage, content) end