sisimai 4.22.3 → 4.22.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sisimai might be problematic. Click here for more details.

Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Benchmarks.mk +54 -0
  4. data/ChangeLog.md +23 -2
  5. data/Developers.mk +42 -35
  6. data/Makefile +10 -0
  7. data/README-JA.md +13 -13
  8. data/README.md +14 -14
  9. data/lib/sisimai.rb +12 -18
  10. data/lib/sisimai/address.rb +64 -82
  11. data/lib/sisimai/arf.rb +27 -42
  12. data/lib/sisimai/bite/email.rb +2 -4
  13. data/lib/sisimai/bite/email/activehunter.rb +12 -17
  14. data/lib/sisimai/bite/email/amazonses.rb +30 -48
  15. data/lib/sisimai/bite/email/amazonworkmail.rb +20 -27
  16. data/lib/sisimai/bite/email/aol.rb +27 -35
  17. data/lib/sisimai/bite/email/apachejames.rb +17 -28
  18. data/lib/sisimai/bite/email/bigfoot.rb +20 -33
  19. data/lib/sisimai/bite/email/biglobe.rb +15 -24
  20. data/lib/sisimai/bite/email/courier.rb +37 -61
  21. data/lib/sisimai/bite/email/domino.rb +19 -28
  22. data/lib/sisimai/bite/email/einsundeins.rb +20 -34
  23. data/lib/sisimai/bite/email/exchange2003.rb +25 -43
  24. data/lib/sisimai/bite/email/exchange2007.rb +15 -23
  25. data/lib/sisimai/bite/email/exim.rb +101 -120
  26. data/lib/sisimai/bite/email/ezweb.rb +28 -44
  27. data/lib/sisimai/bite/email/facebook.rb +26 -37
  28. data/lib/sisimai/bite/email/fml.rb +11 -20
  29. data/lib/sisimai/bite/email/gmx.rb +17 -27
  30. data/lib/sisimai/bite/email/google.rb +19 -29
  31. data/lib/sisimai/bite/email/gsuite.rb +39 -48
  32. data/lib/sisimai/bite/email/imailserver.rb +25 -39
  33. data/lib/sisimai/bite/email/interscanmss.rb +19 -26
  34. data/lib/sisimai/bite/email/kddi.rb +20 -33
  35. data/lib/sisimai/bite/email/mailfoundry.rb +14 -24
  36. data/lib/sisimai/bite/email/mailmarshalsmtp.rb +15 -24
  37. data/lib/sisimai/bite/email/mailru.rb +40 -59
  38. data/lib/sisimai/bite/email/mcafee.rb +21 -35
  39. data/lib/sisimai/bite/email/messagelabs.rb +23 -38
  40. data/lib/sisimai/bite/email/messagingserver.rb +15 -27
  41. data/lib/sisimai/bite/email/mfilter.rb +19 -28
  42. data/lib/sisimai/bite/email/mxlogic.rb +31 -49
  43. data/lib/sisimai/bite/email/notes.rb +16 -24
  44. data/lib/sisimai/bite/email/office365.rb +29 -38
  45. data/lib/sisimai/bite/email/opensmtpd.rb +50 -67
  46. data/lib/sisimai/bite/email/outlook.rb +24 -36
  47. data/lib/sisimai/bite/email/postfix.rb +33 -42
  48. data/lib/sisimai/bite/email/qmail.rb +44 -59
  49. data/lib/sisimai/bite/email/receivingses.rb +28 -36
  50. data/lib/sisimai/bite/email/sendgrid.rb +28 -37
  51. data/lib/sisimai/bite/email/sendmail.rb +35 -51
  52. data/lib/sisimai/bite/email/surfcontrol.rb +17 -25
  53. data/lib/sisimai/bite/email/userdefined.rb +17 -28
  54. data/lib/sisimai/bite/email/v5sendmail.rb +32 -41
  55. data/lib/sisimai/bite/email/verizon.rb +31 -56
  56. data/lib/sisimai/bite/email/x1.rb +11 -18
  57. data/lib/sisimai/bite/email/x2.rb +11 -23
  58. data/lib/sisimai/bite/email/x3.rb +10 -19
  59. data/lib/sisimai/bite/email/x4.rb +46 -65
  60. data/lib/sisimai/bite/email/x5.rb +26 -37
  61. data/lib/sisimai/bite/email/yahoo.rb +11 -19
  62. data/lib/sisimai/bite/email/yandex.rb +19 -30
  63. data/lib/sisimai/bite/email/zoho.rb +21 -30
  64. data/lib/sisimai/bite/json.rb +1 -2
  65. data/lib/sisimai/bite/json/amazonses.rb +20 -25
  66. data/lib/sisimai/bite/json/sendgrid.rb +1 -1
  67. data/lib/sisimai/data.rb +36 -55
  68. data/lib/sisimai/data/json.rb +3 -3
  69. data/lib/sisimai/data/yaml.rb +1 -1
  70. data/lib/sisimai/datetime.rb +5 -21
  71. data/lib/sisimai/mail.rb +4 -6
  72. data/lib/sisimai/mail/maildir.rb +1 -1
  73. data/lib/sisimai/mda.rb +41 -44
  74. data/lib/sisimai/message.rb +2 -3
  75. data/lib/sisimai/message/email.rb +42 -52
  76. data/lib/sisimai/message/json.rb +7 -7
  77. data/lib/sisimai/mime.rb +25 -23
  78. data/lib/sisimai/order/email.rb +2 -2
  79. data/lib/sisimai/order/json.rb +2 -7
  80. data/lib/sisimai/reason.rb +41 -46
  81. data/lib/sisimai/reason/blocked.rb +60 -71
  82. data/lib/sisimai/reason/contenterror.rb +4 -8
  83. data/lib/sisimai/reason/delivered.rb +1 -3
  84. data/lib/sisimai/reason/exceedlimit.rb +10 -20
  85. data/lib/sisimai/reason/expired.rb +5 -9
  86. data/lib/sisimai/reason/feedback.rb +1 -3
  87. data/lib/sisimai/reason/filtered.rb +19 -38
  88. data/lib/sisimai/reason/hasmoved.rb +5 -8
  89. data/lib/sisimai/reason/hostunknown.rb +11 -18
  90. data/lib/sisimai/reason/mailboxfull.rb +14 -24
  91. data/lib/sisimai/reason/mailererror.rb +3 -5
  92. data/lib/sisimai/reason/mesgtoobig.rb +15 -25
  93. data/lib/sisimai/reason/networkerror.rb +8 -10
  94. data/lib/sisimai/reason/norelaying.rb +9 -14
  95. data/lib/sisimai/reason/notaccept.rb +9 -21
  96. data/lib/sisimai/reason/onhold.rb +3 -8
  97. data/lib/sisimai/reason/policyviolation.rb +8 -10
  98. data/lib/sisimai/reason/rejected.rb +36 -49
  99. data/lib/sisimai/reason/securityerror.rb +11 -13
  100. data/lib/sisimai/reason/spamdetected.rb +23 -37
  101. data/lib/sisimai/reason/suspend.rb +9 -10
  102. data/lib/sisimai/reason/syntaxerror.rb +3 -4
  103. data/lib/sisimai/reason/systemerror.rb +7 -9
  104. data/lib/sisimai/reason/systemfull.rb +2 -4
  105. data/lib/sisimai/reason/toomanyconn.rb +17 -30
  106. data/lib/sisimai/reason/undefined.rb +1 -3
  107. data/lib/sisimai/reason/userunknown.rb +28 -38
  108. data/lib/sisimai/reason/vacation.rb +4 -6
  109. data/lib/sisimai/reason/virusdetected.rb +4 -6
  110. data/lib/sisimai/rfc2606.rb +1 -2
  111. data/lib/sisimai/rfc3464.rb +87 -101
  112. data/lib/sisimai/rfc3834.rb +29 -39
  113. data/lib/sisimai/rfc5322.rb +17 -24
  114. data/lib/sisimai/rhost.rb +10 -7
  115. data/lib/sisimai/rhost/exchangeonline.rb +124 -255
  116. data/lib/sisimai/rhost/franceptt.rb +2 -2
  117. data/lib/sisimai/rhost/godaddy.rb +12 -25
  118. data/lib/sisimai/rhost/googleapps.rb +82 -183
  119. data/lib/sisimai/smtp.rb +4 -4
  120. data/lib/sisimai/smtp/error.rb +8 -8
  121. data/lib/sisimai/smtp/reply.rb +1 -1
  122. data/lib/sisimai/smtp/status.rb +1 -0
  123. data/lib/sisimai/string.rb +5 -7
  124. data/lib/sisimai/version.rb +1 -1
  125. data/set-of-emails/README.md +1 -1
  126. data/set-of-emails/maildir/bsd/README.md +50 -50
  127. data/sisimai-java.gemspec +1 -1
  128. data/sisimai.gemspec +1 -1
  129. metadata +5 -5
  130. data/lib/sisimai/skeleton.rb +0 -43
@@ -6,29 +6,18 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/McAfee.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :'x-nai' => %r/Modified by McAfee /,
11
- :'subject' => %r/\ADelivery Status\z/,
12
- }.freeze
13
- Re1 = {
14
- :begin => %r/[-]+ The following addresses had delivery problems [-]+\z/,
15
- :error => %r|\AContent-Type: [^ ]+/[^ ]+; name="deliveryproblems[.]txt"|,
16
- :rfc822 => %r|\AContent-Type: message/rfc822\z|,
17
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
9
+ Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = {
11
+ message: ['--- The following addresses had delivery problems ---'],
12
+ rfc822: ['Content-Type: message/rfc822'],
18
13
  }.freeze
19
- ReFailure = {
20
- userunknown: %r{(?:
21
- User[ ][(].+[@].+[)][ ]unknown[.]
22
- |550[ ]Unknown[ ]user[ ][^ ]+[@][^ ]+
23
- )
24
- }x,
14
+ ReFailures = {
15
+ userunknown: %r/(?:User [(].+[@].+[)] unknown[.]|550 Unknown user [^ ]+[@][^ ]+)/,
25
16
  }.freeze
26
- Indicators = Sisimai::Bite::Email.INDICATORS
27
17
 
28
18
  def description; return 'McAfee Email Appliance'; end
29
19
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
30
20
  def headerlist; return ['X-NAI-Header']; end
31
- def pattern; return Re0; end
32
21
 
33
22
  # Parse bounce messages from McAfee Email Appliance
34
23
  # @param [Hash] mhead Message headers of a bounce email
@@ -45,8 +34,8 @@ module Sisimai::Bite::Email
45
34
  return nil unless mhead
46
35
  return nil unless mbody
47
36
  return nil unless mhead['x-nai-header']
48
- return nil unless mhead['x-nai-header'] =~ Re0[:'x-nai']
49
- return nil unless mhead['subject'] =~ Re0[:'subject']
37
+ return nil unless mhead['x-nai-header'].include?('Modified by McAfee ')
38
+ return nil unless mhead['subject'] == 'Delivery Status'
50
39
 
51
40
  require 'sisimai/address'
52
41
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
@@ -59,14 +48,14 @@ module Sisimai::Bite::Email
59
48
  diagnostic = '' # (String) Alternative diagnostic message
60
49
  v = nil
61
50
 
62
- hasdivided.each do |e|
51
+ while e = hasdivided.shift do
63
52
  # Save the current line for the next loop
64
53
  havepassed << e
65
54
  p = havepassed[-2]
66
55
 
67
56
  if readcursor.zero?
68
57
  # Beginning of the bounce message or delivery status part
69
- if e =~ Re1[:begin]
58
+ if e.include?(StartingOf[:message][0])
70
59
  readcursor |= Indicators[:deliverystatus]
71
60
  next
72
61
  end
@@ -74,7 +63,7 @@ module Sisimai::Bite::Email
74
63
 
75
64
  if (readcursor & Indicators[:'message-rfc822']).zero?
76
65
  # Beginning of the original message part
77
- if e =~ Re1[:rfc822]
66
+ if e == StartingOf[:rfc822][0]
78
67
  readcursor |= Indicators[:'message-rfc822']
79
68
  next
80
69
  end
@@ -88,7 +77,6 @@ module Sisimai::Bite::Email
88
77
  next
89
78
  end
90
79
  rfc822list << e
91
-
92
80
  else
93
81
  # Before "message/rfc822"
94
82
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -116,43 +104,41 @@ module Sisimai::Bite::Email
116
104
  diagnostic = cv[2]
117
105
  recipients += 1
118
106
 
119
- elsif cv = e.match(/\A[Oo]riginal-[Rr]ecipient:[ ]*([^ ]+)\z/)
107
+ elsif cv = e.match(/\AOriginal-Recipient:[ ]*([^ ]+)\z/)
120
108
  # Original-Recipient: <kijitora@example.co.jp>
121
109
  v['alias'] = Sisimai::Address.s3s4(cv[1])
122
110
 
123
- elsif cv = e.match(/\A[Aa]ction:[ ]*(.+)\z/)
111
+ elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
124
112
  # Action: failed
125
113
  v['action'] = cv[1].downcase
126
114
 
127
- elsif cv = e.match(/\A[Rr]emote-MTA:[ ]*(.+)\z/)
115
+ elsif cv = e.match(/\ARemote-MTA:[ ]*(.+)\z/)
128
116
  # Remote-MTA: 192.0.2.192
129
117
  v['rhost'] = cv[1].downcase
130
-
131
118
  else
132
- if cv = e.match(/\A[Dd]iagnostic-[Cc]ode:[ ]*(.+?);[ ]*(.+)\z/)
119
+ if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
133
120
  # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
134
121
  v['spec'] = cv[1].upcase
135
122
  v['diagnosis'] = cv[2]
136
123
 
137
- elsif p =~ /\A[Dd]iagnostic-[Cc]ode:[ ]*/ && cv = e.match(/\A[ \t]+(.+)\z/)
124
+ elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
138
125
  # Continued line of the value of Diagnostic-Code header
139
- v['diagnosis'] ||= ' '
140
- v['diagnosis'] += ' ' + cv[1]
141
- havepassed[-1] = 'Diagnostic-Code: ' + e
126
+ v['diagnosis'] << ' ' << cv[1]
127
+ havepassed[-1] = 'Diagnostic-Code: ' << e
142
128
  end
143
129
  end
144
130
  end
145
131
  end
146
132
  return nil if recipients.zero?
147
- require 'sisimai/string'
148
133
 
134
+ require 'sisimai/string'
149
135
  dscontents.map do |e|
150
136
  e['agent'] = smtpagent
151
137
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'] || diagnostic)
152
138
 
153
- ReFailure.each_key do |r|
139
+ ReFailures.each_key do |r|
154
140
  # Verify each regular expression of session errors
155
- next unless e['diagnosis'] =~ ReFailure[r]
141
+ next unless e['diagnosis'] =~ ReFailures[r]
156
142
  e['reason'] = r.to_s
157
143
  break
158
144
  end
@@ -7,25 +7,15 @@ module Sisimai::Bite::Email
7
7
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/MessageLabs.pm
8
8
  require 'sisimai/bite/email'
9
9
 
10
- Re0 = {
11
- :from => %r/MAILER-DAEMON[@]messagelabs[.]com/,
12
- :subject => %r/\AMail Delivery Failure/,
13
- }.freeze
14
- Re1 = {
15
- :begin => %r|\AContent-Type: message/delivery-status|,
16
- :error => %r/\AReason:[ \t]*(.+)\z/,
17
- :rfc822 => %r|\AContent-Type: text/rfc822-headers\z|,
18
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
10
+ Indicators = Sisimai::Bite::Email.INDICATORS
11
+ StartingOf = {
12
+ message: ['Content-Type: message/delivery-status'],
13
+ rfc822: ['Content-Type: text/rfc822-headers'],
19
14
  }.freeze
20
- ReFailure = {
21
- userunknown: %r{(?:
22
- 542[ ].+[ ]Rejected
23
- |No[ ]such[ ]user
24
- )
25
- }x,
15
+ ReFailures = {
16
+ userunknown: %r/(?:542 .+ Rejected|No such user)/,
26
17
  securityerror: %r/Please turn on SMTP Authentication in your mail client/,
27
18
  }.freeze
28
- Indicators = Sisimai::Bite::Email.INDICATORS
29
19
 
30
20
  def description; return 'Symantec.cloud http://www.messagelabs.com'; end
31
21
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
@@ -36,7 +26,6 @@ module Sisimai::Bite::Email
36
26
  # X-StarScan-Version: 6.12.5; banners=-,-,-
37
27
  # X-VirusChecked: Checked
38
28
  def headerlist; return ['X-Msg-Ref']; end
39
- def pattern; return Re0; end
40
29
 
41
30
  # Parse bounce messages from Symantec.cloud(MessageLabs)
42
31
  # @param [Hash] mhead Message headers of a bounce email
@@ -53,8 +42,8 @@ module Sisimai::Bite::Email
53
42
  return nil unless mhead
54
43
  return nil unless mbody
55
44
  return nil unless mhead['x-msg-ref']
56
- return nil unless mhead['from'] =~ Re0[:from]
57
- return nil unless mhead['subject'] =~ Re0[:subject]
45
+ return nil unless mhead['from'].include?('MAILER-DAEMON@messagelabs.com')
46
+ return nil unless mhead['subject'].start_with?('Mail Delivery Failure')
58
47
 
59
48
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
60
49
  hasdivided = mbody.split("\n")
@@ -71,14 +60,14 @@ module Sisimai::Bite::Email
71
60
  }
72
61
  v = nil
73
62
 
74
- hasdivided.each do |e|
63
+ while e = hasdivided.shift do
75
64
  # Save the current line for the next loop
76
65
  havepassed << e
77
66
  p = havepassed[-2]
78
67
 
79
68
  if readcursor.zero?
80
69
  # Beginning of the bounce message or delivery status part
81
- if e =~ Re1[:begin]
70
+ if e.start_with?(StartingOf[:message][0])
82
71
  readcursor |= Indicators[:deliverystatus]
83
72
  next
84
73
  end
@@ -86,7 +75,7 @@ module Sisimai::Bite::Email
86
75
 
87
76
  if (readcursor & Indicators[:'message-rfc822']).zero?
88
77
  # Beginning of the original message part
89
- if e =~ Re1[:rfc822]
78
+ if e == StartingOf[:rfc822][0]
90
79
  readcursor |= Indicators[:'message-rfc822']
91
80
  next
92
81
  end
@@ -100,7 +89,6 @@ module Sisimai::Bite::Email
100
89
  next
101
90
  end
102
91
  rfc822list << e
103
-
104
92
  else
105
93
  # Before "message/rfc822"
106
94
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -140,7 +128,7 @@ module Sisimai::Bite::Email
140
128
  # Final-Recipient: rfc822; maria@dest.example.net
141
129
  v = dscontents[-1]
142
130
 
143
- if cv = e.match(/\A[Ff]inal-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
131
+ if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
144
132
  # Final-Recipient: rfc822; maria@dest.example.net
145
133
  if v['recipient']
146
134
  # There are multiple recipient addresses in the message body.
@@ -150,38 +138,35 @@ module Sisimai::Bite::Email
150
138
  v['recipient'] = cv[1]
151
139
  recipients += 1
152
140
 
153
- elsif cv = e.match(/\A[Aa]ction:[ ]*(.+)\z/)
141
+ elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
154
142
  # Action: failed
155
143
  v['action'] = cv[1].downcase
156
144
 
157
- elsif cv = e.match(/\A[Ss]tatus:[ ]*(\d[.]\d+[.]\d+)/)
145
+ elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
158
146
  # Status: 5.0.0
159
147
  v['status'] = cv[1]
160
-
161
148
  else
162
- if cv = e.match(/\A[Dd]iagnostic-[Cc]ode:[ ]*(.+?);[ ]*(.+)\z/)
149
+ if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
163
150
  # Diagnostic-Code: smtp; 550 maria@dest.example.net... No such user
164
151
  v['spec'] = cv[1].upcase
165
152
  v['diagnosis'] = cv[2]
166
153
 
167
- elsif p =~ /\A[Dd]iagnostic-[Cc]ode:[ ]*/ && cv = e.match(/\A[ \t]+(.+)\z/)
154
+ elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
168
155
  # Continued line of the value of Diagnostic-Code header
169
- v['diagnosis'] ||= ''
170
- v['diagnosis'] += ' ' + cv[1]
171
- havepassed[-1] = 'Diagnostic-Code: ' + e
156
+ v['diagnosis'] << ' ' << cv[1]
157
+ havepassed[-1] = 'Diagnostic-Code: ' << e
172
158
  end
173
159
  end
174
-
175
160
  else
176
161
  # Reporting-MTA: dns; server-15.bemta-3.messagelabs.com
177
162
  # Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
178
- if cv = e.match(/\A[Rr]eporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
163
+ if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
179
164
  # Reporting-MTA: dns; server-15.bemta-3.messagelabs.com
180
165
  next if connheader['lhost'].size > 0
181
166
  connheader['lhost'] = cv[1].downcase
182
167
  connvalues += 1
183
168
 
184
- elsif cv = e.match(/\A[Aa]rrival-[Dd]ate:[ ]*(.+)\z/)
169
+ elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
185
170
  # Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
186
171
  next if connheader['date'].size > 0
187
172
  connheader['date'] = cv[1]
@@ -191,8 +176,8 @@ module Sisimai::Bite::Email
191
176
  end
192
177
  end
193
178
  return nil if recipients.zero?
194
- require 'sisimai/string'
195
179
 
180
+ require 'sisimai/string'
196
181
  dscontents.map do |e|
197
182
  # Set default values if each value is empty.
198
183
  connheader.each_key { |a| e[a] ||= connheader[a] || '' }
@@ -200,9 +185,9 @@ module Sisimai::Bite::Email
200
185
  e['agent'] = self.smtpagent
201
186
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
202
187
 
203
- ReFailure.each_key do |r|
188
+ ReFailures.each_key do |r|
204
189
  # Verify each regular expression of session errors
205
- next unless e['diagnosis'] =~ ReFailure[r]
190
+ next unless e['diagnosis'] =~ ReFailures[r]
206
191
  e['reason'] = r.to_s
207
192
  break
208
193
  end
@@ -8,25 +8,14 @@ module Sisimai::Bite::Email
8
8
  require 'sisimai/bite'
9
9
  require 'sisimai/rfc5322'
10
10
 
11
- Re0 = {
12
- :subject => %r/\ADelivery Notification: /,
13
- :received => %r/[ ][(]MessagingServer[)][ ]with[ ]/,
14
- :boundary => %r/Boundary_[(]ID_.+[)]/,
15
- }.freeze
16
- Re1 = {
17
- :begin => %r/\AThis report relates to a message you sent with the following header fields:/,
18
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
19
- :rfc822 => %r!\A(?:Content-type:[ ]*message/rfc822|Return-path:[ ]*)!x,
20
- }.freeze
21
- ReFailure = {
22
- hostunknown: %r|Illegal[ ]host/domain[ ]name[ ]found|x,
23
- }.freeze
24
11
  Indicators = Sisimai::Bite::Email.INDICATORS
12
+ StartingOf = { message: ['This report relates to a message you sent with the following header fields:'] }.freeze
13
+ MarkingsOf = { rfc822: %r!\A(?:Content-type:[ ]*message/rfc822|Return-path:[ ]*)! }.freeze
14
+ ReFailures = { hostunknown: %r|Illegal host/domain name found| }.freeze
25
15
 
26
16
  def description; return 'Oracle Communications Messaging Server'; end
27
17
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
28
18
  def headerlist; return []; end
29
- def pattern; return Re0; end
30
19
 
31
20
  # Parse bounce messages from MessagingServer
32
21
  # @param [Hash] mhead Message headers of a bounce email
@@ -43,9 +32,10 @@ module Sisimai::Bite::Email
43
32
  return nil unless mhead
44
33
  return nil unless mbody
45
34
 
35
+ # :received => %r/[ ][(]MessagingServer[)][ ]with[ ]/,
46
36
  match = 0
47
- match += 1 if mhead['content-type'] =~ Re0[:boundary]
48
- match += 1 if mhead['subject'] =~ Re0[:subject]
37
+ match += 1 if mhead['content-type'].include?('Boundary_(ID_')
38
+ match += 1 if mhead['subject'].start_with?('Delivery Notification: ')
49
39
  return nil if match.zero?
50
40
 
51
41
  require 'sisimai/address'
@@ -57,10 +47,10 @@ module Sisimai::Bite::Email
57
47
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
58
48
  v = nil
59
49
 
60
- hasdivided.each do |e|
50
+ while e = hasdivided.shift do
61
51
  if readcursor.zero?
62
52
  # Beginning of the bounce message or delivery status part
63
- if e =~ Re1[:begin]
53
+ if e.start_with?(StartingOf[:message][0])
64
54
  readcursor |= Indicators[:deliverystatus]
65
55
  next
66
56
  end
@@ -68,7 +58,7 @@ module Sisimai::Bite::Email
68
58
 
69
59
  if (readcursor & Indicators[:'message-rfc822']).zero?
70
60
  # Beginning of the original message part
71
- if e =~ Re1[:rfc822]
61
+ if e =~ MarkingsOf[:rfc822]
72
62
  readcursor |= Indicators[:'message-rfc822']
73
63
  next
74
64
  end
@@ -82,7 +72,6 @@ module Sisimai::Bite::Email
82
72
  next
83
73
  end
84
74
  rfc822list << e
85
-
86
75
  else
87
76
  # Before "message/rfc822"
88
77
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -148,7 +137,6 @@ module Sisimai::Bite::Email
148
137
  v['lhost'] = cv[1]
149
138
  v['rhost'] = cv[2] unless remotehost =~ /[^.]+[.][^.]+/
150
139
  end
151
-
152
140
  else
153
141
  # Original-envelope-id: 0NFC009FLKOUVMA0@mr21p30im-asmtp004.me.com
154
142
  # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
@@ -162,16 +150,16 @@ module Sisimai::Bite::Email
162
150
  # (6jo.example.jp ESMTP SENDMAIL-VM)
163
151
  # Diagnostic-code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
164
152
  #
165
- if cv = e.match(/\A[Ss]tatus:[ ]*(\d[.]\d[.]\d)[ ]*[(](.+)[)]\z/)
153
+ if cv = e.match(/\AStatus:[ ]*(\d[.]\d[.]\d)[ ]*[(](.+)[)]\z/)
166
154
  # Status: 5.1.1 (Remote SMTP server has rejected address)
167
155
  v['status'] = cv[1]
168
156
  v['diagnosis'] ||= cv[2]
169
157
 
170
- elsif cv = e.match(/\A[Aa]rrival-[Dd]ate:[ ]*(.+)\z/)
158
+ elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
171
159
  # Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT)
172
160
  v['date'] ||= cv[1]
173
161
 
174
- elsif cv = e.match(/\A[Rr]eporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
162
+ elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
175
163
  # Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
176
164
  localhost = cv[1]
177
165
  v['lhost'] ||= localhost
@@ -181,15 +169,15 @@ module Sisimai::Bite::Email
181
169
  end
182
170
  end
183
171
  return nil if recipients.zero?
184
- require 'sisimai/string'
185
172
 
173
+ require 'sisimai/string'
186
174
  dscontents.map do |e|
187
175
  e['agent'] = self.smtpagent
188
176
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
189
177
 
190
- ReFailure.each_key do |r|
178
+ ReFailures.each_key do |r|
191
179
  # Verify each regular expression of session errors
192
- next unless e['diagnosis'] =~ ReFailure[r]
180
+ next unless e['diagnosis'] =~ ReFailures[r]
193
181
  e['reason'] = r.to_s
194
182
  break
195
183
  end
@@ -7,24 +7,17 @@ module Sisimai::Bite::Email
7
7
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/mFILTER.pm
8
8
  require 'sisimai/bite/email'
9
9
 
10
- Re0 = {
11
- :'from' => %r/\AMailer Daemon [<]MAILER-DAEMON[@]/,
12
- :'subject' => %r/\Afailure notice\z/,
13
- :'x-mailer' => %r/\Am-FILTER\z/,
14
- }.freeze
15
- Re1 = {
16
- :begin => %r/\A[^ ]+[@][^ ]+[.][a-zA-Z]+\z/,
17
- :error => %r/\A-------server message\z/,
18
- :command => %r/\A-------SMTP command\z/,
19
- :rfc822 => %r/\A-------original (?:message|mail info)\z/,
20
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
21
- }.freeze
22
10
  Indicators = Sisimai::Bite::Email.INDICATORS
11
+ StartingOf = {
12
+ error: ['-------server message'],
13
+ command: ['-------SMTP command'],
14
+ rfc822: ['-------original message', '--------original mail info'],
15
+ }.freeze
16
+ MarkingsOf = { message: %r/\A[^ ]+[@][^ ]+[.][a-zA-Z]+\z/ }.freeze
23
17
 
24
18
  def description; return 'Digital Arts m-FILTER'; end
25
19
  def smtpagent; return 'Email::mFILTER'; end
26
20
  def headerlist; return ['X-Mailer']; end
27
- def pattern; return Re0; end
28
21
 
29
22
  # Parse bounce messages from Digital Arts m-FILTER
30
23
  # @param [Hash] mhead Message headers of a bounce email
@@ -40,9 +33,10 @@ module Sisimai::Bite::Email
40
33
  def scan(mhead, mbody)
41
34
  return nil unless mhead
42
35
  return nil unless mbody
43
- return nil unless mhead['x-mailer']
44
- return nil unless mhead['x-mailer'] =~ Re0[:'x-mailer']
45
- return nil unless mhead['subject'] =~ Re0[:'subject']
36
+
37
+ # :'from' => %r/\AMailer Daemon [<]MAILER-DAEMON[@]/,
38
+ return nil unless mhead['x-mailer'].to_s == 'm-FILTER'
39
+ return nil unless mhead['subject'] == 'failure notice'
46
40
 
47
41
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
48
42
  hasdivided = mbody.split("\n")
@@ -53,15 +47,15 @@ module Sisimai::Bite::Email
53
47
  markingset = { 'diagnosis' => false, 'command' => false }
54
48
  v = nil
55
49
 
56
- hasdivided.each do |e|
50
+ while e = hasdivided.shift do
57
51
  if readcursor.zero?
58
52
  # Beginning of the bounce message or delivery status part
59
- readcursor |= Indicators[:deliverystatus] if e =~ Re1[:begin]
53
+ readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
60
54
  end
61
55
 
62
56
  if (readcursor & Indicators[:'message-rfc822']).zero?
63
57
  # Beginning of the original message part
64
- if e =~ Re1[:rfc822]
58
+ if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
65
59
  readcursor |= Indicators[:'message-rfc822']
66
60
  next
67
61
  end
@@ -75,7 +69,6 @@ module Sisimai::Bite::Email
75
69
  next
76
70
  end
77
71
  rfc822list << e
78
-
79
72
  else
80
73
  # Before "message/rfc822"
81
74
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -114,20 +107,18 @@ module Sisimai::Bite::Email
114
107
  # DATA
115
108
  next if v['command']
116
109
  v['command'] = e if markingset['command']
117
-
118
110
  else
119
111
  # Get error message and SMTP command
120
- if e =~ Re1[:error]
112
+ if e == StartingOf[:error][0]
121
113
  # -------server message
122
114
  markingset['diagnosis'] = true
123
115
 
124
- elsif e =~ Re1[:command]
116
+ elsif e == StartingOf[:command][0]
125
117
  # -------SMTP command
126
118
  markingset['command'] = true
127
-
128
119
  else
129
120
  # 550 5.1.1 unknown user <kijitora@example.jp>
130
- next if e =~ /\A[-]+/
121
+ next if e.start_with?('-')
131
122
  next if v['diagnosis']
132
123
  v['diagnosis'] = e
133
124
  end
@@ -135,8 +126,8 @@ module Sisimai::Bite::Email
135
126
  end
136
127
  end
137
128
  return nil if recipients.zero?
138
- require 'sisimai/string'
139
129
 
130
+ require 'sisimai/string'
140
131
  dscontents.map do |e|
141
132
  if mhead['received'].size > 0
142
133
  # Get localhost and remote host name from Received header.
@@ -144,9 +135,9 @@ module Sisimai::Bite::Email
144
135
  rhosts = Sisimai::RFC5322.received(rheads[-1])
145
136
 
146
137
  e['lhost'] ||= Sisimai::RFC5322.received(rheads[0]).shift
147
- rhosts.each do |ee|
138
+ while ee = rhosts.shift do
148
139
  # Avoid "... by m-FILTER"
149
- next unless ee =~ /[.]/
140
+ next unless ee.include?('.')
150
141
  e['rhost'] = ee
151
142
  end
152
143
  end