sisimai 4.22.3 → 4.22.4

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Benchmarks.mk +54 -0
  4. data/ChangeLog.md +23 -2
  5. data/Developers.mk +42 -35
  6. data/Makefile +10 -0
  7. data/README-JA.md +13 -13
  8. data/README.md +14 -14
  9. data/lib/sisimai.rb +12 -18
  10. data/lib/sisimai/address.rb +64 -82
  11. data/lib/sisimai/arf.rb +27 -42
  12. data/lib/sisimai/bite/email.rb +2 -4
  13. data/lib/sisimai/bite/email/activehunter.rb +12 -17
  14. data/lib/sisimai/bite/email/amazonses.rb +30 -48
  15. data/lib/sisimai/bite/email/amazonworkmail.rb +20 -27
  16. data/lib/sisimai/bite/email/aol.rb +27 -35
  17. data/lib/sisimai/bite/email/apachejames.rb +17 -28
  18. data/lib/sisimai/bite/email/bigfoot.rb +20 -33
  19. data/lib/sisimai/bite/email/biglobe.rb +15 -24
  20. data/lib/sisimai/bite/email/courier.rb +37 -61
  21. data/lib/sisimai/bite/email/domino.rb +19 -28
  22. data/lib/sisimai/bite/email/einsundeins.rb +20 -34
  23. data/lib/sisimai/bite/email/exchange2003.rb +25 -43
  24. data/lib/sisimai/bite/email/exchange2007.rb +15 -23
  25. data/lib/sisimai/bite/email/exim.rb +101 -120
  26. data/lib/sisimai/bite/email/ezweb.rb +28 -44
  27. data/lib/sisimai/bite/email/facebook.rb +26 -37
  28. data/lib/sisimai/bite/email/fml.rb +11 -20
  29. data/lib/sisimai/bite/email/gmx.rb +17 -27
  30. data/lib/sisimai/bite/email/google.rb +19 -29
  31. data/lib/sisimai/bite/email/gsuite.rb +39 -48
  32. data/lib/sisimai/bite/email/imailserver.rb +25 -39
  33. data/lib/sisimai/bite/email/interscanmss.rb +19 -26
  34. data/lib/sisimai/bite/email/kddi.rb +20 -33
  35. data/lib/sisimai/bite/email/mailfoundry.rb +14 -24
  36. data/lib/sisimai/bite/email/mailmarshalsmtp.rb +15 -24
  37. data/lib/sisimai/bite/email/mailru.rb +40 -59
  38. data/lib/sisimai/bite/email/mcafee.rb +21 -35
  39. data/lib/sisimai/bite/email/messagelabs.rb +23 -38
  40. data/lib/sisimai/bite/email/messagingserver.rb +15 -27
  41. data/lib/sisimai/bite/email/mfilter.rb +19 -28
  42. data/lib/sisimai/bite/email/mxlogic.rb +31 -49
  43. data/lib/sisimai/bite/email/notes.rb +16 -24
  44. data/lib/sisimai/bite/email/office365.rb +29 -38
  45. data/lib/sisimai/bite/email/opensmtpd.rb +50 -67
  46. data/lib/sisimai/bite/email/outlook.rb +24 -36
  47. data/lib/sisimai/bite/email/postfix.rb +33 -42
  48. data/lib/sisimai/bite/email/qmail.rb +44 -59
  49. data/lib/sisimai/bite/email/receivingses.rb +28 -36
  50. data/lib/sisimai/bite/email/sendgrid.rb +28 -37
  51. data/lib/sisimai/bite/email/sendmail.rb +35 -51
  52. data/lib/sisimai/bite/email/surfcontrol.rb +17 -25
  53. data/lib/sisimai/bite/email/userdefined.rb +17 -28
  54. data/lib/sisimai/bite/email/v5sendmail.rb +32 -41
  55. data/lib/sisimai/bite/email/verizon.rb +31 -56
  56. data/lib/sisimai/bite/email/x1.rb +11 -18
  57. data/lib/sisimai/bite/email/x2.rb +11 -23
  58. data/lib/sisimai/bite/email/x3.rb +10 -19
  59. data/lib/sisimai/bite/email/x4.rb +46 -65
  60. data/lib/sisimai/bite/email/x5.rb +26 -37
  61. data/lib/sisimai/bite/email/yahoo.rb +11 -19
  62. data/lib/sisimai/bite/email/yandex.rb +19 -30
  63. data/lib/sisimai/bite/email/zoho.rb +21 -30
  64. data/lib/sisimai/bite/json.rb +1 -2
  65. data/lib/sisimai/bite/json/amazonses.rb +20 -25
  66. data/lib/sisimai/bite/json/sendgrid.rb +1 -1
  67. data/lib/sisimai/data.rb +36 -55
  68. data/lib/sisimai/data/json.rb +3 -3
  69. data/lib/sisimai/data/yaml.rb +1 -1
  70. data/lib/sisimai/datetime.rb +5 -21
  71. data/lib/sisimai/mail.rb +4 -6
  72. data/lib/sisimai/mail/maildir.rb +1 -1
  73. data/lib/sisimai/mda.rb +41 -44
  74. data/lib/sisimai/message.rb +2 -3
  75. data/lib/sisimai/message/email.rb +42 -52
  76. data/lib/sisimai/message/json.rb +7 -7
  77. data/lib/sisimai/mime.rb +25 -23
  78. data/lib/sisimai/order/email.rb +2 -2
  79. data/lib/sisimai/order/json.rb +2 -7
  80. data/lib/sisimai/reason.rb +41 -46
  81. data/lib/sisimai/reason/blocked.rb +60 -71
  82. data/lib/sisimai/reason/contenterror.rb +4 -8
  83. data/lib/sisimai/reason/delivered.rb +1 -3
  84. data/lib/sisimai/reason/exceedlimit.rb +10 -20
  85. data/lib/sisimai/reason/expired.rb +5 -9
  86. data/lib/sisimai/reason/feedback.rb +1 -3
  87. data/lib/sisimai/reason/filtered.rb +19 -38
  88. data/lib/sisimai/reason/hasmoved.rb +5 -8
  89. data/lib/sisimai/reason/hostunknown.rb +11 -18
  90. data/lib/sisimai/reason/mailboxfull.rb +14 -24
  91. data/lib/sisimai/reason/mailererror.rb +3 -5
  92. data/lib/sisimai/reason/mesgtoobig.rb +15 -25
  93. data/lib/sisimai/reason/networkerror.rb +8 -10
  94. data/lib/sisimai/reason/norelaying.rb +9 -14
  95. data/lib/sisimai/reason/notaccept.rb +9 -21
  96. data/lib/sisimai/reason/onhold.rb +3 -8
  97. data/lib/sisimai/reason/policyviolation.rb +8 -10
  98. data/lib/sisimai/reason/rejected.rb +36 -49
  99. data/lib/sisimai/reason/securityerror.rb +11 -13
  100. data/lib/sisimai/reason/spamdetected.rb +23 -37
  101. data/lib/sisimai/reason/suspend.rb +9 -10
  102. data/lib/sisimai/reason/syntaxerror.rb +3 -4
  103. data/lib/sisimai/reason/systemerror.rb +7 -9
  104. data/lib/sisimai/reason/systemfull.rb +2 -4
  105. data/lib/sisimai/reason/toomanyconn.rb +17 -30
  106. data/lib/sisimai/reason/undefined.rb +1 -3
  107. data/lib/sisimai/reason/userunknown.rb +28 -38
  108. data/lib/sisimai/reason/vacation.rb +4 -6
  109. data/lib/sisimai/reason/virusdetected.rb +4 -6
  110. data/lib/sisimai/rfc2606.rb +1 -2
  111. data/lib/sisimai/rfc3464.rb +87 -101
  112. data/lib/sisimai/rfc3834.rb +29 -39
  113. data/lib/sisimai/rfc5322.rb +17 -24
  114. data/lib/sisimai/rhost.rb +10 -7
  115. data/lib/sisimai/rhost/exchangeonline.rb +124 -255
  116. data/lib/sisimai/rhost/franceptt.rb +2 -2
  117. data/lib/sisimai/rhost/godaddy.rb +12 -25
  118. data/lib/sisimai/rhost/googleapps.rb +82 -183
  119. data/lib/sisimai/smtp.rb +4 -4
  120. data/lib/sisimai/smtp/error.rb +8 -8
  121. data/lib/sisimai/smtp/reply.rb +1 -1
  122. data/lib/sisimai/smtp/status.rb +1 -0
  123. data/lib/sisimai/string.rb +5 -7
  124. data/lib/sisimai/version.rb +1 -1
  125. data/set-of-emails/README.md +1 -1
  126. data/set-of-emails/maildir/bsd/README.md +50 -50
  127. data/sisimai-java.gemspec +1 -1
  128. data/sisimai.gemspec +1 -1
  129. metadata +5 -5
  130. data/lib/sisimai/skeleton.rb +0 -43
@@ -58,7 +58,7 @@ module Sisimai
58
58
  modulelist = []
59
59
  tobeloaded = []
60
60
 
61
- %w|load order|.each do |e|
61
+ %w[load order].each do |e|
62
62
  # The order of MTA(JSON) modules specified by user
63
63
  next unless argvs.key?(e)
64
64
  next unless argvs[e].is_a? Array
@@ -73,7 +73,7 @@ module Sisimai
73
73
  begin
74
74
  require v.to_s.gsub('::', '/').downcase
75
75
  rescue LoadError
76
- warn ' ***warning: Failed to load ' + v
76
+ warn ' ***warning: Failed to load ' << v
77
77
  next
78
78
  end
79
79
  tobeloaded << v
@@ -134,12 +134,12 @@ module Sisimai
134
134
  }
135
135
  havecaught = hookmethod.call(p)
136
136
  rescue StandardError => ce
137
- warn sprintf(' ***warning: Something is wrong in hook method :%s', ce.to_s)
137
+ warn ' ***warning: Something is wrong in hook method :' << ce.to_s
138
138
  end
139
139
  end
140
140
 
141
141
  catch :ADAPTOR do
142
- loop do
142
+ while true
143
143
  # 1. User-Defined Module
144
144
  # 2. MTA(JSON) Module Candidates to be tried on first
145
145
  # 3. Sisimai::Bite::JSON::*
@@ -150,7 +150,7 @@ module Sisimai
150
150
  begin
151
151
  require r.gsub('::', '/').downcase
152
152
  rescue LoadError => ce
153
- warn ' ***warning: Failed to load ' + ce.to_s
153
+ warn ' ***warning: Failed to load ' << ce.to_s
154
154
  next
155
155
  end
156
156
  hasadapted = Module.const_get(r).adapt(bouncedata)
@@ -165,7 +165,7 @@ module Sisimai
165
165
  begin
166
166
  require r.gsub('::', '/').downcase
167
167
  rescue LoadError => ce
168
- warn ' ***warning: ' + ce.to_s
168
+ warn ' ***warning: ' << ce.to_s
169
169
  next
170
170
  end
171
171
  hasadapted = Module.const_get(r).adapt(bouncedata)
@@ -179,7 +179,7 @@ module Sisimai
179
179
  begin
180
180
  require r.gsub('::', '/').downcase
181
181
  rescue => ce
182
- warn ' ***warning: ' + ce.to_s
182
+ warn ' ***warning: ' << ce.to_s
183
183
  next
184
184
  end
185
185
 
@@ -7,12 +7,12 @@ module Sisimai
7
7
  require 'sisimai/string'
8
8
 
9
9
  ReE = {
10
- :'7bit-encoded' => %r/^Content-Transfer-Encoding:[ ]*7bit$/im,
11
- :'quoted-print' => %r/^Content-Transfer-Encoding:[ ]*quoted-printable$/im,
12
- :'some-iso2022' => %r/^Content-Type:[ ]*.+;[ ]*charset=["']?(iso-2022-[-a-z0-9]+?)['"]?$/im,
13
- :'with-charset' => %r/^Content[-]Type:[ ]*.+[;][ ]*charset=['"]?(.+?)['"]?$/i,
14
- :'only-charset' => %r/^[\s\t]+charset=['"]?(.+?)['"]?$/i,
15
- :'html-message' => %r|^Content-Type:[ ]*text/html;|mi,
10
+ :'7bit-encoded' => %r/^content-transfer-encoding:[ ]*7bit$/m,
11
+ :'quoted-print' => %r/^content-transfer-encoding:[ ]*quoted-printable$/m,
12
+ :'some-iso2022' => %r/^content-type:[ ]*.+;[ ]*charset=["']?(iso-2022-[-a-z0-9]+?)['"]?$/m,
13
+ :'with-charset' => %r/^content[-]type:[ ]*.+[;][ ]*charset=['"]?(.+?)['"]?$/,
14
+ :'only-charset' => %r/^[\s\t]+charset=['"]?(.+?)['"]?$/,
15
+ :'html-message' => %r|^content-type:[ ]*text/html;|m,
16
16
  }.freeze
17
17
 
18
18
  # Make MIME-Encoding and Content-Type related headers regurlar expression
@@ -32,14 +32,14 @@ module Sisimai
32
32
  piece = []
33
33
  mime1 = false
34
34
 
35
- if argv1 =~ /[ ]/
35
+ if argv1.include?(' ')
36
36
  # Multiple MIME-Encoded strings in a line
37
37
  piece = argv1.split(' ')
38
38
  else
39
39
  piece << argv1
40
40
  end
41
41
 
42
- piece.each do |e|
42
+ while e = piece.shift do
43
43
  # Check all the string in the array
44
44
  next unless e =~ /[ \t]*=[?][-_0-9A-Za-z]+[?][BbQq][?].+[?]=?[ \t]*/
45
45
  mime1 = true
@@ -58,7 +58,6 @@ module Sisimai
58
58
  encodingname = nil
59
59
  mimeencoded0 = nil
60
60
  decodedtext0 = []
61
-
62
61
  notmimetext0 = ''
63
62
  notmimetext1 = ''
64
63
 
@@ -129,22 +128,24 @@ module Sisimai
129
128
  # or "Content-Transfer-Encoding: quoted-printable" are not included in
130
129
  # the message body.
131
130
  return argv1.unpack('M').first if boundary00.size.zero?
132
- return argv1.unpack('M').first unless argv1 =~ ReE[:'quoted-print']
131
+ return argv1.unpack('M').first unless argv1.downcase =~ ReE[:'quoted-print']
133
132
 
134
133
  boundary01 = Sisimai::MIME.boundary(heads['content-type'], 1)
135
134
  reboundary = {
136
- :begin => Regexp.new('\A' + Regexp.escape(boundary00)),
137
- :until => Regexp.new(Regexp.escape(boundary01) + '\z')
135
+ :begin => Regexp.new('\A' << Regexp.escape(boundary00)),
136
+ :until => Regexp.new(Regexp.escape(boundary01) << '\z')
138
137
  }
139
138
  bodystring = ''
140
139
  notdecoded = ''
141
140
  getencoded = ''
141
+ lowercased = ''
142
142
 
143
143
  encodename = nil
144
144
  ctencoding = nil
145
145
  mimeinside = false
146
+ hasdivided = argv1.split("\n")
146
147
 
147
- argv1.split("\n").each do |e|
148
+ while e = hasdivided.shift do
148
149
  # This is a multi-part message in MIME format. Your mail reader does not
149
150
  # understand MIME message format.
150
151
  # --=_gy7C4Gpes0RP4V5Bs9cK4o2Us2ZT57b-3OLnRN+4klS8dTmQ
@@ -157,8 +158,8 @@ module Sisimai
157
158
  # --=_gy7C4Gpes0RP4V5Bs9cK4o2Us2ZT57b-3OLnRN+4klS8dTmQ
158
159
  getencoded = Sisimai::String.to_utf8(notdecoded.unpack('M').first, encodename)
159
160
 
160
- bodystring += getencoded
161
- bodystring += e + "\n"
161
+ bodystring << getencoded
162
+ bodystring << e + "\n"
162
163
 
163
164
  notdecoded = ''
164
165
  mimeinside = false
@@ -166,10 +167,11 @@ module Sisimai
166
167
  encodename = nil
167
168
  else
168
169
  # Inside of Queoted printable encoded text
169
- notdecoded += e + "\n"
170
+ notdecoded << e + "\n"
170
171
  end
171
172
  else
172
173
  # NOT Quoted-Printable encoded text block
174
+ lowercased = e.downcase
173
175
  if e =~ /\A[-]{2}[^\s]+[^-]\z/
174
176
  # Start of the boundary block
175
177
  # --=_gy7C4Gpes0RP4V5Bs9cK4o2Us2ZT57b-3OLnRN+4klS8dTmQ
@@ -178,16 +180,16 @@ module Sisimai
178
180
  boundary00 = e
179
181
  boundary01 = e + '--'
180
182
  reboundary = {
181
- :begin => Regexp.new('\A' + Regexp.escape(boundary00)),
182
- :until => Regexp.new(Regexp.escape(boundary01) + '\z')
183
+ :begin => Regexp.new('\A' << Regexp.escape(boundary00)),
184
+ :until => Regexp.new(Regexp.escape(boundary01) << '\z')
183
185
  }
184
186
  end
185
- elsif cv = e.match(ReE[:'with-charset']) || e.match(ReE[:'only-charset'])
187
+ elsif cv = lowercased.match(ReE[:'with-charset']) || lowercased.match(ReE[:'only-charset'])
186
188
  # Content-Type: text/plain; charset=ISO-2022-JP
187
189
  encodename = cv[1]
188
190
  mimeinside = true if ctencoding
189
191
 
190
- elsif e =~ ReE[:'quoted-print']
192
+ elsif lowercased =~ ReE[:'quoted-print']
191
193
  # Content-Transfer-Encoding: quoted-printable
192
194
  ctencoding = true
193
195
  mimeinside = true if encodename
@@ -198,7 +200,7 @@ module Sisimai
198
200
  mimeinside = false
199
201
  end
200
202
 
201
- bodystring += e + "\n"
203
+ bodystring << e + "\n"
202
204
  end
203
205
  end
204
206
 
@@ -235,8 +237,8 @@ module Sisimai
235
237
  # boundary="n6H9lKZh014511.1247824040/mx.example.jp"
236
238
  value = cv[1]
237
239
  value = value.delete(%q|'"|)
238
- value = sprintf('--%s', value) if start > -1
239
- value = sprintf('%s--', value) if start > 0
240
+ value = '--' + value if start > -1
241
+ value = value + '--' if start > 0
240
242
  end
241
243
 
242
244
  return value
@@ -154,7 +154,7 @@ module Sisimai
154
154
  # Make default order of MTA modules to be loaded
155
155
  rv = []
156
156
  begin
157
- rv.concat(Sisimai::Bite::Email.index.map { |e| 'Sisimai::Bite::Email::' + e })
157
+ rv.concat(Sisimai::Bite::Email.index.map { |e| 'Sisimai::Bite::Email::' << e })
158
158
  rescue
159
159
  # Failed to load an MTA module
160
160
  next
@@ -203,7 +203,7 @@ module Sisimai
203
203
  begin
204
204
  require e.gsub('::', '/').downcase
205
205
  rescue LoadError
206
- warn ' ***warning: Failed to load ' + e
206
+ warn ' ***warning: Failed to load ' << e
207
207
  next
208
208
  end
209
209
 
@@ -8,18 +8,14 @@ module Sisimai
8
8
  require 'sisimai/bite/json'
9
9
 
10
10
  PatternTable = {
11
- 'keyname' => {
12
- 'notificationType' => [
13
- 'Sisimai::Bite::JSON::AmazonSES',
14
- ],
15
- },
11
+ 'keyname' => { 'notificationType' => ['Sisimai::Bite::JSON::AmazonSES'] },
16
12
  }.freeze
17
13
 
18
14
  make_default_order = lambda do
19
15
  # Make default order of MTA(JSON) modules to be loaded
20
16
  rv = []
21
17
  begin
22
- rv.concat(Sisimai::Bite::JSON.index.map { |e| 'Sisimai::Bite::JSON::' + e })
18
+ rv.concat(Sisimai::Bite::JSON.index.map { |e| 'Sisimai::Bite::JSON::' << e })
23
19
  rescue
24
20
  # Failed to load MTA(JSON) module
25
21
  next
@@ -54,4 +50,3 @@ module Sisimai
54
50
  end
55
51
  end
56
52
 
57
-
@@ -8,12 +8,26 @@ module Sisimai
8
8
  # Reason list better to retry detecting an error reason
9
9
  # @return [Array] Reason list
10
10
  def retry
11
- return %w|
12
- undefined onhold systemerror securityerror networkerror
13
- hostunknown userunknown
14
- |
11
+ return %w[undefined onhold systemerror securityerror networkerror hostunknown userunknown]
15
12
  end
16
- RetryReasons = Sisimai::Reason.retry
13
+ GetRetried = Sisimai::Reason.retry
14
+ ClassOrder = [
15
+ %w[
16
+ MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying UserUnknown
17
+ Filtered Rejected HostUnknown SpamDetected TooManyConn Blocked
18
+ ],
19
+ %w[
20
+ MailboxFull SpamDetected PolicyViolation VirusDetected SecurityError
21
+ SystemError NetworkError Suspend Expired ContentError SystemFull
22
+ NotAccept MailerError
23
+ ],
24
+ %w[
25
+ MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected
26
+ HostUnknown SpamDetected TooManyConn Blocked SpamDetected SecurityError
27
+ SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull
28
+ NotAccept MailerError NoRelaying SyntaxError OnHold
29
+ ]
30
+ ]
17
31
 
18
32
  # All the error reason list Sisimai support
19
33
  # @return [Array] Reason list
@@ -35,7 +49,7 @@ module Sisimai
35
49
  return nil unless argvs
36
50
  return nil unless argvs.is_a? Sisimai::Data
37
51
 
38
- unless RetryReasons.index(argvs.reason)
52
+ unless GetRetried.index(argvs.reason)
39
53
  # Return reason text already decided except reason match with the
40
54
  # regular expression of ->retry() method.
41
55
  return argvs.reason if argvs.reason.size > 0
@@ -43,24 +57,20 @@ module Sisimai
43
57
 
44
58
  statuscode = argvs.deliverystatus || ''
45
59
  reasontext = ''
46
- classorder = %w|
47
- MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying UserUnknown
48
- Filtered Rejected HostUnknown SpamDetected TooManyConn Blocked
49
- |
50
- return 'delivered' if statuscode =~ /\A2[.]/
60
+ return 'delivered' if statuscode.start_with?('2.')
51
61
 
52
62
  if argvs.diagnostictype == 'SMTP' || argvs.diagnostictype == ''
53
63
  # Diagnostic-Code: SMTP; ... or empty value
54
- classorder.each do |e|
64
+ ClassOrder[0].each do |e|
55
65
  # Check the value of Diagnostic-Code: and the value of Status:, it is a
56
66
  # deliverystats, with true() method in each Sisimai::Reason::* class.
57
- p = 'Sisimai::Reason::' + e
67
+ p = 'Sisimai::Reason::' << e
58
68
  r = nil
59
69
  begin
60
70
  require p.downcase.gsub('::', '/')
61
71
  r = Module.const_get(p)
62
72
  rescue
63
- warn ' ***warning: Failed to load ' + p
73
+ warn ' ***warning: Failed to load ' << p
64
74
  next
65
75
  end
66
76
  next unless r.true(argvs)
@@ -80,9 +90,9 @@ module Sisimai
80
90
  unless reasontext
81
91
  # Try to match with message patterns in Sisimai::Reason::Vacation
82
92
  require 'sisimai/reason/vacation'
83
- reasontext = 'vacation' if Sisimai::Reason::Vacation.match(argvs.diagnosticcode)
93
+ reasontext = 'vacation' if Sisimai::Reason::Vacation.match(argvs.diagnosticcode.downcase)
84
94
  end
85
- reasontext ||= 'onhold' if argvs.diagnosticcode.size > 0
95
+ reasontext ||= 'onhold' if argvs.diagnosticcode.size > 0
86
96
  end
87
97
  reasontext ||= 'undefined'
88
98
  end
@@ -100,36 +110,31 @@ module Sisimai
100
110
  return argvs.reason if argvs.reason.size > 0
101
111
 
102
112
  statuscode = argvs.deliverystatus || ''
103
- diagnostic = argvs.diagnosticcode || ''
113
+ diagnostic = argvs.diagnosticcode.downcase || ''
104
114
  commandtxt = argvs.smtpcommand || ''
105
115
  trytomatch = nil
106
116
  reasontext = ''
107
- classorder = %w|
108
- MailboxFull SpamDetected PolicyViolation VirusDetected SecurityError
109
- SystemError NetworkError Suspend Expired ContentError SystemFull
110
- NotAccept MailerError
111
- |
112
117
 
113
118
  require 'sisimai/smtp/status'
114
119
  reasontext = Sisimai::SMTP::Status.name(statuscode)
115
120
 
116
121
  catch :TRY_TO_MATCH do
117
- loop do
122
+ while true
118
123
  trytomatch ||= true if reasontext.empty?
119
- trytomatch ||= true if RetryReasons.index(reasontext)
124
+ trytomatch ||= true if GetRetried.index(reasontext)
120
125
  trytomatch ||= true if argvs.diagnostictype != 'SMTP'
121
126
  throw :TRY_TO_MATCH unless trytomatch
122
127
 
123
128
  # Could not decide the reason by the value of Status:
124
- classorder.each do |e|
129
+ ClassOrder[1].each do |e|
125
130
  # Trying to match with other patterns in Sisimai::Reason::* classes
126
- p = 'Sisimai::Reason::' + e
131
+ p = 'Sisimai::Reason::' << e
127
132
  r = nil
128
133
  begin
129
134
  require p.downcase.gsub('::', '/')
130
135
  r = Module.const_get(p)
131
136
  rescue
132
- warn ' ***warning: Failed to load ' + p
137
+ warn ' ***warning: Failed to load ' << p
133
138
  next
134
139
  end
135
140
 
@@ -149,10 +154,9 @@ module Sisimai
149
154
  # X.7.0 Other or undefined security status
150
155
  reasontext = 'securityerror'
151
156
 
152
- elsif argvs.diagnostictype =~ /\AX-(?:UNIX|POSTFIX)\z/
157
+ elsif %w[X-UNIX X-POSTFIX].include?(argvs.diagnostictype)
153
158
  # Diagnostic-Code: X-UNIX; ...
154
159
  reasontext = 'mailererror'
155
-
156
160
  else
157
161
  # 50X Syntax Error?
158
162
  require 'sisimai/reason/syntaxerror'
@@ -162,16 +166,12 @@ module Sisimai
162
166
 
163
167
  if reasontext.empty?
164
168
  # Check the value of Action: field, first
165
- if argvs.action =~ /\A(?:delayed|expired)/
169
+ if argvs.action.start_with?('delayed', 'expired')
166
170
  # Action: delayed, expired
167
171
  reasontext = 'expired'
168
-
169
172
  else
170
- # Check the value of SMTP command
171
- if commandtxt =~ /\A(?:EHLO|HELO)\z/
172
- # Rejected at connection or after EHLO|HELO
173
- reasontext = 'blocked'
174
- end
173
+ # Rejected at connection or after EHLO|HELO
174
+ reasontext = 'blocked' if %w[HELO EHLO].index(commandtxt)
175
175
  end
176
176
  end
177
177
 
@@ -190,12 +190,7 @@ module Sisimai
190
190
 
191
191
  reasontext = ''
192
192
  typestring = ''
193
- classorder = %w|
194
- MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected
195
- HostUnknown SpamDetected TooManyConn Blocked SpamDetected SecurityError
196
- SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull
197
- NotAccept MailerError NoRelaying SyntaxError OnHold
198
- |
193
+ diagnostic = argv1.downcase
199
194
 
200
195
  statuscode = Sisimai::SMTP::Status.find(argv1)
201
196
  if cv = argv1.match(/\A(SMTP|X-.+);/i)
@@ -203,20 +198,20 @@ module Sisimai
203
198
  end
204
199
 
205
200
  # Diagnostic-Code: SMTP; ... or empty value
206
- classorder.each do |e|
201
+ ClassOrder[2].each do |e|
207
202
  # Check the value of Diagnostic-Code: and the value of Status:, it is a
208
203
  # deliverystats, with true() method in each Sisimai::Reason::* class.
209
- p = 'Sisimai::Reason::' + e
204
+ p = 'Sisimai::Reason::' << e
210
205
  r = nil
211
206
  begin
212
207
  require p.downcase.gsub('::', '/')
213
208
  r = Module.const_get(p)
214
209
  rescue
215
- warn ' ***warning: Failed to load ' + p
210
+ warn ' ***warning: Failed to load ' << p
216
211
  next
217
212
  end
218
213
 
219
- next unless r.match(argv1)
214
+ next unless r.match(diagnostic)
220
215
  reasontext = r.text
221
216
  break
222
217
  end
@@ -10,9 +10,7 @@ module Sisimai
10
10
  # Imported from p5-Sisimail/lib/Sisimai/Reason/Blocked.pm
11
11
  class << self
12
12
  def text; return 'blocked'; end
13
- def description
14
- return 'Email rejected due to client IP address or a hostname'
15
- end
13
+ def description; return 'Email rejected due to client IP address or a hostname'; end
16
14
 
17
15
  # Try to match that the given text and regular expressions
18
16
  # @param [String] argv1 String to be matched with regular expressions
@@ -21,18 +19,21 @@ module Sisimai
21
19
  def match(argv1)
22
20
  return nil unless argv1
23
21
  regex = %r{(?>
24
- access[ ]denied[.][ ]IP[ ]name[ ]lookup[ ]failed
22
+ access[ ]denied[.][ ]ip[ ]name[ ]lookup[ ]failed
25
23
  |access[ ]from[ ]ip[ ]address[ ].+[ ]blocked
26
- |all[ ]mail[ ]servers[ ]must[ ]have[ ]a[ ]PTR[ ]record[ ]with[ ]a[ ]valid[ ]Reverse[ ]DNS[ ]entry
27
- |Bad[ ]sender[ ]IP[ ]address
24
+ |all[ ]mail[ ]servers[ ]must[ ]have[ ]a[ ]ptr[ ]record[ ]with[ ]a[ ]valid[ ]reverse[ ]dns[ ]entry
25
+ |bad[ ]sender[ ]ip[ ]address
28
26
  |blacklisted[ ]by
29
- |(?:Blocked|Refused)[ ]-[ ]see[ ]https?://
30
- |can[']t[ ]determine[ ]Purported[ ]Responsible[ ]Address
31
- |cannot[ ]resolve[ ]your[ ]address
27
+ |(?:blocked|refused)[ ]-[ ]see[ ]https?://
28
+ |can[']t[ ]determine[ ]purported[ ]responsible[ ]address
29
+ |cannot[ ](?:
30
+ find[ ]your[ ]hostname
31
+ |resolve[ ]your[ ]address
32
+ )
32
33
  |client[ ]host[ ](?:
33
34
  .+[ ]blocked[ ]using
34
35
  |rejected:[ ](?:
35
- Abus[ ]detecte[ ]GU_EIB_0[24] # SFR
36
+ abus[ ]detecte[ ]gu_eib_0[24] # SFR
36
37
  |cannot[ ]find[ ]your[ ]hostname # Yahoo!
37
38
  |may[ ]not[ ]be[ ]mail[ ]exchanger
38
39
  |was[ ]not[ ]authenticated # Microsoft
@@ -45,106 +46,106 @@ module Sisimai
45
46
  |reset[ ]by[ ]peer
46
47
  |was[ ]dropped[ ]by[ ]remote[ ]host
47
48
  )
48
- |Connections[ ](?:
49
- not[ ]accepted[ ]from[ ]IP[ ]addresses[ ]on[ ]Spamhaus[ ]XBL
50
- |will[ ]not[ ]be[ ]accepted[ ]from[ ].+because[ ]the[ ]ip[ ]is[ ]in[ ]Spamhaus's[ ]list
49
+ |connections[ ](?:
50
+ not[ ]accepted[ ]from[ ]ip[ ]addresses[ ]on[ ]spamhaus[ ]xbl
51
+ |will[ ]not[ ]be[ ]accepted[ ]from[ ].+because[ ]the[ ]ip[ ]is[ ]in[ ]spamhaus's[ ]list
51
52
  )
52
- |Currently[ ]Sending[ ]Spam[ ]See:[ ]
53
+ |currently[ ]sending[ ]spam[ ]see:[ ]
53
54
  |domain[ ](?:
54
55
  .+[ ]mismatches[ ]client[ ]ip
55
56
  |does[ ]not[ ]exist:
56
57
  )
57
58
  |dns[ ]lookup[ ]failure:[ ].+[ ]try[ ]again[ ]later
58
- |DNSBL:ATTRBL
59
- |Dynamic/zombied/spam[ ]IPs[ ]blocked
60
- |Email[ ]blocked[ ]by[ ](?:.+[.]barracudacentral[.]org|SPAMHAUS)
61
- |Fix[ ]reverse[ ]DNS[ ]for[ ].+
62
- |Go[ ]away
63
- |host[ ].+[ ]refused[ ]to[ ]talk[ ]to[ ]me:[ ]\d+[ ]Blocked
59
+ |dnsbl:attrbl
60
+ |dynamic/zombied/spam[ ]ips[ ]blocked
61
+ |email[ ]blocked[ ]by[ ](?:.+[.]barracudacentral[.]org|spamhaus)
62
+ |fix[ ]reverse[ ]dns[ ]for[ ].+
63
+ |go[ ]away
64
+ |host[ ].+[ ]refused[ ]to[ ]talk[ ]to[ ]me:[ ]\d+[ ]blocked
64
65
  |hosts[ ]with[ ]dynamic[ ]ip
65
66
  |http://(?:
66
67
  spf[.]pobox[.]com/why[.]html
67
68
  |www[.]spamcop[.]net/bl[.]
68
69
  )
69
- |INVALID[ ]IP[ ]FOR[ ]SENDING[ ]MAIL[ ]OF[ ]DOMAIN
70
- |IP[ ]\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}[ ]is[ ]blocked[ ]by[ ]EarthLink # Earthlink
71
- |IP[/]domain[ ]reputation[ ]problems
70
+ |invalid[ ]ip[ ]for[ ]sending[ ]mail[ ]of[ ]domain
71
+ |ip[ ]\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}[ ]is[ ]blocked[ ]by[ ]EarthLink # Earthlink
72
+ |ip[/]domain[ ]reputation[ ]problems
72
73
  |is[ ](?:
73
74
  in[ ]a[ ]black[ ]list[ ]at[ ].+[.]
74
- |in[ ]an[ ].*RBL[ ]on[ ].+
75
+ |in[ ]an[ ].*rbl[ ]on[ ].+
75
76
  |not[ ]allowed[ ]to[ ]send[ ](?:
76
77
  mail[ ]from
77
- |from[ ].+[ ]per[ ]it's[ ]SPF[ ]Record
78
+ |from[ ].+[ ]per[ ]it's[ ]spf[ ]record
78
79
  )
79
80
  )
80
81
  |mail[ ]server[ ]at[ ].+[ ]is[ ]blocked
81
- |Mail[ ]from[ ]\d+[.]\d+[.]\d+[.]\d[ ]refused:
82
- |Message[ ]from[ ].+[ ]rejected[ ]based[ ]on[ ]blacklist
83
- |Messages[ ]from[ ].+[ ]temporarily[ ]deferred[ ]due[ ]to[ ]user[ ]complaints # Yahoo!
82
+ |mail[ ]from[ ]\d+[.]\d+[.]\d+[.]\d[ ]refused:
83
+ |message[ ]from[ ].+[ ]rejected[ ]based[ ]on[ ]blacklist
84
+ |messages[ ]from[ ].+[ ]temporarily[ ]deferred[ ]due[ ]to[ ]user[ ]complaints # Yahoo!
84
85
  |no[ ](?:
85
86
  access[ ]from[ ]mail[ ]server
86
- |PTR[ ]Record[ ]found[.]
87
+ |ptr[ ]record[ ]found[.]
87
88
  )
88
- |Not[ ]currently[ ]accepting[ ]mail[ ]from[ ]your[ ]ip # Microsoft
89
+ |not[ ]currently[ ]accepting[ ]mail[ ]from[ ]your[ ]ip # Microsoft
89
90
  |part[ ]of[ ]their[ ]network[ ]is[ ]on[ ]our[ ]block[ ]list
90
- |Please[ ](?:
91
- get[ ]a[ ]custom[ ]reverse[ ]DNS[ ]name[ ]from[ ]your[ ]ISP[ ]for[ ]your[ ]host
92
- |inspect[ ]your[ ]SPF[ ]settings
93
- |use[ ]the[ ]smtp[ ]server[ ]of[ ]your[ ]ISP
94
- )
95
- |PTR[ ]record[ ]setup
96
- |Rejecting[ ]open[ ]proxy # Sendmail(srvrsmtp.c)
97
- |Reverse[ ]DNS[ ](?:
91
+ |please[ ](?:
92
+ get[ ]a[ ]custom[ ]reverse[ ]dns[ ]name[ ]from[ ]your[ ]isp[ ]for[ ]your[ ]host
93
+ |inspect[ ]your[ ]spf[ ]settings
94
+ |use[ ]the[ ]smtp[ ]server[ ]of[ ]your[ ]isp
95
+ )
96
+ |ptr[ ]record[ ]setup
97
+ |rejecting[ ]open[ ]proxy # Sendmail(srvrsmtp.c)
98
+ |reverse[ ]dns[ ](?:
98
99
  failed
99
100
  |required
100
101
  |lookup[ ]for[ ]host[ ].+[ ]failed[ ]permanently
101
102
  )
102
- |Sender[ ]IP[ ](?:
103
+ |sender[ ]ip[ ](?:
103
104
  address[ ]rejected
104
105
  |reverse[ ]lookup[ ]rejected
105
106
  )
106
- |Server[ ]access[ ](?:
107
- .+[ ]forbidden[ ]by[ ]invalid[ ]RDNS[ ]record[ ]of[ ]your[ ]mail[ ]server
108
- |forbidden[ ]by[ ]your[ ]IP[ ]
107
+ |server[ ]access[ ](?:
108
+ .+[ ]forbidden[ ]by[ ]invalid[ ]rdns[ ]record[ ]of[ ]your[ ]mail[ ]server
109
+ |forbidden[ ]by[ ]your[ ]ip[ ]
109
110
  )
110
- |Server[ ]IP[ ].+[ ]listed[ ]as[ ]abusive
111
- |service[ ]permits[ ]\d+[ ]unverifyable[ ]sending[ ]IPs
112
- |SMTP[ ]error[ ]from[ ]remote[ ]mail[ ]server[ ]after[ ]initial[ ]connection: # Exim
111
+ |server[ ]ip[ ].+[ ]listed[ ]as[ ]abusive
112
+ |service[ ]permits[ ]\d+[ ]unverifyable[ ]sending[ ]ips
113
+ |smtp[ ]error[ ]from[ ]remote[ ]mail[ ]server[ ]after[ ]initial[ ]connection: # Exim
113
114
  |sorry,[ ](?:
114
115
  that[ ]domain[ ]isn'?t[ ]in[ ]my[ ]list[ ]of[ ]allowed[ ]rcpthosts
115
116
  |your[ ]remotehost[ ]looks[ ]suspiciously[ ]like[ ]spammer
116
117
  )
117
- |SPF[ ](?:
118
+ |spf[ ](?:
118
119
  .+[ ]domain[ ]authentication[ ]fail
119
120
  |record
120
121
  |check:[ ]fail
121
122
  )
122
- |SPF:[ ].+[ ]is[ ]not[ ]allowed[ ]to[ ]send[ ]mail.+[A-Z]{3}.+401
123
+ |spf:[ ].+[ ]is[ ]not[ ]allowed[ ]to[ ]send[ ]mail.+[a-z]{3}.+401
123
124
  |the[ ](?:email|domain|ip).+[ ]is[ ]blacklisted
124
- |This[ ]system[ ]will[ ]not[ ]accept[ ]messages[ ]from[ ]servers[/]devices[ ]with[ ]no[ ]reverse[ ]DNS
125
- |Too[ ]many[ ]spams[ ]from[ ]your[ ]IP # free.fr
125
+ |this[ ]system[ ]will[ ]not[ ]accept[ ]messages[ ]from[ ]servers[/]devices[ ]with[ ]no[ ]reverse[ ]dns
126
+ |too[ ]many[ ]spams[ ]from[ ]your[ ]ip # free.fr
126
127
  |unresolvable[ ]relay[ ]host[ ]name
127
- |Veuillez[ ]essayer[ ]plus[ ]tard.+[A-Z]{3}.+(?:103|510)
128
+ |veuillez[ ]essayer[ ]plus[ ]tard.+[a-z]{3}.+(?:103|510)
128
129
  |your[ ](?:
129
130
  network[ ]is[ ]temporary[ ]blacklisted
130
- |sender's[ ]IP[ ]address[ ]is[ ]listed[ ]at[ ].+[.]abuseat[.]org
131
+ |sender's[ ]ip[ ]address[ ]is[ ]listed[ ]at[ ].+[.]abuseat[.]org
131
132
  |server[ ]requires[ ]confirmation
132
133
  )
133
134
  |was[ ]blocked[ ]by[ ].+
134
135
  |we[ ]do[ ]not[ ]accept[ ]mail[ ]from[ ](?: # @mail.ru
135
136
  dynamic[ ]ips
136
- |hosts[ ]with[ ]dynamic[ ]IP[ ]or[ ]generic[ ]dns[ ]PTR-records
137
+ |hosts[ ]with[ ]dynamic[ ]ip[ ]or[ ]generic[ ]dns[ ]ptr-records
137
138
  )
138
- |You[ ]are[ ](?:
139
+ |you[ ]are[ ](?:
139
140
  not[ ]allowed[ ]to[ ]connect
140
141
  |sending[ ]spam
141
142
  )
142
- |Your[ ](?:
143
+ |your[ ](?:
143
144
  access[ ]to[ ]submit[ ]messages[ ]to[ ]this[ ]e-mail[ ]system[ ]has[ ]been[ ]rejected
144
145
  |message[ ]was[ ]rejected[ ]for[ ]possible[ ]spam/virus[ ]content
145
146
  )
146
147
  )
147
- }xi
148
+ }x
148
149
 
149
150
  return true if argv1 =~ regex
150
151
  return false
@@ -158,24 +159,12 @@ module Sisimai
158
159
  def true(argvs)
159
160
  return nil unless argvs
160
161
  return nil unless argvs.is_a? Sisimai::Data
161
- return true if argvs.reason == Sisimai::Reason::Blocked.text
162
+ return true if argvs.reason == 'blocked'
162
163
 
163
164
  require 'sisimai/smtp/status'
164
- diagnostic = argvs.diagnosticcode || ''
165
- statuscode = argvs.deliverystatus || ''
166
- tempreason = Sisimai::SMTP::Status.name(statuscode)
167
- reasontext = Sisimai::Reason::Blocked.text
168
- v = false
169
-
170
- if tempreason == reasontext
171
- # Delivery status code points "blocked".
172
- v = true
173
- else
174
- # Matched with a pattern in this class
175
- v = true if Sisimai::Reason::Blocked.match(diagnostic)
176
- end
177
-
178
- return v
165
+ return true if Sisimai::SMTP::Status.name(argvs.deliverystatus) == 'blocked'
166
+ return true if match(argvs.diagnosticcode.downcase)
167
+ return false
179
168
  end
180
169
 
181
170
  end