sisimai 5.3.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog.md +12 -0
- data/Makefile +3 -2
- data/README-JA.md +2 -2
- data/README.md +6 -6
- data/lib/sisimai/address.rb +45 -56
- data/lib/sisimai/arf.rb +11 -16
- data/lib/sisimai/datetime.rb +16 -50
- data/lib/sisimai/fact/json.rb +5 -5
- data/lib/sisimai/fact/yaml.rb +3 -3
- data/lib/sisimai/fact.rb +11 -12
- data/lib/sisimai/lda.rb +3 -3
- data/lib/sisimai/lhost/activehunter.rb +4 -6
- data/lib/sisimai/lhost/amazonses.rb +5 -6
- data/lib/sisimai/lhost/apachejames.rb +7 -9
- data/lib/sisimai/lhost/biglobe.rb +3 -5
- data/lib/sisimai/lhost/courier.rb +4 -6
- data/lib/sisimai/lhost/domino.rb +4 -5
- data/lib/sisimai/lhost/dragonfly.rb +3 -5
- data/lib/sisimai/lhost/einsundeins.rb +6 -8
- data/lib/sisimai/lhost/exchange2003.rb +10 -12
- data/lib/sisimai/lhost/exchange2007.rb +4 -5
- data/lib/sisimai/lhost/exim.rb +6 -8
- data/lib/sisimai/lhost/ezweb.rb +10 -12
- data/lib/sisimai/lhost/fml.rb +2 -3
- data/lib/sisimai/lhost/gmail.rb +4 -6
- data/lib/sisimai/lhost/gmx.rb +6 -8
- data/lib/sisimai/lhost/googlegroups.rb +1 -2
- data/lib/sisimai/lhost/googleworkspace.rb +3 -4
- data/lib/sisimai/lhost/imailserver.rb +6 -7
- data/lib/sisimai/lhost/interscanmss.rb +1 -2
- data/lib/sisimai/lhost/kddi.rb +5 -8
- data/lib/sisimai/lhost/mailfoundry.rb +4 -7
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +4 -6
- data/lib/sisimai/lhost/messagingserver.rb +5 -7
- data/lib/sisimai/lhost/mfilter.rb +4 -6
- data/lib/sisimai/lhost/notes.rb +7 -9
- data/lib/sisimai/lhost/opensmtpd.rb +2 -4
- data/lib/sisimai/lhost/postfix.rb +8 -11
- data/lib/sisimai/lhost/qmail.rb +5 -8
- data/lib/sisimai/lhost/sendmail.rb +7 -10
- data/lib/sisimai/lhost/v5sendmail.rb +15 -17
- data/lib/sisimai/lhost/verizon.rb +9 -14
- data/lib/sisimai/lhost/x1.rb +4 -6
- data/lib/sisimai/lhost/x2.rb +5 -7
- data/lib/sisimai/lhost/x3.rb +3 -4
- data/lib/sisimai/lhost/x6.rb +4 -6
- data/lib/sisimai/lhost/zoho.rb +6 -8
- data/lib/sisimai/lhost.rb +1 -1
- data/lib/sisimai/mail/mbox.rb +1 -1
- data/lib/sisimai/mail/memory.rb +1 -1
- data/lib/sisimai/mail.rb +8 -8
- data/lib/sisimai/message.rb +11 -13
- data/lib/sisimai/reason/authfailure.rb +10 -10
- data/lib/sisimai/reason/badreputation.rb +4 -6
- data/lib/sisimai/reason/blocked.rb +6 -8
- data/lib/sisimai/reason/contenterror.rb +5 -6
- data/lib/sisimai/reason/delivered.rb +2 -2
- data/lib/sisimai/reason/exceedlimit.rb +7 -8
- data/lib/sisimai/reason/expired.rb +6 -7
- data/lib/sisimai/reason/failedstarttls.rb +5 -7
- data/lib/sisimai/reason/feedback.rb +2 -2
- data/lib/sisimai/reason/filtered.rb +7 -10
- data/lib/sisimai/reason/hasmoved.rb +4 -5
- data/lib/sisimai/reason/hostunknown.rb +6 -7
- data/lib/sisimai/reason/mailboxfull.rb +7 -8
- data/lib/sisimai/reason/mailererror.rb +5 -8
- data/lib/sisimai/reason/mesgtoobig.rb +5 -6
- data/lib/sisimai/reason/networkerror.rb +5 -8
- data/lib/sisimai/reason/norelaying.rb +4 -5
- data/lib/sisimai/reason/notaccept.rb +5 -8
- data/lib/sisimai/reason/notcompliantrfc.rb +5 -6
- data/lib/sisimai/reason/onhold.rb +6 -9
- data/lib/sisimai/reason/policyviolation.rb +6 -9
- data/lib/sisimai/reason/rejected.rb +5 -6
- data/lib/sisimai/reason/requireptr.rb +6 -7
- data/lib/sisimai/reason/securityerror.rb +6 -9
- data/lib/sisimai/reason/spamdetected.rb +8 -9
- data/lib/sisimai/reason/speeding.rb +6 -7
- data/lib/sisimai/reason/suppressed.rb +3 -7
- data/lib/sisimai/reason/suspend.rb +5 -7
- data/lib/sisimai/reason/syntaxerror.rb +3 -5
- data/lib/sisimai/reason/systemerror.rb +6 -9
- data/lib/sisimai/reason/systemfull.rb +5 -8
- data/lib/sisimai/reason/toomanyconn.rb +5 -6
- data/lib/sisimai/reason/undefined.rb +2 -2
- data/lib/sisimai/reason/userunknown.rb +8 -9
- data/lib/sisimai/reason/vacation.rb +4 -5
- data/lib/sisimai/reason/virusdetected.rb +4 -5
- data/lib/sisimai/reason.rb +13 -13
- data/lib/sisimai/rfc1123.rb +4 -8
- data/lib/sisimai/rfc1894.rb +5 -6
- data/lib/sisimai/rfc2045.rb +27 -31
- data/lib/sisimai/rfc3464/thirdparty.rb +1 -1
- data/lib/sisimai/rfc3464.rb +7 -9
- data/lib/sisimai/rfc3834.rb +5 -9
- data/lib/sisimai/rfc5322.rb +8 -26
- data/lib/sisimai/rfc791.rb +6 -4
- data/lib/sisimai/rhost/google.rb +8 -0
- data/lib/sisimai/rhost/microsoft.rb +17 -5
- data/lib/sisimai/rhost.rb +2 -2
- data/lib/sisimai/smtp/command.rb +1 -1
- data/lib/sisimai/smtp/failure.rb +5 -12
- data/lib/sisimai/smtp/reply.rb +3 -5
- data/lib/sisimai/smtp/status.rb +14 -24
- data/lib/sisimai/smtp/transcript.rb +1 -10
- data/lib/sisimai/string.rb +20 -30
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +11 -11
- data/set-of-emails/maildir/bsd/rhost-microsoft-06.eml +45 -0
- metadata +3 -2
    
        data/lib/sisimai/message.rb
    CHANGED
    
    | @@ -37,7 +37,7 @@ module Sisimai | |
| 37 37 | 
             
                  def rise(**argvs)
         | 
| 38 38 | 
             
                    return nil unless argvs
         | 
| 39 39 | 
             
                    email = argvs[:data].scrub('?').gsub("\r\n", "\n")
         | 
| 40 | 
            -
                    thing = { | 
| 40 | 
            +
                    thing = {'from' => '','header' => {}, 'rfc822' => '', 'ds' => [], 'catch' => nil}
         | 
| 41 41 | 
             
                    param = {}
         | 
| 42 42 |  | 
| 43 43 | 
             
                    aftersplit = nil
         | 
| @@ -98,8 +98,6 @@ module Sisimai | |
| 98 98 | 
             
                    return thing
         | 
| 99 99 | 
             
                  end
         | 
| 100 100 |  | 
| 101 | 
            -
                  def load(argvs); ' ***warning: Sisimai::Message.load will be removed at v5.3.0'; return []; end
         | 
| 102 | 
            -
             | 
| 103 101 | 
             
                  # Divide email data up headers and a body part.
         | 
| 104 102 | 
             
                  # @param         [String] email  Email data
         | 
| 105 103 | 
             
                  # @return        [Array]         Email data after split
         | 
| @@ -121,7 +119,7 @@ module Sisimai | |
| 121 119 | 
             
                      # Set pseudo UNIX From line
         | 
| 122 120 | 
             
                      parts[0] = 'MAILER-DAEMON Tue Feb 11 00:00:00 2014'
         | 
| 123 121 | 
             
                    end
         | 
| 124 | 
            -
                    parts[1]  | 
| 122 | 
            +
                    parts[1] += "\n" unless parts[1].end_with?("\n")
         | 
| 125 123 |  | 
| 126 124 | 
             
                    %w[image/ application/ text/html].each do |e|
         | 
| 127 125 | 
             
                      # https://github.com/sisimai/p5-sisimai/issues/492, Reduce email size
         | 
| @@ -130,12 +128,12 @@ module Sisimai | |
| 130 128 | 
             
                      ep = e == 'text/html' ? '</html>' : "--\n"
         | 
| 131 129 | 
             
                      while true
         | 
| 132 130 | 
             
                        # Remove each part from "Content-Type: image/..." to "--\n" (the end of each boundary)
         | 
| 133 | 
            -
                        p0 = parts[2].index( | 
| 131 | 
            +
                        p0 = parts[2].index("Content-Type: #{e}", p0); break unless p0
         | 
| 134 132 | 
             
                        p1 = parts[2].index(ep, p0 + 32);              break unless p1
         | 
| 135 133 | 
             
                        parts[2][p0, p1 - p0] = ''
         | 
| 136 134 | 
             
                      end
         | 
| 137 135 | 
             
                    end
         | 
| 138 | 
            -
                    parts[2]  | 
| 136 | 
            +
                    parts[2] += "\n"
         | 
| 139 137 | 
             
                    return parts
         | 
| 140 138 | 
             
                  end
         | 
| 141 139 |  | 
| @@ -150,11 +148,11 @@ module Sisimai | |
| 150 148 |  | 
| 151 149 | 
             
                    # Select and convert all the headers in $argv0. The following regular expression is based on
         | 
| 152 150 | 
             
                    # https://gist.github.com/xtetsuji/b080e1f5551d17242f6415aba8a00239
         | 
| 153 | 
            -
                    headermaps = { | 
| 151 | 
            +
                    headermaps = {'subject' => ''}
         | 
| 154 152 | 
             
                    receivedby = []
         | 
| 155 153 | 
             
                    argv0.scan(/^([\w-]+):[ ]*(.*?)\n(?!\s)/m) { |e| headermaps[e[0].downcase] = e[1] }
         | 
| 156 154 | 
             
                    headermaps.delete('received')
         | 
| 157 | 
            -
                    headermaps.each_key { |e| headermaps[e].gsub | 
| 155 | 
            +
                    headermaps.each_key { |e| headermaps[e] = headermaps[e].gsub(/\n\s+/, ' ') }
         | 
| 158 156 |  | 
| 159 157 | 
             
                    if argv0.include?('Received:')
         | 
| 160 158 | 
             
                      # Capture values of each Received: header
         | 
| @@ -217,7 +215,7 @@ module Sisimai | |
| 217 215 | 
             
                      index += 1
         | 
| 218 216 | 
             
                      if fn == ''
         | 
| 219 217 | 
             
                        # There is neither ":" character nor the field listed in $FieldTable
         | 
| 220 | 
            -
                        email  | 
| 218 | 
            +
                        email += "#{e}\n"
         | 
| 221 219 | 
             
                        next
         | 
| 222 220 | 
             
                      end
         | 
| 223 221 |  | 
| @@ -295,10 +293,10 @@ module Sisimai | |
| 295 293 |  | 
| 296 294 | 
             
                      # 4. Remove redundant space characters
         | 
| 297 295 | 
             
                      bf = bf.squeeze(' ').strip
         | 
| 298 | 
            -
                      email  | 
| 296 | 
            +
                      email += sprintf("%s: %s\n", fn, bf)
         | 
| 299 297 | 
             
                    end
         | 
| 300 298 |  | 
| 301 | 
            -
                    email  | 
| 299 | 
            +
                    email += "\n" unless email.end_with?("\n\n")
         | 
| 302 300 | 
             
                    return email
         | 
| 303 301 | 
             
                  end
         | 
| 304 302 |  | 
| @@ -363,10 +361,10 @@ module Sisimai | |
| 363 361 | 
             
                    if hookmethod.is_a? Proc
         | 
| 364 362 | 
             
                      # Call the hook method
         | 
| 365 363 | 
             
                      begin
         | 
| 366 | 
            -
                        p = { | 
| 364 | 
            +
                        p = {'headers' => mailheader, 'message' => bodystring}
         | 
| 367 365 | 
             
                        havecaught = hookmethod.call(p)
         | 
| 368 366 | 
             
                      rescue StandardError => ce
         | 
| 369 | 
            -
                        warn ' ***warning: Something is wrong in hook method ":hook":'  | 
| 367 | 
            +
                        warn ' ***warning: Something is wrong in hook method ":hook":' + ce.to_s
         | 
| 370 368 | 
             
                      end
         | 
| 371 369 | 
             
                    end
         | 
| 372 370 |  | 
| @@ -18,11 +18,13 @@ module Sisimai | |
| 18 18 | 
             
                      '//spf.pobox.com',
         | 
| 19 19 | 
             
                      'bad spf records for',
         | 
| 20 20 | 
             
                      'dmarc policy',
         | 
| 21 | 
            +
                      "doesn't meet the required authentication level",
         | 
| 21 22 | 
             
                      'please inspect your spf settings',
         | 
| 22 23 | 
             
                      'sender policy framework (spf) fail',
         | 
| 23 24 | 
             
                      'sender policy framework violation',
         | 
| 24 25 | 
             
                      'spf (sender policy framework) domain authentication fail',
         | 
| 25 26 | 
             
                      'spf check: fail',
         | 
| 27 | 
            +
                      "the 5322.From address doesn't meet the authentication requirements defined for the sender",
         | 
| 26 28 | 
             
                    ].freeze
         | 
| 27 29 | 
             
                    Pairs = [
         | 
| 28 30 | 
             
                      [' is not allowed to send mail.', '_401'],
         | 
| @@ -34,24 +36,22 @@ module Sisimai | |
| 34 36 |  | 
| 35 37 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 36 38 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 37 | 
            -
                    # @return   [ | 
| 38 | 
            -
                    #                           true: Matched
         | 
| 39 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 39 40 | 
             
                    def match(argv1)
         | 
| 40 | 
            -
                      return  | 
| 41 | 
            -
                      return true | 
| 42 | 
            -
                      return true | 
| 41 | 
            +
                      return false unless argv1
         | 
| 42 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 43 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 43 44 | 
             
                      return false
         | 
| 44 45 | 
             
                    end
         | 
| 45 46 |  | 
| 46 47 | 
             
                    # The bounce reason is "authfailure" or not
         | 
| 47 48 | 
             
                    # @param    [Sisimai::Fact] argvs Object to be detected the reason
         | 
| 48 | 
            -
                    # @return   [ | 
| 49 | 
            -
                    #                                 false: is not AuthFailure
         | 
| 49 | 
            +
                    # @return   [Boolean]             true: is AuthFailure, false: is not AuthFailure
         | 
| 50 50 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 51 51 | 
             
                    def true(argvs)
         | 
| 52 | 
            -
                      return  | 
| 53 | 
            -
                      return true | 
| 54 | 
            -
                      return true | 
| 52 | 
            +
                      return false if argvs['deliverystatus'].empty?
         | 
| 53 | 
            +
                      return true  if argvs['reason'] == 'authfailure'
         | 
| 54 | 
            +
                      return true  if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'authfailure'
         | 
| 55 55 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 56 56 | 
             
                    end
         | 
| 57 57 |  | 
| @@ -28,18 +28,16 @@ module Sisimai | |
| 28 28 |  | 
| 29 29 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 30 30 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 31 | 
            -
                    # @return   [ | 
| 32 | 
            -
                    #                           true: Matched
         | 
| 31 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 33 32 | 
             
                    def match(argv1)
         | 
| 34 | 
            -
                      return  | 
| 35 | 
            -
                      return true | 
| 33 | 
            +
                      return false unless argv1
         | 
| 34 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 36 35 | 
             
                      return false
         | 
| 37 36 | 
             
                    end
         | 
| 38 37 |  | 
| 39 38 | 
             
                    # The bounce reason is "badreputation" or not
         | 
| 40 39 | 
             
                    # @param    [Sisimai::Fact] argvs Object to be detected the reason
         | 
| 41 | 
            -
                    # @return   [ | 
| 42 | 
            -
                    #                                 false: is not BadReputation
         | 
| 40 | 
            +
                    # @return   [Boolean]             true: is BadReputation, false: is not BadReputation
         | 
| 43 41 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 44 42 | 
             
                    def true(argvs)
         | 
| 45 43 | 
             
                      return true if argvs['reason'] == 'badreputation'
         | 
| @@ -100,23 +100,21 @@ module Sisimai | |
| 100 100 |  | 
| 101 101 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 102 102 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 103 | 
            -
                    # @return   [ | 
| 104 | 
            -
                    #                           true: Matched
         | 
| 103 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 105 104 | 
             
                    def match(argv1)
         | 
| 106 | 
            -
                      return  | 
| 107 | 
            -
                      return true | 
| 108 | 
            -
                      return true | 
| 105 | 
            +
                      return false unless argv1
         | 
| 106 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 107 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 109 108 | 
             
                      return false
         | 
| 110 109 | 
             
                    end
         | 
| 111 110 |  | 
| 112 111 | 
             
                    # Blocked due to client IP address or hostname
         | 
| 113 112 | 
             
                    # @param    [Hash] argvs  Hash to be detected the value of reason
         | 
| 114 | 
            -
                    # @return   [true,false | 
| 115 | 
            -
                    #                         false: is not blocked by the client
         | 
| 113 | 
            +
                    # @return   [Boolean]     true: is blocked, false: is not blocked by the client
         | 
| 116 114 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 117 115 | 
             
                    def true(argvs)
         | 
| 118 116 | 
             
                      return true if argvs['reason'] == 'blocked'
         | 
| 119 | 
            -
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 117 | 
            +
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'blocked'
         | 
| 120 118 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 121 119 | 
             
                    end
         | 
| 122 120 |  | 
| @@ -25,24 +25,23 @@ module Sisimai | |
| 25 25 |  | 
| 26 26 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 27 27 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 28 | 
            -
                    # @return   [ | 
| 29 | 
            -
                    #                           true: Matched
         | 
| 28 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 30 29 | 
             
                    def match(argv1)
         | 
| 31 | 
            -
                      return  | 
| 32 | 
            -
                      return true | 
| 30 | 
            +
                      return false unless argv1
         | 
| 31 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 33 32 | 
             
                      return false
         | 
| 34 33 | 
             
                    end
         | 
| 35 34 |  | 
| 36 35 | 
             
                    # Rejected email due to header format of the email
         | 
| 37 36 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 38 | 
            -
                    # @return   [ | 
| 37 | 
            +
                    # @return   [Boolean]               true:  rejected due to content error
         | 
| 39 38 | 
             
                    #                                   false: is not content error
         | 
| 40 39 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 41 40 | 
             
                    def true(argvs)
         | 
| 42 41 | 
             
                      require 'sisimai/reason/spamdetected'
         | 
| 43 42 | 
             
                      return true  if argvs["reason"] == "blocked"
         | 
| 44 43 | 
             
                      return false if Sisimai::Reason::SpamDetected.true(argvs)
         | 
| 45 | 
            -
                      return true  if Sisimai::SMTP::Status.name(argvs["deliverystatus"]) | 
| 44 | 
            +
                      return true  if Sisimai::SMTP::Status.name(argvs["deliverystatus"]) == "contenterror"
         | 
| 46 45 | 
             
                      return match(argvs["diagnosticcode"].downcase)
         | 
| 47 46 | 
             
                    end
         | 
| 48 47 |  | 
| @@ -14,8 +14,8 @@ module Sisimai | |
| 14 14 | 
             
                  class << self
         | 
| 15 15 | 
             
                    def text; return 'delivered'; end
         | 
| 16 16 | 
             
                    def description; return 'Email delivered successfully'; end
         | 
| 17 | 
            -
                    def match;   return  | 
| 18 | 
            -
                    def true(*); return  | 
| 17 | 
            +
                    def match;   return false; end
         | 
| 18 | 
            +
                    def true(*); return false; end
         | 
| 19 19 | 
             
                  end
         | 
| 20 20 | 
             
                end
         | 
| 21 21 | 
             
              end
         | 
| @@ -17,27 +17,26 @@ module Sisimai | |
| 17 17 |  | 
| 18 18 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 19 19 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 20 | 
            -
                    # @return   [ | 
| 21 | 
            -
                    #                           true: Matched
         | 
| 20 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 22 21 | 
             
                    def match(argv1)
         | 
| 23 | 
            -
                      return  | 
| 24 | 
            -
                      return true | 
| 22 | 
            +
                      return false unless argv1
         | 
| 23 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 25 24 | 
             
                      return false
         | 
| 26 25 | 
             
                    end
         | 
| 27 26 |  | 
| 28 27 | 
             
                    # Exceed limit or not
         | 
| 29 28 | 
             
                    # @param    [Sisimai::Fact] argvs Object to be detected the reason
         | 
| 30 | 
            -
                    # @return   [ | 
| 29 | 
            +
                    # @return   [Boolean]             true:  Exceeds the limit
         | 
| 31 30 | 
             
                    #                                 false: Did not exceed the limit
         | 
| 32 31 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 33 32 | 
             
                    def true(argvs)
         | 
| 34 | 
            -
                      return  | 
| 35 | 
            -
                      return true | 
| 33 | 
            +
                      return false if argvs['deliverystatus'].empty?
         | 
| 34 | 
            +
                      return true  if argvs['reason'] == 'exceedlimit'
         | 
| 36 35 |  | 
| 37 36 | 
             
                      # Delivery status code points exceedlimit.
         | 
| 38 37 | 
             
                      # Status: 5.2.3
         | 
| 39 38 | 
             
                      # Diagnostic-Code: SMTP; 552 5.2.3 Message size exceeds fixed maximum message size
         | 
| 40 | 
            -
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 39 | 
            +
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'exceedlimit'
         | 
| 41 40 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 42 41 | 
             
                    end
         | 
| 43 42 |  | 
| @@ -40,21 +40,20 @@ module Sisimai | |
| 40 40 |  | 
| 41 41 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 42 42 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 43 | 
            -
                    # @return   [ | 
| 44 | 
            -
                    #                           true: Matched
         | 
| 43 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 45 44 | 
             
                    def match(argv1)
         | 
| 46 | 
            -
                      return  | 
| 47 | 
            -
                      return true | 
| 48 | 
            -
                      return true | 
| 45 | 
            +
                      return false unless argv1
         | 
| 46 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 47 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 49 48 | 
             
                      return false
         | 
| 50 49 | 
             
                    end
         | 
| 51 50 |  | 
| 52 51 | 
             
                    # Delivery expired due to connection failure or network error
         | 
| 53 52 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 54 | 
            -
                    # @return   [ | 
| 53 | 
            +
                    # @return   [Boolean]               true:  is expired
         | 
| 55 54 | 
             
                    #                                   false: is not expired
         | 
| 56 55 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 57 | 
            -
                    def true(_argvs); return  | 
| 56 | 
            +
                    def true(_argvs); return false; end
         | 
| 58 57 |  | 
| 59 58 | 
             
                  end
         | 
| 60 59 | 
             
                end
         | 
| @@ -15,22 +15,20 @@ module Sisimai | |
| 15 15 |  | 
| 16 16 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 17 17 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 18 | 
            -
                    # @return   [ | 
| 19 | 
            -
                    #                           true: Matched
         | 
| 18 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 20 19 | 
             
                    def match(argv1)
         | 
| 21 | 
            -
                      return  | 
| 22 | 
            -
                      return true | 
| 20 | 
            +
                      return false unless argv1
         | 
| 21 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 23 22 | 
             
                      return false
         | 
| 24 23 | 
             
                    end
         | 
| 25 24 |  | 
| 26 25 | 
             
                    # Email delivery failed due to STARTTLS related problem
         | 
| 27 26 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 28 | 
            -
                    # @return   [ | 
| 27 | 
            +
                    # @return   [Boolean]               true:  FailedSTARTTLS
         | 
| 29 28 | 
             
                    #                                   false: Not FailedSTARTTLS
         | 
| 30 29 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 31 30 | 
             
                    def true(argvs)
         | 
| 32 | 
            -
                      return true if argvs["reason"] == "failedstarttls"
         | 
| 33 | 
            -
                      return true if argvs["command"] == "STARTTLS"
         | 
| 31 | 
            +
                      return true if argvs["reason"] == "failedstarttls" || argvs["command"] == "STARTTLS"
         | 
| 34 32 | 
             
                      return true if [523, 524, 538].index(argvs["replycode"].to_i)
         | 
| 35 33 | 
             
                      return match(argvs["diagnosticcode"].downcase)
         | 
| 36 34 | 
             
                    end
         | 
| @@ -6,8 +6,8 @@ module Sisimai | |
| 6 6 | 
             
                  class << self
         | 
| 7 7 | 
             
                    def text; return 'feedback'; end
         | 
| 8 8 | 
             
                    def description; return 'Email forwarded to the sender as a complaint message from your mailbox provider'; end
         | 
| 9 | 
            -
                    def match;   return  | 
| 10 | 
            -
                    def true(*); return  | 
| 9 | 
            +
                    def match;   return false; end
         | 
| 10 | 
            +
                    def true(*); return false; end
         | 
| 11 11 | 
             
                  end
         | 
| 12 12 | 
             
                end
         | 
| 13 13 | 
             
              end
         | 
| @@ -33,39 +33,36 @@ module Sisimai | |
| 33 33 |  | 
| 34 34 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 35 35 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 36 | 
            -
                    # @return   [ | 
| 37 | 
            -
                    #                           true: Matched
         | 
| 36 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 38 37 | 
             
                    def match(argv1)
         | 
| 39 | 
            -
                      return  | 
| 40 | 
            -
                      return true | 
| 38 | 
            +
                      return false unless argv1
         | 
| 39 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 41 40 | 
             
                      return false
         | 
| 42 41 | 
             
                    end
         | 
| 43 42 |  | 
| 44 43 | 
             
                    # Rejected by a sender domain or a sender address by a filter ?
         | 
| 45 44 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 46 | 
            -
                    # @return   [ | 
| 45 | 
            +
                    # @return   [Boolean]               true:  is filtered
         | 
| 47 46 | 
             
                    #                                   false: is not filtered
         | 
| 48 47 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 49 48 | 
             
                    def true(argvs)
         | 
| 50 49 | 
             
                      return true if argvs['reason'] == 'filtered'
         | 
| 51 50 |  | 
| 52 51 | 
             
                      require 'sisimai/reason/userunknown'
         | 
| 53 | 
            -
                      tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 52 | 
            +
                      tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus'])
         | 
| 54 53 | 
             
                      return false if tempreason == 'suspend'
         | 
| 55 54 |  | 
| 56 55 | 
             
                      issuedcode = argvs['diagnosticcode'].downcase || ''
         | 
| 57 56 | 
             
                      thecommand = argvs['command']                 || ''
         | 
| 58 57 | 
             
                      if tempreason == 'filtered'
         | 
| 59 58 | 
             
                        # Delivery status code points "filtered".
         | 
| 60 | 
            -
                        return true if Sisimai::Reason::UserUnknown.match(issuedcode)
         | 
| 61 | 
            -
                        return true if match(issuedcode)
         | 
| 59 | 
            +
                        return true if Sisimai::Reason::UserUnknown.match(issuedcode) || match(issuedcode)
         | 
| 62 60 | 
             
                      else
         | 
| 63 61 | 
             
                        # The value of "reason" isn't "filtered" when the value of "command" is an SMTP command
         | 
| 64 62 | 
             
                        # to be sent before the SMTP DATA command because all the MTAs read the headers and the
         | 
| 65 63 | 
             
                        # entire message body after the DATA command.
         | 
| 66 64 | 
             
                        return false if %w[CONN EHLO HELO MAIL RCPT].include?(thecommand)
         | 
| 67 | 
            -
                        return true  if match(issuedcode)
         | 
| 68 | 
            -
                        return true  if Sisimai::Reason::UserUnknown.match(issuedcode)
         | 
| 65 | 
            +
                        return true  if match(issuedcode) || Sisimai::Reason::UserUnknown.match(issuedcode)
         | 
| 69 66 | 
             
                      end
         | 
| 70 67 | 
             
                      return false
         | 
| 71 68 | 
             
                    end
         | 
| @@ -15,17 +15,16 @@ module Sisimai | |
| 15 15 |  | 
| 16 16 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 17 17 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 18 | 
            -
                    # @return   [ | 
| 19 | 
            -
                    #                           true: Matched
         | 
| 18 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 20 19 | 
             
                    def match(argv1)
         | 
| 21 | 
            -
                      return  | 
| 22 | 
            -
                      return true | 
| 20 | 
            +
                      return false unless argv1
         | 
| 21 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 23 22 | 
             
                      return false
         | 
| 24 23 | 
             
                    end
         | 
| 25 24 |  | 
| 26 25 | 
             
                    # Whether the address has moved or not
         | 
| 27 26 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 28 | 
            -
                    # @return   [ | 
| 27 | 
            +
                    # @return   [Boolean]               true:  The address has moved
         | 
| 29 28 | 
             
                    #                                   false: Has not moved
         | 
| 30 29 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 31 30 | 
             
                    def true(argvs)
         | 
| @@ -32,19 +32,18 @@ module Sisimai | |
| 32 32 |  | 
| 33 33 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 34 34 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 35 | 
            -
                    # @return   [ | 
| 36 | 
            -
                    #                           true:  Matched
         | 
| 35 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 37 36 | 
             
                    # @since v4.0.0
         | 
| 38 37 | 
             
                    def match(argv1)
         | 
| 39 | 
            -
                      return  | 
| 40 | 
            -
                      return true | 
| 41 | 
            -
                      return true | 
| 38 | 
            +
                      return false unless argv1
         | 
| 39 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 40 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 42 41 | 
             
                      return false
         | 
| 43 42 | 
             
                    end
         | 
| 44 43 |  | 
| 45 44 | 
             
                    # Whether the host is unknown or not
         | 
| 46 45 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 47 | 
            -
                    # @return   [ | 
| 46 | 
            +
                    # @return   [Boolean]               true:  is unknown host
         | 
| 48 47 | 
             
                    #                                   false: is not unknown host.
         | 
| 49 48 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 50 49 | 
             
                    def true(argvs)
         | 
| @@ -53,7 +52,7 @@ module Sisimai | |
| 53 52 | 
             
                      issuedcode = argvs['diagnosticcode'].downcase || ''
         | 
| 54 53 | 
             
                      statuscode = argvs['deliverystatus'] || ''
         | 
| 55 54 |  | 
| 56 | 
            -
                      if Sisimai::SMTP::Status.name(statuscode) | 
| 55 | 
            +
                      if Sisimai::SMTP::Status.name(statuscode) == 'hostunknown'
         | 
| 57 56 | 
             
                        # To prevent classifying DNS errors as "HostUnknown"
         | 
| 58 57 | 
             
                        require 'sisimai/reason/networkerror'
         | 
| 59 58 | 
             
                        return true unless Sisimai::Reason::NetworkError.match(issuedcode)
         | 
| @@ -64,27 +64,26 @@ module Sisimai | |
| 64 64 |  | 
| 65 65 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 66 66 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 67 | 
            -
                    # @return   [ | 
| 68 | 
            -
                    #                           true: Matched
         | 
| 67 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 69 68 | 
             
                    def match(argv1)
         | 
| 70 | 
            -
                      return  | 
| 71 | 
            -
                      return true | 
| 69 | 
            +
                      return false unless argv1
         | 
| 70 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 72 71 | 
             
                      return false
         | 
| 73 72 | 
             
                    end
         | 
| 74 73 |  | 
| 75 74 | 
             
                    # The envelope recipient's mailbox is full or not
         | 
| 76 75 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 77 | 
            -
                    # @return   [ | 
| 76 | 
            +
                    # @return   [Boolean]               true:  is mailbox full
         | 
| 78 77 | 
             
                    #                                   false: is not mailbox full
         | 
| 79 78 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 80 79 | 
             
                    def true(argvs)
         | 
| 81 | 
            -
                      return  | 
| 82 | 
            -
                      return true | 
| 80 | 
            +
                      return false if argvs['deliverystatus'].empty?
         | 
| 81 | 
            +
                      return true  if argvs['reason'] == 'mailboxfull'
         | 
| 83 82 |  | 
| 84 83 | 
             
                      # Delivery status code points "mailboxfull".
         | 
| 85 84 | 
             
                      # Status: 4.2.2
         | 
| 86 85 | 
             
                      # Diagnostic-Code: SMTP; 450 4.2.2 <***@example.jp>... Mailbox Full
         | 
| 87 | 
            -
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 86 | 
            +
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'mailboxfull'
         | 
| 88 87 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 89 88 | 
             
                    end
         | 
| 90 89 |  | 
| @@ -28,22 +28,19 @@ module Sisimai | |
| 28 28 |  | 
| 29 29 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 30 30 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 31 | 
            -
                    # @return   [ | 
| 32 | 
            -
                    #                           true: Matched
         | 
| 31 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 33 32 | 
             
                    def match(argv1)
         | 
| 34 | 
            -
                      return  | 
| 35 | 
            -
                      return true | 
| 33 | 
            +
                      return false unless argv1
         | 
| 34 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 36 35 | 
             
                      return false
         | 
| 37 36 | 
             
                    end
         | 
| 38 37 |  | 
| 39 38 | 
             
                    # The bounce reason is mailer error or not
         | 
| 40 39 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 41 | 
            -
                    # @return   [ | 
| 40 | 
            +
                    # @return   [Boolean]               true:  is mailer error
         | 
| 42 41 | 
             
                    #                                   false: is not mailer error
         | 
| 43 42 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 44 | 
            -
                    def true(_argvs)
         | 
| 45 | 
            -
                      return nil
         | 
| 46 | 
            -
                    end
         | 
| 43 | 
            +
                    def true(_argvs); return false; end
         | 
| 47 44 |  | 
| 48 45 | 
             
                  end
         | 
| 49 46 | 
             
                end
         | 
| @@ -27,24 +27,23 @@ module Sisimai | |
| 27 27 |  | 
| 28 28 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 29 29 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 30 | 
            -
                    # @return   [ | 
| 31 | 
            -
                    #                           true: Matched
         | 
| 30 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 32 31 | 
             
                    def match(argv1)
         | 
| 33 | 
            -
                      return  | 
| 34 | 
            -
                      return true | 
| 32 | 
            +
                      return false unless argv1
         | 
| 33 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 35 34 | 
             
                      return false
         | 
| 36 35 | 
             
                    end
         | 
| 37 36 |  | 
| 38 37 | 
             
                    # The message size is too big for the remote host
         | 
| 39 38 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 40 | 
            -
                    # @return   [ | 
| 39 | 
            +
                    # @return   [Boolean]               true:  is too big message size
         | 
| 41 40 | 
             
                    #                                   false: is not big
         | 
| 42 41 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 43 42 | 
             
                    def true(argvs)
         | 
| 44 43 | 
             
                      return true if argvs['reason'] == 'mesgtoobig'
         | 
| 45 44 |  | 
| 46 45 | 
             
                      statuscode = argvs['deliverystatus'] || ''
         | 
| 47 | 
            -
                      tempreason = Sisimai::SMTP::Status.name(statuscode) | 
| 46 | 
            +
                      tempreason = Sisimai::SMTP::Status.name(statuscode)
         | 
| 48 47 |  | 
| 49 48 | 
             
                      # Delivery status code points "mesgtoobig".
         | 
| 50 49 | 
             
                      # Status: 5.3.4
         | 
| @@ -34,22 +34,19 @@ module Sisimai | |
| 34 34 |  | 
| 35 35 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 36 36 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 37 | 
            -
                    # @return   [ | 
| 38 | 
            -
                    #                           true: Matched
         | 
| 37 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 39 38 | 
             
                    def match(argv1)
         | 
| 40 | 
            -
                      return  | 
| 41 | 
            -
                      return true | 
| 39 | 
            +
                      return false unless argv1
         | 
| 40 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 42 41 | 
             
                      return false
         | 
| 43 42 | 
             
                    end
         | 
| 44 43 |  | 
| 45 44 | 
             
                    # The bounce reason is network error or not
         | 
| 46 45 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 47 | 
            -
                    # @return   [ | 
| 46 | 
            +
                    # @return   [Boolean]               true:  is network error
         | 
| 48 47 | 
             
                    #                                   false: is not network error
         | 
| 49 48 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 50 | 
            -
                    def true(_argvs)
         | 
| 51 | 
            -
                      return nil
         | 
| 52 | 
            -
                    end
         | 
| 49 | 
            +
                    def true(_argvs); return false; end
         | 
| 53 50 |  | 
| 54 51 | 
             
                  end
         | 
| 55 52 | 
             
                end
         | 
| @@ -37,17 +37,16 @@ module Sisimai | |
| 37 37 |  | 
| 38 38 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 39 39 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 40 | 
            -
                    # @return   [ | 
| 41 | 
            -
                    #                           true: Matched
         | 
| 40 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 42 41 | 
             
                    def match(argv1)
         | 
| 43 | 
            -
                      return  | 
| 44 | 
            -
                      return true | 
| 42 | 
            +
                      return false unless argv1
         | 
| 43 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 45 44 | 
             
                      return false
         | 
| 46 45 | 
             
                    end
         | 
| 47 46 |  | 
| 48 47 | 
             
                    # Whether the message is rejected by 'Relaying denied'
         | 
| 49 48 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 50 | 
            -
                    # @return   [ | 
| 49 | 
            +
                    # @return   [Boolean]               true:  Rejected for "relaying denied"
         | 
| 51 50 | 
             
                    #                                   false: is not
         | 
| 52 51 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 53 52 | 
             
                    def true(argvs)
         | 
| @@ -26,11 +26,10 @@ module Sisimai | |
| 26 26 |  | 
| 27 27 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 28 28 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 29 | 
            -
                    # @return   [ | 
| 30 | 
            -
                    #                           true: Matched
         | 
| 29 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 31 30 | 
             
                    def match(argv1)
         | 
| 32 | 
            -
                      return  | 
| 33 | 
            -
                      return true | 
| 31 | 
            +
                      return false unless argv1
         | 
| 32 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 34 33 | 
             
                      return false
         | 
| 35 34 | 
             
                    end
         | 
| 36 35 |  | 
| @@ -40,10 +39,8 @@ module Sisimai | |
| 40 39 | 
             
                    #                                   false: Accept
         | 
| 41 40 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 42 41 | 
             
                    def true(argvs)
         | 
| 43 | 
            -
                      return true | 
| 44 | 
            -
             | 
| 45 | 
            -
                      # SMTP Reply Code is 554 or 556
         | 
| 46 | 
            -
                      return true  if [521, 556].index(argvs['replycode'].to_i)
         | 
| 42 | 
            +
                      return true  if argvs['reason'] == 'notaccept'
         | 
| 43 | 
            +
                      return true  if [521, 556].index(argvs['replycode'].to_i) # SMTP Reply Code is 554 or 556
         | 
| 47 44 | 
             
                      return false if argvs['command'] != 'MAIL'
         | 
| 48 45 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 49 46 | 
             
                    end
         |