sisimai 5.4.1-java → 5.6.0-java

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.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codecovio.yml +1 -1
  3. data/.github/workflows/rake-test.yml +1 -1
  4. data/ChangeLog.md +56 -0
  5. data/LICENSE +1 -1
  6. data/Makefile +2 -4
  7. data/README-JA.md +29 -23
  8. data/README.md +30 -24
  9. data/lib/sisimai/address.rb +92 -44
  10. data/lib/sisimai/arf.rb +7 -8
  11. data/lib/sisimai/datetime.rb +2 -2
  12. data/lib/sisimai/fact/json.rb +1 -2
  13. data/lib/sisimai/fact/yaml.rb +1 -2
  14. data/lib/sisimai/fact.rb +76 -36
  15. data/lib/sisimai/lda.rb +2 -2
  16. data/lib/sisimai/lhost/activehunter.rb +4 -5
  17. data/lib/sisimai/lhost/amazonses.rb +4 -5
  18. data/lib/sisimai/lhost/apachejames.rb +2 -2
  19. data/lib/sisimai/lhost/biglobe.rb +6 -6
  20. data/lib/sisimai/lhost/courier.rb +7 -7
  21. data/lib/sisimai/lhost/domino.rb +6 -6
  22. data/lib/sisimai/lhost/dragonfly.rb +5 -5
  23. data/lib/sisimai/lhost/einsundeins.rb +5 -5
  24. data/lib/sisimai/lhost/exchange2003.rb +7 -7
  25. data/lib/sisimai/lhost/exchange2007.rb +5 -5
  26. data/lib/sisimai/lhost/exim.rb +13 -15
  27. data/lib/sisimai/lhost/ezweb.rb +3 -2
  28. data/lib/sisimai/lhost/fml.rb +9 -9
  29. data/lib/sisimai/lhost/gmail.rb +9 -9
  30. data/lib/sisimai/lhost/gmx.rb +3 -3
  31. data/lib/sisimai/lhost/googlegroups.rb +6 -7
  32. data/lib/sisimai/lhost/googleworkspace.rb +5 -6
  33. data/lib/sisimai/lhost/imailserver.rb +4 -4
  34. data/lib/sisimai/lhost/kddi.rb +4 -4
  35. data/lib/sisimai/lhost/mailfoundry.rb +3 -3
  36. data/lib/sisimai/lhost/{mailmarshalsmtp.rb → mailmarshal.rb} +5 -5
  37. data/lib/sisimai/lhost/messagingserver.rb +8 -8
  38. data/lib/sisimai/lhost/mfilter.rb +8 -4
  39. data/lib/sisimai/lhost/mimecast.rb +105 -0
  40. data/lib/sisimai/lhost/notes.rb +5 -5
  41. data/lib/sisimai/lhost/opensmtpd.rb +5 -5
  42. data/lib/sisimai/lhost/postfix.rb +38 -32
  43. data/lib/sisimai/lhost/qmail.rb +11 -11
  44. data/lib/sisimai/lhost/sendmail.rb +13 -13
  45. data/lib/sisimai/lhost/{interscanmss.rb → trendmicro.rb} +8 -9
  46. data/lib/sisimai/lhost/v5sendmail.rb +7 -7
  47. data/lib/sisimai/lhost/verizon.rb +3 -3
  48. data/lib/sisimai/lhost/x1.rb +7 -4
  49. data/lib/sisimai/lhost/x2.rb +40 -12
  50. data/lib/sisimai/lhost/x3.rb +3 -3
  51. data/lib/sisimai/lhost/x6.rb +2 -2
  52. data/lib/sisimai/lhost/zoho.rb +5 -5
  53. data/lib/sisimai/lhost.rb +18 -17
  54. data/lib/sisimai/mail/maildir.rb +4 -4
  55. data/lib/sisimai/mail/mbox.rb +4 -4
  56. data/lib/sisimai/mail/memory.rb +1 -1
  57. data/lib/sisimai/mail/stdin.rb +2 -2
  58. data/lib/sisimai/message.rb +36 -34
  59. data/lib/sisimai/order.rb +5 -4
  60. data/lib/sisimai/reason/authfailure.rb +10 -14
  61. data/lib/sisimai/reason/badreputation.rb +8 -8
  62. data/lib/sisimai/reason/blocked.rb +58 -83
  63. data/lib/sisimai/reason/contenterror.rb +15 -10
  64. data/lib/sisimai/reason/{mesgtoobig.rb → emailtoolarge.rb} +23 -26
  65. data/lib/sisimai/reason/expired.rb +17 -24
  66. data/lib/sisimai/reason/failedstarttls.rb +1 -1
  67. data/lib/sisimai/reason/filtered.rb +14 -18
  68. data/lib/sisimai/reason/hasmoved.rb +3 -2
  69. data/lib/sisimai/reason/hostunknown.rb +18 -21
  70. data/lib/sisimai/reason/mailboxfull.rb +28 -50
  71. data/lib/sisimai/reason/mailererror.rb +1 -1
  72. data/lib/sisimai/reason/networkerror.rb +17 -17
  73. data/lib/sisimai/reason/norelaying.rb +20 -20
  74. data/lib/sisimai/reason/notaccept.rb +7 -10
  75. data/lib/sisimai/reason/notcompliantrfc.rb +6 -10
  76. data/lib/sisimai/reason/policyviolation.rb +12 -28
  77. data/lib/sisimai/reason/ratelimited.rb +62 -0
  78. data/lib/sisimai/reason/rejected.rb +46 -58
  79. data/lib/sisimai/reason/requireptr.rb +14 -26
  80. data/lib/sisimai/reason/securityerror.rb +14 -20
  81. data/lib/sisimai/reason/spamdetected.rb +52 -102
  82. data/lib/sisimai/reason/suspend.rb +27 -24
  83. data/lib/sisimai/reason/systemerror.rb +20 -24
  84. data/lib/sisimai/reason/systemfull.rb +2 -2
  85. data/lib/sisimai/reason/userunknown.rb +82 -114
  86. data/lib/sisimai/reason/vacation.rb +1 -1
  87. data/lib/sisimai/reason/virusdetected.rb +7 -9
  88. data/lib/sisimai/reason.rb +26 -26
  89. data/lib/sisimai/rfc1123.rb +58 -18
  90. data/lib/sisimai/rfc1894.rb +6 -8
  91. data/lib/sisimai/rfc2045.rb +25 -13
  92. data/lib/sisimai/rfc3464/thirdparty.rb +2 -3
  93. data/lib/sisimai/rfc3464.rb +6 -6
  94. data/lib/sisimai/rfc3834.rb +18 -8
  95. data/lib/sisimai/rfc5322.rb +9 -9
  96. data/lib/sisimai/rfc791.rb +2 -2
  97. data/lib/sisimai/rhost/aol.rb +4 -1
  98. data/lib/sisimai/rhost/apple.rb +15 -11
  99. data/lib/sisimai/rhost/cloudflare.rb +2 -0
  100. data/lib/sisimai/rhost/cox.rb +31 -25
  101. data/lib/sisimai/rhost/facebook.rb +24 -18
  102. data/lib/sisimai/rhost/franceptt.rb +92 -38
  103. data/lib/sisimai/rhost/godaddy.rb +34 -7
  104. data/lib/sisimai/rhost/google.rb +69 -70
  105. data/lib/sisimai/rhost/gsuite.rb +1 -1
  106. data/lib/sisimai/rhost/iua.rb +1 -1
  107. data/lib/sisimai/rhost/kddi.rb +1 -1
  108. data/lib/sisimai/rhost/messagelabs.rb +160 -2
  109. data/lib/sisimai/rhost/microsoft.rb +154 -107
  110. data/lib/sisimai/rhost/mimecast.rb +64 -55
  111. data/lib/sisimai/rhost/nttdocomo.rb +70 -90
  112. data/lib/sisimai/rhost/outlook.rb +1 -1
  113. data/lib/sisimai/rhost/spectrum.rb +8 -8
  114. data/lib/sisimai/rhost/tencent.rb +12 -13
  115. data/lib/sisimai/rhost/yahooinc.rb +9 -10
  116. data/lib/sisimai/rhost/zoho.rb +72 -0
  117. data/lib/sisimai/rhost.rb +4 -3
  118. data/lib/sisimai/smtp/command.rb +4 -2
  119. data/lib/sisimai/smtp/reply.rb +11 -4
  120. data/lib/sisimai/smtp/status.rb +67 -98
  121. data/lib/sisimai/smtp/transcript.rb +3 -3
  122. data/lib/sisimai/string.rb +4 -23
  123. data/lib/sisimai/version.rb +1 -1
  124. data/lib/sisimai.rb +1 -1
  125. data/set-of-emails/maildir/bsd/lhost-exim-56.eml +40 -40
  126. data/set-of-emails/maildir/bsd/lhost-mfilter-05.eml +41 -0
  127. data/set-of-emails/maildir/bsd/lhost-mimecast-01.eml +46 -0
  128. data/set-of-emails/maildir/bsd/lhost-mimecast-02.eml +59 -0
  129. data/set-of-emails/maildir/bsd/lhost-postfix-79.eml +81 -0
  130. data/set-of-emails/maildir/bsd/lhost-postfix-80.eml +84 -0
  131. data/set-of-emails/maildir/bsd/lhost-x1-03.eml +26 -0
  132. data/set-of-emails/maildir/bsd/lhost-x1-04.eml +45 -0
  133. data/set-of-emails/maildir/bsd/lhost-x2-07.eml +30 -0
  134. data/set-of-emails/maildir/bsd/rfc3464-66.eml +170 -0
  135. data/set-of-emails/maildir/bsd/rfc3834-06.eml +59 -0
  136. data/set-of-emails/maildir/bsd/rhost-zoho-01.eml +88 -0
  137. data/set-of-emails/maildir/bsd/rhost-zoho-02.eml +86 -0
  138. data/set-of-emails/maildir/bsd/rhost-zoho-03.eml +87 -0
  139. data/set-of-emails/maildir/bsd/rhost-zoho-04.eml +86 -0
  140. data/set-of-emails/maildir/not/rb-issue-368-bug.eml +39 -0
  141. data/sisimai-java.gemspec +1 -1
  142. data/sisimai.gemspec +1 -1
  143. metadata +28 -13
  144. data/lib/sisimai/reason/exceedlimit.rb +0 -47
  145. data/lib/sisimai/reason/speeding.rb +0 -47
  146. data/lib/sisimai/reason/toomanyconn.rb +0 -59
  147. /data/set-of-emails/maildir/bsd/{lhost-mailmarshalsmtp-02.eml → lhost-mailmarshal-02.eml} +0 -0
  148. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-01.eml → lhost-trendmicro-01.eml} +0 -0
  149. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-02.eml → lhost-trendmicro-02.eml} +0 -0
  150. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-03.eml → lhost-trendmicro-03.eml} +0 -0
@@ -38,8 +38,8 @@ module Sisimai::Lhost
38
38
  # @return [Hash] Bounce data list and message/rfc822 part
39
39
  # @return [Nil] it failed to decode or the arguments are missing
40
40
  def inquire(mhead, mbody)
41
- return nil unless mhead['subject'].start_with?('Mail delivery failed')
42
- return nil unless mhead['received'].any? { |a| a.include?(' (DragonFly Mail Agent') }
41
+ return nil if mhead['subject'].start_with?('Mail delivery failed') == false
42
+ return nil if mhead['received'].none? { |a| a.include?(' (DragonFly Mail Agent') }
43
43
 
44
44
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
45
45
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -83,7 +83,7 @@ module Sisimai::Lhost
83
83
 
84
84
  # Pick the remote hostname, and the SMTP command
85
85
  # net.c:500| snprintf(errmsg, sizeof(errmsg), "%s [%s] did not like our %s:\n%s",
86
- next unless e.include?(' did not like our ')
86
+ next if e.include?(' did not like our ') == false
87
87
  next if v['rhost'] != ""
88
88
 
89
89
  p = e.split(' ', 3)
@@ -91,13 +91,13 @@ module Sisimai::Lhost
91
91
  v['command'] = Sisimai::SMTP::Command.find(e)
92
92
  end
93
93
  end
94
- return nil unless recipients > 0
94
+ return nil if recipients == 0
95
95
 
96
96
  dscontents.each do |e|
97
97
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
98
98
  MessagesOf.each_key do |r|
99
99
  # Verify each regular expression of session errors
100
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
100
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
101
101
  e['reason'] = r
102
102
  break
103
103
  end
@@ -11,7 +11,7 @@ module Sisimai::Lhost
11
11
  message: ['This message was created automatically by mail delivery software'],
12
12
  error: ['For the following reason:'],
13
13
  }.freeze
14
- MessagesOf = {'mesgtoobig' => ['Mail size limit exceeded']}.freeze
14
+ MessagesOf = {'emailtoolarge' => ['Mail size limit exceeded']}.freeze
15
15
 
16
16
  # @abstract Decode the bounce message from 1&1
17
17
  # @param [Hash] mhead Message headers of a bounce email
@@ -19,8 +19,8 @@ module Sisimai::Lhost
19
19
  # @return [Hash] Bounce data list and message/rfc822 part
20
20
  # @return [Nil] it failed to decode or the arguments are missing
21
21
  def inquire(mhead, mbody)
22
- return nil unless mhead['from'].start_with?('"Mail Delivery System"')
23
- return nil unless mhead['subject'] == 'Mail delivery failed: returning message to sender'
22
+ return nil if mhead['from'].start_with?('"Mail Delivery System"') == false
23
+ return nil if mhead['subject'] != 'Mail delivery failed: returning message to sender'
24
24
 
25
25
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
26
26
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -76,7 +76,7 @@ module Sisimai::Lhost
76
76
  end
77
77
  end
78
78
  end
79
- return nil unless recipients > 0
79
+ return nil if recipients == 0
80
80
 
81
81
  require 'sisimai/smtp/command'
82
82
  dscontents.each do |e|
@@ -102,7 +102,7 @@ module Sisimai::Lhost
102
102
 
103
103
  MessagesOf.each_key do |r|
104
104
  # Verify each regular expression of session errors
105
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
105
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
106
106
  e['reason'] = r
107
107
  break
108
108
  end
@@ -74,14 +74,14 @@ module Sisimai::Lhost
74
74
  throw :EXCHANGE_OR_NOT if mhead['received'].empty?
75
75
  mhead['received'].each do |e|
76
76
  # Received: by ***.**.** with Internet Mail Service (5.5.2657.72)
77
- next unless e.include?(' with Internet Mail Service (')
77
+ next if e.include?(' with Internet Mail Service (') == false
78
78
  match += 1
79
79
  throw :EXCHANGE_OR_NOT
80
80
  end
81
81
  break
82
82
  end
83
83
  end
84
- return nil unless match > 0
84
+ return nil if match == 0
85
85
 
86
86
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
87
87
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -160,26 +160,26 @@ module Sisimai::Lhost
160
160
  #
161
161
  if e.start_with?(' To: ') || e.start_with?(' To: ')
162
162
  # To: shironeko@example.jp
163
- next unless connheader['to'].empty?
163
+ next if connheader['to'].empty? == false
164
164
  connheader['to'] = e[e.rindex(' ') + 1, e.size]
165
165
  connvalues += 1
166
166
 
167
167
  elsif e.start_with?(' Subject: ') || e.start_with?(' Subject: ')
168
168
  # Subject: ...
169
- next unless connheader['subject'].empty?
169
+ next if connheader['subject'].empty? == false
170
170
  connheader['subject'] = e[e.rindex(' ') + 1, e.size]
171
171
  connvalues += 1
172
172
 
173
173
  elsif e.start_with?(' Sent: ') || e.start_with?(' Sent: ')
174
174
  # Sent: Thu, 29 Apr 2010 18:14:35 +0000
175
175
  # Sent: 4/29/99 9:19:59 AM
176
- next unless connheader['date'].empty?
176
+ next if connheader['date'].empty? == false
177
177
  connheader['date'] = e[e.index(':') + 2, e.size]
178
178
  connvalues += 1
179
179
  end
180
180
  end
181
181
  end
182
- return nil unless recipients > 0
182
+ return nil if recipients == 0
183
183
 
184
184
  dscontents.each do |e|
185
185
  e.delete('msexch')
@@ -193,7 +193,7 @@ module Sisimai::Lhost
193
193
 
194
194
  ErrorCodes.each_key do |r|
195
195
  # Find captured code from the error code table
196
- next unless ErrorCodes[r].index(capturedcode)
196
+ next if ErrorCodes[r].index(capturedcode).nil?
197
197
  e['reason'] = r
198
198
  e['status'] = Sisimai::SMTP::Status.code(r)
199
199
  break
@@ -26,7 +26,7 @@ module Sisimai::Lhost
26
26
  rhost: [
27
27
  "DSN generated by:",
28
28
  "Generating server", # en-US
29
- "Serveur de g", # fr-FR/Serveur de g�Hn�Hration
29
+ "Serveur de g", # fr-FR/Serveur de gènèration
30
30
  "Server di generazione", # it-CH
31
31
  "Genererande server", # sv-SE
32
32
  ]
@@ -38,12 +38,12 @@ module Sisimai::Lhost
38
38
  "RESOLVER.ADR.RecipNotFound" => "userunknown", # 550 5.1.1 RESOLVER.ADR.RecipNotFound
39
39
  "RESOLVER.ADR.RecipientNotFound" => "userunknown", # 550 5.1.1 RESOLVER.ADR.RecipientNotFound
40
40
  "RESOLVER.ADR.ExRecipNotFound" => "userunknown", # 550 5.1.1 RESOLVER.ADR.ExRecipNotFound
41
- "RESOLVER.ADR.RecipLimit" => "toomanyconn", # 550 5.5.3 RESOLVER.ADR.RecipLimit
41
+ "RESOLVER.ADR.RecipLimit" => "ratelimited", # 550 5.5.3 RESOLVER.ADR.RecipLimit
42
42
  "RESOLVER.ADR.InvalidInSmtp" => "systemerror", # 550 5.1.0 RESOLVER.ADR.InvalidInSmtp
43
43
  "RESOLVER.ADR.Ambiguous" => "systemerror", # 550 5.1.4 RESOLVER.ADR.Ambiguous, 420 4.2.0 RESOLVER.ADR.Ambiguous
44
44
  "RESOLVER.RST.AuthRequired" => "securityerror", # 550 5.7.1 RESOLVER.RST.AuthRequired
45
45
  "RESOLVER.RST.NotAuthorized" => "rejected", # 550 5.7.1 RESOLVER.RST.NotAuthorized
46
- "RESOLVER.RST.RecipSizeLimit" => "exceedlimit", # 550 5.2.3 RESOLVER.RST.RecipSizeLimit
46
+ "RESOLVER.RST.RecipSizeLimit" => "emailtoolarge", # 550 5.2.3 RESOLVER.RST.RecipSizeLimit
47
47
  "QUEUE.Expired" => "expired", # 550 4.4.7 QUEUE.Expired
48
48
  }.freeze
49
49
  MailSender = ["postmaster@outlook.com", ".onmicrosoft.com"].freeze
@@ -143,11 +143,11 @@ module Sisimai::Lhost
143
143
  p3 = emailparts[0].index("\n", p2 + 20); break if p3.nil?
144
144
  cv = Sisimai::Address.s3s4(emailparts[0][p2 + 20, p3 - p2 - 20])
145
145
 
146
- break unless Sisimai::Address.is_emailaddress(cv)
146
+ break if Sisimai::Address.is_emailaddress(cv) == false
147
147
  dscontents[0]["recipient"] = cv
148
148
  recipients += 1
149
149
  end
150
- return nil unless recipients > 0
150
+ return nil if recipients == 0
151
151
 
152
152
  dscontents.each do |e|
153
153
  # Tidy up the error message in $e->{'diagnosis'}, Try to detect the bounce reason.
@@ -164,9 +164,11 @@ module Sisimai::Lhost
164
164
  end
165
165
  return nil if proceedsto < 2 && thirdparty == false
166
166
 
167
+ require "sisimai/reason"
167
168
  require "sisimai/address"
168
169
  require "sisimai/rfc2045"
169
170
  require "sisimai/smtp/command"
171
+ require "sisimai/smtp/failure"
170
172
 
171
173
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
172
174
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -190,7 +192,7 @@ module Sisimai::Lhost
190
192
  if StartingOf["message"].any? { |a| e.include?(a) }
191
193
  # Check the message defined in StartingOf["message"], ["frozen"]
192
194
  readcursor |= Indicators[:deliverystatus]
193
- next unless StartingOf["frozen"].any? { |a| e.include?(a) }
195
+ next if StartingOf["frozen"].none? { |a| e.include?(a) }
194
196
  end
195
197
  end
196
198
  next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
@@ -269,7 +271,7 @@ module Sisimai::Lhost
269
271
  # generated by userx@myhost.test.ex
270
272
  e.split(" ").each do |f|
271
273
  # Find the alias address
272
- next unless f.include?('@')
274
+ next if f.include?('@') == false
273
275
  v["alias"] = Sisimai::Address.s3s4(f)
274
276
  end
275
277
  else
@@ -289,7 +291,7 @@ module Sisimai::Lhost
289
291
  if o[3] == "addr"
290
292
  # Final-Recipient: rfc822; kijitora@example.jp
291
293
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
292
- next unless o[0] == "final-recipient"
294
+ next if o[0] != "final-recipient"
293
295
  if v["spec"].empty?
294
296
  v["spec"] = o[2].include?('@') ? "SMTP" : "X-UNIX"
295
297
  end
@@ -301,7 +303,7 @@ module Sisimai::Lhost
301
303
 
302
304
  else
303
305
  # Other DSN fields defined in RFC3464
304
- next unless FieldTable[o[0]]
306
+ next if FieldTable[o[0]].nil?
305
307
  v[FieldTable[o[0]]] = o[2]
306
308
  end
307
309
  else
@@ -311,7 +313,7 @@ module Sisimai::Lhost
311
313
  # Content-type: message/delivery-status
312
314
  nextcursor = true if e.start_with?(StartingOf["deliverystatus"][0])
313
315
  v["alterrors"] ||= ''
314
- v["alterrors"] += "#{e} " unless v["alterrors"].include?(e) if e.start_with?(" ")
316
+ v["alterrors"] += "#{e} " if e.start_with?(" ")
315
317
  end
316
318
  else
317
319
  # There is no boundary string in $boundary00
@@ -322,7 +324,7 @@ module Sisimai::Lhost
322
324
  # Error message when email address above does not include '@' and domain part
323
325
  # pipe to |/path/to/prog ...
324
326
  # generated by kijitora@example.com
325
- next unless e.start_with?(" ")
327
+ next if e.start_with?(" ") == false
326
328
  v["diagnosis"] += "#{e} "
327
329
  end
328
330
  end
@@ -439,7 +441,7 @@ module Sisimai::Lhost
439
441
  # Try to match the error message with each message pattern
440
442
  MessagesOf.each_key do |r|
441
443
  # Check each message pattern
442
- next unless MessagesOf[r].any? { |a| e["diagnosis"].include?(a) }
444
+ next if MessagesOf[r].none? { |a| e["diagnosis"].include?(a) }
443
445
  e["reason"] = r
444
446
  break
445
447
  end
@@ -461,21 +463,17 @@ module Sisimai::Lhost
461
463
  #
462
464
  # The value of "Status:" indicates permanent error but the value of SMTP reply code in
463
465
  # Diagnostic-Code: field is "TEMPERROR"!!!!
464
- re = e["reason"]
465
466
  cr = Sisimai::SMTP::Reply.find(e["diagnosis"], e["status"])
466
467
  cs = Sisimai::SMTP::Status.find(e["diagnosis"], cr)
468
+ re = e["reason"]
467
469
  cv = ""
468
470
 
469
- if cr[0,1] == "4" || re == "expired" || re == "mailboxfull"
471
+ if Sisimai::SMTP::Failure.is_temporary(cr) || re == "expired" || re == "mailboxfull"
470
472
  # Set the pseudo status code as a temporary error
471
- cv = Sisimai::SMTP::Status.code(re, true)
472
-
473
- else
474
- # Set the pseudo status code as a permanent error
475
- cv = Sisimai::SMTP::Status.code(re, false)
473
+ cv = Sisimai::SMTP::Status.code(re, true) if Sisimai::Reason.is_explicit(re)
476
474
  end
477
475
  e["replycode"] = cr if e["replycode"].empty?
478
- e["status"] = Sisimai::SMTP::Status.prefer(cs, cv, cr) if e["status"].empty?
476
+ e["status"] = Sisimai::SMTP::Status.prefer(cv, cs, cr) if e["status"].empty?
479
477
  end
480
478
 
481
479
  return { "ds" => dscontents, "rfc822" => emailparts[1] }
@@ -116,7 +116,7 @@ module Sisimai::Lhost
116
116
  end
117
117
  end
118
118
  end
119
- return nil unless recipients > 0
119
+ return nil if recipients == 0
120
120
 
121
121
  dscontents.each do |e|
122
122
  # Check each value of DeliveryMatter{}, try to detect the bounce reason.
@@ -127,6 +127,7 @@ module Sisimai::Lhost
127
127
  # Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
128
128
  # Filtered recipient returns message that include 'X-SPASIGN' header
129
129
  e['reason'] = 'filtered'
130
+ e['toxic'] = true
130
131
  else
131
132
  # There is no X-SPASIGN header or the value of the header is not "NG"
132
133
  catch :FINDREASON do
@@ -134,7 +135,7 @@ module Sisimai::Lhost
134
135
  # Try to match with each session error message
135
136
  Messagesof[r].each do |f|
136
137
  # Check each error message pattern
137
- next unless e['diagnosis'].include?(f)
138
+ next if e['diagnosis'].include?(f) == false
138
139
  e['reason'] = r
139
140
  throw :FINDREASON
140
141
  end
@@ -30,12 +30,12 @@ module Sisimai::Lhost
30
30
  'reject spammers:',
31
31
  'You are not a member of this mailing list',
32
32
  ],
33
+ 'notcompliantrfc' => ['Duplicated Message-ID'],
34
+ 'securityerror' => ['Security alert:'],
33
35
  'systemerror' => [
34
36
  ' has detected a loop condition so that',
35
- 'Duplicated Message-ID',
36
37
  'Loop Back Warning:',
37
38
  ],
38
- 'securityerror' => ['Security alert:'],
39
39
  }.freeze
40
40
 
41
41
  # @abstract Decodes the bounce message from fml mailling list server/manager
@@ -45,9 +45,9 @@ module Sisimai::Lhost
45
45
  # @return [Nil] it failed to decode or the arguments are missing
46
46
  # @since v4.22.3
47
47
  def inquire(mhead, mbody)
48
- return nil unless mhead['x-mlserver']
49
- return nil unless mhead['from'].include?('-admin@')
50
- return nil unless mhead['message-id'].index('.FML') > 1
48
+ return nil if mhead['x-mlserver'].nil?
49
+ return nil if mhead['from'].include?('-admin@') == false
50
+ return nil if mhead['message-id'].index('.FML') < 2
51
51
 
52
52
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
53
53
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -81,22 +81,22 @@ module Sisimai::Lhost
81
81
  v['diagnosis'] += e
82
82
  end
83
83
  end
84
- return nil unless recipients > 0
84
+ return nil if recipients == 0
85
85
 
86
86
  dscontents.each do |e|
87
87
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
88
88
  ErrorTable.each_key do |f|
89
89
  # Try to match with error messages defined in ErrorTable
90
- next unless ErrorTable[f].any? { |a| e['diagnosis'].include?(a) }
90
+ next if ErrorTable[f].none? { |a| e['diagnosis'].include?(a) }
91
91
  e['reason'] = f
92
92
  break
93
93
  end
94
94
 
95
- unless e['reason']
95
+ if e['reason'].nil?
96
96
  # Error messages in the message body did not matched
97
97
  ErrorTitle.each_key do |f|
98
98
  # Try to match with the Subject string
99
- next unless ErrorTitle[f].any? { |a| mhead["subject"].include?(a) }
99
+ next if ErrorTitle[f].none? { |a| mhead["subject"].include?(a) }
100
100
  e['reason'] = f
101
101
  break
102
102
  end
@@ -52,7 +52,7 @@ module Sisimai::Lhost
52
52
  # We recommend contacting the other email provider for further information about the
53
53
  # cause of this error. The error that the other server returned was:
54
54
  # 500 Remote server does not support SMTP Authenticated Relay (state 12).
55
- '12' => { 'command' => 'AUTH', 'reason' => 'relayingdenied' },
55
+ '12' => { 'command' => 'AUTH', 'reason' => 'norelaying' },
56
56
 
57
57
  # Technical details of permanent failure:
58
58
  # Google tried to deliver your message, but it was rejected by the recipient domain.
@@ -148,8 +148,8 @@ module Sisimai::Lhost
148
148
  # The error that the other server returned was:
149
149
  # 550 5.1.1 <userunknown@example.jp>... User Unknown
150
150
  #
151
- return nil unless mhead['from'].end_with?('<mailer-daemon@googlemail.com>')
152
- return nil unless mhead['subject'].start_with?('Delivery Status Notification')
151
+ return nil if mhead['from'].end_with?('<mailer-daemon@googlemail.com>') == false
152
+ return nil if mhead['subject'].start_with?('Delivery Status Notification') == false
153
153
 
154
154
  require 'sisimai/address'
155
155
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
@@ -193,14 +193,14 @@ module Sisimai::Lhost
193
193
  end
194
194
 
195
195
  r = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
196
- next unless Sisimai::Address.is_emailaddress(r)
196
+ next if Sisimai::Address.is_emailaddress(r) == false
197
197
  v['recipient'] = r
198
198
  recipients += 1
199
199
  else
200
200
  v["diagnosis"] += "#{e }"
201
201
  end
202
202
  end
203
- return nil unless recipients > 0
203
+ return nil if recipients == 0
204
204
 
205
205
  require 'sisimai/string'
206
206
  require 'sisimai/rfc1123'
@@ -222,12 +222,12 @@ module Sisimai::Lhost
222
222
 
223
223
  while true do
224
224
  # Find "(state 18)" and pick "18" as a key of statetable
225
- p1 = e['diagnosis'].rindex(' (state '); break unless p1
226
- p2 = e['diagnosis'].rindex(')'); break unless p2
225
+ p1 = e['diagnosis'].rindex(' (state '); break if p1.nil?
226
+ p2 = e['diagnosis'].rindex(')'); break if p2.nil?
227
227
  break if p1 > p2
228
228
  cu = e['diagnosis'][p1 + 8, p2 - p1 - 8]
229
229
  break if cu.empty?
230
- break unless StateTable[cu]
230
+ break if StateTable[cu].nil?
231
231
  e['reason'] = StateTable[cu]['reason']
232
232
  e['command'] = StateTable[cu]['command']
233
233
  break
@@ -237,7 +237,7 @@ module Sisimai::Lhost
237
237
  # There is no no state code in the error message
238
238
  MessagesOf.each_key do |r|
239
239
  # Verify each regular expression of session errors
240
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
240
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
241
241
  e['reason'] = r
242
242
  break
243
243
  end
@@ -20,7 +20,7 @@ module Sisimai::Lhost
20
20
  # X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3;
21
21
  # X-GMX-Antivirus: 0 (no virus found)
22
22
  # X-UI-Out-Filterresults: unknown:0;
23
- return nil unless mhead['x-gmx-antispam']
23
+ return nil if mhead['x-gmx-antispam'].nil?
24
24
 
25
25
  require 'sisimai/smtp/command'
26
26
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
@@ -79,14 +79,14 @@ module Sisimai::Lhost
79
79
  v['diagnosis'] += "#{e }"
80
80
  end
81
81
  end
82
- return nil unless recipients > 0
82
+ return nil if recipients == 0
83
83
 
84
84
  dscontents.each do |e|
85
85
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
86
86
 
87
87
  MessagesOf.each_key do |r|
88
88
  # Verify each regular expression of session errors
89
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
89
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
90
90
  e['reason'] = r
91
91
  break
92
92
  end
@@ -13,11 +13,10 @@ module Sisimai::Lhost
13
13
  # @return [Nil] it failed to decode or the arguments are missing
14
14
  # @since v4.25.6
15
15
  def inquire(mhead, mbody)
16
- return nil unless mbody.include?("Google Groups")
17
- return nil unless mhead['from'].end_with?('<mailer-daemon@googlemail.com>')
18
- return nil unless mhead['subject'].start_with?('Delivery Status Notification')
19
- return nil unless mhead['x-failed-recipients']
20
- return nil unless mhead['x-google-smtp-source']
16
+ return nil if mbody.include?("Google Groups") == false
17
+ return nil if mhead['from'].end_with?('<mailer-daemon@googlemail.com>') == false
18
+ return nil if mhead['subject'].start_with?('Delivery Status Notification') == false
19
+ return nil if mhead['x-failed-recipients'].nil? || mhead['x-google-smtp-source'].nil?
21
20
 
22
21
  # Hello kijitora@libsisimai.org,
23
22
  #
@@ -55,7 +54,7 @@ module Sisimai::Lhost
55
54
 
56
55
  mhead['x-failed-recipients'].split(',').each do |e|
57
56
  # X-Failed-Recipients: neko@example.jp, nyaan@example.org, ...
58
- next unless Sisimai::Address.is_emailaddress(e)
57
+ next if Sisimai::Address.is_emailaddress(e) == false
59
58
 
60
59
  if v["recipient"] != ""
61
60
  # There are multiple recipient addresses in the message body.
@@ -66,7 +65,7 @@ module Sisimai::Lhost
66
65
  recipients += 1
67
66
  recordwide.each_key { |r| v[r] = recordwide[r] }
68
67
  end
69
- return nil unless recipients > 0
68
+ return nil if recipients == 0
70
69
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
71
70
  end
72
71
  def description; return 'Google Groups: https://groups.google.com'; end
@@ -26,10 +26,9 @@ module Sisimai::Lhost
26
26
  # @return [Nil] it failed to decode or the arguments are missing
27
27
  # @see https://workspace.google.com/.
28
28
  def inquire(mhead, mbody)
29
- return nil if mbody.include?("\nDiagnostic-Code:")
30
- return nil if mbody.include?("\nFinal-Recipient:")
31
- return nil unless mhead["from"].include?('<mailer-daemon@googlemail.com>')
32
- return nil unless mhead["subject"].include?("Delivery Status Notification")
29
+ return nil if mbody.include?("\nDiagnostic-Code:") || mbody.include?("\nFinal-Recipient:")
30
+ return nil if mhead["from"].include?('<mailer-daemon@googlemail.com>') == false
31
+ return nil if mhead["subject"].include?("Delivery Status Notification") == false
33
32
 
34
33
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
35
34
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -64,7 +63,7 @@ module Sisimai::Lhost
64
63
  while recipients == 0 do
65
64
  # Pick the recipient address from the value of To: header of the original message after
66
65
  # Content-Type: message/rfc822 field
67
- p0 = emailparts[1].index("\nTo:"); break unless p0
66
+ p0 = emailparts[1].index("\nTo:"); break if p0.nil?
68
67
  p1 = emailparts[1].index("\n", p0 + 2)
69
68
  cv = Sisimai::Address.s3s4(emailparts[1][p0 + 4, p1 - p0])
70
69
  dscontents[0]["recipient"] = cv
@@ -78,7 +77,7 @@ module Sisimai::Lhost
78
77
  e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
79
78
  MessagesOf.each_key do |r|
80
79
  # Guess an reason of the bounce
81
- next unless MessagesOf[r].any? { |a| e["diagnosis"].include?(a) }
80
+ next if MessagesOf[r].none? { |a| e["diagnosis"].include?(a) }
82
81
  e["reason"] = r
83
82
  break
84
83
  end
@@ -27,7 +27,7 @@ module Sisimai::Lhost
27
27
  match = 0
28
28
  match += 1 if mhead['subject'].start_with?('Undeliverable Mail ')
29
29
  match += 1 if mhead['x-mailer'].to_s.start_with?('<SMTP32 v')
30
- return nil unless match > 0
30
+ return nil if match == 0
31
31
 
32
32
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
33
33
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -61,11 +61,11 @@ module Sisimai::Lhost
61
61
  v['alterrors'] = e if e.include?(StartingOf[:error][0])
62
62
  end
63
63
  end
64
- return nil unless recipients > 0
64
+ return nil if recipients == 0
65
65
 
66
66
  require 'sisimai/smtp/command'
67
67
  dscontents.each do |e|
68
- unless e['alterrors'].to_s.empty?
68
+ if e['alterrors'].nil? == false && e['alterrors'].empty? == false
69
69
  # Copy alternative error message
70
70
  e['diagnosis'] = if e['diagnosis']
71
71
  "#{e['alterrors']} #{e['diagnosis']}"
@@ -80,7 +80,7 @@ module Sisimai::Lhost
80
80
 
81
81
  MessagesOf.each_key do |r|
82
82
  # Verify each regular expression of session errors
83
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
83
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
84
84
  e['reason'] = r
85
85
  break
86
86
  end
@@ -26,7 +26,7 @@ module Sisimai::Lhost
26
26
  match += 1 if mhead['reply-to'].to_s == 'no-reply@app.auone-net.jp'
27
27
  match += 1 if mhead['received'].any? { |a| a.include?('ezweb.ne.jp (') }
28
28
  match += 1 if mhead['received'].any? { |a| a.include?('.au.com (') }
29
- return nil unless match > 0
29
+ return nil if match == 0
30
30
 
31
31
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
32
32
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -55,7 +55,7 @@ module Sisimai::Lhost
55
55
  v = dscontents[-1]
56
56
  end
57
57
  r = Sisimai::Address.s3s4(e[e.index('<') + 1, e.size])
58
- next unless Sisimai::Address.is_emailaddress(r)
58
+ next if Sisimai::Address.is_emailaddress(r) == false
59
59
  v['recipient'] = r
60
60
  recipients += 1
61
61
 
@@ -67,7 +67,7 @@ module Sisimai::Lhost
67
67
  v['diagnosis'] += "#{e} " if e.start_with?(' ')
68
68
  end
69
69
  end
70
- return nil unless recipients > 0
70
+ return nil if recipients == 0
71
71
 
72
72
  require 'sisimai/smtp/command'
73
73
  dscontents.each do |e|
@@ -86,7 +86,7 @@ module Sisimai::Lhost
86
86
  # SMTP command is not RCPT
87
87
  MessagesOf.each_key do |r|
88
88
  # Verify each regular expression of session errors
89
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
89
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
90
90
  e['reason'] = r
91
91
  break
92
92
  end
@@ -18,8 +18,8 @@ module Sisimai::Lhost
18
18
  # @return [Hash] Bounce data list and message/rfc822 part
19
19
  # @return [Nil] it failed to decode or the arguments are missing
20
20
  def inquire(mhead, mbody)
21
- return nil unless mhead['subject'] == 'Message delivery has failed'
22
- return nil unless mhead['received'].any? { |a| a.include?('(MAILFOUNDRY) id ') }
21
+ return nil if mhead['subject'] != 'Message delivery has failed'
22
+ return nil if mhead['received'].none? { |a| a.include?('(MAILFOUNDRY) id ') }
23
23
 
24
24
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
25
25
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -64,7 +64,7 @@ module Sisimai::Lhost
64
64
  end
65
65
  end
66
66
  end
67
- return nil unless recipients > 0
67
+ return nil if recipients == 0
68
68
 
69
69
  dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
70
70
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
@@ -1,8 +1,8 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::MailMarshalSMTP decodes a bounce email which created by Trustwave Secure Email
2
+ # Sisimai::Lhost::MailMarshal decodes a bounce email which created by Trustwave Secure Email
3
3
  # Gateway: formerly MailMarshal SMTP https://www.trustwave.com/en-us/services/email-security/.
4
4
  # Methods in the module are called from only Sisimai::Message.
5
- module MailMarshalSMTP
5
+ module MailMarshal
6
6
  class << self
7
7
  require 'sisimai/lhost'
8
8
 
@@ -14,13 +14,13 @@ module Sisimai::Lhost
14
14
  rcpts: ['The following recipients were affected:'],
15
15
  }.freeze
16
16
 
17
- # @abstract Decodes the bounce message from Trustwave Secure Email Gateway (Formerly MailMarshalSMTP)
17
+ # @abstract Decodes the bounce message from Trustwave Secure Email Gateway (Formerly MailMarshal)
18
18
  # @param [Hash] mhead Message headers of a bounce email
19
19
  # @param [String] mbody Message body of a bounce email
20
20
  # @return [Hash] Bounce data list and message/rfc822 part
21
21
  # @return [Nil] it failed to decode or the arguments are missing
22
22
  def inquire(mhead, mbody)
23
- return nil unless mhead['subject'].start_with?('Undeliverable Mail: "')
23
+ return nil if mhead['subject'].start_with?('Undeliverable Mail: "') == false
24
24
 
25
25
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
26
26
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -109,7 +109,7 @@ module Sisimai::Lhost
109
109
  end
110
110
  end
111
111
  end
112
- return nil unless recipients > 0
112
+ return nil if recipients == 0
113
113
 
114
114
  dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
115
115
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }