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/lhost/ezweb.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ module Sisimai::Lhost | |
| 7 7 |  | 
| 8 8 | 
             
                  Indicators = Sisimai::Lhost.INDICATORS
         | 
| 9 9 | 
             
                  Boundaries = ["--------------------------------------------------", "Content-Type: message/rfc822"].freeze
         | 
| 10 | 
            -
                  StartingOf = { | 
| 10 | 
            +
                  StartingOf = {message: ['The user(s) ', 'Your message ', 'Each of the following', '<']}.freeze
         | 
| 11 11 | 
             
                  Messagesof = {
         | 
| 12 12 | 
             
                    # notaccept: ['The following recipients did not receive this message:'],
         | 
| 13 13 | 
             
                    'expired' => [
         | 
| @@ -43,13 +43,12 @@ module Sisimai::Lhost | |
| 43 43 | 
             
                    return nil if match < 2
         | 
| 44 44 |  | 
| 45 45 | 
             
                    fieldtable = Sisimai::RFC1894.FIELDTABLE
         | 
| 46 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 46 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 47 47 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 48 48 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 49 49 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 50 50 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 51 51 | 
             
                    substrings = []; Messagesof.each_value { |a| substrings << a }; substrings.flatten!
         | 
| 52 | 
            -
                    v = nil
         | 
| 53 52 |  | 
| 54 53 | 
             
                    while e = bodyslices.shift do
         | 
| 55 54 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -58,8 +57,7 @@ module Sisimai::Lhost | |
| 58 57 | 
             
                        # Beginning of the bounce message or delivery status part
         | 
| 59 58 | 
             
                        readcursor |= Indicators[:deliverystatus] if StartingOf[:message].any? { |a| e.include?(a) }
         | 
| 60 59 | 
             
                      end
         | 
| 61 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 62 | 
            -
                      next if e.empty?
         | 
| 60 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 63 61 |  | 
| 64 62 | 
             
                      # The user(s) account is disabled.
         | 
| 65 63 | 
             
                      #
         | 
| @@ -85,7 +83,7 @@ module Sisimai::Lhost | |
| 85 83 | 
             
                          v = dscontents[-1]
         | 
| 86 84 | 
             
                        end
         | 
| 87 85 | 
             
                        v["recipient"]  = Sisimai::Address.s3s4(e[p1, p2 - p1])
         | 
| 88 | 
            -
                        v["diagnosis"]  | 
| 86 | 
            +
                        v["diagnosis"] += " #{e}"
         | 
| 89 87 | 
             
                        recipients += 1
         | 
| 90 88 |  | 
| 91 89 | 
             
                      elsif Sisimai::RFC1894.match(e) > 0
         | 
| @@ -99,22 +97,22 @@ module Sisimai::Lhost | |
| 99 97 | 
             
                        next if Sisimai::String.is_8bit(e)
         | 
| 100 98 | 
             
                        if e.include?(" >>> ")
         | 
| 101 99 | 
             
                          #    >>> RCPT TO:<******@ezweb.ne.jp>
         | 
| 102 | 
            -
                          v["command"] | 
| 103 | 
            -
                          v["diagnosis"]  | 
| 100 | 
            +
                          v["command"]    = Sisimai::SMTP::Command.find(e)
         | 
| 101 | 
            +
                          v["diagnosis"] += " #{e}"
         | 
| 104 102 |  | 
| 105 103 | 
             
                        elsif e.include?(" <<< ")
         | 
| 106 104 | 
             
                          #    <<< 550 ...
         | 
| 107 | 
            -
                          v["diagnosis"]  | 
| 105 | 
            +
                          v["diagnosis"] += " #{e}"
         | 
| 108 106 |  | 
| 109 107 | 
             
                        else
         | 
| 110 108 | 
             
                          # Check error message
         | 
| 111 109 | 
             
                          isincluded = false
         | 
| 112 110 | 
             
                          if substrings.any? { |a| e.include?(a) }
         | 
| 113 111 | 
             
                            # Check with regular expressions of each error
         | 
| 114 | 
            -
                            v["diagnosis"]  | 
| 112 | 
            +
                            v["diagnosis"] += " #{e}"
         | 
| 115 113 | 
             
                            isincluded = true
         | 
| 116 114 | 
             
                          end
         | 
| 117 | 
            -
                          v["diagnosis"]  | 
| 115 | 
            +
                          v["diagnosis"] += " #{e}" if isincluded
         | 
| 118 116 | 
             
                        end
         | 
| 119 117 | 
             
                      end
         | 
| 120 118 | 
             
                    end
         | 
| @@ -148,7 +146,7 @@ module Sisimai::Lhost | |
| 148 146 | 
             
                      e["reason"] = "userunknown" if e["diagnosis"].start_with?("<")
         | 
| 149 147 | 
             
                    end
         | 
| 150 148 |  | 
| 151 | 
            -
                    return { | 
| 149 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 152 150 | 
             
                  end
         | 
| 153 151 | 
             
                  def description; return 'au EZweb: http://www.au.kddi.com/mobile/'; end
         | 
| 154 152 | 
             
                end
         | 
    
        data/lib/sisimai/lhost/fml.rb
    CHANGED
    
    | @@ -49,11 +49,10 @@ module Sisimai::Lhost | |
| 49 49 | 
             
                    return nil unless mhead['from'].include?('-admin@')
         | 
| 50 50 | 
             
                    return nil unless mhead['message-id'].index('.FML') > 1
         | 
| 51 51 |  | 
| 52 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 52 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 53 53 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 54 54 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 55 55 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 56 | 
            -
                    v = nil
         | 
| 57 56 |  | 
| 58 57 | 
             
                    while e = bodyslices.shift do
         | 
| 59 58 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -79,7 +78,7 @@ module Sisimai::Lhost | |
| 79 78 | 
             
                      else
         | 
| 80 79 | 
             
                        # If you know the general guide of this list, please send mail with
         | 
| 81 80 | 
             
                        # the mail body
         | 
| 82 | 
            -
                        v['diagnosis']  | 
| 81 | 
            +
                        v['diagnosis'] += e
         | 
| 83 82 | 
             
                      end
         | 
| 84 83 | 
             
                    end
         | 
| 85 84 | 
             
                    return nil unless recipients > 0
         | 
    
        data/lib/sisimai/lhost/gmail.rb
    CHANGED
    
    | @@ -152,12 +152,11 @@ module Sisimai::Lhost | |
| 152 152 | 
             
                    return nil unless mhead['subject'].start_with?('Delivery Status Notification')
         | 
| 153 153 |  | 
| 154 154 | 
             
                    require 'sisimai/address'
         | 
| 155 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 155 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 156 156 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 157 157 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 158 158 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 159 159 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 160 | 
            -
                    v = nil
         | 
| 161 160 |  | 
| 162 161 | 
             
                    while e = bodyslices.shift do
         | 
| 163 162 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -166,8 +165,7 @@ module Sisimai::Lhost | |
| 166 165 | 
             
                        # Beginning of the bounce message or delivery status part
         | 
| 167 166 | 
             
                        readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
         | 
| 168 167 | 
             
                      end
         | 
| 169 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 170 | 
            -
                      next if e.empty?
         | 
| 168 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 171 169 |  | 
| 172 170 | 
             
                      # Technical details of permanent failure:=20
         | 
| 173 171 | 
             
                      # Google tried to deliver your message, but it was rejected by the recipient =
         | 
| @@ -199,7 +197,7 @@ module Sisimai::Lhost | |
| 199 197 | 
             
                        v['recipient'] = r
         | 
| 200 198 | 
             
                        recipients += 1
         | 
| 201 199 | 
             
                      else
         | 
| 202 | 
            -
                        v["diagnosis"]  | 
| 200 | 
            +
                        v["diagnosis"] += "#{e }"
         | 
| 203 201 | 
             
                      end
         | 
| 204 202 | 
             
                    end
         | 
| 205 203 | 
             
                    return nil unless recipients > 0
         | 
| @@ -249,7 +247,7 @@ module Sisimai::Lhost | |
| 249 247 | 
             
                      # Set pseudo status code
         | 
| 250 248 | 
             
                      e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
         | 
| 251 249 | 
             
                      next if e['status'].size == 0 || e['status'].include?('.0')
         | 
| 252 | 
            -
                      e['reason'] = Sisimai::SMTP::Status.name(e['status']) | 
| 250 | 
            +
                      e['reason'] = Sisimai::SMTP::Status.name(e['status'])
         | 
| 253 251 | 
             
                    end
         | 
| 254 252 |  | 
| 255 253 | 
             
                    return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
         | 
    
        data/lib/sisimai/lhost/gmx.rb
    CHANGED
    
    | @@ -7,8 +7,8 @@ module Sisimai::Lhost | |
| 7 7 |  | 
| 8 8 | 
             
                  Indicators = Sisimai::Lhost.INDICATORS
         | 
| 9 9 | 
             
                  Boundaries = ['--- The header of the original message is following. ---'].freeze
         | 
| 10 | 
            -
                  StartingOf = { | 
| 11 | 
            -
                  MessagesOf = { | 
| 10 | 
            +
                  StartingOf = {message: ['This message was created automatically by mail delivery software']}.freeze
         | 
| 11 | 
            +
                  MessagesOf = {'expired' => ['delivery retry timeout exceeded']}.freeze
         | 
| 12 12 |  | 
| 13 13 | 
             
                  # @abstract Decodes the bounce message from GMX
         | 
| 14 14 | 
             
                  # @param  [Hash] mhead    Message headers of a bounce email
         | 
| @@ -23,12 +23,11 @@ module Sisimai::Lhost | |
| 23 23 | 
             
                    return nil unless mhead['x-gmx-antispam']
         | 
| 24 24 |  | 
| 25 25 | 
             
                    require 'sisimai/smtp/command'
         | 
| 26 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 26 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 27 27 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 28 28 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 29 29 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 30 30 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 31 | 
            -
                    v = nil
         | 
| 32 31 |  | 
| 33 32 | 
             
                    while e = bodyslices.shift do
         | 
| 34 33 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -38,8 +37,7 @@ module Sisimai::Lhost | |
| 38 37 | 
             
                        readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
         | 
| 39 38 | 
             
                        next
         | 
| 40 39 | 
             
                      end
         | 
| 41 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 42 | 
            -
                      next if e.empty?
         | 
| 40 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 43 41 |  | 
| 44 42 | 
             
                      # This message was created automatically by mail delivery software.
         | 
| 45 43 | 
             
                      #
         | 
| @@ -78,7 +76,7 @@ module Sisimai::Lhost | |
| 78 76 | 
             
                      else
         | 
| 79 77 | 
             
                        # Get error messages
         | 
| 80 78 | 
             
                        next if e.empty?
         | 
| 81 | 
            -
                        v['diagnosis'] | 
| 79 | 
            +
                        v['diagnosis'] += "#{e }"
         | 
| 82 80 | 
             
                      end
         | 
| 83 81 | 
             
                    end
         | 
| 84 82 | 
             
                    return nil unless recipients > 0
         | 
| @@ -94,7 +92,7 @@ module Sisimai::Lhost | |
| 94 92 | 
             
                      end
         | 
| 95 93 | 
             
                    end
         | 
| 96 94 |  | 
| 97 | 
            -
                    return { | 
| 95 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 98 96 | 
             
                  end
         | 
| 99 97 | 
             
                  def description; return 'GMX: https://www.gmx.net'; end
         | 
| 100 98 | 
             
                end
         | 
| @@ -36,10 +36,9 @@ module Sisimai::Lhost | |
| 36 36 | 
             
                    # Thanks,
         | 
| 37 37 | 
             
                    #
         | 
| 38 38 | 
             
                    # Google Groups
         | 
| 39 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 39 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = dscontents[-1]
         | 
| 40 40 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 41 41 | 
             
                    recipients = 0
         | 
| 42 | 
            -
                    v = dscontents[-1]
         | 
| 43 42 |  | 
| 44 43 | 
             
                    # * You might have spelled or formatted the group name incorrectly.
         | 
| 45 44 | 
             
                    # * The owner of the group may have removed this group.
         | 
| @@ -46,11 +46,10 @@ module Sisimai::Lhost | |
| 46 46 | 
             
                        if e.start_with?(StartingOf[:message][0])
         | 
| 47 47 | 
             
                          # ** Message not delivered **
         | 
| 48 48 | 
             
                          readcursor |= Indicators[:deliverystatus]
         | 
| 49 | 
            -
                          entiremesg  | 
| 49 | 
            +
                          entiremesg += "#{e }"
         | 
| 50 50 | 
             
                        end
         | 
| 51 51 | 
             
                      end
         | 
| 52 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 53 | 
            -
                      next if e.empty?
         | 
| 52 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 54 53 |  | 
| 55 54 | 
             
                      # ** Message not delivered **
         | 
| 56 55 | 
             
                      # You're sending this from a different address or alias using the 'Send mail as' feature.
         | 
| @@ -59,7 +58,7 @@ module Sisimai::Lhost | |
| 59 58 | 
             
                      # The response was:
         | 
| 60 59 | 
             
                      # Unspecified Error (SENT_SECOND_EHLO): Smtp server does not advertise AUTH capability
         | 
| 61 60 | 
             
                      next if e.start_with?("Content-Type: ")
         | 
| 62 | 
            -
                      entiremesg  | 
| 61 | 
            +
                      entiremesg += "#{e }"
         | 
| 63 62 | 
             
                    end
         | 
| 64 63 |  | 
| 65 64 | 
             
                    while recipients == 0 do
         | 
| @@ -7,7 +7,7 @@ module Sisimai::Lhost | |
| 7 7 | 
             
                  require 'sisimai/lhost'
         | 
| 8 8 |  | 
| 9 9 | 
             
                  Boundaries = ['Original message follows.'].freeze
         | 
| 10 | 
            -
                  StartingOf = { | 
| 10 | 
            +
                  StartingOf = {error: ['Body of message generated response:']}.freeze
         | 
| 11 11 | 
             
                  MessagesOf = {
         | 
| 12 12 | 
             
                    'hostunknown'   => ['Unknown host'],
         | 
| 13 13 | 
             
                    'userunknown'   => ['Unknown user', 'Invalid final delivery userid'],
         | 
| @@ -29,11 +29,10 @@ module Sisimai::Lhost | |
| 29 29 | 
             
                    match += 1 if mhead['x-mailer'].to_s.start_with?('<SMTP32 v')
         | 
| 30 30 | 
             
                    return nil unless match > 0
         | 
| 31 31 |  | 
| 32 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 32 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 33 33 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 34 34 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 35 35 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 36 | 
            -
                    v = nil
         | 
| 37 36 |  | 
| 38 37 | 
             
                    while e = bodyslices.shift do
         | 
| 39 38 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -58,8 +57,8 @@ module Sisimai::Lhost | |
| 58 57 | 
             
                        recipients += 1
         | 
| 59 58 | 
             
                      else
         | 
| 60 59 | 
             
                        # Other error message text
         | 
| 61 | 
            -
                        v['alterrors']  | 
| 62 | 
            -
                        v['alterrors'] | 
| 60 | 
            +
                        v['alterrors'] += " #{e}" if v['alterrors']
         | 
| 61 | 
            +
                        v['alterrors']  = e if e.include?(StartingOf[:error][0])
         | 
| 63 62 | 
             
                      end
         | 
| 64 63 | 
             
                    end
         | 
| 65 64 | 
             
                    return nil unless recipients > 0
         | 
| @@ -69,7 +68,7 @@ module Sisimai::Lhost | |
| 69 68 | 
             
                      unless e['alterrors'].to_s.empty?
         | 
| 70 69 | 
             
                        # Copy alternative error message
         | 
| 71 70 | 
             
                        e['diagnosis'] = if e['diagnosis']
         | 
| 72 | 
            -
                                           e['alterrors']  | 
| 71 | 
            +
                                           "#{e['alterrors']} #{e['diagnosis']}"
         | 
| 73 72 | 
             
                                         else
         | 
| 74 73 | 
             
                                           e['alterrors']
         | 
| 75 74 | 
             
                                         end
         | 
| @@ -87,7 +86,7 @@ module Sisimai::Lhost | |
| 87 86 | 
             
                      end
         | 
| 88 87 | 
             
                    end
         | 
| 89 88 |  | 
| 90 | 
            -
                    return { | 
| 89 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 91 90 | 
             
                  end
         | 
| 92 91 | 
             
                  def description; return 'IPSWITCH IMail Server'; end
         | 
| 93 92 | 
             
                end
         | 
| @@ -26,11 +26,10 @@ module Sisimai::Lhost | |
| 26 26 | 
             
                    return nil unless match > 0
         | 
| 27 27 |  | 
| 28 28 | 
             
                    require 'sisimai/smtp/command'
         | 
| 29 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 29 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 30 30 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 31 31 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 32 32 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 33 | 
            -
                    v = nil
         | 
| 34 33 |  | 
| 35 34 | 
             
                    while e = bodyslices.shift do
         | 
| 36 35 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
    
        data/lib/sisimai/lhost/kddi.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ module Sisimai::Lhost | |
| 7 7 |  | 
| 8 8 | 
             
                  Indicators = Sisimai::Lhost.INDICATORS
         | 
| 9 9 | 
             
                  Boundaries = ['Content-Type: message/rfc822'].freeze
         | 
| 10 | 
            -
                  StartingOf = { | 
| 10 | 
            +
                  StartingOf = {message: ['Your mail sent on:', 'Your mail attempted to be delivered on:']}.freeze
         | 
| 11 11 | 
             
                  MessagesOf = {
         | 
| 12 12 | 
             
                    'mailboxfull' => ['As their mailbox is full'],
         | 
| 13 13 | 
             
                    'norelaying'  => ['Due to the following SMTP relay error'],
         | 
| @@ -28,12 +28,11 @@ module Sisimai::Lhost | |
| 28 28 | 
             
                    match += 1 if mhead['received'].any? { |a| a.include?('.au.com (') }
         | 
| 29 29 | 
             
                    return nil unless match > 0
         | 
| 30 30 |  | 
| 31 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 31 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 32 32 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 33 33 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 34 34 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 35 35 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 36 | 
            -
                    v = nil
         | 
| 37 36 |  | 
| 38 37 | 
             
                    while e = bodyslices.shift do
         | 
| 39 38 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -43,8 +42,7 @@ module Sisimai::Lhost | |
| 43 42 | 
             
                        readcursor |= Indicators[:deliverystatus] if StartingOf[:message].any? { |a| e.start_with?(a) }
         | 
| 44 43 | 
             
                        next
         | 
| 45 44 | 
             
                      end
         | 
| 46 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 47 | 
            -
                      next if e.empty?
         | 
| 45 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 48 46 |  | 
| 49 47 | 
             
                      v = dscontents[-1]
         | 
| 50 48 | 
             
                      if e.include?(' Could not be delivered to: <')
         | 
| @@ -66,7 +64,7 @@ module Sisimai::Lhost | |
| 66 64 | 
             
                        v['date'] = e[19, e.size]
         | 
| 67 65 | 
             
                      else
         | 
| 68 66 | 
             
                        #     As their mailbox is full.
         | 
| 69 | 
            -
                        v['diagnosis']  | 
| 67 | 
            +
                        v['diagnosis'] += "#{e} " if e.start_with?(' ')
         | 
| 70 68 | 
             
                      end
         | 
| 71 69 | 
             
                    end
         | 
| 72 70 | 
             
                    return nil unless recipients > 0
         | 
| @@ -94,10 +92,9 @@ module Sisimai::Lhost | |
| 94 92 | 
             
                          end
         | 
| 95 93 | 
             
                        end
         | 
| 96 94 | 
             
                      end
         | 
| 97 | 
            -
             | 
| 98 95 | 
             
                    end
         | 
| 99 96 |  | 
| 100 | 
            -
                    return { | 
| 97 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 101 98 | 
             
                  end
         | 
| 102 99 | 
             
                  def description; return 'au by KDDI: https://www.au.kddi.com'; end
         | 
| 103 100 | 
             
                end
         | 
| @@ -21,12 +21,11 @@ module Sisimai::Lhost | |
| 21 21 | 
             
                    return nil unless mhead['subject'] == 'Message delivery has failed'
         | 
| 22 22 | 
             
                    return nil unless mhead['received'].any? { |a| a.include?('(MAILFOUNDRY) id ') }
         | 
| 23 23 |  | 
| 24 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 24 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 25 25 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 26 26 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 27 27 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 28 28 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 29 | 
            -
                    v = nil
         | 
| 30 29 |  | 
| 31 30 | 
             
                    while e = bodyslices.shift do
         | 
| 32 31 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -35,8 +34,7 @@ module Sisimai::Lhost | |
| 35 34 | 
             
                        # Beginning of the bounce message or delivery status part
         | 
| 36 35 | 
             
                        readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
         | 
| 37 36 | 
             
                      end
         | 
| 38 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 39 | 
            -
                      next if e.empty?
         | 
| 37 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 40 38 |  | 
| 41 39 | 
             
                      # Unable to deliver message to: <kijitora@example.org>
         | 
| 42 40 | 
             
                      # Delivery failed for the following reason:
         | 
| @@ -61,9 +59,8 @@ module Sisimai::Lhost | |
| 61 59 | 
             
                          v['diagnosis'] = e
         | 
| 62 60 | 
             
                        else
         | 
| 63 61 | 
             
                          # Detect error message
         | 
| 64 | 
            -
                          next if v['diagnosis'].nil? || v['diagnosis'].empty?
         | 
| 65 | 
            -
                           | 
| 66 | 
            -
                          v['diagnosis'] << ' ' << e
         | 
| 62 | 
            +
                          next if v['diagnosis'].nil? || v['diagnosis'].empty? || e.start_with?('-')
         | 
| 63 | 
            +
                          v['diagnosis'] += " #{e}"
         | 
| 67 64 | 
             
                        end
         | 
| 68 65 | 
             
                      end
         | 
| 69 66 | 
             
                    end
         | 
| @@ -22,14 +22,12 @@ module Sisimai::Lhost | |
| 22 22 | 
             
                  def inquire(mhead, mbody)
         | 
| 23 23 | 
             
                    return nil unless mhead['subject'].start_with?('Undeliverable Mail: "')
         | 
| 24 24 |  | 
| 25 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 25 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 26 26 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 27 27 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 28 28 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 29 29 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 30 30 | 
             
                    endoferror = false  # (Boolean) Flag for the end of error message
         | 
| 31 | 
            -
                    q = Sisimai::RFC2045.boundary(mhead['content-type'], 1); Boundaries << q if q
         | 
| 32 | 
            -
                    v = nil
         | 
| 33 31 |  | 
| 34 32 | 
             
                    while e = bodyslices.shift do
         | 
| 35 33 | 
             
                      # Read error messages and delivery status lines from the head of the email
         | 
| @@ -74,7 +72,7 @@ module Sisimai::Lhost | |
| 74 72 | 
             
                          # Append error messages
         | 
| 75 73 | 
             
                          endoferror = true if e.start_with?(StartingOf[:rcpts][0])
         | 
| 76 74 | 
             
                          next if endoferror
         | 
| 77 | 
            -
                          v['diagnosis']  | 
| 75 | 
            +
                          v['diagnosis'] += " #{e}"
         | 
| 78 76 | 
             
                        else
         | 
| 79 77 | 
             
                          # Additional Information
         | 
| 80 78 | 
             
                          # ======================
         | 
| @@ -89,7 +87,7 @@ module Sisimai::Lhost | |
| 89 87 | 
             
                          if e.start_with?('Original Sender: ')
         | 
| 90 88 | 
             
                            # Original Sender:    <originalsender@example.com>
         | 
| 91 89 | 
             
                            # Use this line instead of "From" header of the original message.
         | 
| 92 | 
            -
                            emailparts[1]  | 
| 90 | 
            +
                            emailparts[1] += ("From: #{e[p1 + 1, p2 - p1 - 1]}\n")
         | 
| 93 91 |  | 
| 94 92 | 
             
                          elsif e.start_with?('Sender-MTA: ')
         | 
| 95 93 | 
             
                            # Sender-MTA:         <10.11.12.13>
         | 
| @@ -106,7 +104,7 @@ module Sisimai::Lhost | |
| 106 104 | 
             
                            p2 = e.index(':')
         | 
| 107 105 | 
             
                            cf = e[p1 + 1, p2 - p1 - 1]
         | 
| 108 106 | 
             
                            cv = Sisimai::String.sweep(e[p2 + 1, e.size])
         | 
| 109 | 
            -
                            emailparts[1]  | 
| 107 | 
            +
                            emailparts[1] += sprintf("%s: %s\n", cf, cv)
         | 
| 110 108 | 
             
                          end
         | 
| 111 109 | 
             
                        end
         | 
| 112 110 | 
             
                      end
         | 
| @@ -8,8 +8,8 @@ module Sisimai::Lhost | |
| 8 8 |  | 
| 9 9 | 
             
                  Indicators = Sisimai::Lhost.INDICATORS
         | 
| 10 10 | 
             
                  Boundaries = ['Content-Type: message/rfc822', 'Return-path: '].freeze
         | 
| 11 | 
            -
                  StartingOf = { | 
| 12 | 
            -
                  MessagesOf = { | 
| 11 | 
            +
                  StartingOf = {message: ['This report relates to a message you sent with the following header fields:']}.freeze
         | 
| 12 | 
            +
                  MessagesOf = {'hostunknown' => ['Illegal host/domain name found']}.freeze
         | 
| 13 13 |  | 
| 14 14 | 
             
                  # @abstract Decodes the bounce message from MessagingServer
         | 
| 15 15 | 
             
                  # @param  [Hash] mhead    Message headers of a bounce email
         | 
| @@ -22,12 +22,11 @@ module Sisimai::Lhost | |
| 22 22 | 
             
                    match += 1 if mhead['subject'].start_with?('Delivery Notification: ')
         | 
| 23 23 | 
             
                    return nil unless match > 0
         | 
| 24 24 |  | 
| 25 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 25 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 26 26 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 27 27 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 28 28 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 29 29 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 30 | 
            -
                    v = nil
         | 
| 31 30 |  | 
| 32 31 | 
             
                    while e = bodyslices.shift do
         | 
| 33 32 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -37,8 +36,7 @@ module Sisimai::Lhost | |
| 37 36 | 
             
                        readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
         | 
| 38 37 | 
             
                        next
         | 
| 39 38 | 
             
                      end
         | 
| 40 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 41 | 
            -
                      next if e.empty?
         | 
| 39 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 42 40 |  | 
| 43 41 | 
             
                      # --Boundary_(ID_0000000000000000000000)
         | 
| 44 42 | 
             
                      # Content-type: text/plain; charset=us-ascii
         | 
| @@ -148,7 +146,7 @@ module Sisimai::Lhost | |
| 148 146 | 
             
                      end
         | 
| 149 147 | 
             
                    end
         | 
| 150 148 |  | 
| 151 | 
            -
                    return { | 
| 149 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 152 150 | 
             
                  end
         | 
| 153 151 | 
             
                  def description; return 'Oracle Communications Messaging Server'; end
         | 
| 154 152 | 
             
                end
         | 
| @@ -22,13 +22,12 @@ module Sisimai::Lhost | |
| 22 22 | 
             
                    return nil unless mhead['x-mailer'].to_s == 'm-FILTER'
         | 
| 23 23 | 
             
                    return nil unless mhead['subject'] == 'failure notice'
         | 
| 24 24 |  | 
| 25 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 25 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 26 26 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 27 27 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 28 28 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 29 29 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 30 | 
            -
                    markingset = { | 
| 31 | 
            -
                    v = nil
         | 
| 30 | 
            +
                    markingset = {'diagnosis' => false, 'command' => false}
         | 
| 32 31 |  | 
| 33 32 | 
             
                    while e = bodyslices.shift do
         | 
| 34 33 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -39,8 +38,7 @@ module Sisimai::Lhost | |
| 39 38 | 
             
                          readcursor |= Indicators[:deliverystatus]
         | 
| 40 39 | 
             
                        end
         | 
| 41 40 | 
             
                      end
         | 
| 42 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 43 | 
            -
                      next if e.empty?
         | 
| 41 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 44 42 |  | 
| 45 43 | 
             
                      # このメールは「m-FILTER」が自動的に生成して送信しています。
         | 
| 46 44 | 
             
                      # メールサーバーとの通信中、下記の理由により
         | 
| @@ -111,7 +109,7 @@ module Sisimai::Lhost | |
| 111 109 | 
             
                        e['rhost'] = ee
         | 
| 112 110 | 
             
                      end
         | 
| 113 111 | 
             
                    end
         | 
| 114 | 
            -
                    return { | 
| 112 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 115 113 | 
             
                  end
         | 
| 116 114 | 
             
                  def description; return 'Digital Arts m-FILTER'; end
         | 
| 117 115 | 
             
                end
         | 
    
        data/lib/sisimai/lhost/notes.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ module Sisimai::Lhost | |
| 7 7 |  | 
| 8 8 | 
             
                  Indicators = Sisimai::Lhost.INDICATORS
         | 
| 9 9 | 
             
                  Boundaries = ['------- Returned Message --------'].freeze
         | 
| 10 | 
            -
                  StartingOf = { | 
| 10 | 
            +
                  StartingOf = {message: ['------- Failure Reasons ']}.freeze
         | 
| 11 11 | 
             
                  MessagesOf = {
         | 
| 12 12 | 
             
                    'userunknown' => [
         | 
| 13 13 | 
             
                      'User not listed in public Name & Address Book',
         | 
| @@ -24,7 +24,7 @@ module Sisimai::Lhost | |
| 24 24 | 
             
                  def inquire(mhead, mbody)
         | 
| 25 25 | 
             
                    return nil unless mhead['subject'].start_with?('Undeliverable message')
         | 
| 26 26 |  | 
| 27 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 27 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 28 28 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 29 29 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 30 30 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| @@ -32,7 +32,6 @@ module Sisimai::Lhost | |
| 32 32 | 
             
                    characters = ''     # (String) Character set name of the bounce mail
         | 
| 33 33 | 
             
                    removedmsg = 'MULTIBYTE CHARACTERS HAVE BEEN REMOVED'
         | 
| 34 34 | 
             
                    encodedmsg = ''
         | 
| 35 | 
            -
                    v = nil
         | 
| 36 35 |  | 
| 37 36 | 
             
                    if mhead['content-type'].include?('charset=')
         | 
| 38 37 | 
             
                      # Get character set name, Content-Type: text/plain; charset=ISO-2022-JP
         | 
| @@ -66,8 +65,7 @@ module Sisimai::Lhost | |
| 66 65 | 
             
                        v["recipient"] = e if v["recipient"].empty?
         | 
| 67 66 | 
             
                        recipients += 1
         | 
| 68 67 | 
             
                      else
         | 
| 69 | 
            -
                        next if e.empty?
         | 
| 70 | 
            -
                        next if e.start_with?('-')
         | 
| 68 | 
            +
                        next if e.empty? || e.start_with?('-')
         | 
| 71 69 |  | 
| 72 70 | 
             
                        if e =~ /[^\x20-\x7e]/
         | 
| 73 71 | 
             
                          # Error message is not ISO-8859-1
         | 
| @@ -83,10 +81,10 @@ module Sisimai::Lhost | |
| 83 81 | 
             
                            # No character set in Content-Type header
         | 
| 84 82 | 
             
                            encodedmsg = removedmsg
         | 
| 85 83 | 
             
                          end
         | 
| 86 | 
            -
                          v['diagnosis']  | 
| 84 | 
            +
                          v['diagnosis'] += encodedmsg
         | 
| 87 85 | 
             
                        else
         | 
| 88 86 | 
             
                          # Error message does not include multi-byte character
         | 
| 89 | 
            -
                          v['diagnosis']  | 
| 87 | 
            +
                          v['diagnosis'] += e
         | 
| 90 88 | 
             
                        end
         | 
| 91 89 | 
             
                      end
         | 
| 92 90 | 
             
                    end
         | 
| @@ -96,7 +94,7 @@ module Sisimai::Lhost | |
| 96 94 | 
             
                      p1 = emailparts[1].index("\nTo: ")     || -1
         | 
| 97 95 | 
             
                      p2 = emailparts[1].index("\n", p1 + 6) || -1
         | 
| 98 96 | 
             
                      if p1 > 0
         | 
| 99 | 
            -
                        v['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1 + 5, p2 - p1 - 5]) | 
| 97 | 
            +
                        v['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1 + 5, p2 - p1 - 5])
         | 
| 100 98 | 
             
                        recipients += 1 unless v['recipient'].empty?
         | 
| 101 99 | 
             
                      end
         | 
| 102 100 | 
             
                    end
         | 
| @@ -115,7 +113,7 @@ module Sisimai::Lhost | |
| 115 113 | 
             
                      end
         | 
| 116 114 | 
             
                    end
         | 
| 117 115 |  | 
| 118 | 
            -
                    return { | 
| 116 | 
            +
                    return {"ds" => dscontents, "rfc822" => emailparts[1]}
         | 
| 119 117 | 
             
                  end
         | 
| 120 118 | 
             
                  def description; return 'Lotus Notes'; end
         | 
| 121 119 | 
             
                end
         | 
| @@ -76,12 +76,11 @@ module Sisimai::Lhost | |
| 76 76 | 
             
                    return nil unless mhead['from'].start_with?('Mailer Daemon <')
         | 
| 77 77 | 
             
                    return nil unless mhead['received'].any? { |a| a.include?(' (OpenSMTPD) with ') }
         | 
| 78 78 |  | 
| 79 | 
            -
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
         | 
| 79 | 
            +
                    dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
         | 
| 80 80 | 
             
                    emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
         | 
| 81 81 | 
             
                    bodyslices = emailparts[0].split("\n")
         | 
| 82 82 | 
             
                    readcursor = 0      # (Integer) Points the current cursor position
         | 
| 83 83 | 
             
                    recipients = 0      # (Integer) The number of 'Final-Recipient' header
         | 
| 84 | 
            -
                    v = nil
         | 
| 85 84 |  | 
| 86 85 | 
             
                    while e = bodyslices.shift do
         | 
| 87 86 | 
             
                      # Read error messages and delivery status lines from the head of the email to the previous
         | 
| @@ -91,8 +90,7 @@ module Sisimai::Lhost | |
| 91 90 | 
             
                        readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
         | 
| 92 91 | 
             
                        next
         | 
| 93 92 | 
             
                      end
         | 
| 94 | 
            -
                      next if (readcursor & Indicators[:deliverystatus]) == 0
         | 
| 95 | 
            -
                      next if e.empty?
         | 
| 93 | 
            +
                      next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
         | 
| 96 94 |  | 
| 97 95 | 
             
                      #    Hi!
         | 
| 98 96 | 
             
                      #
         |