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,6 +7,7 @@ module Sisimai::Lhost
7
7
  require 'sisimai/lhost'
8
8
 
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
+ ReBackbone = %r<^Content-Type:[ ](?:message/rfc822|text/rfc822-headers)>.freeze
10
11
  StartingOf = {
11
12
  # Error text regular expressions which defined in sendmail/savemail.c
12
13
  # savemail.c:1040|if (printheader && !putline(" ----- Transcript of session follows -----\n",
@@ -16,7 +17,6 @@ module Sisimai::Lhost
16
17
  # savemail.c:1361| sendbody
17
18
  # savemail.c:1362| ? " ----- Original message follows -----\n"
18
19
  # savemail.c:1363| : " ----- Message header follows -----\n",
19
- rfc822: ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'],
20
20
  message: [' ----- Transcript of session follows -----'],
21
21
  error: ['... while talking to '],
22
22
  }.freeze
@@ -49,10 +49,9 @@ module Sisimai::Lhost
49
49
  permessage = {} # (Hash) Store values of each Per-Message field
50
50
 
51
51
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
52
- hasdivided = mbody.split("\n")
53
- havepassed = ['']
54
- rfc822list = [] # (Array) Each line in message/rfc822 part string
55
- blanklines = 0 # (Integer) The number of blank lines
52
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
53
+ bodyslices = emailsteak[0].split("\n")
54
+ readslices = ['']
56
55
  readcursor = 0 # (Integer) Points the current cursor position
57
56
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
58
57
  commandtxt = '' # (String) SMTP Command name begin with the string '>>>'
@@ -61,139 +60,117 @@ module Sisimai::Lhost
61
60
  anotherset = {} # Another error information
62
61
  v = nil
63
62
 
64
- while e = hasdivided.shift do
65
- # Save the current line for the next loop
66
- havepassed << e
67
- p = havepassed[-2]
63
+ while e = bodyslices.shift do
64
+ # Read error messages and delivery status lines from the head of the email
65
+ # to the previous line of the beginning of the original message.
66
+ readslices << e # Save the current line for the next loop
68
67
 
69
68
  if readcursor == 0
70
69
  # Beginning of the bounce message or message/delivery-status part
71
- if e.start_with?(StartingOf[:message][0])
72
- readcursor |= Indicators[:deliverystatus]
73
- next
74
- end
75
- end
76
-
77
- if (readcursor & Indicators[:'message-rfc822']) == 0
78
- # Beginning of the original message part(message/rfc822)
79
- if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
80
- readcursor |= Indicators[:'message-rfc822']
81
- next
82
- end
70
+ readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
71
+ next
83
72
  end
84
-
85
- if readcursor & Indicators[:'message-rfc822'] > 0
86
- # message/rfc822 OR text/rfc822-headers part
87
- if e.empty?
88
- blanklines += 1
89
- break if blanklines > 1
90
- next
91
- end
92
- rfc822list << e
93
- else
94
- # message/delivery-status part
95
- next if (readcursor & Indicators[:deliverystatus]) == 0
96
- next if e.empty?
97
-
98
- if f = Sisimai::RFC1894.match(e)
99
- # "e" matched with any field defined in RFC3464
100
- o = Sisimai::RFC1894.field(e) || next
101
- v = dscontents[-1]
102
-
103
- if o[-1] == 'addr'
73
+ next if (readcursor & Indicators[:deliverystatus]) == 0
74
+ next if e.empty?
75
+
76
+ if f = Sisimai::RFC1894.match(e)
77
+ # "e" matched with any field defined in RFC3464
78
+ o = Sisimai::RFC1894.field(e) || next
79
+ v = dscontents[-1]
80
+
81
+ if o[-1] == 'addr'
82
+ # Final-Recipient: rfc822; kijitora@example.jp
83
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
84
+ if o[0] == 'final-recipient'
104
85
  # Final-Recipient: rfc822; kijitora@example.jp
105
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
106
- if o[0] == 'final-recipient'
107
- # Final-Recipient: rfc822; kijitora@example.jp
108
- if v['recipient']
109
- # There are multiple recipient addresses in the message body.
110
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
111
- v = dscontents[-1]
112
- end
113
- v['recipient'] = o[2]
114
- recipients += 1
115
- else
116
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
117
- v['alias'] = o[2]
86
+ if v['recipient']
87
+ # There are multiple recipient addresses in the message body.
88
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
89
+ v = dscontents[-1]
118
90
  end
119
- elsif o[-1] == 'code'
120
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
121
- v['spec'] = o[1]
122
- v['diagnosis'] = o[2]
91
+ v['recipient'] = o[2]
92
+ recipients += 1
123
93
  else
124
- # Other DSN fields defined in RFC3464
125
- next unless fieldtable.key?(o[0])
126
- v[fieldtable[o[0]]] = o[2]
127
-
128
- next unless f == 1
129
- permessage[fieldtable[o[0]]] = o[2]
94
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
95
+ v['alias'] = o[2]
130
96
  end
97
+ elsif o[-1] == 'code'
98
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
99
+ v['spec'] = o[1]
100
+ v['diagnosis'] = o[2]
131
101
  else
132
- # The line does not begin with a DSN field defined in RFC3464
133
- #
134
- # ----- Transcript of session follows -----
135
- # ... while talking to mta.example.org.:
136
- # >>> DATA
137
- # <<< 550 Unknown user recipient@example.jp
138
- # 554 5.0.0 Service unavailable
139
- # ...
140
- # Reporting-MTA: dns; mx.example.jp
141
- # Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
142
- # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
143
- unless e.start_with?(' ')
144
- if cv = e.match(/\A[>]{3}[ ]+([A-Z]{4})[ ]?/)
145
- # >>> DATA
146
- commandtxt = cv[1]
147
-
148
- elsif cv = e.match(/\A[<]{3}[ ]+(.+)\z/)
149
- # <<< Response
150
- esmtpreply << cv[1] unless esmtpreply.index(cv[1])
151
- else
152
- # Detect SMTP session error or connection error
153
- next if sessionerr
154
- if e.start_with?(StartingOf[:error][0])
155
- # ----- Transcript of session follows -----
156
- # ... while talking to mta.example.org.:
157
- sessionerr = true
158
- next
159
- end
102
+ # Other DSN fields defined in RFC3464
103
+ next unless fieldtable[o[0]]
104
+ v[fieldtable[o[0]]] = o[2]
160
105
 
161
- if cv = e.match(/\A[<](.+)[>][.]+ (.+)\z/)
162
- # <kijitora@example.co.jp>... Deferred: Name server: example.co.jp.: host name lookup failure
163
- anotherset['recipient'] = cv[1]
164
- anotherset['diagnosis'] = cv[2]
165
- else
166
- # ----- Transcript of session follows -----
106
+ next unless f == 1
107
+ permessage[fieldtable[o[0]]] = o[2]
108
+ end
109
+ else
110
+ # The line does not begin with a DSN field defined in RFC3464
111
+ #
112
+ # ----- Transcript of session follows -----
113
+ # ... while talking to mta.example.org.:
114
+ # >>> DATA
115
+ # <<< 550 Unknown user recipient@example.jp
116
+ # 554 5.0.0 Service unavailable
117
+ # ...
118
+ # Reporting-MTA: dns; mx.example.jp
119
+ # Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
120
+ # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
121
+ unless e.start_with?(' ')
122
+ if cv = e.match(/\A[>]{3}[ ]+([A-Z]{4})[ ]?/)
123
+ # >>> DATA
124
+ commandtxt = cv[1]
125
+
126
+ elsif cv = e.match(/\A[<]{3}[ ]+(.+)\z/)
127
+ # <<< Response
128
+ esmtpreply << cv[1] unless esmtpreply.index(cv[1])
129
+ else
130
+ # Detect SMTP session error or connection error
131
+ next if sessionerr
132
+ if e.start_with?(StartingOf[:error][0])
133
+ # ----- Transcript of session follows -----
134
+ # ... while talking to mta.example.org.:
135
+ sessionerr = true
136
+ next
137
+ end
138
+
139
+ if cv = e.match(/\A[<](.+)[>][.]+ (.+)\z/)
140
+ # <kijitora@example.co.jp>... Deferred: Name server: example.co.jp.: host name lookup failure
141
+ anotherset['recipient'] = cv[1]
142
+ anotherset['diagnosis'] = cv[2]
143
+ else
144
+ # ----- Transcript of session follows -----
145
+ # Message could not be delivered for too long
146
+ # Message will be deleted from queue
147
+ next if e =~ /\A[ \t]*[-]+/
148
+ if cv = e.match(/\A[45]\d\d[ \t]([45][.]\d[.]\d)[ \t].+/)
149
+ # 550 5.1.2 <kijitora@example.org>... Message
150
+ #
151
+ # DBI connect('dbname=...')
152
+ # 554 5.3.0 unknown mailer error 255
153
+ anotherset['status'] = cv[1]
154
+ anotherset['diagnosis'] ||= ''
155
+ anotherset['diagnosis'] << ' ' << e
156
+
157
+ elsif e.start_with?('Message ', 'Warning: ')
167
158
  # Message could not be delivered for too long
168
- # Message will be deleted from queue
169
- next if e =~ /\A[ \t]*[-]+/
170
- if cv = e.match(/\A[45]\d\d[ \t]([45][.]\d[.]\d)[ \t].+/)
171
- # 550 5.1.2 <kijitora@example.org>... Message
172
- #
173
- # DBI connect('dbname=...')
174
- # 554 5.3.0 unknown mailer error 255
175
- anotherset['status'] = cv[1]
176
- anotherset['diagnosis'] ||= ''
177
- anotherset['diagnosis'] << ' ' << e
178
-
179
- elsif e.start_with?('Message ', 'Warning: ')
180
- # Message could not be delivered for too long
181
- # Warning: message still undelivered after 4 hours
182
- anotherset['diagnosis'] ||= ''
183
- anotherset['diagnosis'] << ' ' << e
184
- end
159
+ # Warning: message still undelivered after 4 hours
160
+ anotherset['diagnosis'] ||= ''
161
+ anotherset['diagnosis'] << ' ' << e
185
162
  end
186
163
  end
187
- else
188
- # Continued line of the value of Diagnostic-Code field
189
- next unless p.start_with?('Diagnostic-Code:')
190
- next unless cv = e.match(/\A[ \t]+(.+)\z/)
191
- v['diagnosis'] << ' ' << cv[1]
192
- havepassed[-1] = 'Diagnostic-Code: ' << e
193
164
  end
165
+ else
166
+ # Continued line of the value of Diagnostic-Code field
167
+ next unless readslices[-2].start_with?('Diagnostic-Code:')
168
+ next unless cv = e.match(/\A[ \t]+(.+)\z/)
169
+ v['diagnosis'] << ' ' << cv[1]
170
+ readslices[-1] = 'Diagnostic-Code: ' << e
194
171
  end
195
- end # End of message/delivery-status
196
- end
172
+ end
173
+ end # End of message/delivery-status
197
174
  return nil unless recipients > 0
198
175
 
199
176
  dscontents.each do |e|
@@ -238,8 +215,7 @@ module Sisimai::Lhost
238
215
  e.each_key { |a| e[a] ||= '' }
239
216
  end
240
217
 
241
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
242
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
218
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
243
219
  end
244
220
 
245
221
  end
@@ -8,10 +8,8 @@ module Sisimai::Lhost
8
8
  require 'sisimai/lhost'
9
9
 
10
10
  Indicators = Sisimai::Lhost.INDICATORS
11
- StartingOf = {
12
- message: ['Your message could not be sent.'],
13
- rfc822: ['Content-Type: message/rfc822'],
14
- }.freeze
11
+ ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
12
+ StartingOf = { message: ['Your message could not be sent.'] }.freeze
15
13
 
16
14
  def description; return 'WebSense SurfControl'; end
17
15
  def smtpagent; return Sisimai::Lhost.smtpagent(self); end
@@ -40,92 +38,69 @@ module Sisimai::Lhost
40
38
  require 'sisimai/rfc1894'
41
39
  fieldtable = Sisimai::RFC1894.FIELDTABLE
42
40
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
43
- hasdivided = mbody.split("\n")
44
- havepassed = ['']
45
- rfc822list = [] # (Array) Each line in message/rfc822 part string
46
- blanklines = 0 # (Integer) The number of blank lines
41
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
42
+ bodyslices = emailsteak[0].split("\n")
43
+ readslices = ['']
47
44
  readcursor = 0 # (Integer) Points the current cursor position
48
45
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
49
46
  v = nil
50
47
 
51
- while e = hasdivided.shift do
52
- # Save the current line for the next loop
53
- havepassed << e
54
- p = havepassed[-2]
48
+ while e = bodyslices.shift do
49
+ # Read error messages and delivery status lines from the head of the email
50
+ # to the previous line of the beginning of the original message.
51
+ readslices << e # Save the current line for the next loop
55
52
 
56
53
  if readcursor == 0
57
54
  # Beginning of the bounce message or delivery status part
58
- if e == StartingOf[:message][0]
59
- readcursor |= Indicators[:deliverystatus]
60
- next
61
- end
62
- end
63
-
64
- if (readcursor & Indicators[:'message-rfc822']) == 0
65
- # Beginning of the original message part
66
- if e == StartingOf[:rfc822][0]
67
- readcursor |= Indicators[:'message-rfc822']
68
- next
69
- end
55
+ readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
56
+ next
70
57
  end
71
-
72
- if readcursor & Indicators[:'message-rfc822'] > 0
73
- # Inside of the original message part
74
- if e.empty?
75
- blanklines += 1
76
- break if blanklines > 1
77
- next
58
+ next if (readcursor & Indicators[:deliverystatus]) == 0
59
+ next if e.empty?
60
+
61
+ # Your message could not be sent.
62
+ # A transcript of the attempts to send the message follows.
63
+ # The number of attempts made: 1
64
+ # Addressed To: kijitora@example.com
65
+ #
66
+ # Thu 29 Apr 2010 23:34:45 +0900
67
+ # Failed to send to identified host,
68
+ # kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
69
+ # --- Message non-deliverable.
70
+ v = dscontents[-1]
71
+
72
+ if cv = e.match(/\AAddressed To:[ ]*([^ ]+?[@][^ ]+?)\z/)
73
+ # Addressed To: kijitora@example.com
74
+ if v['recipient']
75
+ # There are multiple recipient addresses in the message body.
76
+ dscontents << Sisimai::Lhost.DELIVERYSTATUS
77
+ v = dscontents[-1]
78
78
  end
79
- rfc822list << e
80
- else
81
- # Error message part
82
- next if (readcursor & Indicators[:deliverystatus]) == 0
83
- next if e.empty?
79
+ v['recipient'] = cv[1]
80
+ recipients += 1
84
81
 
85
- # Your message could not be sent.
86
- # A transcript of the attempts to send the message follows.
87
- # The number of attempts made: 1
88
- # Addressed To: kijitora@example.com
89
- #
82
+ elsif e =~ /\A(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[ ,]/
90
83
  # Thu 29 Apr 2010 23:34:45 +0900
91
- # Failed to send to identified host,
92
- # kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
93
- # --- Message non-deliverable.
94
- v = dscontents[-1]
95
-
96
- if cv = e.match(/\AAddressed To:[ ]*([^ ]+?[@][^ ]+?)\z/)
97
- # Addressed To: kijitora@example.com
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'] = cv[1]
104
- recipients += 1
84
+ v['date'] = e
105
85
 
106
- elsif e =~ /\A(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[ ,]/
107
- # Thu 29 Apr 2010 23:34:45 +0900
108
- v['date'] = e
109
-
110
- elsif cv = e.match(/\A[^ ]+[@][^ ]+:[ ]*\[(\d+[.]\d+[.]\d+[.]\d)\],[ ]*(.+)\z/)
111
- # kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
112
- v['rhost'] = cv[1]
113
- v['diagnosis'] = cv[2]
86
+ elsif cv = e.match(/\A[^ ]+[@][^ ]+:[ ]*\[(\d+[.]\d+[.]\d+[.]\d)\],[ ]*(.+)\z/)
87
+ # kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
88
+ v['rhost'] = cv[1]
89
+ v['diagnosis'] = cv[2]
90
+ else
91
+ # Fallback, parse RFC3464 headers.
92
+ if f = Sisimai::RFC1894.match(e)
93
+ # "e" matched with any field defined in RFC3464
94
+ next unless o = Sisimai::RFC1894.field(e)
95
+ next if o[1] == 'final-recipient'
96
+ next unless fieldtable[o[0]]
97
+ v[fieldtable[o[0]]] = o[2]
114
98
  else
115
- # Fallback, parse RFC3464 headers.
116
- if f = Sisimai::RFC1894.match(e)
117
- # "e" matched with any field defined in RFC3464
118
- next unless o = Sisimai::RFC1894.field(e)
119
- next if o[1] == 'final-recipient'
120
- next unless fieldtable.key?(o[0])
121
- v[fieldtable[o[0]]] = o[2]
122
- else
123
- # Continued line of the value of Diagnostic-Code field
124
- next unless p.start_with?('Diagnostic-Code:')
125
- next unless cv = e.match(/\A[ \t]+(.+)\z/)
126
- v['diagnosis'] << ' ' << cv[1]
127
- havepassed[-1] = 'Diagnostic-Code: ' << e
128
- end
99
+ # Continued line of the value of Diagnostic-Code field
100
+ next unless readslices[-2].start_with?('Diagnostic-Code:')
101
+ next unless cv = e.match(/\A[ \t]+(.+)\z/)
102
+ v['diagnosis'] << ' ' << cv[1]
103
+ readslices[-1] = 'Diagnostic-Code: ' << e
129
104
  end
130
105
  end
131
106
  end
@@ -137,8 +112,7 @@ module Sisimai::Lhost
137
112
  e.each_key { |a| e[a] ||= '' }
138
113
  end
139
114
 
140
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
141
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
115
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
142
116
  end
143
117
 
144
118
  end
@@ -7,6 +7,7 @@ module Sisimai::Lhost
7
7
  require 'sisimai/lhost'
8
8
 
9
9
  Indicators = Sisimai::Lhost.INDICATORS
10
+ ReBackbone = %r<^Content-Type:[ ](?:message/rfc822|text/rfc822-headers)>.freeze
10
11
  MarkingsOf = {
11
12
  # MarkingsOf is a delimiter set of these sections:
12
13
  # message: The first line of a bounce message to be parsed.
@@ -16,7 +17,6 @@ module Sisimai::Lhost
16
17
  # endof: Fixed string ``__END_OF_EMAIL_MESSAGE__''
17
18
  message: %r/\A[ \t]+[-]+ Transcript of session follows [-]+\z/,
18
19
  error: %r/\A[.]+ while talking to .+[:]\z/,
19
- rfc822: %r{\AContent-Type:[ ]*(?:message/rfc822|text/rfc822-headers)\z},
20
20
  }.freeze
21
21
 
22
22
  def description; return 'Module description'; end
@@ -49,42 +49,23 @@ module Sisimai::Lhost
49
49
  # 2. Parse message body(mbody) of the bounce message. See some modules
50
50
  # in lib/sisimai/lhost directory to implement codes.
51
51
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
52
- hasdivided = mbody.split("\n")
53
- rfc822list = [] # (Array) Each line in message/rfc822 part string
54
- blanklines = 0 # (Integer) The number of blank lines
52
+ emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
53
+ bodyslices = emailsteak[0].split("\n")
55
54
  readcursor = 0 # (Integer) Points the current cursor position
56
55
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
57
56
 
58
- while e = hasdivided.shift do
57
+ while e = bodyslices.shift do
58
+ # Read error messages and delivery status lines from the head of the email
59
+ # to the previous line of the beginning of the original message.
59
60
  if readcursor == 0
60
61
  # Beginning of the bounce message or delivery status part
61
- if e =~ MarkingsOf[:message]
62
- readcursor |= Indicators[:deliverystatus]
63
- next
64
- end
62
+ readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
63
+ next
65
64
  end
65
+ next if (readcursor & Indicators[:deliverystatus]) == 0
66
+ next if e.empty?
66
67
 
67
- if (readcursor & Indicators[:'message-rfc822']) == 0
68
- # Beginning of the original message part
69
- if e =~ MarkingsOf[:rfc822]
70
- readcursor |= Indicators[:'message-rfc822']
71
- next
72
- end
73
- end
74
-
75
- if readcursor & Indicators[:'message-rfc822'] > 0
76
- # After "message/rfc822"
77
- if e.empty?
78
- blanklines += 1
79
- break if blanklines > 1
80
- next
81
- end
82
- rfc822list << e
83
- else
84
- # Before "message/rfc822"
85
- next if (readcursor & Indicators[:deliverystatus]) == 0
86
- next if e.empty?
87
- end
68
+ # Code for getting a recipient address and other values you require
88
69
  end
89
70
 
90
71
  # The following code is dummy to be passed "make test".
@@ -96,17 +77,16 @@ module Sisimai::Lhost
96
77
  dscontents[0]['agent'] = self.smtpagent
97
78
  recipients = 1 if dscontents[0]['recipient']
98
79
 
99
- rfc822list << 'From: shironeko@example.org'
100
- rfc822list << 'Subject: Nyaaan'
101
- rfc822list << 'Message-Id: 000000000000@example.jp'
80
+ emailsteak[1] << 'From: shironeko@example.org' << "\n"
81
+ emailsteak[1] << 'Subject: Nyaaan' << "\n"
82
+ emailsteak[1] << 'Message-Id: 000000000000@example.jp' << "\n"
102
83
 
103
84
  # 3. Return nil when there is no recipient address which is failed to
104
85
  # delivery in the bounce message
105
86
  return nil unless recipients > 0
106
87
 
107
88
  # 4. Return the following variable.
108
- rfc822part = Sisimai::RFC5322.weedout(rfc822list)
109
- return { 'ds' => dscontents, 'rfc822' => rfc822part }
89
+ return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
110
90
  end
111
91
 
112
92
  end