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: ['Unable to deliver message to the following address'],
12
- rfc822: ['--- Original message follows'],
13
- }.freeze
10
+ ReBackbone = %r|^--- Original message follows[.]|.freeze
11
+ StartingOf = { message: ['Unable to deliver message to the following address'] }.freeze
14
12
 
15
13
  def description; return 'Unknown MTA #2'; end
16
14
  def smtpagent; return Sisimai::Lhost.smtpagent(self); end
@@ -32,64 +30,43 @@ module Sisimai::Lhost
32
30
  return nil unless mhead['subject'] =~ %r/\A(?>Delivery failure|fail(?:ure|ed) delivery)/
33
31
 
34
32
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
35
- hasdivided = mbody.split("\n")
36
- rfc822list = [] # (Array) Each line in message/rfc822 part string
37
- blanklines = 0 # (Integer) The number of blank lines
33
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
34
+ bodyslices = emailsteak[0].split("\n")
38
35
  readcursor = 0 # (Integer) Points the current cursor position
39
36
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
40
37
  v = nil
41
38
 
42
- while e = hasdivided.shift do
39
+ while e = bodyslices.shift do
40
+ # Read error messages and delivery status lines from the head of the email
41
+ # to the previous line of the beginning of the original message.
43
42
  if readcursor == 0
44
43
  # Beginning of the bounce message or delivery status part
45
- if e.start_with?(StartingOf[:message][0])
46
- readcursor |= Indicators[:deliverystatus]
47
- next
48
- end
44
+ readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
45
+ next
49
46
  end
47
+ next if (readcursor & Indicators[:deliverystatus]) == 0
48
+ next if e.empty?
50
49
 
51
- if (readcursor & Indicators[:'message-rfc822']) == 0
52
- # Beginning of the original message part
53
- if e.start_with?(StartingOf[:rfc822][0])
54
- readcursor |= Indicators[:'message-rfc822']
55
- next
56
- end
57
- end
50
+ # Message from example.com.
51
+ # Unable to deliver message to the following address(es).
52
+ #
53
+ # <kijitora@example.com>:
54
+ # This user doesn't have a example.com account (kijitora@example.com) [0]
55
+ v = dscontents[-1]
58
56
 
59
- if readcursor & Indicators[:'message-rfc822'] > 0
60
- # Inside of the original message part
61
- if e.empty?
62
- blanklines += 1
63
- break if blanklines > 2
64
- next
57
+ if cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>]:\z/)
58
+ # <kijitora@example.com>:
59
+ if v['recipient']
60
+ # There are multiple recipient addresses in the message body.
61
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
62
+ v = dscontents[-1]
65
63
  end
66
- rfc822list << e
64
+ v['recipient'] = cv[1]
65
+ recipients += 1
67
66
  else
68
- # Error message part
69
- next if (readcursor & Indicators[:deliverystatus]) == 0
70
- next if e.empty?
71
-
72
- # Message from example.com.
73
- # Unable to deliver message to the following address(es).
74
- #
75
- # <kijitora@example.com>:
76
67
  # This user doesn't have a example.com account (kijitora@example.com) [0]
77
- v = dscontents[-1]
78
-
79
- if cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>]:\z/)
80
- # <kijitora@example.com>:
81
- if v['recipient']
82
- # There are multiple recipient addresses in the message body.
83
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
84
- v = dscontents[-1]
85
- end
86
- v['recipient'] = cv[1]
87
- recipients += 1
88
- else
89
- # This user doesn't have a example.com account (kijitora@example.com) [0]
90
- v['diagnosis'] ||= ''
91
- v['diagnosis'] << ' ' << e
92
- end
68
+ v['diagnosis'] ||= ''
69
+ v['diagnosis'] << ' ' << e
93
70
  end
94
71
  end
95
72
  return nil unless recipients > 0
@@ -100,8 +77,7 @@ module Sisimai::Lhost
100
77
  e.each_key { |a| e[a] ||= '' }
101
78
  end
102
79
 
103
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
104
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
80
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
105
81
  end
106
82
 
107
83
  end
@@ -7,10 +7,8 @@ module Sisimai::Lhost
7
7
  require 'sisimai/lhost'
8
8
 
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
- StartingOf = {
11
- message: [' This is an automatically generated Delivery Status Notification.'],
12
- rfc822: ['Content-Type: message/rfc822'],
13
- }.freeze
10
+ ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
11
+ StartingOf = { message: [' This is an automatically generated Delivery Status Notification.'] }.freeze
14
12
 
15
13
  def description; return 'Unknown MTA #3'; end
16
14
  def smtpagent; return Sisimai::Lhost.smtpagent(self); end
@@ -32,80 +30,59 @@ module Sisimai::Lhost
32
30
  return nil unless mhead['from'].start_with?('Mail Delivery System')
33
31
 
34
32
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
35
- hasdivided = mbody.split("\n")
36
- rfc822list = [] # (Array) Each line in message/rfc822 part string
37
- blanklines = 0 # (Integer) The number of blank lines
33
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
34
+ bodyslices = emailsteak[0].split("\n")
38
35
  readcursor = 0 # (Integer) Points the current cursor position
39
36
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
40
37
  v = nil
41
38
 
42
- while e = hasdivided.shift do
39
+ while e = bodyslices.shift do
40
+ # Read error messages and delivery status lines from the head of the email
41
+ # to the previous line of the beginning of the original message.
43
42
  if readcursor == 0
44
43
  # Beginning of the bounce message or delivery status part
45
- if e.start_with?(StartingOf[:message][0])
46
- readcursor |= Indicators[:deliverystatus]
47
- next
48
- end
44
+ readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
45
+ next
49
46
  end
47
+ next if (readcursor & Indicators[:deliverystatus]) == 0
48
+ next if e.empty?
50
49
 
51
- if (readcursor & Indicators[:'message-rfc822']) == 0
52
- # Beginning of the original message part
53
- if e.start_with?(StartingOf[:rfc822][0])
54
- readcursor |= Indicators[:'message-rfc822']
55
- next
56
- end
57
- end
50
+ # ============================================================================
51
+ # This is an automatically generated Delivery Status Notification.
52
+ #
53
+ # Delivery to the following recipients failed permanently:
54
+ #
55
+ # * kijitora@example.com
56
+ #
57
+ #
58
+ # ============================================================================
59
+ # Technical details:
60
+ #
61
+ # SMTP:RCPT host 192.0.2.8: 553 5.3.0 <kijitora@example.com>... No such user here
62
+ #
63
+ #
64
+ # ============================================================================
65
+ v = dscontents[-1]
58
66
 
59
- if readcursor & Indicators[:'message-rfc822'] > 0
60
- # Inside of the original message part
61
- if e.empty?
62
- blanklines += 1
63
- break if blanklines > 1
64
- next
67
+ if cv = e.match(/\A[ \t]+[*][ ]([^ ]+[@][^ ]+)\z/)
68
+ # * kijitora@example.com
69
+ if v['recipient']
70
+ # There are multiple recipient addresses in the message body.
71
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
72
+ v = dscontents[-1]
65
73
  end
66
- rfc822list << e
74
+ v['recipient'] = cv[1]
75
+ recipients += 1
67
76
  else
68
- # Error message part
69
- next if (readcursor & Indicators[:deliverystatus]) == 0
70
- next if e.empty?
71
-
72
- # ============================================================================
73
- # This is an automatically generated Delivery Status Notification.
74
- #
75
- # Delivery to the following recipients failed permanently:
76
- #
77
- # * kijitora@example.com
78
- #
79
- #
80
- # ============================================================================
81
- # Technical details:
82
- #
83
- # SMTP:RCPT host 192.0.2.8: 553 5.3.0 <kijitora@example.com>... No such user here
84
- #
85
- #
86
- # ============================================================================
87
- v = dscontents[-1]
88
-
89
- if cv = e.match(/\A[ \t]+[*][ ]([^ ]+[@][^ ]+)\z/)
90
- # * kijitora@example.com
91
- if v['recipient']
92
- # There are multiple recipient addresses in the message body.
93
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
94
- v = dscontents[-1]
95
- end
96
- v['recipient'] = cv[1]
97
- recipients += 1
98
- else
99
- # Detect error message
100
- if cv = e.match(/\ASMTP:([^ ]+)[ ](.+)\z/)
101
- # SMTP:RCPT host 192.0.2.8: 553 5.3.0 <kijitora@example.com>... No such user here
102
- v['command'] = cv[1].upcase
103
- v['diagnosis'] = cv[2]
77
+ # Detect error message
78
+ if cv = e.match(/\ASMTP:([^ ]+)[ ](.+)\z/)
79
+ # SMTP:RCPT host 192.0.2.8: 553 5.3.0 <kijitora@example.com>... No such user here
80
+ v['command'] = cv[1].upcase
81
+ v['diagnosis'] = cv[2]
104
82
 
105
- elsif cv = e.match(/\ARouting: (.+)/)
106
- # Routing: Could not find a gateway for kijitora@example.co.jp
107
- v['diagnosis'] = cv[1]
108
- end
83
+ elsif cv = e.match(/\ARouting: (.+)/)
84
+ # Routing: Could not find a gateway for kijitora@example.co.jp
85
+ v['diagnosis'] = cv[1]
109
86
  end
110
87
  end
111
88
  end
@@ -118,8 +95,7 @@ module Sisimai::Lhost
118
95
  e.each_key { |a| e[a] ||= '' }
119
96
  end
120
97
 
121
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
122
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
98
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
123
99
  end
124
100
 
125
101
  end
@@ -8,10 +8,8 @@ module Sisimai::Lhost
8
8
  require 'sisimai/lhost'
9
9
 
10
10
  Indicators = Sisimai::Lhost.INDICATORS
11
- StartingOf = {
12
- error: ['Remote host said:'],
13
- rfc822: ['--- Below this line is a copy of the message.', '--- Original message follows.'],
14
- }.freeze
11
+ ReBackbone = %r/^---[ ](?:Below this line is a copy of the message|Original message follows)[.]/.freeze
12
+ StartingOf = { error: ['Remote host said:'] }.freeze
15
13
  MarkingsOf = {
16
14
  # qmail-remote.c:248| if (code >= 500) {
17
15
  # qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
@@ -146,70 +144,49 @@ module Sisimai::Lhost
146
144
  return nil unless match > 0
147
145
 
148
146
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
149
- hasdivided = mbody.split("\n")
150
- rfc822list = [] # (Array) Each line in message/rfc822 part string
151
- blanklines = 0 # (Integer) The number of blank lines
147
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
148
+ bodyslices = emailsteak[0].split("\n")
152
149
  readcursor = 0 # (Integer) Points the current cursor position
153
150
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
154
151
  v = nil
155
152
 
156
- while e = hasdivided.shift do
153
+ while e = bodyslices.shift do
154
+ # Read error messages and delivery status lines from the head of the email
155
+ # to the previous line of the beginning of the original message.
157
156
  if readcursor == 0
158
157
  # Beginning of the bounce message or delivery status part
159
- if e =~ MarkingsOf[:message]
160
- readcursor |= Indicators[:deliverystatus]
161
- next
162
- end
158
+ readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
159
+ next
163
160
  end
161
+ next if (readcursor & Indicators[:deliverystatus]) == 0
162
+ next if e.empty?
164
163
 
165
- if (readcursor & Indicators[:'message-rfc822']) == 0
166
- # Beginning of the original message part
167
- if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
168
- readcursor |= Indicators[:'message-rfc822']
169
- next
170
- end
171
- end
172
-
173
- if readcursor & Indicators[:'message-rfc822'] > 0
174
- # Inside of the original message part
175
- if e.empty?
176
- blanklines += 1
177
- break if blanklines > 1
178
- next
179
- end
180
- rfc822list << e
181
- else
182
- # Error message part
183
- next if (readcursor & Indicators[:deliverystatus]) == 0
184
- next if e.empty?
164
+ # <kijitora@example.jp>:
165
+ # 192.0.2.153 does not like recipient.
166
+ # Remote host said: 550 5.1.1 <kijitora@example.jp>... User Unknown
167
+ # Giving up on 192.0.2.153.
168
+ v = dscontents[-1]
185
169
 
170
+ if cv = e.match(/\A(?:To[ ]*:)?[<](.+[@].+)[>]:[ ]*\z/)
186
171
  # <kijitora@example.jp>:
187
- # 192.0.2.153 does not like recipient.
188
- # Remote host said: 550 5.1.1 <kijitora@example.jp>... User Unknown
189
- # Giving up on 192.0.2.153.
190
- v = dscontents[-1]
191
-
192
- if cv = e.match(/\A(?:To[ ]*:)?[<](.+[@].+)[>]:[ ]*\z/)
193
- # <kijitora@example.jp>:
194
- if v['recipient']
195
- # There are multiple recipient addresses in the message body.
196
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
197
- v = dscontents[-1]
198
- end
199
- v['recipient'] = cv[1]
200
- recipients += 1
172
+ if v['recipient']
173
+ # There are multiple recipient addresses in the message body.
174
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
175
+ v = dscontents[-1]
176
+ end
177
+ v['recipient'] = cv[1]
178
+ recipients += 1
201
179
 
202
- elsif dscontents.size == recipients
203
- # Append error message
204
- next if e.empty?
205
- v['diagnosis'] ||= ''
206
- v['diagnosis'] << e + ' '
207
- v['alterrors'] = e if e.start_with?(StartingOf[:error][0])
180
+ elsif dscontents.size == recipients
181
+ # Append error message
182
+ next if e.empty?
183
+ v['diagnosis'] ||= ''
184
+ v['diagnosis'] << e + ' '
185
+ v['alterrors'] = e if e.start_with?(StartingOf[:error][0])
208
186
 
209
- next if v['rhost']
210
- next unless cv = e.match(ReHost)
211
- v['rhost'] = cv[1]
212
- end
187
+ next if v['rhost']
188
+ next unless cv = e.match(ReHost)
189
+ v['rhost'] = cv[1]
213
190
  end
214
191
  end
215
192
  return nil unless recipients > 0
@@ -280,8 +257,7 @@ module Sisimai::Lhost
280
257
  e.each_key { |a| e[a] ||= '' }
281
258
  end
282
259
 
283
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
284
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
260
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
285
261
  end
286
262
 
287
263
  end
@@ -7,10 +7,8 @@ module Sisimai::Lhost
7
7
  require 'sisimai/lhost'
8
8
 
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
- StartingOf = {
11
- message: ['Content-Type: message/delivery-status'],
12
- rfc822: ['Content-Type: message/rfc822'],
13
- }.freeze
10
+ ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
11
+ StartingOf = { message: ['Content-Type: message/delivery-status'] }.freeze
14
12
 
15
13
  def description; return 'Unknown MTA #5'; end
16
14
  def smtpagent; return Sisimai::Lhost.smtpagent(self); end
@@ -51,88 +49,63 @@ module Sisimai::Lhost
51
49
  require 'sisimai/rfc1894'
52
50
  fieldtable = Sisimai::RFC1894.FIELDTABLE
53
51
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
54
- hasdivided = mbody.split("\n")
55
- havepassed = ['']
56
- rfc822list = [] # (Array) Each line in message/rfc822 part string
57
- blanklines = 0 # (Integer) The number of blank lines
52
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
53
+ bodyslices = emailsteak[0].split("\n")
54
+ readslices = ['']
58
55
  readcursor = 0 # (Integer) Points the current cursor position
59
56
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
60
57
  v = nil
61
58
 
62
- while e = hasdivided.shift do
63
- # Save the current line for the next loop
64
- havepassed << e
65
- p = havepassed[-2]
59
+ while e = bodyslices.shift do
60
+ # Read error messages and delivery status lines from the head of the email
61
+ # to the previous line of the beginning of the original message.
62
+ readslices << e # Save the current line for the next loop
66
63
 
67
64
  if readcursor == 0
68
65
  # Beginning of the bounce message or message/delivery-status part
69
- if e.start_with?(StartingOf[:message][0])
70
- readcursor |= Indicators[:deliverystatus]
71
- next
72
- end
66
+ readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
67
+ next
73
68
  end
69
+ next if (readcursor & Indicators['deliverystatus']) == 0
70
+ next if e.empty?
74
71
 
75
- if (readcursor & Indicators[:'message-rfc822']) == 0
76
- # Beginning of the original message part(message/rfc822)
77
- if e.start_with?(StartingOf[:rfc822][0])
78
- readcursor |= Indicators[:'message-rfc822']
79
- next
80
- end
81
- end
82
-
83
- if readcursor & Indicators[:'message-rfc822'] > 0
84
- # message/delivery-status part
85
- next if e.empty?
72
+ v = dscontents[-1]
73
+ if f = Sisimai::RFC1894.match(e)
74
+ # "e" matched with any field defined in RFC3464
75
+ next unless o = Sisimai::RFC1894.field(e)
86
76
  v = dscontents[-1]
87
77
 
88
- if f = Sisimai::RFC1894.match(e)
89
- # "e" matched with any field defined in RFC3464
90
- next unless o = Sisimai::RFC1894.field(e)
91
- v = dscontents[-1]
92
-
93
- if o[-1] == 'addr'
78
+ if o[-1] == 'addr'
79
+ # Final-Recipient: rfc822; kijitora@example.jp
80
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
81
+ if o[0] == 'final-recipient'
94
82
  # Final-Recipient: rfc822; kijitora@example.jp
95
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
96
- if o[0] == 'final-recipient'
97
- # Final-Recipient: rfc822; kijitora@example.jp
98
- if v['recipient']
99
- # There are multiple recipient addresses in the message body.
100
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
101
- v = dscontents[-1]
102
- end
103
- v['recipient'] = o[2]
104
- recipients += 1
105
- else
106
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
107
- v['alias'] = o[2]
83
+ if v['recipient']
84
+ # There are multiple recipient addresses in the message body.
85
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
86
+ v = dscontents[-1]
108
87
  end
109
- elsif o[-1] == 'code'
110
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
111
- v['spec'] = o[1]
112
- v['diagnosis'] = o[2]
88
+ v['recipient'] = o[2]
89
+ recipients += 1
113
90
  else
114
- # Other DSN fields defined in RFC3464
115
- next unless fieldtable.key?(o[0])
116
- v[fieldtable[o[0]]] = o[2]
91
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
92
+ v['alias'] = o[2]
117
93
  end
94
+ elsif o[-1] == 'code'
95
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
96
+ v['spec'] = o[1]
97
+ v['diagnosis'] = o[2]
118
98
  else
119
- # Continued line of the value of Diagnostic-Code field
120
- next unless p.start_with?('Diagnostic-Code:')
121
- next unless cv = e.match(/\A[ \t]+(.+)\z/)
122
- v['diagnosis'] << ' ' << cv[1]
123
- havepassed[-1] = 'Diagnostic-Code: ' << e
99
+ # Other DSN fields defined in RFC3464
100
+ next unless fieldtable[o[0]]
101
+ v[fieldtable[o[0]]] = o[2]
124
102
  end
125
103
  else
126
- # message/rfc822 OR text/rfc822-headers part
127
- next unless recipients > 0
128
- next if (readcursor & Indicators['deliverystatus']) == 0
129
-
130
- if e.empty?
131
- blanklines += 1
132
- break if blanklines > 1
133
- next
134
- end
135
- rfc822list << e
104
+ # Continued line of the value of Diagnostic-Code field
105
+ next unless readslices[-2].start_with?('Diagnostic-Code:')
106
+ next unless cv = e.match(/\A[ \t]+(.+)\z/)
107
+ v['diagnosis'] << ' ' << cv[1]
108
+ readslices[-1] = 'Diagnostic-Code: ' << e
136
109
  end
137
110
  end
138
111
  return nil unless recipients > 0
@@ -143,8 +116,7 @@ module Sisimai::Lhost
143
116
  e.each_key { |a| e[a] ||= '' }
144
117
  end
145
118
 
146
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
147
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
119
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
148
120
  end
149
121
 
150
122
  end