sisimai 4.25.10 → 4.25.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sisimai might be problematic. Click here for more details.

Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -3
  3. data/ChangeLog.md +14 -0
  4. data/lib/sisimai/address.rb +6 -3
  5. data/lib/sisimai/datetime.rb +15 -14
  6. data/lib/sisimai/lhost/amazonses.rb +1 -1
  7. data/lib/sisimai/lhost/domino.rb +29 -4
  8. data/lib/sisimai/lhost/einsundeins.rb +1 -1
  9. data/lib/sisimai/lhost/exim.rb +5 -2
  10. data/lib/sisimai/lhost/gsuite.rb +5 -0
  11. data/lib/sisimai/lhost/imailserver.rb +1 -1
  12. data/lib/sisimai/lhost/mailfoundry.rb +3 -4
  13. data/lib/sisimai/lhost/mailmarshalsmtp.rb +2 -2
  14. data/lib/sisimai/lhost/notes.rb +1 -1
  15. data/lib/sisimai/lhost/office365.rb +1 -1
  16. data/lib/sisimai/lhost/sendgrid.rb +2 -2
  17. data/lib/sisimai/lhost/verizon.rb +4 -4
  18. data/lib/sisimai/mail.rb +2 -1
  19. data/lib/sisimai/reason/blocked.rb +17 -4
  20. data/lib/sisimai/reason/exceedlimit.rb +4 -1
  21. data/lib/sisimai/reason/expired.rb +2 -0
  22. data/lib/sisimai/reason/filtered.rb +1 -0
  23. data/lib/sisimai/reason/hostunknown.rb +1 -0
  24. data/lib/sisimai/reason/norelaying.rb +5 -0
  25. data/lib/sisimai/reason/notaccept.rb +1 -0
  26. data/lib/sisimai/reason/policyviolation.rb +3 -0
  27. data/lib/sisimai/reason/rejected.rb +5 -1
  28. data/lib/sisimai/reason/spamdetected.rb +8 -3
  29. data/lib/sisimai/reason/suspend.rb +1 -0
  30. data/lib/sisimai/reason/systemerror.rb +2 -0
  31. data/lib/sisimai/reason/userunknown.rb +6 -1
  32. data/lib/sisimai/rfc1894.rb +24 -22
  33. data/lib/sisimai/rfc3464.rb +1 -1
  34. data/lib/sisimai/rfc3834.rb +1 -1
  35. data/lib/sisimai/rfc5322.rb +8 -3
  36. data/lib/sisimai/rhost.rb +1 -0
  37. data/lib/sisimai/rhost/exchangeonline.rb +8 -1
  38. data/lib/sisimai/smtp/error.rb +8 -6
  39. data/lib/sisimai/smtp/reply.rb +1 -1
  40. data/lib/sisimai/time.rb +1 -2
  41. data/lib/sisimai/version.rb +1 -1
  42. data/set-of-emails/maildir/bsd/lhost-aol-04.eml +23 -23
  43. data/set-of-emails/maildir/bsd/lhost-domino-02.eml +1 -2
  44. data/set-of-emails/maildir/bsd/lhost-sendmail-08.eml +1 -1
  45. data/set-of-emails/maildir/bsd/lhost-sendmail-11.eml +1 -1
  46. data/set-of-emails/maildir/bsd/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
  47. data/set-of-emails/maildir/bsd/{rhost-exchange-online-02.eml → rhost-exchangeonline-02.eml} +0 -0
  48. data/set-of-emails/maildir/bsd/{rhost-exchange-online-03.eml → rhost-exchangeonline-03.eml} +0 -0
  49. data/set-of-emails/maildir/bsd/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
  50. data/set-of-emails/maildir/bsd/{rhost-google-apps-02.eml → rhost-googleapps-02.eml} +0 -0
  51. data/set-of-emails/maildir/dos/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
  52. data/set-of-emails/maildir/dos/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
  53. data/set-of-emails/maildir/mac/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
  54. data/set-of-emails/maildir/mac/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
  55. data/sisimai-java.gemspec +4 -4
  56. data/sisimai.gemspec +4 -4
  57. metadata +20 -20
@@ -9,7 +9,10 @@ module Sisimai
9
9
  module ExceedLimit
10
10
  # Imported from p5-Sisimail/lib/Sisimai/Reason/ExceedLimit.pm
11
11
  class << self
12
- Index = ['message too large']
12
+ Index = [
13
+ 'message header size exceeds limit',
14
+ 'message too large',
15
+ ]
13
16
 
14
17
  def text; return 'exceedlimit'; end
15
18
  def description; return 'Email rejected due to an email exceeded the limit'; end
@@ -12,9 +12,11 @@ module Sisimai
12
12
  Index = [
13
13
  'connection timed out',
14
14
  'could not find a gateway for',
15
+ 'delivery attempts will continue to be',
15
16
  'delivery time expired',
16
17
  'failed to deliver to domain ',
17
18
  'giving up on',
19
+ 'have been failing for a long time',
18
20
  'has been delayed',
19
21
  'it has not been collected after',
20
22
  'message expired after sitting in queue for',
@@ -18,6 +18,7 @@ module Sisimai
18
18
  'due to extended inactivity new mail is not currently being accepted for this mailbox',
19
19
  'has restricted sms e-mail', # AT&T
20
20
  'is not accepting any mail',
21
+ 'message rejected due to user rules',
21
22
  'refused due to recipient preferences', # Facebook
22
23
  'resolver.rst.notauthorized', # Microsoft Exchange
23
24
  'this account is protected by',
@@ -22,6 +22,7 @@ module Sisimai
22
22
  'recipient domain must exist',
23
23
  'the account or domain may not exist',
24
24
  'unknown host',
25
+ 'unroutable address',
25
26
  'unrouteable address',
26
27
  ]
27
28
  Regex = %r/553[ ][^ ]+[ ]does[ ]not[ ]exist/
@@ -16,16 +16,21 @@ module Sisimai
16
16
  Index = [
17
17
  'as a relay',
18
18
  'insecure mail relay',
19
+ 'is not permitted to relay through this server without authentication',
19
20
  'mail server requires authentication when attempting to send to a non-local e-mail address', # MailEnable
21
+ 'not a gateway',
20
22
  'not allowed to relay through this machine',
21
23
  'not an open relay, so get lost',
24
+ 'not local host',
22
25
  'relay access denied',
23
26
  'relay denied',
24
27
  'relay not permitted',
25
28
  'relaying denied', # Sendmail
29
+ 'relaying mail to ',
26
30
  "that domain isn't in my list of allowed rcpthost",
27
31
  'this system is not configured to relay mail',
28
32
  'unable to relay for',
33
+ "we don't handle mail for",
29
34
  ]
30
35
 
31
36
  def text; return 'norelaying'; end
@@ -17,6 +17,7 @@ module Sisimai
17
17
  'host does not accept mail', # Sendmail
18
18
  'name server: .: host not found', # Sendmail
19
19
  'no mx record found for domain=', # Oath(Yahoo!)
20
+ 'no route for current request',
20
21
  'smtp protocol returned a permanent error',
21
22
  ]
22
23
 
@@ -19,6 +19,7 @@ module Sisimai
19
19
  Index = [
20
20
  'an illegal attachment on your message',
21
21
  'because the recipient is not accepting mail with ', # AOL Phoenix
22
+ 'by non-member to a members-only list',
22
23
  'closed mailing list',
23
24
  'denied by policy',
24
25
  'dmarc policy',
@@ -28,6 +29,7 @@ module Sisimai
28
29
  'header are not accepted',
29
30
  'header error',
30
31
  'local policy violation',
32
+ 'message bounced due to organizational settings',
31
33
  'message given low priority',
32
34
  'message not accepted for policy reasons',
33
35
  'messages with multiple addresses',
@@ -35,6 +37,7 @@ module Sisimai
35
37
  'protocol violation',
36
38
  'the email address used to send your message is not subscribed to this group',
37
39
  'this message was blocked because its content presents a potential',
40
+ 'we do not accept messages containing images or other attachments',
38
41
  'you have exceeded the allowable number of posts without solving a captcha',
39
42
  'you have exceeded the the allowable number of posts without solving a captcha',
40
43
  ]
@@ -21,8 +21,8 @@ module Sisimai
21
21
  'sender ip address rejected',
22
22
  ]
23
23
  Index = [
24
- '<> invalid sender',
25
24
  'access denied (in reply to mail from command)',
25
+ 'access denied (sender blacklisted)',
26
26
  'address rejected',
27
27
  'administrative prohibition',
28
28
  'batv failed to verify', # SoniWall
@@ -31,6 +31,7 @@ module Sisimai
31
31
  'bogus mail from', # IMail - block empty sender
32
32
  'connections not accepted from servers without a valid sender domain',
33
33
  'denied [bouncedeny]', # McAfee
34
+ 'denied by secumail valid-address-filter',
34
35
  'delivery not authorized, message refused',
35
36
  'does not exist e2110',
36
37
  'domain of sender address ',
@@ -41,6 +42,7 @@ module Sisimai
41
42
  'from: domain is invalid. please provide a valid from:',
42
43
  'fully qualified email address required', # McAfee
43
44
  'invalid domain, see <url:',
45
+ 'invalid sender',
44
46
  'is not a registered gateway user',
45
47
  'mail from not owned by user',
46
48
  'message rejected: email address is not verified',
@@ -51,6 +53,7 @@ module Sisimai
51
53
  'returned mail not accepted here',
52
54
  'rfc 1035 violation: recursive cname records for',
53
55
  'rule imposed mailbox access for', # MailMarshal
56
+ 'sender address has been blacklisted',
54
57
  'sender email address rejected',
55
58
  'sender is spammer',
56
59
  'sender not pre-approved',
@@ -59,6 +62,7 @@ module Sisimai
59
62
  'sender verify failed', # Exim callout
60
63
  'syntax error: empty email address',
61
64
  'the message has been rejected by batv defense',
65
+ 'this server does not accept mail from',
62
66
  'transaction failed unsigned dsn for',
63
67
  'unroutable sender address',
64
68
  'you are sending to/from an address that has been blacklisted',
@@ -30,10 +30,12 @@ module Sisimai
30
30
  )
31
31
  |blocked[ ]for[ ]abuse[.][ ]see[ ]http://att[.]net/blocks # AT&T
32
32
  |bulk[ ]email
33
+ |considered[ ]unsolicited[ ]bulk[ ]e-mail[ ][(]spam[)][ ]by[ ]our[ ]mail[ ]filters
33
34
  |content[ ]filter[ ]rejection
34
35
  |cyberoam[ ]anti[ ]spam[ ]engine[ ]has[ ]identified[ ]this[ ]email[ ]as[ ]a[ ]bulk[ ]email
35
36
  |denied[ ]due[ ]to[ ]spam[ ]list
36
37
  |greylisted.?.[ ]please[ ]try[ ]again[ ]in
38
+ |high[ ]probability[ ]of[ ]spam
37
39
  |https?://(?:www[.]spamhaus[.]org|dsbl[.]org|mail[.]163[.]com/help/help_spam_16[.]htm)
38
40
  |listed[ ]in[ ]work[.]drbl[.]imedia[.]ru
39
41
  |mail[ ](?:
@@ -51,7 +53,10 @@ module Sisimai
51
53
  |refer[ ]to[ ]the[ ]troubleshooting[ ]page[ ]at[ ]
52
54
  )
53
55
  |looks[ ]like[ ]spam
54
- |refused[ ]by[ ]mailmarshal[ ]spamprofiler
56
+ |refused[ ]by[ ](?:
57
+ mailmarshal[ ]spamprofiler
58
+ |trustwave[ ]seg[ ]spamprofiler
59
+ )
55
60
  |rejected[ ](?:
56
61
  as[ ]spam
57
62
  |because[ ]of[ ]unacceptable[ ]content
@@ -69,9 +74,9 @@ module Sisimai
69
74
  |rejected(?:
70
75
  :[ ]spamassassin[ ]score[ ]
71
76
  |[ ]by[ ][^ ]+[ ][(]spam[)]
72
- |[ ]due[ ]to[ ]spam[ ](?:classification|content)
77
+ |[ ]due[ ]to[ ]spam[ ](?:url[ ]in[ ])?(?:classification|content)
73
78
  )
74
- |rejecting[ ]banned[ ]content
79
+ |rejecting[ ](?:banned|mail)[ ]content
75
80
  |related[ ]to[ ]content[ ]with[ ]spam[-]like[ ]characteristics
76
81
  |rule[ ]imposed[ ]as[ ][^ ]+[ ]is[ ]blacklisted[ ]on
77
82
  |sender[ ]domain[ ]listed[ ]at[ ][^ ]+
@@ -13,6 +13,7 @@ module Sisimai
13
13
  ' temporary locked',
14
14
  'boite du destinataire archivee',
15
15
  'email account that you tried to reach is disabled',
16
+ 'has been suspended',
16
17
  'invalid/inactive user',
17
18
  'is a deactivated mailbox', # http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=20022&&no=1000742
18
19
  'mailbox currently suspended',
@@ -13,6 +13,7 @@ module Sisimai
13
13
  # Imported from p5-Sisimail/lib/Sisimai/Reason/SystemError.pm
14
14
  class << self
15
15
  Index = [
16
+ 'aliasing/forwarding loop broken',
16
17
  "can't create user output file",
17
18
  'could not load drd for domain',
18
19
  'internal error reading data', # Microsoft
@@ -25,6 +26,7 @@ module Sisimai
25
26
  'loop was found in the mail exchanger',
26
27
  'loops back to myself',
27
28
  'mail system configuration error',
29
+ 'remote server is misconfigured',
28
30
  'server configuration error',
29
31
  'service currently unavailable',
30
32
  'system config error',
@@ -28,10 +28,13 @@ module Sisimai
28
28
  [#]5[.]1[.]1[ ]bad[ ]address
29
29
  |[<][^ ]+[>][ ]not[ ]found
30
30
  |[<][^ ]+[@][^ ]+[>][.][.][.][ ]blocked[ ]by[ ]
31
+ |550[ ]address[ ]invalid
31
32
  |5[.]0[.]0[.][ ]mail[ ]rejected[.]
32
33
  |5[.]1[.]0[ ]address[ ]rejected[.]
34
+ |account[ ][^ ]+[ ]does[ ]not[ ]exist[ ]at[ ]the[ ]organization
33
35
  |adresse[ ]d[ ]au[ ]moins[ ]un[ ]destinataire[ ]invalide[.][ ]invalid[ ]recipient[.][0-9a-z_]+41[68]
34
36
  |address[ ](?:does[ ]not[ ]exist|unknown)
37
+ |address[ ](?:does[ ]not[ ]exist|not[ ]present[ ]in[ ]directory|unknown)
35
38
  |archived[ ]recipient
36
39
  |bad[-_ ]recipient
37
40
  |can[']t[ ]accept[ ]user
@@ -43,7 +46,7 @@ module Sisimai
43
46
  |email[ ]address[ ](?:does[ ]not[ ]exist|could[ ]not[ ]be[ ]found)
44
47
  |invalid[ ](?:
45
48
  address
46
- |mailbox:
49
+ |mailbox:?
47
50
  |mailbox[ ]path
48
51
  |recipient
49
52
  )
@@ -61,6 +64,7 @@ module Sisimai
61
64
  |not[ ](?:present|found)
62
65
  |unavailable
63
66
  )
67
+ |nessun[ ]utente[ ]simile[ ]in[ ]questo[ ]indirizzo
64
68
  |no[ ](?:
65
69
  [ ][^ ]+[ ]in[ ]name[ ]directory
66
70
  |account[ ]by[ ]that[ ]name[ ]here
@@ -138,6 +142,7 @@ module Sisimai
138
142
  |not[ ](?:active|exist|found|known)
139
143
  |unknown
140
144
  )
145
+ |utilisateur[ ]inconnu[ ]!
141
146
  |vdeliver:[ ]invalid[ ]or[ ]unknown[ ]virtual[ ]user
142
147
  |your[ ]envelope[ ]recipient[ ]is[ ]in[ ]my[ ]badrcptto[ ]list
143
148
  )
@@ -38,14 +38,14 @@ module Sisimai
38
38
  'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ]*(.+?);[ ]*(.+)/,
39
39
  'code' => %r/\A(Diagnostic-Code):[ ]*(.+?);[ ]*(.*)/,
40
40
  'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ]*(.+)/,
41
- 'host' => %r/\A((?:Reporting|Received-From|Remote)-MTA):[ ]*(.+?);[ ]*(.+)/,
42
- 'list' => %r/\A(Action):[ ]*(failed|delayed|delivered|relayed|expanded|expired|failure)/i,
41
+ 'host' => %r/\A((?:Received-From|Remote|Reporting)-MTA):[ ]*(.+?);[ ]*(.+)/,
42
+ 'list' => %r/\A(Action):[ ]*(delayed|deliverable|delivered|expanded|expired|failed|failure|relayed)/i,
43
43
  'stat' => %r/\A(Status):[ ]*([245][.]\d+[.]\d+)/,
44
44
  'text' => %r/\A(X-Original-Message-ID):[ ]*(.+)/,
45
- #text: %r/\A(Original-Envelope-Id|Final-Log-ID):[ ]*(.+)/,
45
+ #'text' => %r/\A(Final-Log-ID|Original-Envelope-Id):[ ]*(.+)/,
46
46
  }.freeze
47
47
 
48
- Correction = { action: { 'failure' => 'failed', 'expired' => 'delayed' } }
48
+ Correction = { action: { 'deliverable' => 'delivered', 'expired' => 'delayed', 'failure' => 'failed' }}
49
49
  FieldGroup = {
50
50
  'original-recipient' => 'addr',
51
51
  'final-recipient' => 'addr',
@@ -86,8 +86,8 @@ module Sisimai
86
86
  # @since v4.25.0
87
87
  def match(argv0 = '')
88
88
  return nil if argv0.empty?
89
- return 1 if FieldNames[0].any? { |a| argv0.start_with?(a) }
90
- return 2 if FieldNames[1].any? { |a| argv0.start_with?(a) }
89
+ return 1 if FieldNames[0].any? { |a| argv0.start_with?(a) }
90
+ return 2 if FieldNames[1].any? { |a| argv0.start_with?(a) }
91
91
  return nil
92
92
  end
93
93
 
@@ -98,42 +98,44 @@ module Sisimai
98
98
  def field(argv0 = '')
99
99
  return nil if argv0.empty?
100
100
  group = FieldGroup[argv0.split(':',2).shift.downcase] || ''
101
- match = []
102
101
 
103
102
  return nil if group.empty?
104
103
  return nil unless CapturesOn[group]
105
104
 
105
+ table = ['', '', '', '']
106
+ match = false
106
107
  while cv = argv0.match(CapturesOn[group])
107
108
  # Try to match with each pattern of Per-Message field, Per-Recipient field
108
- # - 0: Field-Name
109
- # - 1: Sub Type: RFC822, DNS, X-Unix, and so on)
110
- # - 2: Value
111
- # - 3: Field Group(addr, code, date, host, stat, text)
112
- match[0] = cv[1].downcase
113
- match[3] = group
109
+ # - 0: Field-Name
110
+ # - 1: Sub Type: RFC822, DNS, X-Unix, and so on)
111
+ # - 2: Value
112
+ # - 3: Field Group(addr, code, date, host, stat, text)
113
+ match = true
114
+ table[0] = cv[1].downcase
115
+ table[3] = group
114
116
 
115
117
  if group == 'addr' || group == 'code' || group == 'host'
116
118
  # - Final-Recipient: RFC822; kijitora@nyaan.jp
117
119
  # - Diagnostic-Code: SMTP; 550 5.1.1 <kijitora@example.jp>... User Unknown
118
120
  # - Remote-MTA: DNS; mx.example.jp
119
- match[1] = cv[2].upcase
120
- match[2] = group == 'host' ? cv[3].downcase : cv[3]
121
- match[2] = '' if match[2] =~ /\A\s+\z/ # Remote-MTA: dns;
121
+ table[1] = cv[2].upcase
122
+ table[2] = group == 'host' ? cv[3].downcase : cv[3]
123
+ table[2] = '' if table[2] =~ /\A\s+\z/ # Remote-MTA: dns;
122
124
  else
123
125
  # - Action: failed
124
126
  # - Status: 5.2.2
125
- match[1] = ''
126
- match[2] = group == 'date' ? cv[2] : cv[2].downcase
127
+ table[1] = ''
128
+ table[2] = group == 'date' ? cv[2] : cv[2].downcase
127
129
 
128
130
  # Correct invalid value in Action field:
129
131
  break unless group == 'list'
130
- break unless Correction[:action][match[2]]
131
- match[2] = Correction[:action][match[2]]
132
+ break unless Correction[:action][table[2]]
133
+ table[2] = Correction[:action][table[2]]
132
134
  end
133
135
  break
134
136
  end
135
- return nil if match.empty?
136
- return match
137
+ return nil unless match
138
+ return table
137
139
  end
138
140
 
139
141
  end
@@ -174,7 +174,7 @@ module Sisimai
174
174
  maybealias = cv[2]
175
175
  else
176
176
  # Final-Recipient: ...
177
- x = v['recipienet'] || ''
177
+ x = v['recipient'] || ''
178
178
  y = Sisimai::Address.s3s4(cv[2])
179
179
  y = maybealias unless Sisimai::RFC5322.is_emailaddress(y)
180
180
 
@@ -99,7 +99,7 @@ module Sisimai
99
99
  if mhead['content-type']
100
100
  # Get the boundary string and set regular expression for matching with
101
101
  # the boundary string.
102
- b0 = Sisimai::MIME.boundary(mhead['content-type'], 0)
102
+ b0 = Sisimai::MIME.boundary(mhead['content-type'], 0) || ''
103
103
  MarkingsOf[:boundary] = %r/\A\Q#{b0}\E\z/ unless b0.empty?
104
104
  end
105
105
 
@@ -64,7 +64,7 @@ module Sisimai
64
64
  # Fields that might be long
65
65
  # @return [Hash] Long filed(email header) list
66
66
  def LONGFIELDS
67
- return { 'to' => 1, 'from' => 1, 'subject' => 1, 'message-id' => 1 }
67
+ return { 'to' => true, 'from' => true, 'subject' => true, 'message-id' => true }
68
68
  end
69
69
 
70
70
  # Check that the argument is an email address or not
@@ -191,8 +191,13 @@ module Sisimai
191
191
  v[1] ||= ''
192
192
 
193
193
  unless v[1].empty?
194
- v[1].sub(/\A[\r\n\s]+/, '')
195
- v[1].sub(/\n\n.+\z/m, '')
194
+ # Remove blank lines, the message body of the original message, and append "\n" at the end
195
+ # of the original message headers
196
+ # 1. Remove leading blank lines
197
+ # 2. Remove text after the first blank line: \n\n
198
+ # 3. Append "\n" at the end of test block when the last character is not "\n"
199
+ v[1].sub!(/\A[\r\n\s]+/, '')
200
+ v[1] = v[1][0, v[1].index("\n\n")] if v[1].include?("\n\n")
196
201
  v[1] << "\n" unless v[1].end_with?("\n")
197
202
  end
198
203
  return v
data/lib/sisimai/rhost.rb CHANGED
@@ -59,6 +59,7 @@ module Sisimai
59
59
  rhostclass = modulename.gsub('::', '/').downcase
60
60
  break
61
61
  end
62
+ return nil if rhostclass.empty?
62
63
 
63
64
  require rhostclass
64
65
  reasontext = Module.const_get(modulename).get(argvs)
@@ -22,6 +22,7 @@ module Sisimai
22
22
  '5.2.2' => [{ reason: 'mailboxfull', string: 'Mailbox full' }],
23
23
  '5.2.3' => [{ reason: 'exceedlimit', string: 'Message too large' }],
24
24
  '5.2.4' => [{ reason: 'systemerror', string: 'Mailing list expansion problem' }],
25
+ '5.2.14' => [{ reason: 'systemerror', string: 'misconfigured forwarding address' }],
25
26
  '5.2.122' => [{ reason: 'toomanyconn' ,string: 'The recipient has exceeded their limit for' }],
26
27
  '5.3.3' => [{ reason: 'systemfull', string: 'Unrecognized command' }],
27
28
  '5.3.4' => [{ reason: 'mesgtoobig', string: 'Message too big for system' }],
@@ -29,6 +30,7 @@ module Sisimai
29
30
  '5.4.1' => [{ reason: 'rejected', string: 'Recipient address rejected: Access denied' }],
30
31
  '5.4.11' => [{ reason: 'contenterror',string: 'Agent generated message depth exceeded' }],
31
32
  '5.4.14' => [{ reason: 'networkerror',string: 'Hop count exceeded' }],
33
+ '5.4.310' => [{ reason: 'systemerror', string: 'does not exist' }], # DNS domain * does not exist
32
34
  '5.5.2' => [{ reason: 'syntaxerror', string: 'Send hello first' }],
33
35
  '5.5.3' => [{ reason: 'syntaxerror', string: 'Too many recipients' }],
34
36
  '5.5.4' => [{ reason: 'filtered', string: 'Invalid domain name' }],
@@ -100,7 +102,12 @@ module Sisimai
100
102
  'networkerror' => ['SMTPSEND.DNS.MxLoopback'],
101
103
  'rejected' => ['RESOLVER.RST.NotAuthorized'],
102
104
  'securityerror' => ['RESOLVER.RST.AuthRequired'],
103
- 'systemerror' => ['RESOLVER.ADR.Ambiguous', 'RESOLVER.ADR.BadPrimary', 'RESOLVER.ADR.InvalidInSmtp'],
105
+ 'systemerror' => [
106
+ 'RESOLVER.ADR.Ambiguous',
107
+ 'RESOLVER.ADR.BadPrimary',
108
+ 'RESOLVER.ADR.InvalidInSmtp',
109
+ 'RESOLVER.FWD.NotFound',
110
+ ],
104
111
  'toomanyconn' => ['RESOLVER.ADR.RecipLimit', 'RESOLVER.ADR.RecipientLimit'],
105
112
  'userunknown' => [
106
113
  'RESOLVER.ADR.RecipNotFound',
@@ -24,27 +24,28 @@ module Sisimai
24
24
  # nil: is not an error
25
25
  # @since v4.17.3
26
26
  def is_permanent(argv1 = '')
27
- getchecked = nil
27
+ return nil unless argv1
28
+ permanent1 = nil
28
29
  statuscode = Sisimai::SMTP::Status.find(argv1) || Sisimai::SMTP::Reply.find(argv1) || '0'
29
30
 
30
31
  if (classvalue = statuscode[0, 1].to_i) > 0
31
32
  # 2, 4, or 5
32
33
  if classvalue == 5
33
34
  # Permanent error
34
- getchecked = true
35
+ permanent1 = true
35
36
 
36
37
  elsif classvalue == 4
37
38
  # Temporary error
38
- getchecked = false
39
+ permanent1 = false
39
40
 
40
41
  elsif classvalue == 2
41
42
  # Succeeded
42
- getchecked = nil
43
+ permanent1 = nil
43
44
  end
44
45
  else
45
46
  # Check with regular expression
46
47
  v = argv1.downcase
47
- getchecked = if v.include?('temporar') || v.include?('persistent')
48
+ permanent1 = if v.include?('temporar') || v.include?('persistent')
48
49
  # Temporary failure
49
50
  false
50
51
  elsif v.include?('permanent')
@@ -53,7 +54,7 @@ module Sisimai
53
54
  end
54
55
  end
55
56
 
56
- return getchecked
57
+ return permanent1
57
58
  end
58
59
 
59
60
  # Check softbounce or not
@@ -64,6 +65,7 @@ module Sisimai
64
65
  # '': May not be bounce ?
65
66
  # @since v4.17.3
66
67
  def soft_or_hard(argv1 = '', argv2 = '')
68
+ return nil unless argv1
67
69
  return nil if argv1.empty?
68
70
  value = nil
69
71