sisimai 5.4.0-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 (147) 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 +45 -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 +26 -22
  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 +80 -29
  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 +5 -4
  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-apple-05.eml +96 -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 +27 -9
  144. /data/set-of-emails/maildir/bsd/{lhost-mailmarshalsmtp-02.eml → lhost-mailmarshal-02.eml} +0 -0
  145. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-01.eml → lhost-trendmicro-01.eml} +0 -0
  146. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-02.eml → lhost-trendmicro-02.eml} +0 -0
  147. /data/set-of-emails/maildir/bsd/{lhost-interscanmss-03.eml → lhost-trendmicro-03.eml} +0 -0
@@ -0,0 +1,105 @@
1
+ module Sisimai::Lhost
2
+ # Sisimai::Lhost::Mimecast decodes a bounce email which created by Mimecast https://www.mimecast.com/.
3
+ # Methods in the module are called from only Sisimai::Message.
4
+ module Mimecast
5
+ class << self
6
+ require 'sisimai/lhost'
7
+
8
+ Indicators = Sisimai::Lhost.INDICATORS
9
+ Boundaries = ['Content-Type: message/rfc822'].freeze # No such line in lhost-mimecast-*
10
+ StartingOf = {message: ['-- ']}.freeze
11
+
12
+ # @abstract Decodes the bounce message from Mimecast
13
+ # @param [Hash] mhead Message headers of a bounce email
14
+ # @param [String] mbody Message body of a bounce email
15
+ # @return [Hash] Bounce data list and message/rfc822 part
16
+ # @return [Nil] it failed to decode or the arguments are missing
17
+ def inquire(mhead, mbody)
18
+ match = 0
19
+ match += 1 if mhead['subject'].include?('Email Delivery Failure')
20
+ if mhead['message-id']
21
+ # Message-Id: <0123456789-1102117314000@us-mta-25.us.mimecast.lan>
22
+ match += 1 if mhead['message-id'].include?('.mimecast.lan>')
23
+ end
24
+ return nil if match == 0
25
+
26
+ require 'sisimai/rfc1123'
27
+ require 'sisimai/rfc1894'
28
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
29
+ permessage = {} # (Hash) Store values of each Per-Message field
30
+
31
+ dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
32
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
33
+ bodyslices = emailparts[0].split("\n")
34
+ readcursor = 0 # (Integer) Points the current cursor position
35
+ recipients = 0 # (Integer) The number of 'Final-Recipient' header
36
+
37
+ while e = bodyslices.shift do
38
+ # Read error messages and delivery status lines from the head of the email to the previous
39
+ # line of the beginning of the original message.
40
+ if readcursor == 0
41
+ # Beginning of the bounce message or message/delivery-status part
42
+ readcursor |= Indicators[:deliverystatus] if e.include?(StartingOf[:message][0])
43
+ end
44
+ next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
45
+
46
+ v = dscontents[-1]
47
+ if e.start_with?('-- ')
48
+ # An email that you attempted to send to the following address could not be delivered:
49
+ # -- sabineko@neko.ef.example.org
50
+ cv = e[3, 256]
51
+ if cv.include?(' ') == false
52
+ # -- sotoneko@cat.example.com
53
+ if v["recipient"] != ""
54
+ # There are multiple recipient addresses in the message body.
55
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
56
+ v = dscontents[-1]
57
+ end
58
+ v['recipient'] = Sisimai::Address.s3s4(cv)
59
+ recipients += 1
60
+ else
61
+ # Deal each line begins with "-- " as an error message.
62
+ # The problem appears to be :
63
+ # -- Recipient email address is possibly incorrect
64
+ # Additional information follows :
65
+ # -- 5.4.1 Recipient address rejected: Access denied.
66
+ v["diagnosis"] += cv + " "
67
+ end
68
+ else
69
+ # Lines after Content-Type: message/delivery-status
70
+ f = Sisimai::RFC1894.match(e)
71
+ if f > 0
72
+ # "e" matched with any field defined in RFC3464
73
+ next unless o = Sisimai::RFC1894.field(e)
74
+
75
+ if o[3] == 'code'
76
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
77
+ v['spec'] = o[1]
78
+ v['diagnosis'] = o[2]
79
+ else
80
+ # Other DSN fields defined in RFC3464
81
+ next if fieldtable[o[0]].nil?
82
+ next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
83
+ v[fieldtable[o[0]]] = o[2]
84
+
85
+ next if f != 1
86
+ permessage[fieldtable[o[0]]] = o[2]
87
+ end
88
+ end
89
+ end
90
+ end
91
+ return nil if recipients == 0
92
+
93
+ dscontents.each do |e|
94
+ # Set default values if each value is empty.
95
+ permessage.each_key { |a| e[a] ||= permessage[a] || '' }
96
+ e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
97
+ end
98
+
99
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
100
+ end
101
+ def description; return 'Mimecast'; end
102
+ end
103
+ end
104
+ end
105
+
@@ -22,7 +22,7 @@ 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['subject'].start_with?('Undeliverable message')
25
+ return nil if mhead['subject'].start_with?('Undeliverable message') == false
26
26
 
27
27
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
28
28
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -89,16 +89,16 @@ module Sisimai::Lhost
89
89
  end
90
90
  end
91
91
 
92
- unless recipients > 0
92
+ if recipients == 0
93
93
  # Fallback: Get the recpient address from RFC822 part
94
94
  p1 = emailparts[1].index("\nTo: ") || -1
95
95
  p2 = emailparts[1].index("\n", p1 + 6) || -1
96
96
  if p1 > 0
97
97
  v['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1 + 5, p2 - p1 - 5])
98
- recipients += 1 unless v['recipient'].empty?
98
+ recipients += 1 if v['recipient'].empty? == false
99
99
  end
100
100
  end
101
- return nil unless recipients > 0
101
+ return nil if recipients == 0
102
102
 
103
103
  dscontents.each do |e|
104
104
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
@@ -106,7 +106,7 @@ module Sisimai::Lhost
106
106
 
107
107
  MessagesOf.each_key do |r|
108
108
  # Check each regular expression of Notes error messages
109
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
109
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
110
110
  e['reason'] = r
111
111
  e['status'] = Sisimai::SMTP::Status.code(r.to_s) || ''
112
112
  break
@@ -72,9 +72,9 @@ module Sisimai::Lhost
72
72
  # @return [Hash] Bounce data list and message/rfc822 part
73
73
  # @return [Nil] it failed to decode or the arguments are missing
74
74
  def inquire(mhead, mbody)
75
- return nil unless mhead['subject'].start_with?('Delivery status notification')
76
- return nil unless mhead['from'].start_with?('Mailer Daemon <')
77
- return nil unless mhead['received'].any? { |a| a.include?(' (OpenSMTPD) with ') }
75
+ return nil if mhead['subject'].start_with?('Delivery status notification') == false
76
+ return nil if mhead['from'].start_with?('Mailer Daemon <') == false
77
+ return nil if mhead['received'].none? { |a| a.include?(' (OpenSMTPD) with ') }
78
78
 
79
79
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
80
80
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -116,13 +116,13 @@ module Sisimai::Lhost
116
116
  recipients += 1
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
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
123
123
  MessagesOf.each_key do |r|
124
124
  # Verify each regular expression of session errors
125
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
125
+ next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
126
126
  e['reason'] = r
127
127
  break
128
128
  end
@@ -6,6 +6,7 @@ module Sisimai::Lhost
6
6
  require 'sisimai/lhost'
7
7
  require 'sisimai/rfc1123'
8
8
  require 'sisimai/smtp/reply'
9
+ require 'sisimai/smtp/status'
9
10
  require 'sisimai/smtp/command'
10
11
 
11
12
  # Postfix manual - bounce(5) - http://www.postfix.org/bounce.5.html
@@ -55,8 +56,7 @@ module Sisimai::Lhost
55
56
  require 'sisimai/smtp/transcript'
56
57
  transcript = Sisimai::SMTP::Transcript.rise(emailparts[0], 'In:', 'Out:')
57
58
 
58
- return nil unless transcript
59
- return nil if transcript.size == 0
59
+ return nil if transcript.nil? || transcript.size == 0
60
60
 
61
61
  transcript.each do |e|
62
62
  # Pick email addresses, error messages, and the last SMTP command.
@@ -113,18 +113,22 @@ module Sisimai::Lhost
113
113
  if o[3] == 'addr'
114
114
  # Final-Recipient: rfc822; kijitora@example.jp
115
115
  # X-Actual-Recipient: rfc822; kijitora@example.co.jp
116
- if o[0] == 'final-recipient'
117
- # Final-Recipient: rfc822; kijitora@example.jp
118
- if v["recipient"] != ""
119
- # There are multiple recipient addresses in the message body.
120
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
121
- v = dscontents[-1]
116
+ if Sisimai::Address.is_emailaddress(o[2])
117
+ # The email address is a valid email address, avoid an email address
118
+ # without a valid domain part such as "neko@mailhost".
119
+ if o[0] == 'final-recipient'
120
+ # Final-Recipient: rfc822; kijitora@example.jp
121
+ if v["recipient"] != ""
122
+ # There are multiple recipient addresses in the message body.
123
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
124
+ v = dscontents[-1]
125
+ end
126
+ v['recipient'] = o[2]
127
+ recipients += 1
128
+ else
129
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
130
+ v['alias'] = o[2]
122
131
  end
123
- v['recipient'] = o[2]
124
- recipients += 1
125
- else
126
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
127
- v['alias'] = o[2]
128
132
  end
129
133
  elsif o[3] == 'code'
130
134
  # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
@@ -133,11 +137,11 @@ module Sisimai::Lhost
133
137
  v['diagnosis'] = o[2]
134
138
  else
135
139
  # Other DSN fields defined in RFC3464
136
- next unless fieldtable[o[0]]
140
+ next if fieldtable[o[0]].nil?
137
141
  next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
138
142
  v[fieldtable[o[0]]] = o[2]
139
143
 
140
- next unless f == 1
144
+ next if f != 1
141
145
  permessage[fieldtable[o[0]]] = o[2]
142
146
  end
143
147
  else
@@ -161,15 +165,15 @@ module Sisimai::Lhost
161
165
  # Alternative error message and recipient
162
166
  if e.include?(' (in reply to ') || e.include?('command)')
163
167
  # 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
164
- cv = Sisimai::SMTP::Command.find(e) || ""; commandset << cv unless cv.empty?
168
+ cv = Sisimai::SMTP::Command.find(e) || ""; commandset << cv if cv.empty? == false
165
169
  anotherset['diagnosis'] ||= ''
166
170
  anotherset['diagnosis'] += " #{e}"
167
171
 
168
- elsif Sisimai::String.aligned(e, ['<', '@', '>', '(expanded from<', '):'])
172
+ elsif Sisimai::String.aligned(e, ['<', '@', '>', '(expanded from ', '):'])
169
173
  # <r@example.ne.jp> (expanded from <kijitora@example.org>): user ...
170
- p1 = e.index('> ')
171
- p2 = e.index('(expanded from ', p1)
172
- p3 = e.index('>): ', p2 + 14)
174
+ p1 = e.index('> '); next unless p1
175
+ p2 = e.index('(expanded from ', p1); next unless p2
176
+ p3 = e.index('>): ', p2 + 14); next unless p3
173
177
  anotherset['recipient'] = Sisimai::Address.s3s4(e[0, p1])
174
178
  anotherset['alias'] = Sisimai::Address.s3s4(e[p2 + 15, p3 - p2 - 15])
175
179
  anotherset['diagnosis'] = e[p3 + 3, e.size]
@@ -192,7 +196,7 @@ module Sisimai::Lhost
192
196
  nomessages = true
193
197
  else
194
198
  # Get an error message continued from the previous line
195
- next unless anotherset['diagnosis']
199
+ next if anotherset['diagnosis'].nil?
196
200
  if e.start_with?(' ')
197
201
  # host mx.example.jp said:...
198
202
  anotherset['diagnosis'] += " #{e[4, e.size]}"
@@ -201,16 +205,20 @@ module Sisimai::Lhost
201
205
  end
202
206
  end
203
207
  end # end of while()
204
-
205
208
  end
206
209
 
207
210
  if recipients == 0
208
211
  # Fallback: get a recipient address from error messages
209
- if anotherset['recipient'].to_s.size > 0
210
- # Set a recipient address
211
- dscontents[-1]['recipient'] = anotherset['recipient']
212
+ %w[recipient alias].each do |e|
213
+ # Set a valid recipient address picked from the anotherset
214
+ next if anotherset[e].nil? || Sisimai::Address.is_emailaddress(anotherset[e]) == false
215
+ break if dscontents[-1]['recipient'].empty? == false
216
+ dscontents[-1]['recipient'] = anotherset[e]
212
217
  recipients += 1
213
- else
218
+ break
219
+ end
220
+
221
+ if recipients == 0
214
222
  # Get a recipient address from message/rfc822 part if the delivery report was unavailable:
215
223
  # '--- Delivery report unavailable ---'
216
224
  p1 = emailparts[1].index("\nTo: ") || -1
@@ -222,7 +230,7 @@ module Sisimai::Lhost
222
230
  end
223
231
  end
224
232
  end
225
- return nil unless recipients > 0
233
+ return nil if recipients == 0
226
234
 
227
235
  dscontents.each do |e|
228
236
  # Set default values if each value is empty.
@@ -240,13 +248,11 @@ module Sisimai::Lhost
240
248
  # More detailed error message is in "anotherset"
241
249
  as = '' # status
242
250
  ar = '' # replycode
243
- if e['status'].empty? || e['status'].start_with?('4.0.0', '5.0.0')
251
+ if Sisimai::SMTP::Status.is_ambiguous(e['status'])
244
252
  # Check the value of D.S.N. in anotherset
253
+ # The D.S.N. is neither an empty nor *.0.0
245
254
  as = Sisimai::SMTP::Status.find(anotherset['diagnosis'])
246
- if as.size > 0 && as[-4, 4] != '.0.0'
247
- # The D.S.N. is neither an empty nor *.0.0
248
- e['status'] = as
249
- end
255
+ e['status'] = as if Sisimai::SMTP::Status.is_ambiguous(as) == false
250
256
  end
251
257
 
252
258
  if e['replycode'].empty? || e['replycode'].end_with?('00')
@@ -182,7 +182,7 @@ module Sisimai::Lhost
182
182
  next if v["rhost"] != ""
183
183
  StartingOf["rhost"].each do |r|
184
184
  # Find a remote host name
185
- p1 = e.index(r); next unless p1
185
+ p1 = e.index(r); next if p1.nil?
186
186
  cm = r.size
187
187
  p2 = e.index(" ", p1 + cm + 1) || p2 = e.rindex(".")
188
188
 
@@ -191,7 +191,7 @@ module Sisimai::Lhost
191
191
  end
192
192
  end
193
193
  end
194
- return nil unless recipients > 0
194
+ return nil if recipients == 0
195
195
 
196
196
  dscontents.each do |e|
197
197
  # Tidy up the error message in e['diagnosis'], Try to detect the bounce reason.
@@ -200,7 +200,7 @@ module Sisimai::Lhost
200
200
  # Get the SMTP command name for the session
201
201
  CommandSet.each_key do |r|
202
202
  # Get the last SMTP command
203
- next unless CommandSet[r].any? { |a| e["diagnosis"].include?(a) }
203
+ next if CommandSet[r].none? { |a| e["diagnosis"].include?(a) }
204
204
  e["command"] = r
205
205
  break
206
206
  end
@@ -224,10 +224,10 @@ module Sisimai::Lhost
224
224
  [e["alterrors"], e["diagnosis"]].each do |f|
225
225
  # Try to detect an error reason
226
226
  break if e["reason"] != ""
227
- next unless f
227
+ next if f.nil?
228
228
  MessagesOf.each_key do |r|
229
229
  # The key is a bounce reason name
230
- next unless MessagesOf[r].any? { |a| f.include?(a) }
230
+ next if MessagesOf[r].none? { |a| f.include?(a) }
231
231
  e["reason"] = r
232
232
  break
233
233
  end
@@ -235,7 +235,7 @@ module Sisimai::Lhost
235
235
 
236
236
  FailOnLDAP.each_key do |r|
237
237
  # The key is a bounce reason name
238
- next unless FailOnLDAP[r].any? { |a| f.include?(a) }
238
+ next if FailOnLDAP[r].none? { |a| f.include?(a) }
239
239
  e["reason"] = r
240
240
  break
241
241
  end
@@ -31,10 +31,10 @@ module Sisimai::Lhost
31
31
  # @return [Nil] it failed to decode or the arguments are missing
32
32
  def inquire(mhead, mbody)
33
33
  return nil if mhead['x-aol-ip']
34
- match = nil
34
+ match = false
35
35
  match ||= true if mhead['subject'].end_with?('see transcript for details')
36
36
  match ||= true if mhead['subject'].start_with?('Warning: ')
37
- return nil unless match
37
+ return nil if match == false
38
38
 
39
39
  fieldtable = Sisimai::RFC1894.FIELDTABLE
40
40
  permessage = {} # (Hash) Store values of each Per-Message field
@@ -89,11 +89,11 @@ module Sisimai::Lhost
89
89
  v['diagnosis'] = o[2]
90
90
  else
91
91
  # Other DSN fields defined in RFC3464
92
- next unless fieldtable[o[0]]
92
+ next if fieldtable[o[0]].nil?
93
93
  next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
94
94
  v[fieldtable[o[0]]] = o[2]
95
95
 
96
- next unless f == 1
96
+ next if f != 1
97
97
  permessage[fieldtable[o[0]]] = o[2]
98
98
  end
99
99
  else
@@ -108,7 +108,7 @@ module Sisimai::Lhost
108
108
  # Reporting-MTA: dns; mx.example.jp
109
109
  # Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
110
110
  # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
111
- unless e.start_with?(' ')
111
+ if e.start_with?(' ') == false
112
112
  if e.start_with?('>>> ')
113
113
  # >>> DATA (Client Command)
114
114
  thecommand = Sisimai::SMTP::Command.find(e) if thecommand.empty?
@@ -116,7 +116,7 @@ module Sisimai::Lhost
116
116
  elsif e.start_with?('<<< ')
117
117
  # <<< Response from the SMTP server
118
118
  cv = e[4, e.size - 4]
119
- esmtpreply << cv unless esmtpreply.index(cv)
119
+ esmtpreply << cv if esmtpreply.index(cv).nil?
120
120
  else
121
121
  # Detect an SMTP session error or a connection error
122
122
  next if sessionerr
@@ -157,14 +157,14 @@ module Sisimai::Lhost
157
157
  end
158
158
  else
159
159
  # Continued line of the value of Diagnostic-Code field
160
- next unless readslices[-2].start_with?('Diagnostic-Code:')
161
- next unless e.start_with?(' ')
160
+ next if readslices[-2].start_with?('Diagnostic-Code:') == false
161
+ next if e.start_with?(' ') == false
162
162
  v['diagnosis'] += " #{Sisimai::String.sweep(e)}"
163
163
  readslices[-1] = "Diagnostic-Code: #{e}"
164
164
  end
165
165
  end
166
166
  end # End of message/delivery-status
167
- return nil unless recipients > 0
167
+ return nil if recipients == 0
168
168
 
169
169
  dscontents.each do |e|
170
170
  # Set default values if each value is empty.
@@ -193,9 +193,9 @@ module Sisimai::Lhost
193
193
 
194
194
  while true
195
195
  # Check alternative status code and override it
196
- break unless anotherset.has_key?('status')
197
- break unless anotherset['status'].size > 0
198
- break if Sisimai::SMTP::Status.test(e['status'])
196
+ break if anotherset.has_key?('status') == false
197
+ break if anotherset['status'].size == 0
198
+ break if Sisimai::SMTP::Status.test(e['status'])
199
199
 
200
200
  e['status'] = anotherset['status']
201
201
  break
@@ -203,7 +203,7 @@ module Sisimai::Lhost
203
203
 
204
204
  # @example.jp, no local part
205
205
  # # Get email address from the value of Diagnostic-Code field
206
- next unless e['recipient'].start_with?('@')
206
+ next if e['recipient'].start_with?('@') == false
207
207
  cv = Sisimai::Address.find(e['diagnosis'], true) || []
208
208
  e['recipient'] = cv[0][:address] if cv.size > 0
209
209
  end
@@ -1,13 +1,13 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::InterScanMSS decodes a bounce email which created by Trend Micro InterScan
3
- # Messaging Security Suite https://www.trendmicro.com/en_us/business/products/user-protection/sps/email-and-collaboration/interscan-messaging.html.
2
+ # Sisimai::Lhost::TrendMicro decodes a bounce email which created by TREND VISION ONE: Email and
3
+ # Collaboration Security: https://www.trendmicro.com/en_us/business/products/email-and-collaboration.html
4
4
  # Methods in the module are called from only Sisimai::Message.
5
- module InterScanMSS
5
+ module TrendMicro
6
6
  class << self
7
7
  require 'sisimai/lhost'
8
8
  Boundaries = ['Content-Type: message/rfc822'].freeze
9
9
 
10
- # @abstract Decodes the bounce message from Trend Micro InterScanMSS Messaging Secutiry Suie
10
+ # @abstract Decodes the bounce message from Trend Micro TREND VISION ONE
11
11
  # @param [Hash] mhead Message headers of a bounce email
12
12
  # @param [String] mbody Message body of a bounce email
13
13
  # @return [Hash] Bounce data list and message/rfc822 part
@@ -23,7 +23,7 @@ module Sisimai::Lhost
23
23
  match += 1 if mhead['from'].start_with?('"InterScan MSS"')
24
24
  match += 1 if mhead['from'].start_with?('"InterScan Notification"')
25
25
  match += 1 if tryto.any? { |a| mhead['subject'] == a }
26
- return nil unless match > 0
26
+ return nil if match == 0
27
27
 
28
28
  require 'sisimai/smtp/command'
29
29
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
@@ -65,12 +65,11 @@ module Sisimai::Lhost
65
65
  else
66
66
  # Error message in non-English
67
67
  v['command'] = Sisimai::SMTP::Command.find(e) if e.include?(' >>> ')
68
- p3 = e.index(' <<< ')
69
- next unless p3
68
+ p3 = e.index(' <<< '); next if p3.nil?
70
69
  v['diagnosis'] = e[p3 + 4, e.size]
71
70
  end
72
71
  end
73
- return nil unless recipients > 0
72
+ return nil if recipients == 0
74
73
 
75
74
  dscontents.each do |e|
76
75
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
@@ -78,7 +77,7 @@ module Sisimai::Lhost
78
77
  end
79
78
  return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
80
79
  end
81
- def description; return 'Trend Micro InterScan Messaging Security Suite'; end
80
+ def description; return 'TREND VISION ONE(Email and Collaboration Security)'; end
82
81
  end
83
82
  end
84
83
  end
@@ -36,10 +36,10 @@ module Sisimai::Lhost
36
36
  # @return [Nil] it failed to decode or the arguments are missing
37
37
  def inquire(mhead, mbody)
38
38
  # :from => %r/\AMail Delivery Subsystem/,
39
- return nil unless mhead['subject'].start_with?('Returned mail: ')
39
+ return nil if mhead['subject'].start_with?('Returned mail: ') == false
40
40
 
41
41
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
42
- return nil unless emailparts[1].size > 0
42
+ return nil if emailparts[1].size == 0
43
43
 
44
44
  require 'sisimai/rfc1123'
45
45
  require 'sisimai/smtp/command'
@@ -133,7 +133,7 @@ module Sisimai::Lhost
133
133
  # There is no recipient address in the error message
134
134
  anotherone.each_key do |e|
135
135
  # Try to pick an recipient address, a reply code, and error messages
136
- cv = Sisimai::Address.s3s4(anotherone[e]); next unless Sisimai::Address.is_emailaddress(cv)
136
+ cv = Sisimai::Address.s3s4(anotherone[e]); next if Sisimai::Address.is_emailaddress(cv) == false
137
137
  cr = Sisimai::SMTP::Reply.find(anotherone[e])
138
138
 
139
139
  dscontents[e]["recipient"] = cv
@@ -150,13 +150,13 @@ module Sisimai::Lhost
150
150
  if p1 > 0
151
151
  # Get the recipient address from "To:" header at the original message
152
152
  cv = Sisimai::Address.s3s4(emailparts[1][p1, p2 - p1 - 5])
153
- return nil unless Sisimai::Address.is_emailaddress(cv)
153
+ return nil if Sisimai::Address.is_emailaddress(cv) == false
154
154
  dscontents[0]["recipient"] = cv
155
155
  recipients += 1
156
156
  end
157
157
  end
158
158
  end
159
- return nil unless recipients > 0
159
+ return nil if recipients == 0
160
160
 
161
161
  j = 0; dscontents.each do |e|
162
162
  # Tidy up the error message in e.Diagnosis
@@ -169,8 +169,8 @@ module Sisimai::Lhost
169
169
  # @example.jp, no local part
170
170
  # Get email address from the value of Diagnostic-Code header
171
171
  next if e['recipient'].include?('@')
172
- p1 = e['diagnosis'].index('<'); next unless p1
173
- p2 = e['diagnosis'].index('>'); next unless p2
172
+ p1 = e['diagnosis'].index('<'); next if p1.nil?
173
+ p2 = e['diagnosis'].index('>'); next if p2.nil?
174
174
  e['recipient'] = Sisimai::Address.s3s4(e[p1, p2 - p1])
175
175
  end
176
176
 
@@ -16,7 +16,7 @@ module Sisimai::Lhost
16
16
  while true
17
17
  # Check the value of "From" header
18
18
  # :'subject' => %r/Undeliverable Message/,
19
- break unless mhead['received'].any? { |a| a.include?('.vtext.com (') }
19
+ break if mhead['received'].none? { |a| a.include?('.vtext.com (') }
20
20
  match = 1 if mhead['from'] == 'post_master@vtext.com'
21
21
  match = 0 if Sisimai::String.aligned(mhead['from'], ['sysadmin@', '.vzwpix.com'])
22
22
  break
@@ -130,7 +130,7 @@ module Sisimai::Lhost
130
130
  end
131
131
  end
132
132
  end
133
- return nil unless recipients > 0
133
+ return nil if recipients == 0
134
134
 
135
135
  # Set the value of "MAIL FROM:" and "From:"
136
136
  emailparts[1] += "From: #{senderaddr}\n" if emailparts[1].include?("\nFrom: ") == false
@@ -140,7 +140,7 @@ module Sisimai::Lhost
140
140
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
141
141
  messagesof.each_key do |r|
142
142
  # Verify each regular expression of session errors
143
- next unless messagesof[r].any? { |a| e['diagnosis'].include?(a) }
143
+ next if messagesof[r].none? { |a| e['diagnosis'].include?(a) }
144
144
  e['reason'] = r
145
145
  break
146
146
  end
@@ -6,7 +6,7 @@ module Sisimai::Lhost
6
6
  require 'sisimai/lhost'
7
7
 
8
8
  Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Received: from '].freeze
9
+ Boundaries = ['Content-Type: message/rfc822', 'Received: from '].freeze
10
10
  MarkingsOf = {message: ['The original message was received at ']}.freeze
11
11
 
12
12
  # @abstract Decodes the bounce message from Unknown MTA #1
@@ -15,8 +15,11 @@ module Sisimai::Lhost
15
15
  # @return [Hash] Bounce data list and message/rfc822 part
16
16
  # @return [Nil] it failed to decode or the arguments are missing
17
17
  def inquire(mhead, mbody)
18
- return nil unless mhead['subject'].start_with?('Returned Mail: ')
19
- return nil unless mhead['from'].start_with?('"Mail Deliver System" ')
18
+ proceedsto = false
19
+ proceedsto = true if mhead['subject'].start_with?('Returned Mail: ')
20
+ proceedsto = true if mhead['subject'].start_with?('Mail Delivery Failure')
21
+ proceedsto = true if Sisimai::String.aligned(mhead['from'], ['"Mail Deliver', 'System" '])
22
+ return nil if proceedsto == false
20
23
 
21
24
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
22
25
  emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
@@ -61,7 +64,7 @@ module Sisimai::Lhost
61
64
  datestring = e[MarkingsOf[:message][0].size, e.size]
62
65
  end
63
66
  end
64
- return nil unless recipients > 0
67
+ return nil if recipients == 0
65
68
 
66
69
  dscontents.each do |e|
67
70
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])