module Sisimai::RFC3834
Sisimai::RFC3834
- RFC3834
auto reply message detector
Constants
- AutoReply1
- Excludings
- MarkingsOf
- SubjectSet
Public Class Methods
description()
click to toggle source
# File lib/sisimai/rfc3834.rb, line 138 def description; 'Detector for auto replied message'; end
make(mhead, mbody)
click to toggle source
Detect auto reply message as RFC3834
@param [Hash] mhead Message
headers of a bounce email @param [String] mbody Message
body of a bounce email @return [Hash] Bounce data list and message/rfc822 part @return [Nil] it failed to parse or the arguments are missing
# File lib/sisimai/rfc3834.rb, line 46 def make(mhead, mbody) leave = 0 match = 0 # DETECT_EXCLUSION_MESSAGE Excludings.each_key do |e| # Exclude message from root@ next unless mhead[e] next unless mhead[e] next unless mhead[e].downcase =~ Excludings[e] leave = 1 break end return nil if leave > 0 # DETECT_AUTO_REPLY_MESSAGE AutoReply1.each_key do |e| # RFC3834 Auto-Submitted and other headers next unless mhead[e] next unless mhead[e] next unless mhead[e].downcase =~ AutoReply1[e] match += 1 break end return nil if match < 1 require 'sisimai/lhost' dscontents = [Sisimai::Lhost.DELIVERYSTATUS] bodyslices = mbody.scrub('?').split("\n") rfc822part = '' # (String) message/rfc822-headers part recipients = 0 # (Integer) The number of 'Final-Recipient' header maxmsgline = 5 # (Integer) Max message length(lines) haveloaded = 0 # (Integer) The number of lines loaded from message body blanklines = 0 # (Integer) Counter for countinuous blank lines countuntil = 1 # (Integer) Maximum value of blank lines in the body part v = dscontents[-1] # RECIPIENT_ADDRESS %w[from return-path].each do |e| # Try to get the address of the recipient next unless mhead[e] next unless mhead[e] v['recipient'] = mhead[e] break end if v['recipient'] # Clean-up the recipient address v['recipient'] = Sisimai::Address.s3s4(v['recipient']) recipients += 1 end return nil unless recipients > 0 if mhead['content-type'] # Get the boundary string and set regular expression for matching with # the boundary string. b0 = Sisimai::MIME.boundary(mhead['content-type'], 0) || '' MarkingsOf[:boundary] = %r/\A\Q#{b0}\E\z/ unless b0.empty? end # BODY_PARSER: Get vacation message while e = bodyslices.shift do # Read the first 5 lines except a blank line countuntil += 1 if e =~ MarkingsOf[:boundary] if e.empty? # Check a blank line blanklines += 1 break if blanklines > countuntil next end next unless e.include?(' ') next if e.start_with?('Content-Type') next if e.start_with?('Content-Transfer') v['diagnosis'] ||= '' v['diagnosis'] << e + ' ' haveloaded += 1 break if haveloaded >= maxmsgline end v['diagnosis'] ||= mhead['subject'] v['diagnosis'] = Sisimai::String.sweep(v['diagnosis']) v['reason'] = 'vacation' v['date'] = mhead['date'] v['status'] = '' if cv = mhead['subject'].match(SubjectSet) # Get the Subject header from the original message rfc822part = 'Subject: ' << cv[1] + "\n" end return { 'ds' => dscontents, 'rfc822' => rfc822part } end