sisimai 5.6.0-java → 5.7.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake-test.yml +0 -4
  3. data/ChangeLog.md +32 -0
  4. data/README-JA.md +19 -16
  5. data/README.md +23 -21
  6. data/lib/sisimai/address.rb +8 -31
  7. data/lib/sisimai/arf.rb +3 -5
  8. data/lib/sisimai/fact.rb +12 -37
  9. data/lib/sisimai/lhost/activehunter.rb +0 -2
  10. data/lib/sisimai/lhost/amazonses.rb +6 -8
  11. data/lib/sisimai/lhost/apachejames.rb +0 -1
  12. data/lib/sisimai/lhost/biglobe.rb +0 -16
  13. data/lib/sisimai/lhost/courier.rb +5 -4
  14. data/lib/sisimai/lhost/deutschetelekom.rb +120 -0
  15. data/lib/sisimai/lhost/domino.rb +0 -3
  16. data/lib/sisimai/lhost/dragonfly.rb +0 -27
  17. data/lib/sisimai/lhost/einsundeins.rb +1 -10
  18. data/lib/sisimai/lhost/exchange2003.rb +4 -4
  19. data/lib/sisimai/lhost/exchange2007.rb +3 -4
  20. data/lib/sisimai/lhost/exim.rb +30 -78
  21. data/lib/sisimai/lhost/ezweb.rb +12 -49
  22. data/lib/sisimai/lhost/fml.rb +4 -29
  23. data/lib/sisimai/lhost/gmail.rb +0 -23
  24. data/lib/sisimai/lhost/gmx.rb +7 -24
  25. data/lib/sisimai/lhost/googlegroups.rb +3 -3
  26. data/lib/sisimai/lhost/googleworkspace.rb +0 -4
  27. data/lib/sisimai/lhost/imailserver.rb +3 -9
  28. data/lib/sisimai/lhost/kddi.rb +6 -20
  29. data/lib/sisimai/lhost/mailfoundry.rb +0 -2
  30. data/lib/sisimai/lhost/mailmarshal.rb +1 -3
  31. data/lib/sisimai/lhost/messagingserver.rb +4 -15
  32. data/lib/sisimai/lhost/mfilter.rb +0 -1
  33. data/lib/sisimai/lhost/mimecast.rb +0 -1
  34. data/lib/sisimai/lhost/notes.rb +1 -2
  35. data/lib/sisimai/lhost/opensmtpd.rb +0 -40
  36. data/lib/sisimai/lhost/postfix.rb +10 -11
  37. data/lib/sisimai/lhost/qmail.rb +14 -81
  38. data/lib/sisimai/lhost/sendmail.rb +4 -4
  39. data/lib/sisimai/lhost/trendmicro.rb +3 -3
  40. data/lib/sisimai/lhost/v5sendmail.rb +0 -1
  41. data/lib/sisimai/lhost/verizon.rb +1 -2
  42. data/lib/sisimai/lhost/x1.rb +1 -2
  43. data/lib/sisimai/lhost/x2.rb +0 -2
  44. data/lib/sisimai/lhost/x3.rb +4 -9
  45. data/lib/sisimai/lhost/x6.rb +0 -1
  46. data/lib/sisimai/lhost/zoho.rb +0 -12
  47. data/lib/sisimai/lhost.rb +38 -19
  48. data/lib/sisimai/message.rb +1 -1
  49. data/lib/sisimai/order.rb +4 -1
  50. data/lib/sisimai/reason/authfailure.rb +2 -2
  51. data/lib/sisimai/reason/contenterror.rb +2 -0
  52. data/lib/sisimai/reason/emailtoolarge.rb +1 -1
  53. data/lib/sisimai/reason/expired.rb +13 -2
  54. data/lib/sisimai/reason/hostunknown.rb +9 -0
  55. data/lib/sisimai/reason/mailboxfull.rb +3 -2
  56. data/lib/sisimai/reason/networkerror.rb +13 -1
  57. data/lib/sisimai/reason/norelaying.rb +4 -3
  58. data/lib/sisimai/reason/notaccept.rb +10 -3
  59. data/lib/sisimai/reason/notcompliantrfc.rb +1 -0
  60. data/lib/sisimai/reason/policyviolation.rb +6 -1
  61. data/lib/sisimai/reason/rejected.rb +6 -0
  62. data/lib/sisimai/reason/securityerror.rb +1 -0
  63. data/lib/sisimai/reason/suspend.rb +4 -0
  64. data/lib/sisimai/reason/syntaxerror.rb +1 -8
  65. data/lib/sisimai/reason/systemerror.rb +18 -0
  66. data/lib/sisimai/reason/userunknown.rb +2 -0
  67. data/lib/sisimai/reason.rb +7 -7
  68. data/lib/sisimai/rfc1123.rb +1 -1
  69. data/lib/sisimai/rfc1894.rb +7 -6
  70. data/lib/sisimai/rfc2045.rb +2 -2
  71. data/lib/sisimai/rfc3464/thirdparty.rb +1 -1
  72. data/lib/sisimai/rfc3464.rb +10 -14
  73. data/lib/sisimai/rfc3834.rb +3 -4
  74. data/lib/sisimai/rfc791.rb +3 -38
  75. data/lib/sisimai/rhost/microsoft.rb +4 -0
  76. data/lib/sisimai/rhost.rb +1 -1
  77. data/lib/sisimai/smtp/status.rb +23 -19
  78. data/lib/sisimai/string.rb +0 -12
  79. data/lib/sisimai/version.rb +1 -1
  80. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-01.eml +66 -0
  81. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-02.eml +68 -0
  82. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-03.eml +50 -0
  83. data/set-of-emails/should-not-crash/p5-664-iomart-mail-filter.eml +258 -0
  84. data/set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yet/.gitkeep +0 -0
  85. metadata +8 -2
@@ -11,17 +11,6 @@ module Sisimai::Lhost
11
11
  message: ['Delivery to the following recipient'],
12
12
  error: ['The error that the other server returned was:'],
13
13
  }.freeze
14
- MessagesOf = {
15
- 'expired' => [
16
- 'DNS Error: Could not contact DNS servers',
17
- 'Delivery to the following recipient has been delayed',
18
- 'The recipient server did not accept our requests to connect',
19
- ],
20
- 'hostunknown' => [
21
- 'DNS Error: Domain name not found',
22
- 'DNS Error: DNS server returned answer with no data',
23
- ],
24
- }.freeze
25
14
  StateTable = {
26
15
  # Technical details of permanent failure:
27
16
  # Google tried to deliver your message, but it was rejected by the recipient domain.
@@ -205,8 +194,6 @@ module Sisimai::Lhost
205
194
  require 'sisimai/string'
206
195
  require 'sisimai/rfc1123'
207
196
  dscontents.each do |e|
208
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
209
-
210
197
  if Sisimai::String.aligned(e['diagnosis'], [' by ', '. [', ']. '])
211
198
  # Get the value of remote host
212
199
  # Google tried to deliver your message, but it was rejected by the server for the recipient
@@ -232,16 +219,6 @@ module Sisimai::Lhost
232
219
  e['command'] = StateTable[cu]['command']
233
220
  break
234
221
  end
235
-
236
- if e['reason'].empty?
237
- # There is no no state code in the error message
238
- MessagesOf.each_key do |r|
239
- # Verify each regular expression of session errors
240
- next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
241
- e['reason'] = r
242
- break
243
- end
244
- end
245
222
  next if e['reason'].empty?
246
223
 
247
224
  # Set pseudo status code
@@ -8,7 +8,6 @@ module Sisimai::Lhost
8
8
  Indicators = Sisimai::Lhost.INDICATORS
9
9
  Boundaries = ['--- The header of the original message is following. ---'].freeze
10
10
  StartingOf = {message: ['This message was created automatically by mail delivery software']}.freeze
11
- MessagesOf = {'expired' => ['delivery retry timeout exceeded']}.freeze
12
11
 
13
12
  # @abstract Decodes the bounce message from GMX
14
13
  # @param [Hash] mhead Message headers of a bounce email
@@ -65,33 +64,17 @@ module Sisimai::Lhost
65
64
  end
66
65
  v['recipient'] = Sisimai::Address.s3s4(e)
67
66
  recipients += 1
68
-
69
- elsif e.start_with?('SMTP error ')
70
- # SMTP error from remote server after RCPT command:
71
- v['command'] = Sisimai::SMTP::Command.find(e)
72
-
73
- elsif e.start_with?('host:')
74
- # host: mx.example.jp
75
- v['rhost'] = e[6, e.size]
76
67
  else
77
- # Get error messages
78
- next if e.empty?
79
- v['diagnosis'] += "#{e }"
68
+ # - SMTP error from remote server after RCPT command:
69
+ # - host: mx.example.jp
70
+ case
71
+ when e.start_with?('SMTP error ') then v['command'] = Sisimai::SMTP::Command.find(e)
72
+ when e.start_with?('host:') then v['rhost'] = e[6, e.size]
73
+ else v['diagnosis'] += "#{e }" if e.empty? == false
74
+ end
80
75
  end
81
76
  end
82
77
  return nil if recipients == 0
83
-
84
- dscontents.each do |e|
85
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
86
-
87
- MessagesOf.each_key do |r|
88
- # Verify each regular expression of session errors
89
- next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
90
- e['reason'] = r
91
- break
92
- end
93
- end
94
-
95
78
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
96
79
  end
97
80
  def description; return 'GMX: https://www.gmx.net'; end
@@ -13,10 +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 if mbody.include?("Google Groups") == false
16
+ return nil if mbody.include?("Google Group") == false
17
17
  return nil if mhead['from'].end_with?('<mailer-daemon@googlemail.com>') == false
18
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?
19
+ return nil if mhead['x-failed-recipients'].nil?
20
20
 
21
21
  # Hello kijitora@libsisimai.org,
22
22
  #
@@ -46,7 +46,7 @@ module Sisimai::Lhost
46
46
  entiremesg = emailparts[0].split(/\n\n/, 5).slice(0, 4).join(' ').tr("\n", ' ');
47
47
  receivedby = mhead['received'] || []
48
48
  recordwide = {
49
- 'diagnosis' => Sisimai::String.sweep(entiremesg),
49
+ 'diagnosis' => entiremesg,
50
50
  'reason' => 'onhold',
51
51
  'rhost' => Sisimai::RFC5322.received(receivedby[0])[1],
52
52
  }
@@ -15,8 +15,6 @@ module Sisimai::Lhost
15
15
  }.freeze
16
16
  MessagesOf = {
17
17
  "userunknown" => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
- "notaccept" => ["Null MX"],
19
- "networkerror" => [" had no relevant answers.", " responded with code NXDOMAIN"],
20
18
  }.freeze
21
19
 
22
20
  # @abstract Decodes the bounce message from Google Workspace
@@ -73,8 +71,6 @@ module Sisimai::Lhost
73
71
 
74
72
  dscontents[0]["diagnosis"] = entiremesg
75
73
  dscontents.each do |e|
76
- # Tidy up the error message in e["diagnosis"], Try to detect the bounce reason.
77
- e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
78
74
  MessagesOf.each_key do |r|
79
75
  # Guess an reason of the bounce
80
76
  next if MessagesOf[r].none? { |a| e["diagnosis"].include?(a) }
@@ -9,12 +9,8 @@ module Sisimai::Lhost
9
9
  Boundaries = ['Original message follows.'].freeze
10
10
  StartingOf = {error: ['Body of message generated response:']}.freeze
11
11
  MessagesOf = {
12
- 'hostunknown' => ['Unknown host'],
13
- 'userunknown' => ['Unknown user', 'Invalid final delivery userid'],
14
- 'mailboxfull' => ['User mailbox exceeds allowed size'],
15
- 'virusdetected' => ['Requested action not taken: virus detected'],
16
- 'spamdetected' => ['Blacklisted URL in message'],
17
- 'expired' => ['Delivery failed '],
12
+ 'userunknown' => ['Unknown user', 'Invalid final delivery userid'],
13
+ 'expired' => ['Delivery failed '],
18
14
  }.freeze
19
15
 
20
16
  # @abstract Decodes the bounce message from Progress iMail Server
@@ -72,11 +68,9 @@ module Sisimai::Lhost
72
68
  else
73
69
  e['alterrors']
74
70
  end
75
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
76
71
  e.delete('alterrors')
77
72
  end
78
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
79
- e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
73
+ e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
80
74
 
81
75
  MessagesOf.each_key do |r|
82
76
  # Verify each regular expression of session errors
@@ -8,11 +8,6 @@ module Sisimai::Lhost
8
8
  Indicators = Sisimai::Lhost.INDICATORS
9
9
  Boundaries = ['Content-Type: message/rfc822'].freeze
10
10
  StartingOf = {message: ['Your mail sent on:', 'Your mail attempted to be delivered on:']}.freeze
11
- MessagesOf = {
12
- 'mailboxfull' => ['As their mailbox is full'],
13
- 'norelaying' => ['Due to the following SMTP relay error'],
14
- 'hostunknown' => ['As the remote domain doesnt exist'],
15
- }.freeze
16
11
 
17
12
  # @abstract Decodes the bounce message from au by KDDI
18
13
  # @param [Hash] mhead Message headers of a bounce email
@@ -45,7 +40,8 @@ module Sisimai::Lhost
45
40
  next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
46
41
 
47
42
  v = dscontents[-1]
48
- if e.include?(' Could not be delivered to: <')
43
+ case
44
+ when e.include?(' Could not be delivered to: <')
49
45
  # Your mail sent on: Thu, 29 Apr 2010 11:04:47 +0900
50
46
  # Could not be delivered to: <******@**.***.**>
51
47
  # As their mailbox is full.
@@ -59,7 +55,7 @@ module Sisimai::Lhost
59
55
  v['recipient'] = r
60
56
  recipients += 1
61
57
 
62
- elsif e.include?('Your mail sent on: ')
58
+ when e.include?('Your mail sent on: ')
63
59
  # Your mail sent on: Thu, 29 Apr 2010 11:04:47 +0900
64
60
  v['date'] = e[19, e.size]
65
61
  else
@@ -71,7 +67,6 @@ module Sisimai::Lhost
71
67
 
72
68
  require 'sisimai/smtp/command'
73
69
  dscontents.each do |e|
74
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
75
70
  e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
76
71
 
77
72
  if mhead['x-spasign'].to_s == 'NG'
@@ -79,18 +74,9 @@ module Sisimai::Lhost
79
74
  # Filtered recipient returns message that include 'X-SPASIGN' header
80
75
  e['reason'] = 'filtered'
81
76
  else
82
- if e['command'] == 'RCPT'
83
- # set "userunknown" when the remote server rejected after RCPT command.
84
- e['reason'] = 'userunknown'
85
- else
86
- # SMTP command is not RCPT
87
- MessagesOf.each_key do |r|
88
- # Verify each regular expression of session errors
89
- next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
90
- e['reason'] = r
91
- break
92
- end
93
- end
77
+ # There is no X-SPASIGN: header in the bounce message
78
+ # set "userunknown" when the remote server rejected after RCPT command.
79
+ e['reason'] = 'userunknown' if e['command'] == 'RCPT'
94
80
  end
95
81
  end
96
82
 
@@ -65,8 +65,6 @@ module Sisimai::Lhost
65
65
  end
66
66
  end
67
67
  return nil if recipients == 0
68
-
69
- dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
70
68
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
71
69
  end
72
70
  def description; return 'MailFoundry'; end
@@ -103,15 +103,13 @@ module Sisimai::Lhost
103
103
  p1 = e.index(' From:') || e.index(' Subject:')
104
104
  p2 = e.index(':')
105
105
  cf = e[p1 + 1, p2 - p1 - 1]
106
- cv = Sisimai::String.sweep(e[p2 + 1, e.size])
106
+ cv = e[p2 + 1, e.size]
107
107
  emailparts[1] += sprintf("%s: %s\n", cf, cv)
108
108
  end
109
109
  end
110
110
  end
111
111
  end
112
112
  return nil if recipients == 0
113
-
114
- dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
115
113
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
116
114
  end
117
115
  def description; return 'Trustwave Secure Email Gateway'; end
@@ -9,7 +9,6 @@ module Sisimai::Lhost
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
10
  Boundaries = ['Content-Type: message/rfc822', 'Return-path: '].freeze
11
11
  StartingOf = {message: ['This report relates to a message you sent with the following header fields:']}.freeze
12
- MessagesOf = {'hostunknown' => ['Illegal host/domain name found']}.freeze
13
12
 
14
13
  # @abstract Decodes the bounce message from MessagingServer
15
14
  # @param [Hash] mhead Message headers of a bounce email
@@ -115,18 +114,19 @@ module Sisimai::Lhost
115
114
  # (6jo.example.jp ESMTP SENDMAIL-VM)
116
115
  # Diagnostic-code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
117
116
  #
118
- if e.start_with?('Status: ')
117
+ case
118
+ when e.start_with?('Status: ')
119
119
  # Status: 5.1.1 (Remote SMTP server has rejected address)
120
120
  p1 = e.index(':')
121
121
  p2 = e.index('('); next if p2.nil?
122
122
  v['status'] = e[p1 + 2, p2 - p1 - 3]
123
123
  v['diagnosis'] = e[p2 + 1, e[e.index(')') - p2 - 1]] if v["diagnosis"].empty?
124
124
 
125
- elsif e.start_with?('Arrival-Date: ')
125
+ when e.start_with?('Arrival-Date: ')
126
126
  # Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT)
127
127
  v['date'] = e[e.index(':') + 2, e.size] if v["date"].empty?
128
128
 
129
- elsif e.start_with?('Reporting-MTA: ')
129
+ when e.start_with?('Reporting-MTA: ')
130
130
  # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
131
131
  localhost = e[e.index(';') + 1, e.size]
132
132
  v['lhost'] = localhost if v["lhost"].empty?
@@ -135,17 +135,6 @@ module Sisimai::Lhost
135
135
  end
136
136
  end
137
137
  return nil if recipients == 0
138
-
139
- dscontents.each do |e|
140
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
141
- MessagesOf.each_key do |r|
142
- # Verify each regular expression of session errors
143
- next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
144
- e['reason'] = r
145
- break
146
- end
147
- end
148
-
149
138
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
150
139
  end
151
140
  def description; return 'Oracle Communications Messaging Server'; end
@@ -98,7 +98,6 @@ module Sisimai::Lhost
98
98
  return nil if recipients == 0
99
99
 
100
100
  dscontents.each do |e|
101
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
102
101
  e['agent'] = 'mFILTER'
103
102
 
104
103
  # Get localhost and remote host name from Received header.
@@ -93,7 +93,6 @@ module Sisimai::Lhost
93
93
  dscontents.each do |e|
94
94
  # Set default values if each value is empty.
95
95
  permessage.each_key { |a| e[a] ||= permessage[a] || '' }
96
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
97
96
  end
98
97
 
99
98
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
@@ -13,7 +13,6 @@ module Sisimai::Lhost
13
13
  'User not listed in public Name & Address Book',
14
14
  'ディレクトリのリストにありません',
15
15
  ],
16
- 'networkerror' => ['Message has exceeded maximum hop count'],
17
16
  }.freeze
18
17
 
19
18
  # @abstract Decodes the bounce messages from HCL Notes (Formerly IBM Notes (Formerly Lotus Notes))
@@ -101,7 +100,7 @@ module Sisimai::Lhost
101
100
  return nil if recipients == 0
102
101
 
103
102
  dscontents.each do |e|
104
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
103
+ e['diagnosis'] = e['diagnosis'].split.join(" ")
105
104
  e['recipient'] = Sisimai::Address.s3s4(e['recipient'])
106
105
 
107
106
  MessagesOf.each_key do |r|
@@ -35,36 +35,6 @@ module Sisimai::Lhost
35
35
  # bounce.c/339:
36
36
  message: [' This is the MAILER-DAEMON, please DO NOT REPLY to this '],
37
37
  }.freeze
38
- MessagesOf = {
39
- # smtpd/queue.c:221| envelope_set_errormsg(&evp, "Envelope expired");
40
- 'expired' => ['Envelope expired'],
41
- # smtpd/mta.c:976| relay->failstr = "Invalid domain name";
42
- # smtpd/mta.c:980| relay->failstr = "Domain does not exist";
43
- 'hostunknown' => [
44
- 'Invalid domain name',
45
- 'Domain does not exist',
46
- ],
47
- # smtp/mta.c:1085| relay->failstr = "Destination seem to reject all mails";
48
- 'notaccept' => [
49
- 'Destination seem to reject all mails',
50
- 'No MX found for domain',
51
- 'No MX found for destination',
52
- ],
53
- # smtpd/mta.c:972| relay->failstr = "Temporary failure in MX lookup";
54
- 'networkerror' => [
55
- 'Address family mismatch on destination MXs',
56
- 'All routes to destination blocked',
57
- 'bad DNS lookup error code',
58
- 'Could not retrieve source address',
59
- 'Loop detected',
60
- 'Network error on destination MXs',
61
- 'No valid route to remote MX',
62
- 'No valid route to destination',
63
- 'Temporary failure in MX lookup',
64
- ],
65
- # smtpd/mta.c:1013| relay->failstr = "Could not retrieve credentials";
66
- 'securityerror' => ['Could not retrieve credentials'],
67
- }.freeze
68
38
 
69
39
  # @abstract Decodes the bounce message from OpenSMTPD
70
40
  # @param [Hash] mhead Message headers of a bounce email
@@ -117,16 +87,6 @@ module Sisimai::Lhost
117
87
  end
118
88
  end
119
89
  return nil if recipients == 0
120
-
121
- dscontents.each do |e|
122
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
123
- MessagesOf.each_key do |r|
124
- # Verify each regular expression of session errors
125
- next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
126
- e['reason'] = r
127
- break
128
- end
129
- end
130
90
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
131
91
  end
132
92
  def description; return 'OpenSMTPD'; end
@@ -63,15 +63,14 @@ module Sisimai::Lhost
63
63
  v ||= dscontents[-1]
64
64
  p = e['response']
65
65
 
66
- if e['command'] == 'HELO' || e['command'] == 'EHLO'
67
- # Use the argument of EHLO/HELO command as a value of "lhost"
68
- v['lhost'] = e['argument']
69
-
70
- elsif e['command'] == 'MAIL'
66
+ case e["command"]
67
+ # Use the argument of EHLO/HELO command as a value of "lhost"
68
+ when "HELO", "EHLO" then v['lhost'] = e['argument']
69
+ when "MAIL"
71
70
  # Set the argument of "MAIL" command to pseudo To: header of the original message
72
71
  emailparts[1] += sprintf("To: %s\n", e['argument']) if emailparts[1].size == 0
73
72
 
74
- elsif e['command'] == 'RCPT'
73
+ when "RCPT"
75
74
  # RCPT TO: <...>
76
75
  if v["recipient"] != ""
77
76
  # There are multiple recipient addresses in the transcript of session
@@ -110,7 +109,8 @@ module Sisimai::Lhost
110
109
  next unless o = Sisimai::RFC1894.field(e)
111
110
  v = dscontents[-1]
112
111
 
113
- if o[3] == 'addr'
112
+ case o[3]
113
+ when "addr"
114
114
  # Final-Recipient: rfc822; kijitora@example.jp
115
115
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
116
116
  if Sisimai::Address.is_emailaddress(o[2])
@@ -130,7 +130,7 @@ module Sisimai::Lhost
130
130
  v['alias'] = o[2]
131
131
  end
132
132
  end
133
- elsif o[3] == 'code'
133
+ when "code"
134
134
  # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
135
135
  v['spec'] = o[1]
136
136
  v['spec'] = 'SMTP' if v['spec'].upcase == 'X-POSTFIX'
@@ -154,7 +154,7 @@ module Sisimai::Lhost
154
154
  # 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO command)
155
155
  if readslices[-2].start_with?('Diagnostic-Code:') && e.include?(' ')
156
156
  # Continued line of the value of Diagnostic-Code header
157
- v['diagnosis'] += " #{Sisimai::String.sweep(e)}"
157
+ v['diagnosis'] += " " + e.split.join(" ")
158
158
  readslices[-1] = "Diagnostic-Code: #{e}"
159
159
 
160
160
  elsif Sisimai::String.aligned(e, ['X-Postfix-Sender:', 'rfc822;', '@'])
@@ -238,7 +238,7 @@ module Sisimai::Lhost
238
238
 
239
239
  if anotherset['diagnosis']
240
240
  # Copy alternative error message
241
- anotherset['diagnosis'] = Sisimai::String.sweep(anotherset['diagnosis'])
241
+ anotherset['diagnosis'] = anotherset['diagnosis'].split.join(" ")
242
242
  e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'].nil? || e['diagnosis'].empty?
243
243
 
244
244
  if e['diagnosis'] =~ /\A\d+\z/
@@ -277,7 +277,6 @@ module Sisimai::Lhost
277
277
  end
278
278
  end
279
279
 
280
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
281
280
  e['command'] = commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis'])
282
281
  e['command'] = 'HELO' if e["command"].empty? && e['diagnosis'].include?('refused to talk to me:')
283
282
  e['spec'] = 'SMTP' if e["spec"].empty? && Sisimai::String.aligned(e['diagnosis'], ['host ', ' said:'])
@@ -66,59 +66,9 @@ module Sisimai::Lhost
66
66
  "DATA" => [" failed on DATA command", " failed after I sent the message"],
67
67
  }.freeze
68
68
 
69
- # qmail-send.c:922| ... (&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
70
- # qmail-remote-fallback.patch
71
- HasExpired = "this message has been in the queue too long.".freeze
72
- OnHoldPair = [" does not like recipient.", "this message has been in the queue too long."].freeze
73
- FailOnLDAP = {
74
- # qmail-ldap-1.03-20040101.patch:19817 - 19866
75
- "emailtoolarge" => ["The message exeeded the maximum size the user accepts"], # 5.2.3
76
- "userunknown" => ["Sorry, no mailbox here by that name"], # 5.1.1
77
- "suspend" => [ # 5.2.1
78
- "Mailaddress is administrativly disabled",
79
- "Mailaddress is administrativley disabled",
80
- "Mailaddress is administratively disabled",
81
- "Mailaddress is administrativeley disabled",
82
- ],
83
- "systemerror" => [
84
- "Automatic homedir creator crashed", # 4.3.0
85
- "Illegal value in LDAP attribute", # 5.3.5
86
- "LDAP attribute is not given but mandatory", # 5.3.5
87
- "Timeout while performing search on LDAP server", # 4.4.3
88
- "Too many results returned but needs to be unique", # 5.3.5
89
- "Permanent error while executing qmail-forward", # 5.4.4
90
- "Temporary error in automatic homedir creation", # 4.3.0 or 5.3.0
91
- "Temporary error while executing qmail-forward", # 4.4.4
92
- "Temporary failure in LDAP lookup", # 4.4.3
93
- "Unable to contact LDAP server", # 4.4.3
94
- "Unable to login into LDAP server, bad credentials",# 4.4.3
95
- ],
96
- }.freeze
97
69
  MessagesOf = {
98
- # qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
99
- # qmail-remote.c:78| Sorry, I couldn't find any host named ");
100
- "hostunknown" => ["Sorry, I couldn't find any host "],
101
- # error_str.c:192| X(EDQUOT,"disk quota exceeded")
102
- "mailboxfull" => ["disk quota exceeded"],
103
- # qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
104
- # qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
105
- "emailtoolarge" => ["Message size exceeds fixed maximum message size:"],
106
- "networkerror" => [
107
- "Sorry, I wasn't able to establish an SMTP connection",
108
- "Sorry. Although I'm listed as a best-preference MX or A for that host",
109
- ],
110
- "notaccept" => [
111
- # notqmail 1.08 returns the following error message when the destination MX is NullMX
112
- "Sorry, I couldn't find a mail exchanger or IP address",
113
- ],
114
- "systemerror" => [
115
- "bad interpreter: No such file or directory",
116
- "system error",
117
- "Unable to",
118
- ],
119
- "systemfull" => ["Requested action not taken: mailbox unavailable (not enough free space)"],
120
- # qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
121
- # qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
70
+ # notqmail 1.08 returns the following error message when the destination MX is NullMX
71
+ "notaccept" => ["Sorry, I couldn't find a mail exchanger or IP address"],
122
72
  "userunknown" => ["no mailbox here by that name"],
123
73
  }.freeze
124
74
 
@@ -186,7 +136,7 @@ module Sisimai::Lhost
186
136
  cm = r.size
187
137
  p2 = e.index(" ", p1 + cm + 1) || p2 = e.rindex(".")
188
138
 
189
- v["rhost"] = Sisimai::String.sweep(e[p1 + cm, p2 - p1 - cm])
139
+ v["rhost"] = e[p1 + cm, p2 - p1 - cm]
190
140
  break
191
141
  end
192
142
  end
@@ -194,9 +144,6 @@ module Sisimai::Lhost
194
144
  return nil if recipients == 0
195
145
 
196
146
  dscontents.each do |e|
197
- # Tidy up the error message in e['diagnosis'], Try to detect the bounce reason.
198
- e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
199
-
200
147
  # Get the SMTP command name for the session
201
148
  CommandSet.each_key do |r|
202
149
  # Get the last SMTP command
@@ -216,32 +163,18 @@ module Sisimai::Lhost
216
163
  e["reason"] = "blocked"
217
164
  else
218
165
  # Try to match with each error message in the table
219
- if Sisimai::String.aligned(e["diagnosis"], OnHoldPair)
220
- # To decide the reason require pattern match with Sisimai::Reason::* modules
221
- e["reason"] = "onhold"
222
- else
223
- # Check that the error message includes any of message patterns or not
224
- [e["alterrors"], e["diagnosis"]].each do |f|
225
- # Try to detect an error reason
226
- break if e["reason"] != ""
227
- next if f.nil?
228
- MessagesOf.each_key do |r|
229
- # The key is a bounce reason name
230
- next if MessagesOf[r].none? { |a| f.include?(a) }
231
- e["reason"] = r
232
- break
233
- end
234
- break if e["reason"]
235
-
236
- FailOnLDAP.each_key do |r|
237
- # The key is a bounce reason name
238
- next if FailOnLDAP[r].none? { |a| f.include?(a) }
239
- e["reason"] = r
240
- break
241
- end
242
- break if e["reason"]
243
- e["reason"] = "expired" if e["diagnosis"].include?(HasExpired)
166
+ # Check that the error message includes any of message patterns or not
167
+ [e["alterrors"], e["diagnosis"]].each do |f|
168
+ # Try to detect an error reason
169
+ break if e["reason"] != ""
170
+ next if f.nil?
171
+ MessagesOf.each_key do |r|
172
+ # The key is a bounce reason name
173
+ next if MessagesOf[r].none? { |a| f.include?(a) }
174
+ e["reason"] = r
175
+ break
244
176
  end
177
+ break if e["reason"]
245
178
  end
246
179
  end
247
180
 
@@ -67,7 +67,8 @@ module Sisimai::Lhost
67
67
  o = Sisimai::RFC1894.field(e) || next
68
68
  v = dscontents[-1]
69
69
 
70
- if o[3] == 'addr'
70
+ case o[3]
71
+ when "addr"
71
72
  # Final-Recipient: rfc822; kijitora@example.jp
72
73
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
73
74
  if o[0] == 'final-recipient'
@@ -83,7 +84,7 @@ module Sisimai::Lhost
83
84
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
84
85
  v['alias'] = o[2]
85
86
  end
86
- elsif o[3] == 'code'
87
+ when "code"
87
88
  # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
88
89
  v['spec'] = o[1]
89
90
  v['diagnosis'] = o[2]
@@ -159,7 +160,7 @@ module Sisimai::Lhost
159
160
  # Continued line of the value of Diagnostic-Code field
160
161
  next if readslices[-2].start_with?('Diagnostic-Code:') == false
161
162
  next if e.start_with?(' ') == false
162
- v['diagnosis'] += " #{Sisimai::String.sweep(e)}"
163
+ v['diagnosis'] += " " + e
163
164
  readslices[-1] = "Diagnostic-Code: #{e}"
164
165
  end
165
166
  end
@@ -186,7 +187,6 @@ module Sisimai::Lhost
186
187
  break
187
188
  end
188
189
 
189
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
190
190
  e["command"] = thecommand if e["command"].empty?
191
191
  e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
192
192
  e["command"] = "EHLO" if e["command"].empty? && esmtpreply.size > 0
@@ -55,11 +55,12 @@ module Sisimai::Lhost
55
55
  recipients = dscontents.size
56
56
  end
57
57
 
58
- if e.start_with?('Sent <<< ')
58
+ case
59
+ when e.start_with?('Sent <<< ')
59
60
  # Sent <<< RCPT TO:<kijitora@example.co.jp>
60
61
  v['command'] = Sisimai::SMTP::Command.find(e)
61
62
 
62
- elsif e.start_with?('Received >>> ')
63
+ when e.start_with?('Received >>> ')
63
64
  # Received >>> 550 5.1.1 <kijitora@example.co.jp>... user unknown
64
65
  v['diagnosis'] = e[e.index(' >>> ') + 4, e.size]
65
66
  else
@@ -72,7 +73,6 @@ module Sisimai::Lhost
72
73
  return nil if recipients == 0
73
74
 
74
75
  dscontents.each do |e|
75
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
76
76
  e['reason'] = 'userunknown' if e['diagnosis'].include?('Unable to deliver')
77
77
  end
78
78
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
@@ -161,7 +161,6 @@ module Sisimai::Lhost
161
161
  j = 0; dscontents.each do |e|
162
162
  # Tidy up the error message in e.Diagnosis
163
163
  e["diagnosis"] = anotherone[j] if e["diagnosis"].empty?
164
- e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
165
164
  e["command"] = Sisimai::SMTP::Command.find(e["diagnosis"]) if e["command"].empty?
166
165
  e["replycode"] = Sisimai::SMTP::Reply.find(e["diagnosis"])
167
166
  e["replycode"] = Sisimai::SMTP::Reply.find(anotherone[j]) if e["replycode"].empty?