sisimai 4.25.4 → 4.25.5

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/ChangeLog.md +50 -0
  4. data/README-JA.md +10 -37
  5. data/README.md +10 -37
  6. data/lib/sisimai.rb +15 -64
  7. data/lib/sisimai/address.rb +13 -17
  8. data/lib/sisimai/arf.rb +4 -4
  9. data/lib/sisimai/data.rb +3 -5
  10. data/lib/sisimai/lhost.rb +0 -14
  11. data/lib/sisimai/lhost/activehunter.rb +31 -55
  12. data/lib/sisimai/lhost/amavis.rb +41 -66
  13. data/lib/sisimai/lhost/amazonses.rb +189 -235
  14. data/lib/sisimai/lhost/amazonworkmail.rb +48 -71
  15. data/lib/sisimai/lhost/aol.rb +49 -75
  16. data/lib/sisimai/lhost/apachejames.rb +60 -83
  17. data/lib/sisimai/lhost/bigfoot.rb +61 -85
  18. data/lib/sisimai/lhost/biglobe.rb +40 -62
  19. data/lib/sisimai/lhost/courier.rb +60 -82
  20. data/lib/sisimai/lhost/domino.rb +50 -76
  21. data/lib/sisimai/lhost/einsundeins.rb +57 -55
  22. data/lib/sisimai/lhost/exchange2003.rb +79 -101
  23. data/lib/sisimai/lhost/exchange2007.rb +66 -74
  24. data/lib/sisimai/lhost/exim.rb +119 -142
  25. data/lib/sisimai/lhost/ezweb.rb +53 -73
  26. data/lib/sisimai/lhost/facebook.rb +49 -75
  27. data/lib/sisimai/lhost/fml.rb +25 -50
  28. data/lib/sisimai/lhost/gmx.rb +55 -79
  29. data/lib/sisimai/lhost/google.rb +39 -66
  30. data/lib/sisimai/lhost/gsuite.rb +74 -94
  31. data/lib/sisimai/lhost/imailserver.rb +34 -67
  32. data/lib/sisimai/lhost/interscanmss.rb +33 -67
  33. data/lib/sisimai/lhost/kddi.rb +30 -52
  34. data/lib/sisimai/lhost/mailfoundry.rb +35 -57
  35. data/lib/sisimai/lhost/mailmarshalsmtp.rb +66 -89
  36. data/lib/sisimai/lhost/mailru.rb +51 -76
  37. data/lib/sisimai/lhost/mcafee.rb +53 -79
  38. data/lib/sisimai/lhost/messagelabs.rb +49 -75
  39. data/lib/sisimai/lhost/messagingserver.rb +91 -113
  40. data/lib/sisimai/lhost/mfilter.rb +50 -70
  41. data/lib/sisimai/lhost/mxlogic.rb +38 -63
  42. data/lib/sisimai/lhost/notes.rb +53 -82
  43. data/lib/sisimai/lhost/office365.rb +64 -81
  44. data/lib/sisimai/lhost/opensmtpd.rb +30 -52
  45. data/lib/sisimai/lhost/outlook.rb +49 -75
  46. data/lib/sisimai/lhost/postfix.rb +116 -117
  47. data/lib/sisimai/lhost/qmail.rb +33 -55
  48. data/lib/sisimai/lhost/receivingses.rb +49 -75
  49. data/lib/sisimai/lhost/sendgrid.rb +68 -203
  50. data/lib/sisimai/lhost/sendmail.rb +101 -125
  51. data/lib/sisimai/lhost/surfcontrol.rb +53 -79
  52. data/lib/sisimai/lhost/userdefined.rb +15 -35
  53. data/lib/sisimai/lhost/v5sendmail.rb +59 -89
  54. data/lib/sisimai/lhost/verizon.rb +75 -124
  55. data/lib/sisimai/lhost/x1.rb +30 -54
  56. data/lib/sisimai/lhost/x2.rb +28 -52
  57. data/lib/sisimai/lhost/x3.rb +44 -68
  58. data/lib/sisimai/lhost/x4.rb +34 -58
  59. data/lib/sisimai/lhost/x5.rb +42 -70
  60. data/lib/sisimai/lhost/yahoo.rb +44 -68
  61. data/lib/sisimai/lhost/yandex.rb +59 -85
  62. data/lib/sisimai/lhost/zoho.rb +54 -78
  63. data/lib/sisimai/mail.rb +5 -9
  64. data/lib/sisimai/mail/maildir.rb +10 -14
  65. data/lib/sisimai/mail/mbox.rb +8 -12
  66. data/lib/sisimai/mail/memory.rb +5 -9
  67. data/lib/sisimai/mail/stdin.rb +7 -11
  68. data/lib/sisimai/mda.rb +2 -2
  69. data/lib/sisimai/message.rb +51 -154
  70. data/lib/sisimai/mime.rb +2 -2
  71. data/lib/sisimai/order.rb +2 -27
  72. data/lib/sisimai/reason.rb +3 -5
  73. data/lib/sisimai/rfc1894.rb +1 -1
  74. data/lib/sisimai/rfc3464.rb +29 -29
  75. data/lib/sisimai/rfc3834.rb +7 -6
  76. data/lib/sisimai/rfc5322.rb +20 -31
  77. data/lib/sisimai/rhost/franceptt.rb +120 -24
  78. data/lib/sisimai/rhost/iua.rb +1 -1
  79. data/lib/sisimai/smtp/error.rb +7 -7
  80. data/lib/sisimai/version.rb +1 -1
  81. data/set-of-emails/maildir/bsd/email-einsundeins-03.eml +66 -0
  82. data/set-of-emails/maildir/bsd/email-exchange2007-05.eml +1469 -0
  83. data/set-of-emails/maildir/bsd/email-exchange2007-06.eml +764 -0
  84. data/set-of-emails/maildir/bsd/email-postfix-64.eml +96 -0
  85. data/set-of-emails/maildir/bsd/rfc3834-03.eml +26 -0
  86. data/set-of-emails/maildir/bsd/rhost-franceptt-04.eml +66 -0
  87. data/set-of-emails/maildir/bsd/rhost-franceptt-05.eml +96 -0
  88. data/set-of-emails/maildir/bsd/rhost-franceptt-06.eml +100 -0
  89. data/set-of-emails/maildir/bsd/rhost-franceptt-07.eml +97 -0
  90. data/set-of-emails/maildir/bsd/rhost-franceptt-08.eml +78 -0
  91. data/set-of-emails/maildir/bsd/rhost-franceptt-10.eml +79 -0
  92. data/set-of-emails/maildir/bsd/rhost-franceptt-11.eml +96 -0
  93. metadata +14 -9
  94. data/lib/sisimai/bite.rb +0 -42
  95. data/lib/sisimai/bite/email.rb +0 -18
  96. data/lib/sisimai/bite/json.rb +0 -16
  97. data/lib/sisimai/message/email.rb +0 -26
  98. data/lib/sisimai/message/json.rb +0 -24
  99. data/lib/sisimai/order/email.rb +0 -20
  100. data/lib/sisimai/order/json.rb +0 -16
@@ -7,10 +7,8 @@ module Sisimai::Lhost
7
7
  require 'sisimai/lhost'
8
8
 
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
- StartingOf = {
11
- message: ['------- Failure Reasons '],
12
- rfc822: ['------- Returned Message '],
13
- }.freeze
10
+ ReBackbone = %r|^-------[ ]Returned[ ]Message[ ]--------|.freeze
11
+ StartingOf = { message: ['------- Failure Reasons '] }.freeze
14
12
  MessagesOf = {
15
13
  'userunknown' => [
16
14
  'User not listed in public Name & Address Book',
@@ -38,9 +36,8 @@ module Sisimai::Lhost
38
36
  return nil unless mhead['subject'].start_with?('Undeliverable message')
39
37
 
40
38
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
41
- hasdivided = mbody.split("\n")
42
- rfc822list = [] # (Array) Each line in message/rfc822 part string
43
- blanklines = 0 # (Integer) The number of blank lines
39
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
40
+ bodyslices = emailsteak[0].split("\n")
44
41
  readcursor = 0 # (Integer) Points the current cursor position
45
42
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
46
43
  characters = '' # (String) Character set name of the bounce mail
@@ -48,96 +45,71 @@ module Sisimai::Lhost
48
45
  encodedmsg = ''
49
46
  v = nil
50
47
 
51
- while e = hasdivided.shift do
48
+ if cv = mhead['content-type'].match(/\A.+;[ ]*charset=(.+)\z/)
49
+ # Get character set name
50
+ # Content-Type: text/plain; charset=ISO-2022-JP
51
+ characters = cv[1].downcase
52
+ end
53
+
54
+ while e = bodyslices.shift do
55
+ # Read error messages and delivery status lines from the head of the email
56
+ # to the previous line of the beginning of the original message.
52
57
  if readcursor == 0
53
58
  # Beginning of the bounce message or delivery status part
54
- if e.start_with?(StartingOf[:message][0])
55
- readcursor |= Indicators[:deliverystatus]
56
- next
57
- end
58
- end
59
-
60
- if (readcursor & Indicators[:'message-rfc822']) == 0
61
- # Beginning of the original message part
62
- if e.start_with?(StartingOf[:rfc822][0])
63
- readcursor |= Indicators[:'message-rfc822']
64
- next
65
- end
66
- end
67
-
68
- if characters.empty?
69
- # Get character set name
70
- if cv = mhead['content-type'].match(/\A.+;[ ]*charset=(.+)\z/)
71
- # Content-Type: text/plain; charset=ISO-2022-JP
72
- characters = cv[1].downcase
73
- end
59
+ readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
60
+ next
74
61
  end
75
-
76
- if readcursor & Indicators[:'message-rfc822'] > 0
77
- # Inside of the original message part
78
- if e.empty?
79
- blanklines += 1
80
- break if blanklines > 1
81
- next
62
+ next if (readcursor & Indicators[:deliverystatus]) == 0
63
+
64
+ # ------- Failure Reasons --------
65
+ #
66
+ # User not listed in public Name & Address Book
67
+ # kijitora@notes.example.jp
68
+ #
69
+ # ------- Returned Message --------
70
+ v = dscontents[-1]
71
+ if e =~ /\A[^ ]+[@][^ ]+/
72
+ # kijitora@notes.example.jp
73
+ if v['recipient']
74
+ # There are multiple recipient addresses in the message body.
75
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
76
+ v = dscontents[-1]
82
77
  end
83
- rfc822list << e
78
+ v['recipient'] ||= e
79
+ recipients += 1
84
80
  else
85
- # Error message part
86
- next if (readcursor & Indicators[:deliverystatus]) == 0
87
-
88
- # ------- Failure Reasons --------
89
- #
90
- # User not listed in public Name & Address Book
91
- # kijitora@notes.example.jp
92
- #
93
- # ------- Returned Message --------
94
- v = dscontents[-1]
95
- if e =~ /\A[^ ]+[@][^ ]+/
96
- # kijitora@notes.example.jp
97
- if v['recipient']
98
- # There are multiple recipient addresses in the message body.
99
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
100
- v = dscontents[-1]
101
- end
102
- v['recipient'] ||= e
103
- recipients += 1
104
- else
105
- next if e.empty?
106
- next if e.start_with?('-')
107
-
108
- if e =~ /[^\x20-\x7e]/
109
- # Error message is not ISO-8859-1
110
- if characters.size > 0
111
- # Try to convert string
112
- begin
113
- encodedmsg = e.encode('UTF-8', characters)
114
- rescue
115
- # Failed to convert
116
- encodedmsg = removedmsg
117
- end
118
- else
119
- # No character set in Content-Type header
81
+ next if e.empty?
82
+ next if e.start_with?('-')
83
+
84
+ if e =~ /[^\x20-\x7e]/
85
+ # Error message is not ISO-8859-1
86
+ if characters.size > 0
87
+ # Try to convert string
88
+ begin
89
+ encodedmsg = e.encode('UTF-8', characters)
90
+ rescue
91
+ # Failed to convert
120
92
  encodedmsg = removedmsg
121
93
  end
122
- v['diagnosis'] ||= ''
123
- v['diagnosis'] << encodedmsg
124
94
  else
125
- # Error message does not include multi-byte character
126
- v['diagnosis'] ||= ''
127
- v['diagnosis'] << e
95
+ # No character set in Content-Type header
96
+ encodedmsg = removedmsg
128
97
  end
98
+ v['diagnosis'] ||= ''
99
+ v['diagnosis'] << encodedmsg
100
+ else
101
+ # Error message does not include multi-byte character
102
+ v['diagnosis'] ||= ''
103
+ v['diagnosis'] << e
129
104
  end
130
105
  end
131
106
  end
132
107
 
133
108
  unless recipients > 0
134
109
  # Fallback: Get the recpient address from RFC822 part
135
- rfc822list.each do |e|
136
- next unless cv = e.match(/^To:[ ]*(.+)$/m)
137
-
110
+ if cv = emailsteak[1].match(/^To:[ ]*(.+)$/)
138
111
  v['recipient'] = Sisimai::Address.s3s4(cv[1])
139
112
  recipients += 1 unless v['recipient'].empty?
140
- break
141
113
  end
142
114
  end
143
115
  return nil unless recipients > 0
@@ -157,8 +129,7 @@ module Sisimai::Lhost
157
129
  e.each_key { |a| e[a] ||= '' }
158
130
  end
159
131
 
160
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
161
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
132
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
162
133
  end
163
134
 
164
135
  end
@@ -8,8 +8,8 @@ module Sisimai::Lhost
8
8
  require 'sisimai/lhost'
9
9
 
10
10
  Indicators = Sisimai::Lhost.INDICATORS
11
+ ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
11
12
  StartingOf = {
12
- rfc822: ['Content-Type: message/rfc822'],
13
13
  error: ['Diagnostic information for administrators:'],
14
14
  eoerr: ['Original message headers:'],
15
15
  }.freeze
@@ -20,6 +20,15 @@ module Sisimai::Lhost
20
20
  )
21
21
  }x,
22
22
  }.freeze
23
+ Headers365 = %w[
24
+ x-ms-exchange-message-is-ndr
25
+ x-microsoft-antispam-prvs
26
+ x-exchange-antispam-report-test
27
+ x-exchange-antispam-report-cfa-test
28
+ x-ms-exchange-crosstenant-originalarrivaltime
29
+ x-ms-exchange-crosstenant-fromentityheader
30
+ x-ms-exchange-transport-crosstenantheadersstamped
31
+ ]
23
32
  StatusList = {
24
33
  # https://support.office.com/en-us/article/Email-non-delivery-reports-in-Office-365-51daa6b9-2e35-49c4-a0c9-df85bf8533c3
25
34
  %r/\A4[.]4[.]7\z/ => 'expired',
@@ -56,7 +65,6 @@ module Sisimai::Lhost
56
65
 
57
66
  def description; return 'Microsoft Office 365: https://office.microsoft.com/'; end
58
67
  def smtpagent; return Sisimai::Lhost.smtpagent(self); end
59
-
60
68
  def headerlist
61
69
  # X-MS-Exchange-Message-Is-Ndr:
62
70
  # X-Microsoft-Antispam-PRVS: <....@...outlook.com>
@@ -92,13 +100,11 @@ module Sisimai::Lhost
92
100
  tryto = %r/.+[.](?:outbound[.]protection|prod)[.]outlook[.]com\b/
93
101
  match = 0
94
102
  match += 1 if mhead['subject'].include?('Undeliverable:')
95
- match += 1 if mhead['x-ms-exchange-message-is-ndr']
96
- match += 1 if mhead['x-microsoft-antispam-prvs']
97
- match += 1 if mhead['x-exchange-antispam-report-test']
98
- match += 1 if mhead['x-exchange-antispam-report-cfa-test']
99
- match += 1 if mhead['x-ms-exchange-crosstenant-originalarrivaltime']
100
- match += 1 if mhead['x-ms-exchange-crosstenant-fromentityheader']
101
- match += 1 if mhead['x-ms-exchange-transport-crosstenantheadersstamped']
103
+ Headers365.each do |e|
104
+ next if mhead[e].nil?
105
+ next if mhead[e].empty?
106
+ match += 1
107
+ end
102
108
  match += 1 if mhead['received'].any? { |a| a =~ tryto }
103
109
  if mhead['message-id']
104
110
  # Message-ID: <00000000-0000-0000-0000-000000000000@*.*.prod.outlook.com>
@@ -111,9 +117,8 @@ module Sisimai::Lhost
111
117
  permessage = {} # (Hash) Store values of each Per-Message field
112
118
 
113
119
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
114
- hasdivided = mbody.split("\n")
115
- rfc822list = [] # (Array) Each line in message/rfc822 part string
116
- blanklines = 0 # (Integer) The number of blank lines
120
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
121
+ bodyslices = emailsteak[0].split("\n")
117
122
  readcursor = 0 # (Integer) Points the current cursor position
118
123
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
119
124
  connheader = {}
@@ -121,85 +126,64 @@ module Sisimai::Lhost
121
126
  htmlbegins = false # (Boolean) Flag for HTML part
122
127
  v = nil
123
128
 
124
- while e = hasdivided.shift do
129
+ while e = bodyslices.shift do
130
+ # Read error messages and delivery status lines from the head of the email
131
+ # to the previous line of the beginning of the original message.
125
132
  if readcursor == 0
126
133
  # Beginning of the bounce message or delivery status part
127
- if e =~ MarkingsOf[:message]
128
- readcursor |= Indicators[:deliverystatus]
129
- next
130
- end
131
- end
132
-
133
- if (readcursor & Indicators[:'message-rfc822']) == 0
134
- # Beginning of the original message part
135
- if e == StartingOf[:rfc822][0]
136
- readcursor |= Indicators[:'message-rfc822']
137
- next
138
- end
134
+ readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
135
+ next
139
136
  end
137
+ next if (readcursor & Indicators[:deliverystatus]) == 0
138
+ next if e.empty?
140
139
 
141
- if readcursor & Indicators[:'message-rfc822'] > 0
142
- # Inside of the original message part
143
- if e.empty?
144
- blanklines += 1
145
- break if blanklines > 1
146
- next
147
- end
148
- rfc822list << e
149
- else
150
- # Error message part
151
- next if (readcursor & Indicators[:deliverystatus]) == 0
152
- next if e.empty?
140
+ # kijitora@example.com<mailto:kijitora@example.com>
141
+ # The email address wasn't found at the destination domain. It might
142
+ # be misspelled or it might not exist any longer. Try retyping the
143
+ # address and resending the message.
144
+ v = dscontents[-1]
153
145
 
146
+ if cv = e.match(/\A.+[@].+[<]mailto:(.+[@].+)[>]\z/)
154
147
  # kijitora@example.com<mailto:kijitora@example.com>
155
- # The email address wasn't found at the destination domain. It might
156
- # be misspelled or it might not exist any longer. Try retyping the
157
- # address and resending the message.
158
- v = dscontents[-1]
159
-
160
- if cv = e.match(/\A.+[@].+[<]mailto:(.+[@].+)[>]\z/)
161
- # kijitora@example.com<mailto:kijitora@example.com>
162
- if v['recipient']
163
- # There are multiple recipient addresses in the message body.
164
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
165
- v = dscontents[-1]
166
- end
167
- v['recipient'] = cv[1]
168
- recipients += 1
148
+ if v['recipient']
149
+ # There are multiple recipient addresses in the message body.
150
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
151
+ v = dscontents[-1]
152
+ end
153
+ v['recipient'] = cv[1]
154
+ recipients += 1
169
155
 
170
- elsif cv = e.match(/\AGenerating server: (.+)\z/)
171
- # Generating server: FFFFFFFFFFFF.e0.prod.outlook.com
172
- connheader['lhost'] = cv[1].downcase
156
+ elsif cv = e.match(/\AGenerating server: (.+)\z/)
157
+ # Generating server: FFFFFFFFFFFF.e0.prod.outlook.com
158
+ connheader['lhost'] = cv[1].downcase
159
+ else
160
+ if endoferror
161
+ # After "Original message headers:"
162
+ next unless f = Sisimai::RFC1894.match(e)
163
+ next unless o = Sisimai::RFC1894.field(e)
164
+ next unless fieldtable[o[0]]
165
+ next if o[0] =~ /\A(?:diagnostic-code|final-recipient)\z/
166
+ v[fieldtable[o[0]]] = o[2]
167
+
168
+ next unless f == 1
169
+ permessage[fieldtable[o[0]]] = o[2]
173
170
  else
174
- if endoferror
175
- # After "Original message headers:"
176
- next unless f = Sisimai::RFC1894.match(e)
177
- next unless o = Sisimai::RFC1894.field(e)
178
- next unless fieldtable.key?(o[0])
179
- next if o[0] =~ /\A(?:diagnostic-code|final-recipient)\z/
180
- v[fieldtable[o[0]]] = o[2]
181
-
182
- next unless f == 1
183
- permessage[fieldtable[o[0]]] = o[2]
171
+ if e == StartingOf[:error][0]
172
+ # Diagnostic information for administrators:
173
+ v['diagnosis'] = e
184
174
  else
185
- if e == StartingOf[:error][0]
186
- # Diagnostic information for administrators:
187
- v['diagnosis'] = e
188
- else
189
- # kijitora@example.com
190
- # Remote Server returned '550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipien=
191
- # t not found by SMTP address lookup'
192
- next unless v['diagnosis']
193
- if e == StartingOf[:eoerr][0]
194
- # Original message headers:
195
- endoferror = true
196
- next
197
- end
198
- v['diagnosis'] << ' ' << e
175
+ # kijitora@example.com
176
+ # Remote Server returned '550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipien=
177
+ # t not found by SMTP address lookup'
178
+ next unless v['diagnosis']
179
+ if e == StartingOf[:eoerr][0]
180
+ # Original message headers:
181
+ endoferror = true
182
+ next
199
183
  end
184
+ v['diagnosis'] << ' ' << e
200
185
  end
201
186
  end
202
-
203
187
  end
204
188
  end
205
189
  return nil unless recipients > 0
@@ -233,8 +217,7 @@ module Sisimai::Lhost
233
217
  end
234
218
  end
235
219
 
236
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
237
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
220
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
238
221
  end
239
222
 
240
223
  end
@@ -7,6 +7,7 @@ module Sisimai::Lhost
7
7
  require 'sisimai/lhost'
8
8
 
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
+ ReBackbone = %r|^[ ]+Below is a copy of the original message:|.freeze
10
11
  StartingOf = {
11
12
  # http://www.openbsd.org/cgi-bin/man.cgi?query=smtpd&sektion=8
12
13
  # opensmtpd-5.4.2p1/smtpd/
@@ -34,7 +35,6 @@ module Sisimai::Lhost
34
35
  # bounce.c/338: " Your message was relayed to these recipients.\n\n";
35
36
  # bounce.c/339:
36
37
  message: [' This is the MAILER-DAEMON, please DO NOT REPLY to this '],
37
- rfc822: [' Below is a copy of the original message:'],
38
38
  }.freeze
39
39
  MessagesOf = {
40
40
  # smtpd/queue.c:221| envelope_set_errormsg(&evp, "Envelope expired");
@@ -86,66 +86,45 @@ module Sisimai::Lhost
86
86
  return nil unless mhead['received'].any? { |a| a.include?(' (OpenSMTPD) with ') }
87
87
 
88
88
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
89
- hasdivided = mbody.split("\n")
90
- rfc822list = [] # (Array) Each line in message/rfc822 part string
91
- blanklines = 0 # (Integer) The number of blank lines
89
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
90
+ bodyslices = emailsteak[0].split("\n")
92
91
  readcursor = 0 # (Integer) Points the current cursor position
93
92
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
94
93
  v = nil
95
94
 
96
- while e = hasdivided.shift do
95
+ while e = bodyslices.shift do
96
+ # Read error messages and delivery status lines from the head of the email
97
+ # to the previous line of the beginning of the original message.
97
98
  if readcursor == 0
98
99
  # Beginning of the bounce message or delivery status part
99
- if e.start_with?(StartingOf[:message][0])
100
- readcursor |= Indicators[:deliverystatus]
101
- next
102
- end
103
- end
104
-
105
- if (readcursor & Indicators[:'message-rfc822']) == 0
106
- # Beginning of the original message part
107
- if e.start_with?(StartingOf[:rfc822][0])
108
- readcursor |= Indicators[:'message-rfc822']
109
- next
110
- end
100
+ readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
101
+ next
111
102
  end
103
+ next if (readcursor & Indicators[:deliverystatus]) == 0
104
+ next if e.empty?
112
105
 
113
- if readcursor & Indicators[:'message-rfc822'] > 0
114
- # Inside of the original message part
115
- if e.empty?
116
- blanklines += 1
117
- break if blanklines > 1
118
- next
119
- end
120
- rfc822list << e
121
- else
122
- # Error message part
123
- next if (readcursor & Indicators[:deliverystatus]) == 0
124
- next if e.empty?
106
+ # Hi!
107
+ #
108
+ # This is the MAILER-DAEMON, please DO NOT REPLY to this e-mail.
109
+ #
110
+ # An error has occurred while attempting to deliver a message for
111
+ # the following list of recipients:
112
+ #
113
+ # kijitora@example.jp: 550 5.2.2 <kijitora@example>... Mailbox Full
114
+ #
115
+ # Below is a copy of the original message:
116
+ v = dscontents[-1]
125
117
 
126
- # Hi!
127
- #
128
- # This is the MAILER-DAEMON, please DO NOT REPLY to this e-mail.
129
- #
130
- # An error has occurred while attempting to deliver a message for
131
- # the following list of recipients:
132
- #
118
+ if cv = e.match(/\A([^ ]+?[@][^ ]+?):?[ ](.+)\z/)
133
119
  # kijitora@example.jp: 550 5.2.2 <kijitora@example>... Mailbox Full
134
- #
135
- # Below is a copy of the original message:
136
- v = dscontents[-1]
137
-
138
- if cv = e.match(/\A([^ ]+?[@][^ ]+?):?[ ](.+)\z/)
139
- # kijitora@example.jp: 550 5.2.2 <kijitora@example>... Mailbox Full
140
- if v['recipient']
141
- # There are multiple recipient addresses in the message body.
142
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
143
- v = dscontents[-1]
144
- end
145
- v['recipient'] = cv[1]
146
- v['diagnosis'] = cv[2]
147
- recipients += 1
120
+ if v['recipient']
121
+ # There are multiple recipient addresses in the message body.
122
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
123
+ v = dscontents[-1]
148
124
  end
125
+ v['recipient'] = cv[1]
126
+ v['diagnosis'] = cv[2]
127
+ recipients += 1
149
128
  end
150
129
  end
151
130
  return nil unless recipients > 0
@@ -163,8 +142,7 @@ module Sisimai::Lhost
163
142
  e.each_key { |a| e[a] ||= '' }
164
143
  end
165
144
 
166
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
167
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
145
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
168
146
  end
169
147
 
170
148
  end