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/smtp/status.rb
    CHANGED
    
    | @@ -677,11 +677,10 @@ module Sisimai | |
| 677 677 | 
             
                    # @param    [String]     argv1  Reason name
         | 
| 678 678 | 
             
                    # @param    [True,False] argv2  false: Permanent error
         | 
| 679 679 | 
             
                    #                               true:  Temporary error
         | 
| 680 | 
            -
                    # @return   [String | 
| 680 | 
            +
                    # @return   [String]            DSN or an empty string if the 1st argument is missing
         | 
| 681 681 | 
             
                    # @see      name
         | 
| 682 682 | 
             
                    def code(argv1 = nil, argv2 = false)
         | 
| 683 | 
            -
                      return  | 
| 684 | 
            -
                      return nil if argv1.empty?
         | 
| 683 | 
            +
                      return "" if argv1.to_s.empty?
         | 
| 685 684 |  | 
| 686 685 | 
             
                      table = argv2 ? InternalCode[:temporary] : InternalCode[:permanent]
         | 
| 687 686 | 
             
                      code0 = table[argv1] || InternalCode[:permanent][argv1] || nil
         | 
| @@ -690,13 +689,11 @@ module Sisimai | |
| 690 689 |  | 
| 691 690 | 
             
                    # Convert from the status code to the reason string
         | 
| 692 691 | 
             
                    # @param    [String] argv1  Status code(DSN)
         | 
| 693 | 
            -
                    # @return   [String]        Reason name 
         | 
| 694 | 
            -
                    #           [Nil]           The first argument did not match with values in reason list
         | 
| 692 | 
            +
                    # @return   [String]        Reason name or an empty string
         | 
| 695 693 | 
             
                    # @see      code
         | 
| 696 694 | 
             
                    def name(argv1 = nil)
         | 
| 697 | 
            -
                      return  | 
| 698 | 
            -
                      return  | 
| 699 | 
            -
                      return StandardCode[argv1] || nil
         | 
| 695 | 
            +
                      return "" unless Sisimai::SMTP::Status.test(argv1.to_s)
         | 
| 696 | 
            +
                      return StandardCode[argv1] || ""
         | 
| 700 697 | 
             
                    end
         | 
| 701 698 |  | 
| 702 699 | 
             
                    # Check whether a status code is a valid code or not
         | 
| @@ -705,29 +702,23 @@ module Sisimai | |
| 705 702 | 
             
                    # @see      code
         | 
| 706 703 | 
             
                    # @since v5.0.0
         | 
| 707 704 | 
             
                    def test(argv1 = '')
         | 
| 708 | 
            -
                      return false if argv1.to_s.empty?
         | 
| 709 | 
            -
                      return false if argv1.size < 5
         | 
| 710 | 
            -
                      return false if argv1.size > 7
         | 
| 705 | 
            +
                      return false if argv1.to_s.empty? || argv1.size < 5 || argv1.size > 7
         | 
| 711 706 |  | 
| 712 707 | 
             
                      token = []
         | 
| 713 708 | 
             
                      argv1.split('.').each { |e| token << e.to_i }
         | 
| 714 709 | 
             
                      return false unless token.size == 3
         | 
| 715 | 
            -
                      return false if token[0] | 
| 716 | 
            -
                      return false if token[0]  | 
| 717 | 
            -
                      return false if token[ | 
| 718 | 
            -
                      return false if token[1]  < 0
         | 
| 719 | 
            -
                      return false if token[1]  > 7
         | 
| 720 | 
            -
                      return false if token[2]  < 0
         | 
| 710 | 
            +
                      return false if token[0] < 2 || token[0] == 3 || token[0]  > 5
         | 
| 711 | 
            +
                      return false if token[1] < 0 || token[1]  > 7
         | 
| 712 | 
            +
                      return false if token[2] < 0
         | 
| 721 713 | 
             
                      return true
         | 
| 722 714 | 
             
                    end
         | 
| 723 715 |  | 
| 724 716 | 
             
                    # Get a DSN code value from given string including DSN
         | 
| 725 717 | 
             
                    # @param    [String] argv1  String including DSN
         | 
| 726 718 | 
             
                    # @param    [String] argv2  An SMTP Reply Code or 2 or 4 or 5
         | 
| 727 | 
            -
                    # @return   [String | 
| 719 | 
            +
                    # @return   [String]        An SMTP Status Code or an empty string
         | 
| 728 720 | 
             
                    def find(argv1 = nil, argv2 = '0')
         | 
| 729 | 
            -
                      return "" if argv1.to_s.empty?
         | 
| 730 | 
            -
                      return "" if argv1.size < 7
         | 
| 721 | 
            +
                      return "" if argv1.to_s.empty? || argv1.size < 7
         | 
| 731 722 |  | 
| 732 723 | 
             
                      givenclass = argv2[0, 1]
         | 
| 733 724 | 
             
                      eestatuses = if givenclass == '2' || givenclass == '4' || givenclass == '5' 
         | 
| @@ -856,8 +847,8 @@ module Sisimai | |
| 856 847 | 
             
                      end
         | 
| 857 848 | 
             
                      return statuscode if statuscode == codeinmesg
         | 
| 858 849 |  | 
| 859 | 
            -
                      zeroindex1 = { | 
| 860 | 
            -
                      zeroindex2 = { | 
| 850 | 
            +
                      zeroindex1 = {'field' => statuscode.index('.0')   || -1, 'error' => codeinmesg.index('.0')   || -1}
         | 
| 851 | 
            +
                      zeroindex2 = {'field' => statuscode.index('.0.0') || -1, 'error' => codeinmesg.index('.0.0') || -1}
         | 
| 861 852 |  | 
| 862 853 | 
             
                      if zeroindex2['field'] > 0
         | 
| 863 854 | 
             
                        # "Status:" field is "X.0.0"
         | 
| @@ -896,8 +887,7 @@ module Sisimai | |
| 896 887 | 
             
                    # @param    string argv1  Status code
         | 
| 897 888 | 
             
                    # @return   bool          false: The delivery status code is not explicit
         | 
| 898 889 | 
             
                    def is_explicit(argv1 = '')
         | 
| 899 | 
            -
                      return false if argv1.nil?
         | 
| 900 | 
            -
                      return false if argv1.empty?
         | 
| 890 | 
            +
                      return false if argv1.nil? || argv1.empty?
         | 
| 901 891 | 
             
                      return false if argv1.size == 7 && argv1.start_with?("5.0.9", "4.0.9")
         | 
| 902 892 | 
             
                      return true
         | 
| 903 893 | 
             
                    end
         | 
| @@ -97,10 +97,8 @@ module Sisimai | |
| 97 97 | 
             
                        else
         | 
| 98 98 | 
             
                          # SMTP server sent a response "<<< response text"
         | 
| 99 99 | 
             
                          p = e.index('<<< '); next unless p == 0
         | 
| 100 | 
            +
                          e = e[4, e.size].sub(/\A<<<[ ]/, '')
         | 
| 100 101 |  | 
| 101 | 
            -
                          e = e[4, e.size]
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                          e.sub!(/\A<<<[ ]/, '')
         | 
| 104 102 | 
             
                          if cv = e.match(/\A([2-5]\d\d)[ ]/) then cx['response']['reply'] = cv[1] end
         | 
| 105 103 | 
             
                          if cv = e.match(/\A[245]\d\d[ ]([245][.]\d{1,3}[.]\d{1,3})[ ]/) then cx['response']['status'] = cv[1] end
         | 
| 106 104 | 
             
                          cx['response']['text'] << e
         | 
| @@ -110,13 +108,6 @@ module Sisimai | |
| 110 108 | 
             
                      return nil if esmtp.size == 0
         | 
| 111 109 | 
             
                      return esmtp
         | 
| 112 110 | 
             
                    end
         | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
                      
         | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 111 | 
             
                  end
         | 
| 121 112 | 
             
                end
         | 
| 122 113 | 
             
              end
         | 
    
        data/lib/sisimai/string.rb
    CHANGED
    
    | @@ -11,31 +11,26 @@ module Sisimai | |
| 11 11 | 
             
                  # @param  [String]  addr1 Sender address
         | 
| 12 12 | 
             
                  # @param  [String]  addr2 Recipient address
         | 
| 13 13 | 
             
                  # @param  [Integer] epoch Machine time of the email bounce
         | 
| 14 | 
            -
                  # @return [String]        Message token(MD5 hex digest)
         | 
| 15 | 
            -
                  # @return [String]        Blank/failed to create token
         | 
| 14 | 
            +
                  # @return [String]        Message token(MD5 hex digest) or blank(failed to create token)
         | 
| 16 15 | 
             
                  # @see    http://en.wikipedia.org/wiki/ASCII
         | 
| 17 16 | 
             
                  def token(addr1, addr2, epoch)
         | 
| 18 | 
            -
                    return  | 
| 19 | 
            -
                    return  | 
| 20 | 
            -
                    return  | 
| 21 | 
            -
                    return  | 
| 22 | 
            -
                    return nil if addr2.empty?
         | 
| 17 | 
            +
                    return "" unless addr1.is_a?(::String)
         | 
| 18 | 
            +
                    return "" unless addr2.is_a?(::String)
         | 
| 19 | 
            +
                    return "" unless epoch.is_a?(Integer)
         | 
| 20 | 
            +
                    return "" if addr1.empty? || addr2.empty?
         | 
| 23 21 |  | 
| 24 22 | 
             
                    # Format: STX(0x02) Sender-Address RS(0x1e) Recipient-Address ETX(0x03)
         | 
| 25 23 | 
             
                    require 'digest/sha1'
         | 
| 26 | 
            -
                    return Digest::SHA1.hexdigest(
         | 
| 27 | 
            -
                      sprintf("\x02%s\x1e%s\x1e%d\x03", addr1.downcase, addr2.downcase, epoch)
         | 
| 28 | 
            -
                    )
         | 
| 24 | 
            +
                    return Digest::SHA1.hexdigest(sprintf("\x02%s\x1e%s\x1e%d\x03", addr1.downcase, addr2.downcase, epoch))
         | 
| 29 25 | 
             
                  end
         | 
| 30 26 |  | 
| 31 27 | 
             
                  # The argument is 8-bit text or not
         | 
| 32 28 | 
             
                  # @param    [String] argvs  Any string to be checked
         | 
| 33 | 
            -
                  # @return   [ | 
| 34 | 
            -
                  #                           true:  Including 8-bit character
         | 
| 29 | 
            +
                  # @return   [Boolean]       false: ASCII Characters only, true: Including 8-bit character
         | 
| 35 30 | 
             
                  def is_8bit(argvs)
         | 
| 36 31 | 
             
                    v = argvs.to_s
         | 
| 37 | 
            -
                    return  | 
| 38 | 
            -
                    return true | 
| 32 | 
            +
                    return false if v.empty?
         | 
| 33 | 
            +
                    return true  unless v =~ /\A[\x00-\x7f]*\z/
         | 
| 39 34 | 
             
                    return false
         | 
| 40 35 | 
             
                  end
         | 
| 41 36 |  | 
| @@ -54,12 +49,12 @@ module Sisimai | |
| 54 49 | 
             
                  # Check if each element of the 2nd argument is aligned in the 1st argument or not
         | 
| 55 50 | 
             
                  # @param    [String] argv1  String to be checked
         | 
| 56 51 | 
             
                  # @param    [Array]  argv2  List including the ordered strings
         | 
| 57 | 
            -
                  # @return   [ | 
| 52 | 
            +
                  # @return   [Boolean]
         | 
| 58 53 | 
             
                  # @since v5.0.0
         | 
| 59 54 | 
             
                  def aligned(argv1, argv2)
         | 
| 60 | 
            -
                    return  | 
| 61 | 
            -
                    return  | 
| 62 | 
            -
                    return  | 
| 55 | 
            +
                    return false if argv1.to_s.empty?
         | 
| 56 | 
            +
                    return false unless argv2.is_a? Array
         | 
| 57 | 
            +
                    return false unless argv2.size > 1
         | 
| 63 58 |  | 
| 64 59 | 
             
                    align = -1
         | 
| 65 60 | 
             
                    right =  0
         | 
| @@ -80,7 +75,7 @@ module Sisimai | |
| 80 75 | 
             
                  # @param    [Boolean] loose Loose check flag
         | 
| 81 76 | 
             
                  # @return   [String]  Plain text
         | 
| 82 77 | 
             
                  def to_plain(argv1 = '', loose = false)
         | 
| 83 | 
            -
                    return  | 
| 78 | 
            +
                    return "" if argv1.empty?
         | 
| 84 79 |  | 
| 85 80 | 
             
                    plain = argv1
         | 
| 86 81 | 
             
                    if loose || plain =~ Match[:html] || plain =~ Match[:body]
         | 
| @@ -89,20 +84,15 @@ module Sisimai | |
| 89 84 | 
             
                      # 3. <a href = 'http://...'>...</a> to " http://... "
         | 
| 90 85 | 
             
                      # 4. <a href = 'mailto:...'>...</a> to " Value <mailto:...> "
         | 
| 91 86 | 
             
                      plain.scrub!('?')
         | 
| 92 | 
            -
                      plain.gsub | 
| 93 | 
            -
                      plain.gsub | 
| 94 | 
            -
                      plain.gsub | 
| 95 | 
            -
                      plain.gsub | 
| 96 | 
            -
             | 
| 87 | 
            +
                      plain = plain.gsub(%r|<head>.+</head>|im, '')
         | 
| 88 | 
            +
                      plain = plain.gsub(%r|<style.+?>.+</style>|im, '')
         | 
| 89 | 
            +
                      plain = plain.gsub(%r|<a\s+href\s*=\s*['"](https?://.+?)['"].*?>(.*?)</a>|i, '[\2](\1)')
         | 
| 90 | 
            +
                      plain = plain.gsub(%r|<a\s+href\s*=\s*["']mailto:([^\s]+?)["']>(.*?)</a>|i, '[\2](mailto:\1)')
         | 
| 97 91 | 
             
                      plain = plain.gsub(/<[^<@>]+?>\s*/, ' ')              # Delete HTML tags except <neko@example.jp>
         | 
| 98 92 | 
             
                      plain = plain.gsub(/</, '<').gsub(/>/, '>')     # Convert to angle brackets
         | 
| 99 93 | 
             
                      plain = plain.gsub(/&/, '&').gsub(/ /, ' ')  # Convert to "&"
         | 
| 100 94 | 
             
                      plain = plain.gsub(/"/, '"').gsub(/'/, "'") # Convert to " and '
         | 
| 101 | 
            -
             | 
| 102 | 
            -
                      if argv1.size > plain.size
         | 
| 103 | 
            -
                        plain  = plain.squeeze(' ')
         | 
| 104 | 
            -
                        plain << "\n"
         | 
| 105 | 
            -
                      end
         | 
| 95 | 
            +
                      plain = "#{plain.squeeze(' ')}\n" if argv1.size > plain.size
         | 
| 106 96 | 
             
                    end
         | 
| 107 97 |  | 
| 108 98 | 
             
                    return plain
         | 
| @@ -113,7 +103,7 @@ module Sisimai | |
| 113 103 | 
             
                  # @param    [String] argv2  Encoding name before converting
         | 
| 114 104 | 
             
                  # @return   [String]        UTF-8 Encoded string
         | 
| 115 105 | 
             
                  def to_utf8(argv1 = '', argv2 = nil)
         | 
| 116 | 
            -
                    return  | 
| 106 | 
            +
                    return "" if argv1.empty?
         | 
| 117 107 |  | 
| 118 108 | 
             
                    encodefrom = argv2 || false
         | 
| 119 109 | 
             
                    getencoded = ''
         | 
    
        data/lib/sisimai/version.rb
    CHANGED
    
    
    
        data/lib/sisimai.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 | 
            -
            # Sisimai is a library that decodes complex and diverse bounce emails and | 
| 2 | 
            -
            # the delivery failure, such as the reason for the bounce and the recipient | 
| 3 | 
            -
            # structured data. It is also possible to output in JSON format. 
         | 
| 1 | 
            +
            # Sisimai (pronounced /ɕi.ɕi.ma.i/) is a library that decodes complex and diverse bounce emails and
         | 
| 2 | 
            +
            # outputs the results of the delivery failure, such as the reason for the bounce and the recipient
         | 
| 3 | 
            +
            # email address, in structured data. It is also possible to output in JSON format. 
         | 
| 4 4 | 
             
            require 'sisimai/version'
         | 
| 5 5 | 
             
            module Sisimai
         | 
| 6 6 | 
             
              class << self
         | 
| @@ -30,17 +30,17 @@ module Sisimai | |
| 30 30 | 
             
                  while r = mail.data.read do
         | 
| 31 31 | 
             
                    # Read and decode each email file
         | 
| 32 32 | 
             
                    path = mail.data.path
         | 
| 33 | 
            -
                    args = { | 
| 33 | 
            +
                    args = {data: r, hook: c___[0], origin: path, delivered: argv1[:delivered], vacation: argv1[:vacation]}
         | 
| 34 34 | 
             
                    fact = Sisimai::Fact.rise(**args) || []
         | 
| 35 35 |  | 
| 36 36 | 
             
                    if c___[1]
         | 
| 37 37 | 
             
                      # Run the callback function specified with "c___" parameter of Sisimai.rise after reading
         | 
| 38 38 | 
             
                      # each email file in Maildir/ every time
         | 
| 39 | 
            -
                      args = { | 
| 39 | 
            +
                      args = {'kind' => kind, 'mail' => r, 'path' => path, 'fact' => fact}
         | 
| 40 40 | 
             
                      begin
         | 
| 41 41 | 
             
                        c___[1].call(args) if c___[1].is_a?(Proc)
         | 
| 42 42 | 
             
                      rescue StandardError => ce
         | 
| 43 | 
            -
                        warn ' ***warning: Something is wrong in the second element of the ":c___":'  | 
| 43 | 
            +
                        warn ' ***warning: Something is wrong in the second element of the ":c___":' + ce.to_s
         | 
| 44 44 | 
             
                      end
         | 
| 45 45 | 
             
                    end
         | 
| 46 46 |  | 
| @@ -61,7 +61,7 @@ module Sisimai | |
| 61 61 | 
             
                # @options argv1 [Lambda]  hook      Lambda object to be called back
         | 
| 62 62 | 
             
                # @return        [String]            Decoded data as JSON text
         | 
| 63 63 | 
             
                def dump(argv0, **argv1)
         | 
| 64 | 
            -
                  return  | 
| 64 | 
            +
                  return "" unless argv0
         | 
| 65 65 | 
             
                  nyaan = Sisimai.rise(argv0, **argv1) || []
         | 
| 66 66 |  | 
| 67 67 | 
             
                  if RUBY_PLATFORM.start_with?('java')
         | 
| @@ -81,14 +81,14 @@ module Sisimai | |
| 81 81 | 
             
                  table = {}
         | 
| 82 82 |  | 
| 83 83 | 
             
                  %w[Lhost ARF RFC3464 RFC3834].each do |e|
         | 
| 84 | 
            -
                    r =  | 
| 84 | 
            +
                    r = "Sisimai::#{e}"
         | 
| 85 85 | 
             
                    require r.gsub('::', '/').downcase
         | 
| 86 86 |  | 
| 87 87 | 
             
                    if e == 'Lhost'
         | 
| 88 88 | 
             
                      # Sisimai::Lhost::*
         | 
| 89 89 | 
             
                      Module.const_get(r).send(:index).each do |ee|
         | 
| 90 90 | 
             
                        # Load and get the value of "description" from each module
         | 
| 91 | 
            -
                        rr =  | 
| 91 | 
            +
                        rr = "Sisimai::#{e}::#{ee}"
         | 
| 92 92 | 
             
                        require rr.gsub('::', '/').downcase
         | 
| 93 93 | 
             
                        table[rr.to_sym] = Module.const_get(rr).send(:description)
         | 
| 94 94 | 
             
                      end
         | 
| @@ -112,7 +112,7 @@ module Sisimai | |
| 112 112 | 
             
                  names += %w[Delivered Feedback Undefined Vacation]
         | 
| 113 113 | 
             
                  while e = names.shift do
         | 
| 114 114 | 
             
                    # Call .description() method of Sisimai::Reason::*
         | 
| 115 | 
            -
                    r =  | 
| 115 | 
            +
                    r = "Sisimai::Reason::#{e}"
         | 
| 116 116 | 
             
                    require r.gsub('::', '/').downcase
         | 
| 117 117 | 
             
                    table[e.to_sym] = Module.const_get(r).send(:description)
         | 
| 118 118 | 
             
                  end
         | 
| @@ -124,7 +124,7 @@ module Sisimai | |
| 124 124 | 
             
                # @param    [String]    Error message text
         | 
| 125 125 | 
             
                # @return   [String]    Reason text
         | 
| 126 126 | 
             
                def match(argvs = '')
         | 
| 127 | 
            -
                  return  | 
| 127 | 
            +
                  return "" if argvs.empty?
         | 
| 128 128 | 
             
                  require 'sisimai/reason'
         | 
| 129 129 | 
             
                  return Sisimai::Reason.match(argvs.downcase)
         | 
| 130 130 | 
             
                end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            Return-Path: <>
         | 
| 2 | 
            +
            Delivered-To: neko@e.nyaaaan.example.onmicrosoft.com
         | 
| 3 | 
            +
            Received: from relay.nyaaaan.example.onmicrosoft.com (unknown [192.0.2.25])
         | 
| 4 | 
            +
            	by ee.nyaaaan.example.onmicrosoft.com (Postfix) with ESMTPS id JFzCqYfyTkzvHbZW
         | 
| 5 | 
            +
            	for <neko@e.nyaaaan.example.onmicrosoft.com>; Sun, 25 May 2025 22:22:22 +0900 (JST)
         | 
| 6 | 
            +
            Received: from cat.example.co.jp (ip-192-0-2-225.us-west-1.compute.internal [192.0.2.225])
         | 
| 7 | 
            +
            	by relay.nyaaaan.example.onmicrosoft.com (Postfix) with ESMTPS id D09y2f7PVFzmfJf9
         | 
| 8 | 
            +
            	for <kijitora@nyaaaan.example.onmicrosoft.com>; Sun, 25 May 2025 22:22:22 +0900 (JST)
         | 
| 9 | 
            +
            Message-ID: <20250525222222.00002.nekochan@cat.example.co.jp>
         | 
| 10 | 
            +
            Date: 25 May 2025 22:22:22 +0900
         | 
| 11 | 
            +
            From: MAILER-DAEMON@cat.example.co.jp
         | 
| 12 | 
            +
            To: kijitora@nyaaaan.example.onmicrosoft.com
         | 
| 13 | 
            +
            Subject: failure notice
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            Hi. This is the qmail-send program at cat.example.co.jp.
         | 
| 16 | 
            +
            I'm afraid I wasn't able to deliver your message to the following addresses.
         | 
| 17 | 
            +
            This is a permanent error; I've given up. Sorry it didn't work out.
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            <sabineko@example.onmicrosoft.com>:
         | 
| 20 | 
            +
            198.51.100.25 failed after I sent the message.
         | 
| 21 | 
            +
            Remote host said: 550 5.7.515 Access denied, sending domain NYAAAAN.EXAMPLE.JP doesn't meet the required authentication level. The sender's domain in the 5322.From address doesn't meet the authentication requirements defined for the sender. To learn how to fix this see: https://go.microsoft.com/fwlink/p/?linkid=2319303 Spf= Fail , Dkim= Pass , DMARC= Pass [0000000000000.JPNP255.PROD.OUTLOOK.COM 2025-05-25T22:22:22.000Z 0000000000000EEE] [0000000000000.jpnprd00.prod.outlook.com 2025-05-25T22:22:22.000Z 0000000000000EEE] [0000000000000EE.apcprd00.prod.outlook.com 2025-05-25T22:22:22.000Z 0000000000000EEE]
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            --- Below this line is a copy of the message.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            Return-Path: <kijitora@nyaaaan.example.onmicrosoft.com>
         | 
| 26 | 
            +
            Received: (qmail 32768 invoked by uid 99); 25 May 2025 22:22:22 +0900
         | 
| 27 | 
            +
            Delivered-To: mikeneko@example.org
         | 
| 28 | 
            +
            Received: (qmail 32767 invoked by uid 99); 25 May 2025 22:22:22 +0900
         | 
| 29 | 
            +
            Received: from relay-2.nyaaaan.example.onmicrosoft.com (203.0.113.25)
         | 
| 30 | 
            +
              by cat.example.co.jp with ESMTPS (AES256-GCM-SHA384 encrypted); 25 May 2025 22:22:22 +0900
         | 
| 31 | 
            +
            Received: from relay-1.nyaaaan.example.onmicrosoft.com (unknown [192.0.2.254])
         | 
| 32 | 
            +
            	by relay-2.nyaaaan.example.onmicrosoft.com (Postfix) with ESMTP id djK8m53Kqpzf8pK9
         | 
| 33 | 
            +
            	for <mikeneko@example.org>; Sun, 25 May 2025 22:22:22 +0900 (JST)
         | 
| 34 | 
            +
            DKIM-Filter: OpenDKIM Filter v2.11.0 relay-2.nyaaaan.example.onmicrosoft.com djK8m53Kqpzf8pK9
         | 
| 35 | 
            +
            DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nyaaaan.example.onmicrosoft.com;
         | 
| 36 | 
            +
            Content-Type: text/plain; charset=us-ascii
         | 
| 37 | 
            +
            MIME-Version: 1.0
         | 
| 38 | 
            +
            From: <kijitora@nyaaaan.example.onmicrosoft.com>
         | 
| 39 | 
            +
            Date: Sun, 25 May 2025 22:22:22 +0900
         | 
| 40 | 
            +
            Subject: Nyaaaan?
         | 
| 41 | 
            +
            Message-Id: <5E82FFFE9D95.88616A92ACCB@relay-1.nyaaaan.example.onmicrosoft.com>
         | 
| 42 | 
            +
            To: <mikeneko@example.org>
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            Nyaaaan?
         | 
| 45 | 
            +
             | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: sisimai
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 5. | 
| 4 | 
            +
              version: 5.4.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - azumakuniyuki
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2025- | 
| 11 | 
            +
            date: 2025-07-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -813,6 +813,7 @@ files: | |
| 813 813 | 
             
            - set-of-emails/maildir/bsd/rhost-microsoft-03.eml
         | 
| 814 814 | 
             
            - set-of-emails/maildir/bsd/rhost-microsoft-04.eml
         | 
| 815 815 | 
             
            - set-of-emails/maildir/bsd/rhost-microsoft-05.eml
         | 
| 816 | 
            +
            - set-of-emails/maildir/bsd/rhost-microsoft-06.eml
         | 
| 816 817 | 
             
            - set-of-emails/maildir/bsd/rhost-mimecast-01.eml
         | 
| 817 818 | 
             
            - set-of-emails/maildir/bsd/rhost-mimecast-02.eml
         | 
| 818 819 | 
             
            - set-of-emails/maildir/bsd/rhost-nttdocomo-01.eml
         |