class QuickML::Processor
Constants
- UNSUBSCRIBE_RE
- UNSUBSCRIBE_THRESHOLD
Public Class Methods
new(config, mail)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 23 def initialize (config, mail) @config = config @mail = mail @logger = @config.logger @catalog = @config.catalog if mail.multipart? sub_mail = Mail.new sub_mail.read(mail.parts.first) @message_charset = sub_mail.charset else @message_charset = mail.charset end # FIXME: too ad-hoc @rejection_ignore_list = %w(info ajax study test) if $test @rejection_ignore_list = [] if $test_rejection_ignore_list @rejection_ignore_list = $test_rejection_ignore_list end end end
Private Class Methods
unsubscribe_requested?(body)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 128 def self.unsubscribe_requested?(body) return true if body.empty? return true if Mail.empty_body?(body) return false if UNSUBSCRIBE_THRESHOLD <= body.length return true if UNSUBSCRIBE_RE.match(body.tosjis) return false end
Public Instance Methods
process()
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 46 def process mail_log if @mail.looping? @logger.log "Looping Mail: from #{@mail.from}" return end @mail.recipients.each {|recipient| process_recipient(recipient) } end
Private Instance Methods
acceptable_submission?(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 378 def acceptable_submission? (ml) ml.newly_created? || ml.active_members_include?(@mail.from) || ml.former_members_include?(@mail.from) || sender_knows_an_active_member?(ml) end
add_member(ml, address)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 316 def add_member (ml, address) begin ml.add_member(address) rescue TooManyMembers @unadded_addresses.push(address) end end
confirmation_required?(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 385 def confirmation_required? (ml) @config.confirm_ml_creation and ml.newly_created? end
content_type()
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 180 def content_type return Mail.content_type(@config.content_type, @message_charset) end
mail_log()
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 60 def mail_log @logger.vlog "MAIL FROM:<#{@mail.mail_from}>" @mail.recipients.each {|recipient| @logger.vlog "RCPT TO:<#{recipient}>" } @logger.vlog 'From: ' + @mail.from @logger.vlog 'Cc: ' + @mail.collect_cc.join(', ') @logger.vlog 'bare From: ' + @mail['From'] @logger.vlog 'bare Cc: ' + @mail['Cc'] end
ml_address_in_to?(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 324 def ml_address_in_to? (ml) return @mail.collect_to.find {|address| address == ml.address } end
process_recipient(recipient)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 71 def process_recipient (recipient) mladdress = recipient # Error mail handling. if to_return_address?(mladdress) handler = ErrorMailHandler.new(@config, @message_charset) handler.handle(@mail) return end # Confirm to create a new mailing list. if @config.confirm_ml_creation && to_confirmation_address?(mladdress) validate_confirmation(mladdress) return end begin ServerMemory.ml_mutex(@config, mladdress).synchronize { ml = Group.new(@config, mladdress, @mail.from, @message_charset) @message_charset ||= ml.charset #qp @mail.body if Processor.unsubscribe_requested?(@mail.body) unsubscribe(ml) return end submit(ml) } rescue InvalidMLName report_invalid_mladdress(mladdress) end end
report_invalid_mladdress(mladdress)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 161 def report_invalid_mladdress (mladdress) mail = { :mail_from => '', :recipient => @mail.from, :header => [ ['To', @mail.from], ['From', @config.ml_postmaster], ['Subject', Mail.encode_field(_("[QuickML] Error: %s", @mail['Subject']))], ['Content-Type', content_type] ], :body => _("Invalid mailing list name: <%s>\n", mladdress) + _("You can only use 0-9, a-z, A-Z, `-' for mailing list name\n") + generate_footer, } Sendmail.send_mail(@config.smtp_host, @config.smtp_port, @logger, mail) @logger.log "Invalid ML Address: #{mladdress}" end
report_rejection(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 188 def report_rejection (ml) # FIXME: too ad-hoc if @rejection_ignore_list.include?(ml.name) @logger.log "[#{ml.name}]: Reject quietly: #{@mail.from}" # do nothing return end header = [] subject = Mail.encode_field(_("[QuickML] Error: %s", @mail['Subject'])) header.push(['To', @mail.from], ['From', ml.address], ['Subject', subject]) body = _("You are not a member of the mailing list:\n<%s>\n", ml.address) body << "\n" body << _("Did you send a mail with a different address from the address registered in the mailing list?\n") body << _("Please check your 'From:' address.\n") body << generate_footer body << "\n" body << _("----- Original Message -----\n") 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" body << "\n" =begin if @mail.multipart? ['Content-Type', 'Mime-Version', 'Content-Transfer-Encoding'].each {|key| header.push([key, @mail[key]]) unless @mail[key].empty? } sub_mail = Mail.new parts = @mail.parts sub_mail.read(parts.first) body << sub_mail.body sub_mail.body = body parts[0] = sub_mail.to_s body = Mail.join_parts(parts, @mail.boundary) else unless @mail['Content-Type'].empty? header.push(['Content-Type', @mail['Content-Type']]) end body << @mail.body end =end body << _("The original body is omitted to avoid spam trouble.\n") mail = { :mail_from => '', :recipient => @mail.from, :header => header, :body => body, } Sendmail.send_mail(@config.smtp_host, @config.smtp_port, @logger, mail) @logger.log "[#{ml.name}]: Reject: #{@mail.from}" end
report_too_many_members(ml, unadded_addresses)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 281 def report_too_many_members (ml, unadded_addresses) header = [ ['To', @mail.from], ['From', ml.address], ['Subject', Mail.encode_field(_("[QuickML] Error: %s", @mail['Subject']))], ['Content-Type', content_type] ] body = _("The following addresses cannot be added because <%s> mailing list reaches the maximum number of members (%d persons)\n\n", ml.address, ml.get_max_members) unadded_addresses.each {|address| body << sprintf("<%s>\n", address) } body << generate_footer mail = { :mail_from => '', :recipient => @mail.from, :header => header, :body => body, } Sendmail(@config.smtp_host, @config.smtp_port, @logger, mail) str = unadded_addresses.join(',') @logger.log "[#{ml.name}]: Too Many Members: #{str}" end
report_unsubscription(ml, member, requested_by = nil)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 252 def report_unsubscription (ml, member, requested_by = nil) header = [] subject = Mail.encode_field(_("[%s] Unsubscribe: %s", ml.name, ml.address)) header.push(['To', member], ['From', ml.address], ['Subject', subject], ['Content-Type', content_type]) if requested_by body = _("You are removed from the mailing list:\n<%s>\n", ml.address) body << _("by the request of <%s>.\n", requested_by) else body = _("You have unsubscribed from the mailing list:\n<%s>.\n", ml.address) end body << generate_footer mail = { :mail_from => '', :recipient => member, :header => header, :body => body, } Sendmail.send_mail(@config.smtp_host, @config.smtp_port, @logger, mail) @logger.log "[#{ml.name}]: Unsubscribe: #{member}" end
sender_knows_an_active_member?(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 310 def sender_knows_an_active_member? (ml) return @mail.collect_cc.find {|address| ml.active_members_include?(address) } end
submit(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 136 def submit (ml) if Group.exclude?(@mail.from, @config.ml_domain) @logger.log "Invalid From Address: #{@mail.from}" return end if ml.forward? @logger.log "Forward Address: #{ml.address}" ml.submit(@mail) return end if confirmation_required?(ml) ml.prepare_confirmation(@mail) return end if acceptable_submission?(ml) submit_article(ml) return end report_rejection(ml) end
submit_article(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 330 def submit_article (ml) @unadded_addresses = [] if ml_address_in_to?(ml) add_member(ml, @mail.from) @mail.collect_cc.each {|address| add_member(ml, address) } end if ! @unadded_addresses.empty? report_too_many_members(ml, @unadded_addresses) end ml.submit(@mail) end
to_confirmation_address?(address)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 111 def to_confirmation_address? (address) return /\Aconfirm\+/.match(address) end
to_return_address?(recipient)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 106 def to_return_address? (recipient) # "return=" for XVERP, 'return@' for without XVERP. return /^[^=]*=return[=@]/ =~ recipient end
unsubscribe(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 369 def unsubscribe (ml) cc = @mail.collect_cc if cc.empty? unsubscribe_self(ml) else unsubscribe_other(ml, cc) end end
unsubscribe_other(ml, cc)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 356 def unsubscribe_other (ml, cc) if ml.active_members_include?(@mail.from) cc.each {|other| if ml.active_members_include?(other) ml.remove_member(other) report_unsubscription(ml, other, @mail.from) end } else @logger.vlog 'rejected' end end
unsubscribe_self(ml)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 347 def unsubscribe_self (ml) if ml.active_members_include?(@mail.from) ml.remove_member(@mail.from) report_unsubscription(ml, @mail.from) else report_rejection(ml) end end
validate_confirmation(confirmation_address)
click to toggle source
# File vendor/qwik/lib/qwik/ml-processor.rb, line 115 def validate_confirmation (confirmation_address) m = /\Aconfirm\+(\d+)\+(.*)/.match(confirmation_address) return if m.nil? time = m[1] mladdress = m[2] ml = Group.new(@config, mladdress) if ml.validate_confirmation(time) ml.accept_confirmation end end