sisimai 5.4.1-java → 5.5.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 (146) 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 +35 -0
  5. data/Makefile +2 -4
  6. data/README-JA.md +23 -20
  7. data/README.md +23 -20
  8. data/lib/sisimai/address.rb +92 -44
  9. data/lib/sisimai/arf.rb +7 -8
  10. data/lib/sisimai/datetime.rb +2 -2
  11. data/lib/sisimai/fact/json.rb +1 -2
  12. data/lib/sisimai/fact/yaml.rb +1 -2
  13. data/lib/sisimai/fact.rb +60 -35
  14. data/lib/sisimai/lda.rb +2 -2
  15. data/lib/sisimai/lhost/activehunter.rb +4 -5
  16. data/lib/sisimai/lhost/amazonses.rb +3 -4
  17. data/lib/sisimai/lhost/apachejames.rb +2 -2
  18. data/lib/sisimai/lhost/biglobe.rb +6 -6
  19. data/lib/sisimai/lhost/courier.rb +7 -7
  20. data/lib/sisimai/lhost/domino.rb +6 -6
  21. data/lib/sisimai/lhost/dragonfly.rb +5 -5
  22. data/lib/sisimai/lhost/einsundeins.rb +4 -4
  23. data/lib/sisimai/lhost/exchange2003.rb +7 -7
  24. data/lib/sisimai/lhost/exchange2007.rb +3 -3
  25. data/lib/sisimai/lhost/exim.rb +7 -7
  26. data/lib/sisimai/lhost/ezweb.rb +3 -2
  27. data/lib/sisimai/lhost/fml.rb +9 -9
  28. data/lib/sisimai/lhost/gmail.rb +9 -9
  29. data/lib/sisimai/lhost/gmx.rb +3 -3
  30. data/lib/sisimai/lhost/googlegroups.rb +6 -7
  31. data/lib/sisimai/lhost/googleworkspace.rb +5 -6
  32. data/lib/sisimai/lhost/imailserver.rb +4 -4
  33. data/lib/sisimai/lhost/kddi.rb +4 -4
  34. data/lib/sisimai/lhost/mailfoundry.rb +3 -3
  35. data/lib/sisimai/lhost/{mailmarshalsmtp.rb → mailmarshal.rb} +5 -5
  36. data/lib/sisimai/lhost/messagingserver.rb +8 -8
  37. data/lib/sisimai/lhost/mfilter.rb +8 -4
  38. data/lib/sisimai/lhost/mimecast.rb +105 -0
  39. data/lib/sisimai/lhost/notes.rb +5 -5
  40. data/lib/sisimai/lhost/opensmtpd.rb +5 -5
  41. data/lib/sisimai/lhost/postfix.rb +38 -32
  42. data/lib/sisimai/lhost/qmail.rb +6 -6
  43. data/lib/sisimai/lhost/sendmail.rb +13 -13
  44. data/lib/sisimai/lhost/{interscanmss.rb → trendmicro.rb} +8 -9
  45. data/lib/sisimai/lhost/v5sendmail.rb +7 -7
  46. data/lib/sisimai/lhost/verizon.rb +3 -3
  47. data/lib/sisimai/lhost/x1.rb +7 -4
  48. data/lib/sisimai/lhost/x2.rb +40 -12
  49. data/lib/sisimai/lhost/x3.rb +3 -3
  50. data/lib/sisimai/lhost/x6.rb +2 -2
  51. data/lib/sisimai/lhost/zoho.rb +5 -5
  52. data/lib/sisimai/lhost.rb +18 -17
  53. data/lib/sisimai/mail/maildir.rb +4 -4
  54. data/lib/sisimai/mail/mbox.rb +4 -4
  55. data/lib/sisimai/mail/memory.rb +1 -1
  56. data/lib/sisimai/mail/stdin.rb +2 -2
  57. data/lib/sisimai/message.rb +34 -34
  58. data/lib/sisimai/order.rb +5 -4
  59. data/lib/sisimai/reason/authfailure.rb +1 -1
  60. data/lib/sisimai/reason/badreputation.rb +1 -1
  61. data/lib/sisimai/reason/blocked.rb +2 -1
  62. data/lib/sisimai/reason/contenterror.rb +1 -2
  63. data/lib/sisimai/reason/exceedlimit.rb +1 -1
  64. data/lib/sisimai/reason/expired.rb +1 -1
  65. data/lib/sisimai/reason/failedstarttls.rb +1 -1
  66. data/lib/sisimai/reason/filtered.rb +1 -1
  67. data/lib/sisimai/reason/hasmoved.rb +1 -1
  68. data/lib/sisimai/reason/hostunknown.rb +2 -2
  69. data/lib/sisimai/reason/mailboxfull.rb +1 -1
  70. data/lib/sisimai/reason/mailererror.rb +1 -1
  71. data/lib/sisimai/reason/mesgtoobig.rb +1 -1
  72. data/lib/sisimai/reason/networkerror.rb +1 -1
  73. data/lib/sisimai/reason/norelaying.rb +2 -2
  74. data/lib/sisimai/reason/notaccept.rb +2 -3
  75. data/lib/sisimai/reason/notcompliantrfc.rb +1 -1
  76. data/lib/sisimai/reason/policyviolation.rb +2 -4
  77. data/lib/sisimai/reason/rejected.rb +5 -3
  78. data/lib/sisimai/reason/requireptr.rb +1 -1
  79. data/lib/sisimai/reason/securityerror.rb +1 -1
  80. data/lib/sisimai/reason/spamdetected.rb +1 -1
  81. data/lib/sisimai/reason/speeding.rb +1 -1
  82. data/lib/sisimai/reason/suspend.rb +2 -1
  83. data/lib/sisimai/reason/systemerror.rb +1 -1
  84. data/lib/sisimai/reason/systemfull.rb +1 -1
  85. data/lib/sisimai/reason/toomanyconn.rb +1 -1
  86. data/lib/sisimai/reason/userunknown.rb +4 -3
  87. data/lib/sisimai/reason/vacation.rb +1 -1
  88. data/lib/sisimai/reason/virusdetected.rb +1 -1
  89. data/lib/sisimai/reason.rb +12 -12
  90. data/lib/sisimai/rfc1123.rb +58 -18
  91. data/lib/sisimai/rfc1894.rb +6 -8
  92. data/lib/sisimai/rfc2045.rb +25 -13
  93. data/lib/sisimai/rfc3464/thirdparty.rb +2 -3
  94. data/lib/sisimai/rfc3464.rb +6 -6
  95. data/lib/sisimai/rfc3834.rb +18 -8
  96. data/lib/sisimai/rfc5322.rb +9 -9
  97. data/lib/sisimai/rfc791.rb +2 -2
  98. data/lib/sisimai/rhost/aol.rb +4 -1
  99. data/lib/sisimai/rhost/apple.rb +11 -7
  100. data/lib/sisimai/rhost/cox.rb +9 -5
  101. data/lib/sisimai/rhost/facebook.rb +9 -3
  102. data/lib/sisimai/rhost/franceptt.rb +86 -37
  103. data/lib/sisimai/rhost/godaddy.rb +10 -1
  104. data/lib/sisimai/rhost/google.rb +6 -6
  105. data/lib/sisimai/rhost/gsuite.rb +1 -1
  106. data/lib/sisimai/rhost/kddi.rb +1 -1
  107. data/lib/sisimai/rhost/messagelabs.rb +160 -2
  108. data/lib/sisimai/rhost/microsoft.rb +77 -26
  109. data/lib/sisimai/rhost/mimecast.rb +30 -21
  110. data/lib/sisimai/rhost/nttdocomo.rb +69 -89
  111. data/lib/sisimai/rhost/outlook.rb +1 -1
  112. data/lib/sisimai/rhost/spectrum.rb +1 -1
  113. data/lib/sisimai/rhost/tencent.rb +5 -4
  114. data/lib/sisimai/rhost/yahooinc.rb +2 -2
  115. data/lib/sisimai/rhost/zoho.rb +72 -0
  116. data/lib/sisimai/rhost.rb +4 -3
  117. data/lib/sisimai/smtp/command.rb +2 -2
  118. data/lib/sisimai/smtp/reply.rb +11 -4
  119. data/lib/sisimai/smtp/status.rb +17 -8
  120. data/lib/sisimai/smtp/transcript.rb +3 -3
  121. data/lib/sisimai/string.rb +6 -10
  122. data/lib/sisimai/version.rb +1 -1
  123. data/lib/sisimai.rb +1 -1
  124. data/set-of-emails/maildir/bsd/lhost-exim-56.eml +40 -40
  125. data/set-of-emails/maildir/bsd/lhost-mfilter-05.eml +41 -0
  126. data/set-of-emails/maildir/bsd/lhost-mimecast-01.eml +46 -0
  127. data/set-of-emails/maildir/bsd/lhost-mimecast-02.eml +59 -0
  128. data/set-of-emails/maildir/bsd/lhost-postfix-79.eml +81 -0
  129. data/set-of-emails/maildir/bsd/lhost-postfix-80.eml +84 -0
  130. data/set-of-emails/maildir/bsd/lhost-x1-03.eml +26 -0
  131. data/set-of-emails/maildir/bsd/lhost-x1-04.eml +45 -0
  132. data/set-of-emails/maildir/bsd/lhost-x2-07.eml +30 -0
  133. data/set-of-emails/maildir/bsd/rfc3464-66.eml +170 -0
  134. data/set-of-emails/maildir/bsd/rfc3834-06.eml +59 -0
  135. data/set-of-emails/maildir/bsd/rhost-zoho-01.eml +88 -0
  136. data/set-of-emails/maildir/bsd/rhost-zoho-02.eml +86 -0
  137. data/set-of-emails/maildir/bsd/rhost-zoho-03.eml +87 -0
  138. data/set-of-emails/maildir/bsd/rhost-zoho-04.eml +86 -0
  139. data/set-of-emails/maildir/not/rb-issue-368-bug.eml +39 -0
  140. data/sisimai-java.gemspec +1 -1
  141. data/sisimai.gemspec +1 -1
  142. metadata +26 -9
  143. /data/set-of-emails/maildir/bsd/{lhost-mailmarshalsmtp-02.eml → lhost-mailmarshal-02.eml} +0 -0
  144. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-01.eml → lhost-trendmicro-01.eml} +0 -0
  145. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-02.eml → lhost-trendmicro-02.eml} +0 -0
  146. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-03.eml → lhost-trendmicro-03.eml} +0 -0
@@ -8,8 +8,7 @@ module Sisimai
8
8
  # @param [Sisimai::Fact] argvs Object
9
9
  # @return [String] Dumped data or an empty string if the argument is missing
10
10
  def dump(argvs)
11
- return "" unless argvs
12
- return "" unless argvs.is_a? Sisimai::Fact
11
+ return "" if argvs.nil? || argvs.is_a?(Sisimai::Fact) == false
13
12
 
14
13
  if RUBY_PLATFORM.start_with?('java')
15
14
  # java-based ruby environment like JRuby.
@@ -10,8 +10,7 @@ module Sisimai
10
10
  # @param [Sisimai::Fact] argvs Object
11
11
  # @return [String, nil] Dumped data or nil if the argument is missing
12
12
  def dump(argvs)
13
- return "" unless argvs
14
- return "" unless argvs.is_a? Sisimai::Fact
13
+ return "" if argvs.nil? || argvs.is_a?(Sisimai::Fact) == false
15
14
 
16
15
  damneddata = argvs.damn
17
16
  yamlstring = nil
data/lib/sisimai/fact.rb CHANGED
@@ -43,6 +43,7 @@ module Sisimai
43
43
  :timestamp, # [Sisimai::Time] Date: header in the original message
44
44
  :timezoneoffset, # [Integer] Time zone offset(seconds)
45
45
  :token, # [String] Message token/MD5 Hex digest value
46
+ :toxic, # [Boolean] EXPERIMENTAL
46
47
  ]
47
48
  attr_accessor(*@@rwaccessors)
48
49
 
@@ -93,6 +94,7 @@ module Sisimai
93
94
  @token = argvs['token']
94
95
  @timestamp = argvs['timestamp']
95
96
  @timezoneoffset = argvs['timezoneoffset']
97
+ @toxic = argvs['toxic']
96
98
  end
97
99
 
98
100
  # Constructor of Sisimai::Fact
@@ -104,15 +106,12 @@ module Sisimai
104
106
  # @options argvs [String] origin Path to the original email file
105
107
  # @return [Array] Array of Sisimai::Fact objects
106
108
  def self.rise(**argvs)
107
- return nil unless argvs
108
- return nil unless argvs.is_a? Hash
109
+ return nil if argvs.is_a?(Hash) == false
109
110
 
110
- email = argvs[:data]; return nil unless email
111
+ email = argvs[:data]; return nil if email.nil?
111
112
  args1 = {data: email, hook: argvs[:hook]}
112
113
  mesg1 = Sisimai::Message.rise(**args1)
113
- return nil unless mesg1
114
- return nil unless mesg1['ds']
115
- return nil unless mesg1['rfc822']
114
+ return nil if mesg1.nil? || mesg1['ds'].nil? || mesg1['rfc822'].nil?
116
115
 
117
116
  deliveries = mesg1['ds'].dup
118
117
  rfc822data = mesg1['rfc822']
@@ -142,36 +141,36 @@ module Sisimai
142
141
  "replycode" => e["replycode"],
143
142
  "rhost" => e["rhost"],
144
143
  "decodedby" => e["agent"],
144
+ "toxic" => e["toxic"],
145
145
  }
146
146
 
147
147
  # EMAILADDRESS: Detect an email address from message/rfc822 part
148
148
  RFC822Head[:addresser].each do |f|
149
149
  # Check each header in message/rfc822 part
150
- next unless rfc822data[f]
151
- next if rfc822data[f].empty?
150
+ next if rfc822data[f].nil? || rfc822data[f].empty?
152
151
 
153
152
  j = Sisimai::Address.find(rfc822data[f]) || next
154
153
  piece['addresser'] = j.shift
155
154
  break
156
155
  end
157
156
 
158
- unless piece['addresser']
157
+ if piece['addresser'].nil?
159
158
  # Fallback: Get the sender address from the header of the bounced email if the address is
160
159
  # not set at loop above.
161
160
  j = Sisimai::Address.find(mesg1['header']['to']) || []
162
161
  piece['addresser'] = j.shift
163
162
  end
164
- next unless piece['addresser']
163
+ next if piece['addresser'].nil?
165
164
 
166
165
  # TIMESTAMP: Convert from a time stamp or a date string to a machine time.
167
166
  datestring = nil
168
167
  zoneoffset = 0
169
- datevalues = []; datevalues << e['date'] unless e['date'].to_s.empty?
168
+ datevalues = []; datevalues << e['date'] if e['date'].to_s.empty? == false
170
169
 
171
170
  # Date information did not exist in message/delivery-status part,...
172
171
  RFC822Head[:date].each do |f|
173
172
  # Get the value of Date header or other date related header.
174
- next unless rfc822data[f]
173
+ next if rfc822data[f].nil?
175
174
  datevalues << rfc822data[f]
176
175
  end
177
176
 
@@ -197,7 +196,7 @@ module Sisimai
197
196
  rescue
198
197
  warn " ***warning: Failed to strptime #{datestring.to_s}"
199
198
  end
200
- next unless piece['timestamp']
199
+ next if piece['timestamp'].nil?
201
200
 
202
201
  # OTHER_TEXT_HEADERS:
203
202
  recv = mesg1["header"]["received"] || []
@@ -213,7 +212,7 @@ module Sisimai
213
212
  # Check the Received: headers backwards and get a remote hostname
214
213
  break if piece["rhost"].size > 0
215
214
  cv = Sisimai::RFC5322.received(re)[0]
216
- next unless Sisimai::RFC1123.is_internethost(cv)
215
+ next if Sisimai::RFC1123.is_internethost(cv) == false
217
216
  piece['rhost'] = cv
218
217
  end
219
218
  end
@@ -225,7 +224,7 @@ module Sisimai
225
224
  recv.each do |le|
226
225
  # Check the Received: headers backwards and get a local hostname
227
226
  cv = Sisimai::RFC5322.received(le)[0]
228
- next unless Sisimai::RFC1123.is_internethost(cv)
227
+ next if Sisimai::RFC1123.is_internethost(cv) == false
229
228
  piece['lhost'] = cv
230
229
  break
231
230
  end
@@ -241,7 +240,7 @@ module Sisimai
241
240
  end
242
241
  piece[v].delete!('[]()') # Remove square brackets and curly brackets from the host variable
243
242
  piece[v].sub!(/\A.+=/, '') # Remove string before "="
244
- piece[v].sub!("\r", '') # Remove CR at the end of the value
243
+ piece[v].delete_suffix("\r")# Remove CR at the end of the value
245
244
 
246
245
  if piece[v].include?(' ')
247
246
  # Check space character in each value and get the first hostname
@@ -255,13 +254,13 @@ module Sisimai
255
254
  end
256
255
  end
257
256
  piece[v] = ee[0] if piece[v].include?(' ')
258
- piece[v].chomp!('.') if piece[v].end_with?('.') # Remove "." at the end of the value
257
+ piece[v].delete_suffix!('.') # Remove "." at the end of the value
259
258
  end
260
259
 
261
260
  # Subject: header of the original message
262
261
  piece['subject'] = rfc822data['subject'] || ''
263
262
  piece['subject'].scrub!('?')
264
- piece['subject'].chomp!("\r") if piece['subject'].end_with?("\r")
263
+ piece['subject'].delete_suffix("\r")
265
264
 
266
265
  # The value of "List-Id" header
267
266
  if Sisimai::String.aligned(rfc822data['list-id'], ['<', '.', '>'])
@@ -290,7 +289,7 @@ module Sisimai
290
289
  # CHECK_DELIVERY_STATUS_VALUE: Cleanup the value of "Diagnostic-Code:" header
291
290
  if piece['diagnosticcode'].to_s.size > 0
292
291
  # Get an SMTP Reply Code and an SMTP Enhanced Status Code
293
- piece['diagnosticcode'].chop if piece['diagnosticcode'][-1, 1] == "\r"
292
+ piece['diagnosticcode'].delete_suffix("\r")
294
293
 
295
294
  cs = Sisimai::SMTP::Status.find(piece['diagnosticcode'])
296
295
  cr = Sisimai::SMTP::Reply.find(piece['diagnosticcode'], cs)
@@ -355,11 +354,11 @@ module Sisimai
355
354
 
356
355
  piece["diagnostictype"] = "X-UNIX" if piece["reason"] == "mailererror"
357
356
  if piece["diagnostictype"].empty?
358
- piece["diagnostictype"] = "SMTP" unless %w[feedback vacation].include?(piece["reason"])
357
+ piece["diagnostictype"] = "SMTP" if %w[feedback vacation].include?(piece["reason"]) == false
359
358
  end
360
359
 
361
360
  # Check the value of SMTP command
362
- piece['command'] = '' unless Sisimai::SMTP::Command.test(piece['command'])
361
+ piece['command'] = '' if Sisimai::SMTP::Command.test(piece['command']) == false
363
362
 
364
363
  # Create parameters for the constructor
365
364
  as = Sisimai::Address.new(piece['addresser']) || next; next if as.void
@@ -383,6 +382,7 @@ module Sisimai
383
382
  thing['catch'] = piece['catch'] || nil
384
383
  thing["feedbackid"] = ""
385
384
  thing['hardbounce'] = piece['hardbounce']
385
+ thing['toxic'] = piece['toxic']
386
386
  thing['replycode'] = Sisimai::SMTP::Reply.find(piece['diagnosticcode']) if thing['replycode'].empty?
387
387
  thing['timestamp'] = TimeModule.parse(::Time.at(piece['timestamp']).to_s)
388
388
  thing['timezoneoffset'] = piece['timezoneoffset'] || '+0000'
@@ -394,16 +394,15 @@ module Sisimai
394
394
  # when the recipient address is same with the value of thing['alias'].
395
395
  break if thing['alias'].empty?
396
396
  break if thing['recipient'].address != thing['alias']
397
- break unless rfc822data.has_key?('received')
397
+ break if rfc822data.has_key?('received') == false
398
398
  break if rfc822data['received'].empty?
399
399
 
400
400
  rfc822data['received'].reverse.each do |er|
401
401
  # Search for the string " for " from the Received: header
402
- next unless er.include?(' for ')
402
+ next if er.include?(' for ') == false
403
403
 
404
404
  af = Sisimai::RFC5322.received(er)
405
- next if af.empty? || af[5].empty?
406
- next unless Sisimai::Address.is_emailaddress(af[5])
405
+ next if af.empty? || af[5].empty? || Sisimai::Address.is_emailaddress(af[5]) == false
407
406
  next if thing['recipient'].address == af[5]
408
407
 
409
408
  thing['alias'] = af[5]
@@ -430,7 +429,7 @@ module Sisimai
430
429
  # HARDBOUNCE: Set the value of "hardbounce", default value of "bouncebounce" is false
431
430
  if thing['reason'] == 'delivered' || thing['reason'] == 'feedback' || thing['reason'] == 'vacation'
432
431
  # Delete the value of ReplyCode when the Reason is "feedback" or "vacation"
433
- thing['replycode'] = '' unless thing['reason'] == 'delivered'
432
+ thing['replycode'] = '' if thing['reason'] != 'delivered'
434
433
  else
435
434
  # The reason is not "delivered", or "feedback", or "vacation"
436
435
  smtperrors = "#{piece['deliverystatus']} #{piece['diagnosticcode']}"
@@ -456,7 +455,7 @@ module Sisimai
456
455
  thing['replycode'] = cx[1].start_with?(cx[0]) ? cx[1] : ''
457
456
  end
458
457
 
459
- unless ActionList.has_key?(thing['action'])
458
+ if ActionList.has_key?(thing['action']) == false
460
459
  # There is an action value which is not described at RFC1894
461
460
  if ox = Sisimai::RFC1894.field("Action: #{thing['action']}")
462
461
  # Rewrite the value of "Action:" field to the valid value
@@ -484,12 +483,44 @@ module Sisimai
484
483
 
485
484
  # Feedback-ID: 1.us-west-2.QHuyeCQrGtIIMGKQfVdUhP9hCQR2LglVOrRamBc+Prk=:AmazonSES
486
485
  thing["feedbackid"] = rfc822data["feedback-id"] || ""
486
+ thing["toxic"] ||= is_toxic(thing)
487
487
 
488
488
  listoffact << Sisimai::Fact.new(thing)
489
489
  end
490
490
  return listoffact
491
491
  end
492
492
 
493
+ def self.is_toxic(thing = nil)
494
+ return false unless thing
495
+ cr = thing['reason'] || 'undefined'
496
+ cv = thing['replycode'] || ''
497
+ cw = thing['deliverystatus'] || ''
498
+
499
+ # 1. Hard bounces or some soft bounces with a permanent error.
500
+ # 1-1. Hard bounce: UserUnknown, HostUnknown, HasMoved, NotAccept
501
+ # 1-2. Almost hard bounce: Suspend, Suppressed
502
+ return false if cv.start_with?('4') || cw.start_with?('4')
503
+ return true if %w[userunknown hostunknown hasmoved notaccept suspend suppressed].any? { |a| cr == a }
504
+
505
+ if %w[mailboxfull filtered norelaying].any? { |a| cr == a }
506
+ # 2. Several softbounces: MailboxFull, Filtered, NoRelaying
507
+ # 2-1. The SMTP command is "RCPT" except "MailboxFull".
508
+ # 2-2. The SMTP reply code begins with "5" such as "550".
509
+ # 2-3. The SMTP status code is explicit code (not empty, not 5.0.9XX).
510
+ # 2-4. The SMTP status code begins with "5." such as "5.1.1".
511
+ return true if cr != 'mailboxfull' && thing['command'] == "RCPT"
512
+ return true if cv.start_with?('5')
513
+ return false if Sisimai::SMTP::Status.is_explicit(cw) == false
514
+ return true if cw.start_with?('5.')
515
+
516
+ elsif cr == 'feedback'
517
+ # 3. Feedback Loop
518
+ # 3-1. The Feedback Type is any of "abuse", "fraud", "opt-out"
519
+ return true if %w[abuse fraud opt-out].any? { |a| thing['feedbacktype'] == a }
520
+ end
521
+ return false
522
+ end
523
+
493
524
  # Convert from Sisimai::Fact object to a Hash
494
525
  # @return [Hash] Hashed data
495
526
  def damn
@@ -504,13 +535,10 @@ module Sisimai
504
535
  v = {}
505
536
  stringdata.each { |e| v[e] = self.send(e.to_sym) || '' }
506
537
  v['hardbounce'] = self.hardbounce
538
+ v['toxic'] = self.toxic
507
539
  v['addresser'] = self.addresser.address
508
540
  v['recipient'] = self.recipient.address
509
541
  v['timestamp'] = self.timestamp.to_time.to_i
510
-
511
- # Backward compatibility until v5.5.0
512
- v["smtpagent"] = self.decodedby
513
- v["smtpcommand"] = self.command
514
542
  data = v
515
543
  rescue
516
544
  warn ' ***warning: Failed to execute Sisimai::Fact.damn'
@@ -524,7 +552,7 @@ module Sisimai
524
552
  # @return [String] data
525
553
  # [Nil] The value of the first argument is neither "json" nor "yaml"
526
554
  def dump(type = 'json')
527
- return nil unless %w[json yaml].include?(type)
555
+ return nil if %w[json yaml].include?(type) == false
528
556
  referclass = "Sisimai::Fact::#{type.upcase}"
529
557
 
530
558
  begin
@@ -542,9 +570,6 @@ module Sisimai
542
570
  def to_json(*)
543
571
  return self.dump('json')
544
572
  end
545
-
546
- def smtpagent; warn " ***warning: Sisimai::Fact.smtpagent will be removed at v5.5.0"; return self.decodedby; end
547
- def smtpcomand; warn " ***warning: Sisimai::Fact.smtpcommand will be removed at v5.5.0"; return self.command; end
548
573
  end
549
574
  end
550
575
 
data/lib/sisimai/lda.rb CHANGED
@@ -78,14 +78,14 @@ module Sisimai
78
78
 
79
79
  LocalAgent.each_key do |e|
80
80
  # Find a lcoal delivery agent name from the entire message body
81
- next unless LocalAgent[e].any? { |a| issuedcode.include?(a) }
81
+ next if LocalAgent[e].none? { |a| issuedcode.include?(a) }
82
82
  deliversby = e; break
83
83
  end
84
84
  return "" if deliversby.empty?
85
85
 
86
86
  MessagesOf[deliversby].each_key do |e|
87
87
  # The key is a bounce reason name
88
- next unless MessagesOf[deliversby][e].any? { |a| issuedcode.include?(a) }
88
+ next if MessagesOf[deliversby][e].none? { |a| issuedcode.include?(a) }
89
89
  reasontext = e; break
90
90
  end
91
91
 
@@ -18,7 +18,7 @@ module Sisimai::Lhost
18
18
  def inquire(mhead, mbody)
19
19
  # :from => %r/\A"MAILER-DAEMON"/,
20
20
  # :subject => %r/FAILURE NOTICE :/,
21
- return nil unless mhead['x-ahmailid']
21
+ return nil if mhead['x-ahmailid'].nil?
22
22
 
23
23
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
24
24
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -57,13 +57,12 @@ module Sisimai::Lhost
57
57
  else
58
58
  # ----- Transcript of session follows -----
59
59
  # 550 sorry, no mailbox here by that name (#5.1.1 - chkusr)
60
- next if e[0, 1].ord < 48
61
- next if e[0, 1].ord > 122
62
- next unless v['diagnosis'].empty?
60
+ next if e[0, 1].ord < 48 || e[0, 1].ord > 122
61
+ next if v['diagnosis'].empty? == false
63
62
  v['diagnosis'] = e
64
63
  end
65
64
  end
66
- return nil unless recipients > 0
65
+ return nil if recipients == 0
67
66
 
68
67
  dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
69
68
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
@@ -45,7 +45,7 @@ module Sisimai::Lhost
45
45
  require 'sisimai/lhost'
46
46
 
47
47
  ReasonPair = {
48
- "Supressed" => "suppressed",
48
+ "Suppressed" => "suppressed",
49
49
  "OnAccountSuppressionList" => "suppressed",
50
50
  "General" => "onhold",
51
51
  "MailboxFull" => "mailboxfull",
@@ -87,8 +87,7 @@ module Sisimai::Lhost
87
87
  p3 = sespayload.index("{", p2 + 9)
88
88
  p4 = sespayload.index("\n", p2 + 9)
89
89
  sespayload = sespayload[p3, p4 - p3]
90
- sespayload = sespayload.chop if sespayload[-1, 1] == ","
91
- sespayload = sespayload.chop if sespayload[-1, 1] == '"'
90
+ sespayload = sespayload.delete_suffix(',').delete_suffix('"')
92
91
  end
93
92
 
94
93
  break if sespayload.include?("notificationType") == false
@@ -150,7 +149,7 @@ module Sisimai::Lhost
150
149
 
151
150
  ReasonPair.each_key do |f|
152
151
  # Try to find the bounce reason by "bounceSubType"
153
- next unless ReasonPair[f] == p["bounceSubType"]
152
+ next if ReasonPair[f] != p["bounceSubType"]
154
153
  v["reason"] = f; break
155
154
  end
156
155
 
@@ -24,7 +24,7 @@ module Sisimai::Lhost
24
24
  match += 1 if mhead["subject"] == "[BOUNCE]"
25
25
  match += 1 if mhead["message-id"].to_s.include?(".JavaMail.")
26
26
  match += 1 if mhead["received"].any? { |a| a.include?("JAMES SMTP Server") }
27
- return nil unless match > 0
27
+ return nil if match == 0
28
28
 
29
29
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = dscontents[-1]
30
30
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -87,7 +87,7 @@ module Sisimai::Lhost
87
87
 
88
88
  end
89
89
  end
90
- return nil unless recipients > 0
90
+ return nil if recipients == 0
91
91
 
92
92
  if emailparts[1].empty?
93
93
  # The original message is empty
@@ -22,9 +22,9 @@ module Sisimai::Lhost
22
22
  # @return [Hash] Bounce data list and message/rfc822 part
23
23
  # @return [Nil] it failed to decode or the arguments are missing
24
24
  def inquire(mhead, mbody)
25
- return nil unless mhead['from'].include?('postmaster@')
26
- return nil unless %w[biglobe inacatv tmtv ttv].any? { |a| mhead['from'].include?('@' + a + '.ne.jp') }
27
- return nil unless mhead['subject'].start_with?('Returned mail:')
25
+ return nil if mhead['from'].include?('postmaster@') == false
26
+ return nil if %w[biglobe inacatv tmtv ttv].none? { |a| mhead['from'].include?('@' + a + '.ne.jp') }
27
+ return nil if mhead['subject'].start_with?('Returned mail:') == false
28
28
 
29
29
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
30
30
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -67,7 +67,7 @@ module Sisimai::Lhost
67
67
  v = dscontents[-1]
68
68
  end
69
69
 
70
- next unless Sisimai::Address.is_emailaddress(e)
70
+ next if Sisimai::Address.is_emailaddress(e) == false
71
71
  v['recipient'] = e
72
72
  recipients += 1
73
73
  else
@@ -75,14 +75,14 @@ module Sisimai::Lhost
75
75
  v['diagnosis'] += "#{e }"
76
76
  end
77
77
  end
78
- return nil unless recipients > 0
78
+ return nil if recipients == 0
79
79
 
80
80
  dscontents.each do |e|
81
81
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
82
82
 
83
83
  MessagesOf.each_key do |r|
84
84
  # Verify each regular expression of session errors
85
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
85
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
86
86
  e['reason'] = r
87
87
  break
88
88
  end
@@ -36,7 +36,7 @@ module Sisimai::Lhost
36
36
  # Message-ID: <courier.4D025E3A.00001792@5jo.example.org>
37
37
  match += 1 if mhead['message-id'].start_with?('<courier.')
38
38
  end
39
- return nil unless match > 0
39
+ return nil if match == 0
40
40
 
41
41
  require 'sisimai/rfc1123'
42
42
  require 'sisimai/rfc1894'
@@ -94,11 +94,11 @@ module Sisimai::Lhost
94
94
  v['diagnosis'] = o[2]
95
95
  else
96
96
  # Other DSN fields defined in RFC3464
97
- next unless fieldtable[o[0]]
97
+ next if fieldtable[o[0]].nil?
98
98
  next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
99
99
  v[fieldtable[o[0]]] = o[2]
100
100
 
101
- next unless f == 1
101
+ next if f != 1
102
102
  permessage[fieldtable[o[0]]] = o[2]
103
103
  end
104
104
  else
@@ -114,14 +114,14 @@ module Sisimai::Lhost
114
114
  thecommand = Sisimai::SMTP::Command.find(e)
115
115
  else
116
116
  # Continued line of the value of Diagnostic-Code field
117
- next unless readslices[-2].start_with?('Diagnostic-Code:')
118
- next unless e.start_with?(' ')
117
+ next if readslices[-2].start_with?('Diagnostic-Code:') == false
118
+ next if e.start_with?(' ') == false
119
119
  v['diagnosis'] += " #{Sisimai::String.sweep(e)}"
120
120
  readslices[-1] = "Diagnostic-Code: #{e}"
121
121
  end
122
122
  end
123
123
  end
124
- return nil unless recipients > 0
124
+ return nil if recipients == 0
125
125
 
126
126
  dscontents.each do |e|
127
127
  # Set default values if each value is empty.
@@ -131,7 +131,7 @@ module Sisimai::Lhost
131
131
 
132
132
  MessagesOf.each_key do |r|
133
133
  # Verify each regular expression of session errors
134
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
134
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
135
135
  e['reason'] = r
136
136
  break
137
137
  end
@@ -26,7 +26,7 @@ module Sisimai::Lhost
26
26
  # @return [Hash] Bounce data list and message/rfc822 part
27
27
  # @return [Nil] it failed to decode or the arguments are missing
28
28
  def inquire(mhead, mbody)
29
- return nil unless mhead['subject'].start_with?('DELIVERY FAILURE:', 'DELIVERY_FAILURE:')
29
+ return nil if mhead['subject'].start_with?('DELIVERY FAILURE:', 'DELIVERY_FAILURE:') == false
30
30
 
31
31
  require 'sisimai/rfc1123'
32
32
  require 'sisimai/rfc1894'
@@ -107,17 +107,17 @@ module Sisimai::Lhost
107
107
  v['diagnosis'] = o[2] if v['diagnosis'].empty?
108
108
  else
109
109
  # Other DSN fields defined in RFC3464
110
- next unless fieldtable[o[0]]
110
+ next if fieldtable[o[0]].nil?
111
111
  next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
112
112
  v[fieldtable[o[0]]] = o[2]
113
113
 
114
- next unless f == 1
114
+ next if f != 1
115
115
  permessage[fieldtable[o[0]]] = o[2]
116
116
  end
117
117
  end
118
118
  end
119
119
  end
120
- return nil unless recipients > 0
120
+ return nil if recipients == 0
121
121
 
122
122
  dscontents.each do |e|
123
123
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
@@ -126,7 +126,7 @@ module Sisimai::Lhost
126
126
 
127
127
  MessagesOf.each_key do |r|
128
128
  # Check each regular expression of Domino error messages
129
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
129
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
130
130
  e['reason'] = r
131
131
  e['status'] = Sisimai::SMTP::Status.code(r, false) if e["status"].empty?
132
132
  break
@@ -134,7 +134,7 @@ module Sisimai::Lhost
134
134
  end
135
135
 
136
136
  # Set the value of subjecttxt as a Subject if there is no original message in the bounce mail.
137
- emailparts[1] += "Subject: #{subjecttxt}\n" unless emailparts[1].include?("\nSubject:")
137
+ emailparts[1] += "Subject: #{subjecttxt}\n" if emailparts[1].include?("\nSubject:") == false
138
138
 
139
139
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
140
140
  end
@@ -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
@@ -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