sisimai 4.25.4-java → 4.25.5-java
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.
- checksums.yaml +5 -5
- data/.travis.yml +2 -2
- data/ChangeLog.md +50 -0
- data/README-JA.md +10 -37
- data/README.md +10 -37
- data/lib/sisimai.rb +15 -64
- data/lib/sisimai/address.rb +13 -17
- data/lib/sisimai/arf.rb +4 -4
- data/lib/sisimai/data.rb +3 -5
- data/lib/sisimai/lhost.rb +0 -14
- data/lib/sisimai/lhost/activehunter.rb +31 -55
- data/lib/sisimai/lhost/amavis.rb +41 -66
- data/lib/sisimai/lhost/amazonses.rb +189 -235
- data/lib/sisimai/lhost/amazonworkmail.rb +48 -71
- data/lib/sisimai/lhost/aol.rb +49 -75
- data/lib/sisimai/lhost/apachejames.rb +60 -83
- data/lib/sisimai/lhost/bigfoot.rb +61 -85
- data/lib/sisimai/lhost/biglobe.rb +40 -62
- data/lib/sisimai/lhost/courier.rb +60 -82
- data/lib/sisimai/lhost/domino.rb +50 -76
- data/lib/sisimai/lhost/einsundeins.rb +57 -55
- data/lib/sisimai/lhost/exchange2003.rb +79 -101
- data/lib/sisimai/lhost/exchange2007.rb +66 -74
- data/lib/sisimai/lhost/exim.rb +119 -142
- data/lib/sisimai/lhost/ezweb.rb +53 -73
- data/lib/sisimai/lhost/facebook.rb +49 -75
- data/lib/sisimai/lhost/fml.rb +25 -50
- data/lib/sisimai/lhost/gmx.rb +55 -79
- data/lib/sisimai/lhost/google.rb +39 -66
- data/lib/sisimai/lhost/gsuite.rb +74 -94
- data/lib/sisimai/lhost/imailserver.rb +34 -67
- data/lib/sisimai/lhost/interscanmss.rb +33 -67
- data/lib/sisimai/lhost/kddi.rb +30 -52
- data/lib/sisimai/lhost/mailfoundry.rb +35 -57
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +66 -89
- data/lib/sisimai/lhost/mailru.rb +51 -76
- data/lib/sisimai/lhost/mcafee.rb +53 -79
- data/lib/sisimai/lhost/messagelabs.rb +49 -75
- data/lib/sisimai/lhost/messagingserver.rb +91 -113
- data/lib/sisimai/lhost/mfilter.rb +50 -70
- data/lib/sisimai/lhost/mxlogic.rb +38 -63
- data/lib/sisimai/lhost/notes.rb +53 -82
- data/lib/sisimai/lhost/office365.rb +64 -81
- data/lib/sisimai/lhost/opensmtpd.rb +30 -52
- data/lib/sisimai/lhost/outlook.rb +49 -75
- data/lib/sisimai/lhost/postfix.rb +116 -117
- data/lib/sisimai/lhost/qmail.rb +33 -55
- data/lib/sisimai/lhost/receivingses.rb +49 -75
- data/lib/sisimai/lhost/sendgrid.rb +68 -203
- data/lib/sisimai/lhost/sendmail.rb +101 -125
- data/lib/sisimai/lhost/surfcontrol.rb +53 -79
- data/lib/sisimai/lhost/userdefined.rb +15 -35
- data/lib/sisimai/lhost/v5sendmail.rb +59 -89
- data/lib/sisimai/lhost/verizon.rb +75 -124
- data/lib/sisimai/lhost/x1.rb +30 -54
- data/lib/sisimai/lhost/x2.rb +28 -52
- data/lib/sisimai/lhost/x3.rb +44 -68
- data/lib/sisimai/lhost/x4.rb +34 -58
- data/lib/sisimai/lhost/x5.rb +42 -70
- data/lib/sisimai/lhost/yahoo.rb +44 -68
- data/lib/sisimai/lhost/yandex.rb +59 -85
- data/lib/sisimai/lhost/zoho.rb +54 -78
- data/lib/sisimai/mail.rb +5 -9
- data/lib/sisimai/mail/maildir.rb +10 -14
- data/lib/sisimai/mail/mbox.rb +8 -12
- data/lib/sisimai/mail/memory.rb +5 -9
- data/lib/sisimai/mail/stdin.rb +7 -11
- data/lib/sisimai/mda.rb +2 -2
- data/lib/sisimai/message.rb +51 -154
- data/lib/sisimai/mime.rb +2 -2
- data/lib/sisimai/order.rb +2 -27
- data/lib/sisimai/reason.rb +3 -5
- data/lib/sisimai/rfc1894.rb +1 -1
- data/lib/sisimai/rfc3464.rb +29 -29
- data/lib/sisimai/rfc3834.rb +7 -6
- data/lib/sisimai/rfc5322.rb +20 -31
- data/lib/sisimai/rhost/franceptt.rb +120 -24
- data/lib/sisimai/rhost/iua.rb +1 -1
- data/lib/sisimai/smtp/error.rb +7 -7
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/maildir/bsd/email-einsundeins-03.eml +66 -0
- data/set-of-emails/maildir/bsd/email-exchange2007-05.eml +1469 -0
- data/set-of-emails/maildir/bsd/email-exchange2007-06.eml +764 -0
- data/set-of-emails/maildir/bsd/email-postfix-64.eml +96 -0
- data/set-of-emails/maildir/bsd/rfc3834-03.eml +26 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-04.eml +66 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-05.eml +96 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-06.eml +100 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-07.eml +97 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-08.eml +78 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-10.eml +79 -0
- data/set-of-emails/maildir/bsd/rhost-franceptt-11.eml +96 -0
- metadata +27 -21
- data/lib/sisimai/bite.rb +0 -42
- data/lib/sisimai/bite/email.rb +0 -18
- data/lib/sisimai/bite/json.rb +0 -16
- data/lib/sisimai/message/email.rb +0 -26
- data/lib/sisimai/message/json.rb +0 -24
- data/lib/sisimai/order/email.rb +0 -20
- 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
|
-
|
53
|
-
|
54
|
-
|
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 =
|
65
|
-
#
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
120
|
-
|
121
|
-
v['spec'] = o[1]
|
122
|
-
v['diagnosis'] = o[2]
|
91
|
+
v['recipient'] = o[2]
|
92
|
+
recipients += 1
|
123
93
|
else
|
124
|
-
#
|
125
|
-
|
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
|
-
#
|
133
|
-
|
134
|
-
|
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
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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
|
-
#
|
169
|
-
|
170
|
-
|
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
|
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
|
-
|
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
|
-
|
12
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
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 =
|
52
|
-
#
|
53
|
-
|
54
|
-
|
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
|
-
|
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
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
80
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
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
|
-
#
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
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
|
-
|
53
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
109
|
-
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
89
|
+
return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
|
110
90
|
end
|
111
91
|
|
112
92
|
end
|