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
| @@ -23,18 +23,17 @@ module Sisimai | |
| 23 23 |  | 
| 24 24 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 25 25 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 26 | 
            -
                    # @return   [ | 
| 27 | 
            -
                    #                           true: Matched
         | 
| 26 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 28 27 | 
             
                    def match(argv1)
         | 
| 29 | 
            -
                      return  | 
| 30 | 
            -
                      return true | 
| 31 | 
            -
                      return true | 
| 28 | 
            +
                      return false unless argv1
         | 
| 29 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 30 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 32 31 | 
             
                      return false
         | 
| 33 32 | 
             
                    end
         | 
| 34 33 |  | 
| 35 34 | 
             
                    # Whether the email is RFC compliant or not
         | 
| 36 35 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 37 | 
            -
                    # @return   [ | 
| 36 | 
            +
                    # @return   [Boolean]               true:   RFC comliant
         | 
| 38 37 | 
             
                    #                                   false: Is not RFC compliant
         | 
| 39 38 | 
             
                    # @see http://www.ietf.org/rfc/rfc5322.txt
         | 
| 40 39 | 
             
                    def true(argvs)
         | 
| @@ -10,21 +10,18 @@ module Sisimai | |
| 10 10 |  | 
| 11 11 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 12 12 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 13 | 
            -
                    # @return   [ | 
| 14 | 
            -
                     | 
| 15 | 
            -
                    def match(_argv1)
         | 
| 16 | 
            -
                      return false
         | 
| 17 | 
            -
                    end
         | 
| 13 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 14 | 
            +
                    def match(_argv1); return false; end
         | 
| 18 15 |  | 
| 19 16 | 
             
                    # On hold, Could not decide the bounce reason...
         | 
| 20 17 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 21 | 
            -
                    # @return   [ | 
| 18 | 
            +
                    # @return   [Boolean]               true:  Status code is "onhold"
         | 
| 22 19 | 
             
                    #                                   false: is not "onhold"
         | 
| 23 20 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 24 21 | 
             
                    def true(argvs)
         | 
| 25 | 
            -
                      return  | 
| 26 | 
            -
                      return true | 
| 27 | 
            -
                      return true | 
| 22 | 
            +
                      return false if argvs['deliverystatus'].empty?
         | 
| 23 | 
            +
                      return true  if argvs['reason'] == 'onhold'
         | 
| 24 | 
            +
                      return true  if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'onhold'
         | 
| 28 25 | 
             
                      return false
         | 
| 29 26 | 
             
                    end
         | 
| 30 27 | 
             
                  end
         | 
| @@ -50,25 +50,22 @@ module Sisimai | |
| 50 50 |  | 
| 51 51 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 52 52 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 53 | 
            -
                    # @return   [ | 
| 54 | 
            -
                    #                           true: Matched
         | 
| 53 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 55 54 | 
             
                    # @since 4.22.0
         | 
| 56 55 | 
             
                    def match(argv1)
         | 
| 57 | 
            -
                      return  | 
| 58 | 
            -
                      return true | 
| 59 | 
            -
                      return true | 
| 56 | 
            +
                      return false unless argv1
         | 
| 57 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 58 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 60 59 | 
             
                      return false
         | 
| 61 60 | 
             
                    end
         | 
| 62 61 |  | 
| 63 62 | 
             
                    # The bounce reason is "policyviolation" or not
         | 
| 64 63 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 65 | 
            -
                    # @return   [ | 
| 64 | 
            +
                    # @return   [Boolean]               true:  is policy violation
         | 
| 66 65 | 
             
                    #                                   false: is not policy violation
         | 
| 67 66 | 
             
                    # @since 4.22.0
         | 
| 68 67 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 69 | 
            -
                    def true(_argvs)
         | 
| 70 | 
            -
                      return nil
         | 
| 71 | 
            -
                    end
         | 
| 68 | 
            +
                    def true(_argvs); return false; end
         | 
| 72 69 |  | 
| 73 70 | 
             
                  end
         | 
| 74 71 | 
             
                end
         | 
| @@ -81,10 +81,9 @@ module Sisimai | |
| 81 81 |  | 
| 82 82 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 83 83 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 84 | 
            -
                    # @return   [ | 
| 85 | 
            -
                    #                           true: Matched
         | 
| 84 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 86 85 | 
             
                    def match(argv1)
         | 
| 87 | 
            -
                      return  | 
| 86 | 
            +
                      return false unless argv1
         | 
| 88 87 | 
             
                      return false if IsNot.any? { |a| argv1.include?(a) }
         | 
| 89 88 | 
             
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 90 89 | 
             
                      return false
         | 
| @@ -92,12 +91,12 @@ module Sisimai | |
| 92 91 |  | 
| 93 92 | 
             
                    # Rejected by the envelope sender address or not
         | 
| 94 93 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 95 | 
            -
                    # @return   [ | 
| 94 | 
            +
                    # @return   [Boolean]               true:  is rejected
         | 
| 96 95 | 
             
                    #                                   false: is not rejected by the sender
         | 
| 97 96 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 98 97 | 
             
                    def true(argvs)
         | 
| 99 98 | 
             
                      return true if argvs['reason'] == 'rejected'
         | 
| 100 | 
            -
                      tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 99 | 
            +
                      tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus'])
         | 
| 101 100 | 
             
                      return true if tempreason == 'rejected' # Delivery status code points "rejected".
         | 
| 102 101 |  | 
| 103 102 | 
             
                      # Check the value of Diagnosic-Code: header with patterns
         | 
| @@ -113,7 +112,7 @@ module Sisimai | |
| 113 112 | 
             
                          # Except "userunknown"
         | 
| 114 113 | 
             
                          return true if match(issuedcode)
         | 
| 115 114 | 
             
                        end
         | 
| 116 | 
            -
                      elsif %w[onhold undefined securityerror systemerror].include?(tempreason)
         | 
| 115 | 
            +
                      elsif %w[onhold undefined securityerror systemerror].include?(tempreason) || tempreason == ""
         | 
| 117 116 | 
             
                        # Try to match with message patterns when the temporary reason is "onhold", "undefined",
         | 
| 118 117 | 
             
                        # "securityerror", or "systemerror"
         | 
| 119 118 | 
             
                        return true if match(issuedcode)
         | 
| @@ -42,23 +42,22 @@ module Sisimai | |
| 42 42 |  | 
| 43 43 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 44 44 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 45 | 
            -
                    # @return   [ | 
| 46 | 
            -
                    #                           true: Matched
         | 
| 45 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 47 46 | 
             
                    def match(argv1)
         | 
| 48 | 
            -
                      return  | 
| 49 | 
            -
                      return true | 
| 50 | 
            -
                      return true | 
| 47 | 
            +
                      return false unless argv1
         | 
| 48 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 49 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 51 50 | 
             
                      return false
         | 
| 52 51 | 
             
                    end
         | 
| 53 52 |  | 
| 54 53 | 
             
                    # Check the email rejected due to missing PTR record or having invalid PTR record OR not
         | 
| 55 54 | 
             
                    # @param    [Hash] argvs  Hash to be detected the value of reason
         | 
| 56 | 
            -
                    # @return   [ | 
| 55 | 
            +
                    # @return   [Boolean]     true:  is missing PTR or invalid PTR
         | 
| 57 56 | 
             
                    #                         false: is not blocked due to missing PTR record
         | 
| 58 57 | 
             
                    # @see      http://www.ietf.org/rfc/rfc5322.txt
         | 
| 59 58 | 
             
                    def true(argvs)
         | 
| 60 59 | 
             
                      return true if argvs['reason'] == 'requireptr'
         | 
| 61 | 
            -
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 60 | 
            +
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'requireptr'
         | 
| 62 61 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 63 62 | 
             
                    end
         | 
| 64 63 |  | 
| @@ -46,23 +46,20 @@ module Sisimai | |
| 46 46 |  | 
| 47 47 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 48 48 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 49 | 
            -
                    # @return   [ | 
| 50 | 
            -
                    #                           true: Matched
         | 
| 49 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 51 50 | 
             
                    def match(argv1)
         | 
| 52 | 
            -
                      return  | 
| 53 | 
            -
                      return true | 
| 54 | 
            -
                      return true | 
| 51 | 
            +
                      return false unless argv1
         | 
| 52 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 53 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 55 54 | 
             
                      return false
         | 
| 56 55 | 
             
                    end
         | 
| 57 56 |  | 
| 58 57 | 
             
                    # The bounce reason is SecurityError or not
         | 
| 59 58 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 60 | 
            -
                    # @return   [ | 
| 59 | 
            +
                    # @return   [Boolean]               true:  is security error
         | 
| 61 60 | 
             
                    #                                   false: is not security error
         | 
| 62 61 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 63 | 
            -
                    def true(_argvs)
         | 
| 64 | 
            -
                      return nil
         | 
| 65 | 
            -
                    end
         | 
| 62 | 
            +
                    def true(_argvs); return false; end
         | 
| 66 63 |  | 
| 67 64 | 
             
                  end
         | 
| 68 65 | 
             
                end
         | 
| @@ -120,24 +120,23 @@ module Sisimai | |
| 120 120 |  | 
| 121 121 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 122 122 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 123 | 
            -
                    # @return   [ | 
| 124 | 
            -
                    #                           true: Matched
         | 
| 123 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 125 124 | 
             
                    def match(argv1)
         | 
| 126 | 
            -
                      return  | 
| 127 | 
            -
                      return true | 
| 128 | 
            -
                      return true | 
| 125 | 
            +
                      return false unless argv1
         | 
| 126 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 127 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 129 128 | 
             
                      return false
         | 
| 130 129 | 
             
                    end
         | 
| 131 130 |  | 
| 132 131 | 
             
                    # Rejected due to spam content in the message
         | 
| 133 132 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 134 | 
            -
                    # @return   [ | 
| 133 | 
            +
                    # @return   [Boolean]               true: rejected due to spam
         | 
| 135 134 | 
             
                    #                                   false: is not rejected due to spam
         | 
| 136 135 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 137 136 | 
             
                    def true(argvs)
         | 
| 138 | 
            -
                      return  | 
| 139 | 
            -
                      return true | 
| 140 | 
            -
                      return true | 
| 137 | 
            +
                      return false if argvs['deliverystatus'].empty?
         | 
| 138 | 
            +
                      return true  if argvs['reason'] == 'spamdetected'
         | 
| 139 | 
            +
                      return true  if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'spamdetected'
         | 
| 141 140 |  | 
| 142 141 | 
             
                      # The value of "reason" isn't "spamdetected" when the value of "command" is an SMTP command
         | 
| 143 142 | 
             
                      # to be sent before the SMTP DATA command because all the MTAs read the headers and the
         | 
| @@ -16,22 +16,21 @@ module Sisimai | |
| 16 16 |  | 
| 17 17 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 18 18 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 19 | 
            -
                    # @return   [ | 
| 20 | 
            -
                    #                           true: Matched
         | 
| 19 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 21 20 | 
             
                    def match(argv1)
         | 
| 22 | 
            -
                      return  | 
| 23 | 
            -
                      return true | 
| 21 | 
            +
                      return false unless argv1
         | 
| 22 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 24 23 | 
             
                      return false
         | 
| 25 24 | 
             
                    end
         | 
| 26 25 |  | 
| 27 26 | 
             
                    # Speeding or not
         | 
| 28 27 | 
             
                    # @param    [Sisimai::Fact] argvs Object to be detected the reason
         | 
| 29 | 
            -
                    # @return   [ | 
| 28 | 
            +
                    # @return   [Boolean]             true:  is speeding
         | 
| 30 29 | 
             
                    #                                 false: is not speeding
         | 
| 31 30 | 
             
                    # @see      http://www.ietf.org/rfc/rfc2822.txt
         | 
| 32 31 | 
             
                    def true(argvs)
         | 
| 33 | 
            -
                      return  | 
| 34 | 
            -
                      return true | 
| 32 | 
            +
                      return false if argvs['deliverystatus'].empty?
         | 
| 33 | 
            +
                      return true  if argvs['reason'] == 'speeding'
         | 
| 35 34 |  | 
| 36 35 | 
             
                      # Action: failed
         | 
| 37 36 | 
             
                      # Status: 4.7.1
         | 
| @@ -12,16 +12,12 @@ module Sisimai | |
| 12 12 |  | 
| 13 13 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 14 14 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 15 | 
            -
                    # @return   [ | 
| 16 | 
            -
                     | 
| 17 | 
            -
                    def match(argv1)
         | 
| 18 | 
            -
                      return nil unless argv1
         | 
| 19 | 
            -
                      return false
         | 
| 20 | 
            -
                    end
         | 
| 15 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 16 | 
            +
                    def match(argv1); return false; end
         | 
| 21 17 |  | 
| 22 18 | 
             
                    # Whether the address is listed in the suppression list
         | 
| 23 19 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 24 | 
            -
                    # @return   [ | 
| 20 | 
            +
                    # @return   [Boolean]               true:  The address is listed in the suppression list
         | 
| 25 21 | 
             
                    #                                   false: is not listed in the suppression list
         | 
| 26 22 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 27 23 | 
             
                    def true(argvs)
         | 
| @@ -36,22 +36,20 @@ module Sisimai | |
| 36 36 |  | 
| 37 37 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 38 38 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 39 | 
            -
                    # @return   [ | 
| 40 | 
            -
                    #                           true: Matched
         | 
| 39 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 41 40 | 
             
                    def match(argv1)
         | 
| 42 | 
            -
                      return  | 
| 43 | 
            -
                      return true | 
| 41 | 
            +
                      return false unless argv1
         | 
| 42 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 44 43 | 
             
                      return false
         | 
| 45 44 | 
             
                    end
         | 
| 46 45 |  | 
| 47 46 | 
             
                    # The envelope recipient's mailbox is suspended or not
         | 
| 48 47 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 49 | 
            -
                    # @return   [ | 
| 48 | 
            +
                    # @return   [Boolean]               true:  is mailbox suspended
         | 
| 50 49 | 
             
                    #                                   false: is not suspended
         | 
| 51 50 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 52 51 | 
             
                    def true(argvs)
         | 
| 53 | 
            -
                      return true if argvs['reason'] == 'suspend'
         | 
| 54 | 
            -
                      return true if argvs['replycode'].to_i == 525
         | 
| 52 | 
            +
                      return true if argvs['reason'] == 'suspend' || argvs['replycode'].to_i == 525
         | 
| 55 53 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 56 54 | 
             
                    end
         | 
| 57 55 |  | 
| @@ -14,12 +14,11 @@ module Sisimai | |
| 14 14 | 
             
                  class << self
         | 
| 15 15 | 
             
                    def text; return 'syntaxerror'; end
         | 
| 16 16 | 
             
                    def description; return 'Email rejected due to syntax error at sent commands in SMTP session'; end
         | 
| 17 | 
            -
                    def match(*); return  | 
| 17 | 
            +
                    def match(*); return false; end
         | 
| 18 18 |  | 
| 19 19 | 
             
                    # Connection rejected due to syntax error or not
         | 
| 20 20 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 21 | 
            -
                    # @return   [ | 
| 22 | 
            -
                    #                                         syntax error
         | 
| 21 | 
            +
                    # @return   [Boolean]               true:  Connection rejected due to syntax error
         | 
| 23 22 | 
             
                    #                                   false: is not syntax error
         | 
| 24 23 | 
             
                    # @since 4.1.25
         | 
| 25 24 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| @@ -27,8 +26,7 @@ module Sisimai | |
| 27 26 | 
             
                      return true if argvs['reason'] == 'syntaxerror'
         | 
| 28 27 |  | 
| 29 28 | 
             
                      reply = argvs['replycode'].to_i
         | 
| 30 | 
            -
                      return true if reply > 400 && reply < 408
         | 
| 31 | 
            -
                      return true if reply > 500 && reply < 508
         | 
| 29 | 
            +
                      return true if reply > 400 && reply < 408 || reply > 500 && reply < 508
         | 
| 32 30 | 
             
                      return false
         | 
| 33 31 | 
             
                    end
         | 
| 34 32 |  | 
| @@ -43,23 +43,20 @@ module Sisimai | |
| 43 43 |  | 
| 44 44 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 45 45 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 46 | 
            -
                    # @return   [ | 
| 47 | 
            -
                    #                           true: Matched
         | 
| 46 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 48 47 | 
             
                    def match(argv1)
         | 
| 49 | 
            -
                      return  | 
| 50 | 
            -
                      return true | 
| 51 | 
            -
                      return true | 
| 48 | 
            +
                      return false unless argv1
         | 
| 49 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 50 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 52 51 | 
             
                      return false
         | 
| 53 52 | 
             
                    end
         | 
| 54 53 |  | 
| 55 54 | 
             
                    # The bounce reason is system error or not
         | 
| 56 55 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 57 | 
            -
                    # @return   [ | 
| 56 | 
            +
                    # @return   [Boolean]               true:  is system error
         | 
| 58 57 | 
             
                    #                                   false: is not system error
         | 
| 59 58 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 60 | 
            -
                    def true(_argvs)
         | 
| 61 | 
            -
                      return nil
         | 
| 62 | 
            -
                    end
         | 
| 59 | 
            +
                    def true(_argvs); return false; end
         | 
| 63 60 |  | 
| 64 61 | 
             
                  end
         | 
| 65 62 | 
             
                end
         | 
| @@ -18,22 +18,19 @@ module Sisimai | |
| 18 18 |  | 
| 19 19 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 20 20 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 21 | 
            -
                    # @return   [ | 
| 22 | 
            -
                    #                           true: Matched
         | 
| 21 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 23 22 | 
             
                    def match(argv1)
         | 
| 24 | 
            -
                      return  | 
| 25 | 
            -
                      return true | 
| 23 | 
            +
                      return false unless argv1
         | 
| 24 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 26 25 | 
             
                      return false
         | 
| 27 26 | 
             
                    end
         | 
| 28 27 |  | 
| 29 28 | 
             
                    # The bounce reason is system full or not
         | 
| 30 29 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 31 | 
            -
                    # @return   [ | 
| 30 | 
            +
                    # @return   [Boolean]               true:  is system full
         | 
| 32 31 | 
             
                    #                                   false: is not system full
         | 
| 33 32 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 34 | 
            -
                    def true(_argvs)
         | 
| 35 | 
            -
                      return nil
         | 
| 36 | 
            -
                    end
         | 
| 33 | 
            +
                    def true(_argvs); return false; end
         | 
| 37 34 |  | 
| 38 35 | 
             
                  end
         | 
| 39 36 | 
             
                end
         | 
| @@ -32,22 +32,21 @@ 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 | 
             
                    def match(argv1)
         | 
| 38 | 
            -
                      return  | 
| 39 | 
            -
                      return true | 
| 37 | 
            +
                      return false unless argv1
         | 
| 38 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 40 39 | 
             
                      return false
         | 
| 41 40 | 
             
                    end
         | 
| 42 41 |  | 
| 43 42 | 
             
                    # Rejected by domain or address filter ?
         | 
| 44 43 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 45 | 
            -
                    # @return   [ | 
| 44 | 
            +
                    # @return   [Boolean]               true:  is filtered
         | 
| 46 45 | 
             
                    #                                   false: is not filtered
         | 
| 47 46 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 48 47 | 
             
                    def true(argvs)
         | 
| 49 48 | 
             
                      return true if argvs['reason'] == 'toomanyconn'
         | 
| 50 | 
            -
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 49 | 
            +
                      return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'toomanyconn'
         | 
| 51 50 | 
             
                      return match(argvs['diagnosticcode'].downcase)
         | 
| 52 51 | 
             
                    end
         | 
| 53 52 |  | 
| @@ -6,8 +6,8 @@ module Sisimai | |
| 6 6 | 
             
                  class << self
         | 
| 7 7 | 
             
                    def text; return 'undefined'; end
         | 
| 8 8 | 
             
                    def description; return 'Sisimai could not detect an error reason'; 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
         | 
| @@ -145,24 +145,23 @@ module Sisimai | |
| 145 145 |  | 
| 146 146 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 147 147 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 148 | 
            -
                    # @return   [ | 
| 149 | 
            -
                    #                           true: Matched
         | 
| 148 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 150 149 | 
             
                    def match(argv1)
         | 
| 151 | 
            -
                      return  | 
| 152 | 
            -
                      return true | 
| 153 | 
            -
                      return true | 
| 150 | 
            +
                      return false unless argv1
         | 
| 151 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 152 | 
            +
                      return true  if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
         | 
| 154 153 | 
             
                      return false
         | 
| 155 154 | 
             
                    end
         | 
| 156 155 |  | 
| 157 156 | 
             
                    # Whether the address is "userunknown" or not
         | 
| 158 157 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 159 | 
            -
                    # @return   [ | 
| 158 | 
            +
                    # @return   [Boolean]               true:  is unknown user
         | 
| 160 159 | 
             
                    #                                   false: is not unknown user.
         | 
| 161 160 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
| 162 161 | 
             
                    def true(argvs)
         | 
| 163 162 | 
             
                      return true if argvs['reason'] == 'userunknown'
         | 
| 164 163 |  | 
| 165 | 
            -
                      tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus']) | 
| 164 | 
            +
                      tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus'])
         | 
| 166 165 | 
             
                      return false if tempreason == 'suspend'
         | 
| 167 166 |  | 
| 168 167 | 
             
                      issuedcode = argvs['diagnosticcode'].downcase
         | 
| @@ -174,13 +173,13 @@ module Sisimai | |
| 174 173 | 
             
                        matchother = false
         | 
| 175 174 | 
             
                        PreMatches.each do |e|
         | 
| 176 175 | 
             
                          # Check the value of "Diagnostic-Code" with other error patterns.
         | 
| 177 | 
            -
                          p =  | 
| 176 | 
            +
                          p = "Sisimai::Reason::#{e}"
         | 
| 178 177 | 
             
                          r = nil
         | 
| 179 178 | 
             
                          begin
         | 
| 180 179 | 
             
                            require ModulePath[p]
         | 
| 181 180 | 
             
                            r = Module.const_get(p)
         | 
| 182 181 | 
             
                          rescue
         | 
| 183 | 
            -
                            warn  | 
| 182 | 
            +
                            warn "***warning: Failed to load #{p}"
         | 
| 184 183 | 
             
                            next
         | 
| 185 184 | 
             
                          end
         | 
| 186 185 |  | 
| @@ -16,15 +16,14 @@ module Sisimai | |
| 16 16 |  | 
| 17 17 | 
             
                    # Try to match that the given text and regular expressions
         | 
| 18 18 | 
             
                    # @param    [String] argv1  String to be matched with regular expressions
         | 
| 19 | 
            -
                    # @return   [ | 
| 20 | 
            -
                    #                           true: Matched
         | 
| 19 | 
            +
                    # @return   [Boolean]       false: Did not match, true: Matched
         | 
| 21 20 | 
             
                    def match(argv1)
         | 
| 22 | 
            -
                      return  | 
| 23 | 
            -
                      return true | 
| 21 | 
            +
                      return false unless argv1
         | 
| 22 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 24 23 | 
             
                      return false
         | 
| 25 24 | 
             
                    end
         | 
| 26 25 |  | 
| 27 | 
            -
                    def true(*); return  | 
| 26 | 
            +
                    def true(*); return false; end
         | 
| 28 27 | 
             
                  end
         | 
| 29 28 | 
             
                end
         | 
| 30 29 | 
             
              end
         | 
| @@ -28,18 +28,17 @@ 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 | 
             
                    # @since 4.22.0
         | 
| 34 33 | 
             
                    def match(argv1)
         | 
| 35 | 
            -
                      return  | 
| 36 | 
            -
                      return true | 
| 34 | 
            +
                      return false unless argv1
         | 
| 35 | 
            +
                      return true  if Index.any? { |a| argv1.include?(a) }
         | 
| 37 36 | 
             
                      return false
         | 
| 38 37 | 
             
                    end
         | 
| 39 38 |  | 
| 40 39 | 
             
                    # The bounce reason is "virusdetected" or not
         | 
| 41 40 | 
             
                    # @param    [Sisimai::Fact] argvs   Object to be detected the reason
         | 
| 42 | 
            -
                    # @return   [ | 
| 41 | 
            +
                    # @return   [Boolean]               true:  virus detected
         | 
| 43 42 | 
             
                    #                                   false: virus was not detected
         | 
| 44 43 | 
             
                    # @since 4.22.0
         | 
| 45 44 | 
             
                    # @see http://www.ietf.org/rfc/rfc2822.txt
         | 
    
        data/lib/sisimai/reason.rb
    CHANGED
    
    | @@ -30,7 +30,7 @@ module Sisimai | |
| 30 30 | 
             
                  def path
         | 
| 31 31 | 
             
                    index = Sisimai::Reason.index
         | 
| 32 32 | 
             
                    table = {}
         | 
| 33 | 
            -
                    index.each { |e| table[ | 
| 33 | 
            +
                    index.each { |e| table["Sisimai::Reason::#{e}"] = "sisimai/reason/#{e.downcase}" }
         | 
| 34 34 | 
             
                    return table
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 |  | 
| @@ -65,10 +65,10 @@ module Sisimai | |
| 65 65 |  | 
| 66 66 | 
             
                  # Detect the bounce reason
         | 
| 67 67 | 
             
                  # @param    [Hash] argvs  Decoded email object
         | 
| 68 | 
            -
                  # @return   [String | 
| 68 | 
            +
                  # @return   [String] Bounce reason or an empty string if the argument is missing or not Hash
         | 
| 69 69 | 
             
                  # @see anotherone
         | 
| 70 70 | 
             
                  def find(argvs)
         | 
| 71 | 
            -
                    return  | 
| 71 | 
            +
                    return "" unless argvs
         | 
| 72 72 | 
             
                    unless GetRetried[argvs['reason']]
         | 
| 73 73 | 
             
                      # Return reason text already decided except reason match with the regular expression of
         | 
| 74 74 | 
             
                      # retry() method.
         | 
| @@ -85,13 +85,13 @@ module Sisimai | |
| 85 85 | 
             
                      ClassOrder[0].each do |e|
         | 
| 86 86 | 
             
                        # Check the value of Diagnostic-Code: and the value of Status:, it is a deliverystats,
         | 
| 87 87 | 
             
                        # with true() method in each Sisimai::Reason::* class.
         | 
| 88 | 
            -
                        p =  | 
| 88 | 
            +
                        p = "Sisimai::Reason::#{e}"
         | 
| 89 89 | 
             
                        r = nil
         | 
| 90 90 | 
             
                        begin
         | 
| 91 91 | 
             
                          require ModulePath[p]
         | 
| 92 92 | 
             
                          r = Module.const_get(p)
         | 
| 93 93 | 
             
                        rescue
         | 
| 94 | 
            -
                          warn  | 
| 94 | 
            +
                          warn " ***warning: Failed to load #{p}"
         | 
| 95 95 | 
             
                          next
         | 
| 96 96 | 
             
                        end
         | 
| 97 97 | 
             
                        next unless r.true(argvs)
         | 
| @@ -132,7 +132,7 @@ module Sisimai | |
| 132 132 | 
             
                    codeformat = argvs['diagnostictype']          || ''
         | 
| 133 133 | 
             
                    actiontext = argvs['action']                  || ''
         | 
| 134 134 | 
             
                    statuscode = argvs['deliverystatus']          || ''
         | 
| 135 | 
            -
                    reasontext = Sisimai::SMTP::Status.name(statuscode) | 
| 135 | 
            +
                    reasontext = Sisimai::SMTP::Status.name(statuscode)
         | 
| 136 136 | 
             
                    trytomatch = reasontext.empty? ? true : false
         | 
| 137 137 | 
             
                    trytomatch ||= true if GetRetried[reasontext] || codeformat != 'SMTP'
         | 
| 138 138 |  | 
| @@ -140,13 +140,13 @@ module Sisimai | |
| 140 140 | 
             
                      # Could not decide the reason by the value of Status:
         | 
| 141 141 | 
             
                      ClassOrder[1].each do |e|
         | 
| 142 142 | 
             
                        # Trying to match with other patterns in Sisimai::Reason::* classes
         | 
| 143 | 
            -
                        p =  | 
| 143 | 
            +
                        p = "Sisimai::Reason::#{e}"
         | 
| 144 144 | 
             
                        r = nil
         | 
| 145 145 | 
             
                        begin
         | 
| 146 146 | 
             
                          require ModulePath[p]
         | 
| 147 147 | 
             
                          r = Module.const_get(p)
         | 
| 148 148 | 
             
                        rescue
         | 
| 149 | 
            -
                          warn  | 
| 149 | 
            +
                          warn " ***warning: Failed to load #{p}"
         | 
| 150 150 | 
             
                          next
         | 
| 151 151 | 
             
                        end
         | 
| 152 152 |  | 
| @@ -195,7 +195,7 @@ module Sisimai | |
| 195 195 | 
             
                  # @param    [String] argv1  Error message
         | 
| 196 196 | 
             
                  # @return   [String]        Bounce reason
         | 
| 197 197 | 
             
                  def match(argv1)
         | 
| 198 | 
            -
                    return  | 
| 198 | 
            +
                    return "" unless argv1
         | 
| 199 199 |  | 
| 200 200 | 
             
                    reasontext = ''
         | 
| 201 201 | 
             
                    issuedcode = argv1.downcase
         | 
| @@ -204,13 +204,13 @@ module Sisimai | |
| 204 204 | 
             
                    ClassOrder[2].each do |e|
         | 
| 205 205 | 
             
                      # Check the value of Diagnostic-Code: and the value of Status:, it is a deliverystats, with
         | 
| 206 206 | 
             
                      # true() method in each Sisimai::Reason::* class.
         | 
| 207 | 
            -
                      p =  | 
| 207 | 
            +
                      p = "Sisimai::Reason::#{e}"
         | 
| 208 208 | 
             
                      r = nil
         | 
| 209 209 | 
             
                      begin
         | 
| 210 210 | 
             
                        require ModulePath[p]
         | 
| 211 211 | 
             
                        r = Module.const_get(p)
         | 
| 212 212 | 
             
                      rescue
         | 
| 213 | 
            -
                        warn  | 
| 213 | 
            +
                        warn " ***warning: Failed to load #{p}"
         | 
| 214 214 | 
             
                        next
         | 
| 215 215 | 
             
                      end
         | 
| 216 216 |  | 
| @@ -226,8 +226,8 @@ module Sisimai | |
| 226 226 | 
             
                    else
         | 
| 227 227 | 
             
                      # Detect the bounce reason from "Status:" code
         | 
| 228 228 | 
             
                      require 'sisimai/smtp/status'
         | 
| 229 | 
            -
                       | 
| 230 | 
            -
                      reasontext =  | 
| 229 | 
            +
                      reasontext = Sisimai::SMTP::Status.name(Sisimai::SMTP::Status.find(argv1))
         | 
| 230 | 
            +
                      reasontext = "undefined" if reasontext.empty?
         | 
| 231 231 | 
             
                    end
         | 
| 232 232 | 
             
                    return reasontext
         | 
| 233 233 | 
             
                  end
         | 
    
        data/lib/sisimai/rfc1123.rb
    CHANGED
    
    | @@ -24,7 +24,7 @@ module Sisimai | |
| 24 24 | 
             
                  ].freeze
         | 
| 25 25 | 
             
                  StartAfter = [
         | 
| 26 26 | 
             
                      "generating server: ",      # (Exchange2007) en-US/Generating server: mta4.example.org
         | 
| 27 | 
            -
                      "serveur de g",             # (Exchange2007) fr-FR/Serveur de g | 
| 27 | 
            +
                      "serveur de g",             # (Exchange2007) fr-FR/Serveur de g辿?辿?ation
         | 
| 28 28 | 
             
                      "server di generazione",    # (Exchange2007) it-CH
         | 
| 29 29 | 
             
                      "genererande server",       # (Exchange2007) sv-SE
         | 
| 30 30 | 
             
                  ].freeze
         | 
| @@ -38,14 +38,10 @@ module Sisimai | |
| 38 38 | 
             
                  # @since v5.2.0
         | 
| 39 39 | 
             
                  def is_internethost(argv0 = '')
         | 
| 40 40 | 
             
                    return false unless argv0
         | 
| 41 | 
            -
                    return false if argv0.size < | 
| 42 | 
            -
                    return false if argv0.size > 255
         | 
| 41 | 
            +
                    return false if argv0.size < 4 || argv0.size > 255
         | 
| 43 42 | 
             
                    return false if argv0.include?(".") == false
         | 
| 44 | 
            -
                    return false if argv0.include?("..")
         | 
| 45 | 
            -
                    return false if argv0. | 
| 46 | 
            -
                    return false if argv0.start_with?(".")
         | 
| 47 | 
            -
                    return false if argv0.start_with?("-")
         | 
| 48 | 
            -
                    return false if argv0.end_with?("-")
         | 
| 43 | 
            +
                    return false if argv0.include?("..") || argv0.include?("--")
         | 
| 44 | 
            +
                    return false if argv0.start_with?(".", "-") || argv0.end_with?("-")
         | 
| 49 45 |  | 
| 50 46 | 
             
                    hostnameok = true
         | 
| 51 47 | 
             
                    characters = argv0.upcase.split("")
         |