sisimai 4.16.0-java → 4.17.0-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 +4 -4
- data/.rubocop.yml +3 -0
- data/ANALYTICAL-PRECISION +7 -7
- data/Changes +15 -0
- data/Makefile +1 -1
- data/README.md +30 -28
- data/lib/sisimai.rb +20 -1
- data/lib/sisimai/address.rb +28 -9
- data/lib/sisimai/arf.rb +37 -46
- data/lib/sisimai/data.rb +67 -43
- data/lib/sisimai/datetime.rb +210 -210
- data/lib/sisimai/mda.rb +30 -30
- data/lib/sisimai/message.rb +3 -5
- data/lib/sisimai/msp/de/einsundeins.rb +14 -42
- data/lib/sisimai/msp/de/gmx.rb +17 -44
- data/lib/sisimai/msp/jp/biglobe.rb +15 -44
- data/lib/sisimai/msp/jp/ezweb.rb +20 -50
- data/lib/sisimai/msp/jp/kddi.rb +16 -43
- data/lib/sisimai/msp/ru/mailru.rb +20 -48
- data/lib/sisimai/msp/ru/yandex.rb +16 -50
- data/lib/sisimai/msp/uk/messagelabs.rb +17 -51
- data/lib/sisimai/msp/us/amazonses.rb +18 -40
- data/lib/sisimai/msp/us/amazonworkmail.rb +17 -35
- data/lib/sisimai/msp/us/aol.rb +17 -41
- data/lib/sisimai/msp/us/bigfoot.rb +15 -48
- data/lib/sisimai/msp/us/facebook.rb +63 -90
- data/lib/sisimai/msp/us/google.rb +15 -44
- data/lib/sisimai/msp/us/office365.rb +21 -46
- data/lib/sisimai/msp/us/outlook.rb +17 -50
- data/lib/sisimai/msp/us/receivingses.rb +20 -43
- data/lib/sisimai/msp/us/sendgrid.rb +13 -37
- data/lib/sisimai/msp/us/verizon.rb +30 -74
- data/lib/sisimai/msp/us/yahoo.rb +12 -40
- data/lib/sisimai/msp/us/zoho.rb +14 -42
- data/lib/sisimai/mta/activehunter.rb +11 -40
- data/lib/sisimai/mta/apachejames.rb +18 -40
- data/lib/sisimai/mta/courier.rb +20 -57
- data/lib/sisimai/mta/domino.rb +24 -56
- data/lib/sisimai/mta/exchange.rb +26 -54
- data/lib/sisimai/mta/exim.rb +20 -39
- data/lib/sisimai/mta/imailserver.rb +26 -71
- data/lib/sisimai/mta/interscanmss.rb +26 -44
- data/lib/sisimai/mta/mailfoundry.rb +12 -42
- data/lib/sisimai/mta/mailmarshalsmtp.rb +13 -43
- data/lib/sisimai/mta/mcafee.rb +17 -46
- data/lib/sisimai/mta/messagingserver.rb +14 -47
- data/lib/sisimai/mta/mfilter.rb +12 -35
- data/lib/sisimai/mta/mxlogic.rb +18 -42
- data/lib/sisimai/mta/notes.rb +22 -45
- data/lib/sisimai/mta/opensmtpd.rb +18 -48
- data/lib/sisimai/mta/postfix.rb +15 -45
- data/lib/sisimai/mta/qmail.rb +32 -60
- data/lib/sisimai/mta/sendmail.rb +13 -38
- data/lib/sisimai/mta/surfcontrol.rb +15 -44
- data/lib/sisimai/mta/userdefined.rb +14 -30
- data/lib/sisimai/mta/v5sendmail.rb +18 -40
- data/lib/sisimai/mta/x1.rb +12 -41
- data/lib/sisimai/mta/x2.rb +12 -41
- data/lib/sisimai/mta/x3.rb +12 -39
- data/lib/sisimai/mta/x4.rb +33 -66
- data/lib/sisimai/mta/x5.rb +15 -42
- data/lib/sisimai/reason.rb +8 -71
- data/lib/sisimai/reason/blocked.rb +3 -0
- data/lib/sisimai/reason/contenterror.rb +3 -0
- data/lib/sisimai/reason/delivered.rb +27 -0
- data/lib/sisimai/reason/exceedlimit.rb +3 -0
- data/lib/sisimai/reason/expired.rb +3 -0
- data/lib/sisimai/reason/feedback.rb +18 -0
- data/lib/sisimai/reason/filtered.rb +4 -0
- data/lib/sisimai/reason/hasmoved.rb +3 -0
- data/lib/sisimai/reason/hostunknown.rb +3 -0
- data/lib/sisimai/reason/mailboxfull.rb +3 -0
- data/lib/sisimai/reason/mailererror.rb +3 -0
- data/lib/sisimai/reason/mesgtoobig.rb +3 -0
- data/lib/sisimai/reason/networkerror.rb +3 -0
- data/lib/sisimai/reason/norelaying.rb +3 -0
- data/lib/sisimai/reason/notaccept.rb +3 -0
- data/lib/sisimai/reason/onhold.rb +3 -0
- data/lib/sisimai/reason/rejected.rb +3 -0
- data/lib/sisimai/reason/securityerror.rb +3 -0
- data/lib/sisimai/reason/spamdetected.rb +3 -0
- data/lib/sisimai/reason/suspend.rb +3 -0
- data/lib/sisimai/reason/syntaxerror.rb +41 -0
- data/lib/sisimai/reason/systemerror.rb +3 -0
- data/lib/sisimai/reason/systemfull.rb +3 -0
- data/lib/sisimai/reason/toomanyconn.rb +3 -0
- data/lib/sisimai/reason/undefined.rb +18 -0
- data/lib/sisimai/reason/userunknown.rb +3 -0
- data/lib/sisimai/reason/vacation.rb +18 -0
- data/lib/sisimai/rfc3464.rb +15 -40
- data/lib/sisimai/rfc3834.rb +1 -10
- data/lib/sisimai/rfc5322.rb +57 -19
- data/lib/sisimai/rhost/googleapps.rb +82 -82
- data/lib/sisimai/smtp/reply.rb +2 -1
- data/lib/sisimai/smtp/status.rb +154 -152
- data/lib/sisimai/string.rb +2 -3
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/maildir/bsd/rfc3464-29.eml +60 -0
- data/set-of-emails/maildir/bsd/us-amazonworkmail-06.eml +156 -0
- data/set-of-emails/maildir/bsd/us-amazonworkmail-07.eml +158 -0
- data/set-of-emails/maildir/bsd/us-google-15.eml +97 -0
- data/set-of-emails/maildir/bsd/us-google-16.eml +99 -0
- data/set-of-emails/maildir/bsd/us-google-17.eml +104 -0
- data/set-of-emails/maildir/dos/apachejames-01.eml +4 -4
- data/set-of-emails/maildir/dos/us-amazonworkmail-01.eml +156 -0
- data/set-of-emails/maildir/dos/us-office365-01.eml +102 -0
- data/set-of-emails/maildir/mac/apachejames-01.eml +1 -9
- data/set-of-emails/maildir/mac/us-amazonworkmail-01.eml +1 -7
- data/set-of-emails/maildir/mac/us-office365-01.eml +1 -4
- metadata +17 -2
@@ -23,8 +23,6 @@ module Sisimai
|
|
23
23
|
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
24
24
|
}
|
25
25
|
Indicators = Sisimai::MTA.INDICATORS
|
26
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
27
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
28
26
|
|
29
27
|
def description; return 'Java Apache Mail Enterprise Server'; end
|
30
28
|
def smtpagent; return 'ApacheJames'; end
|
@@ -52,11 +50,10 @@ module Sisimai
|
|
52
50
|
match += 1 if mhead['received'].find { |a| a =~ Re0[:received] }
|
53
51
|
return if match == 0
|
54
52
|
|
55
|
-
dscontents = [
|
53
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
56
54
|
hasdivided = mbody.split("\n")
|
57
|
-
|
58
|
-
|
59
|
-
previousfn = '' # (String) Previous field name
|
55
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
56
|
+
blanklines = 0 # (Integer) The number of blank lines
|
60
57
|
readcursor = 0 # (Integer) Points the current cursor position
|
61
58
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
62
59
|
diagnostic = '' # (String) Alternative diagnostic message
|
@@ -65,11 +62,10 @@ module Sisimai
|
|
65
62
|
v = nil
|
66
63
|
|
67
64
|
hasdivided.each do |e|
|
68
|
-
|
69
65
|
if readcursor == 0
|
70
66
|
# Beginning of the bounce message or delivery status part
|
71
67
|
if e =~ Re1[:begin]
|
72
|
-
readcursor |= Indicators[:
|
68
|
+
readcursor |= Indicators[:deliverystatus]
|
73
69
|
next
|
74
70
|
end
|
75
71
|
end
|
@@ -84,30 +80,16 @@ module Sisimai
|
|
84
80
|
|
85
81
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
86
82
|
# After "message/rfc822"
|
87
|
-
if
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
next unless RFC822Head.key?(lhs)
|
92
|
-
|
93
|
-
previousfn = lhs
|
94
|
-
rfc822part += e + "\n"
|
95
|
-
|
96
|
-
elsif e =~ /\A[ \t]+/
|
97
|
-
# Continued line from the previous line
|
98
|
-
next if rfc822next[previousfn]
|
99
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
100
|
-
|
101
|
-
else
|
102
|
-
# Check the end of headers in rfc822 part
|
103
|
-
next unless LongFields.key?(previousfn)
|
104
|
-
next unless e.empty?
|
105
|
-
rfc822next[previousfn] = true
|
83
|
+
if e.empty?
|
84
|
+
blanklines += 1
|
85
|
+
break if blanklines > 1
|
86
|
+
next
|
106
87
|
end
|
88
|
+
rfc822list << e
|
107
89
|
|
108
90
|
else
|
109
91
|
# Before "message/rfc822"
|
110
|
-
next if readcursor & Indicators[:
|
92
|
+
next if readcursor & Indicators[:deliverystatus] == 0
|
111
93
|
next if e.empty?
|
112
94
|
|
113
95
|
# Message details:
|
@@ -164,26 +146,22 @@ module Sisimai
|
|
164
146
|
end
|
165
147
|
end
|
166
148
|
end
|
167
|
-
|
168
149
|
return nil if recipients == 0
|
169
150
|
require 'sisimai/string'
|
170
|
-
|
151
|
+
|
152
|
+
unless rfc822list.find { |a| a =~ /^Subject:/ }
|
153
|
+
# Set the value of $subjecttxt as a Subject if there is no original
|
154
|
+
# message in the bounce mail.
|
155
|
+
rfc822list << sprintf('Subject: %s', subjecttxt)
|
156
|
+
end
|
171
157
|
|
172
158
|
dscontents.map do |e|
|
173
|
-
e['agent']
|
174
|
-
|
175
|
-
if mhead['received'].size > 0
|
176
|
-
# Get localhost and remote host name from Received header.
|
177
|
-
r0 = mhead['received']
|
178
|
-
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
179
|
-
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
180
|
-
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
181
|
-
end
|
159
|
+
e['agent'] = Sisimai::MTA::ApacheJames.smtpagent
|
182
160
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'] || diagnostic)
|
183
|
-
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
184
161
|
e.each_key { |a| e[a] ||= '' }
|
185
162
|
end
|
186
163
|
|
164
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
187
165
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
188
166
|
end
|
189
167
|
|
data/lib/sisimai/mta/courier.rb
CHANGED
@@ -34,24 +34,16 @@ module Sisimai
|
|
34
34
|
}
|
35
35
|
ReFailure = {
|
36
36
|
# courier/module.esmtp/esmtpclient.c:526| hard_error(del, ctf, "No such domain.");
|
37
|
-
|
38
|
-
\ANo[ ]such[ ]domain[.]\z
|
39
|
-
}x,
|
37
|
+
hostunknown: %r/\ANo[ ]such[ ]domain[.]\z/x,
|
40
38
|
# courier/module.esmtp/esmtpclient.c:531| hard_error(del, ctf,
|
41
39
|
# courier/module.esmtp/esmtpclient.c:532| "This domain's DNS violates RFC 1035.");
|
42
|
-
|
43
|
-
\AThis[ ]domain's[ ]DNS[ ]violates[ ]RFC[ ]1035[.]\z
|
44
|
-
}x,
|
40
|
+
systemerror: %r/\AThis[ ]domain's[ ]DNS[ ]violates[ ]RFC[ ]1035[.]\z/x,
|
45
41
|
}
|
46
42
|
ReDelayed = {
|
47
43
|
# courier/module.esmtp/esmtpclient.c:535| soft_error(del, ctf, "DNS lookup failed.");
|
48
|
-
|
49
|
-
\ADNS[ ]lookup[ ]failed[.]\z
|
50
|
-
},
|
44
|
+
networkerror: %r/\ADNS[ ]lookup[ ]failed[.]\z/x,
|
51
45
|
}
|
52
46
|
Indicators = Sisimai::MTA.INDICATORS
|
53
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
54
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
55
47
|
|
56
48
|
def description; return 'Courier MTA'; end
|
57
49
|
def smtpagent; return 'Courier'; end
|
@@ -82,12 +74,11 @@ module Sisimai
|
|
82
74
|
end
|
83
75
|
return nil if match == 0
|
84
76
|
|
85
|
-
dscontents = [
|
77
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
86
78
|
hasdivided = mbody.split("\n")
|
87
|
-
havepassed = ['']
|
88
|
-
|
89
|
-
|
90
|
-
previousfn = '' # (String) Previous field name
|
79
|
+
havepassed = ['']
|
80
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
81
|
+
blanklines = 0 # (Integer) The number of blank lines
|
91
82
|
readcursor = 0 # (Integer) Points the current cursor position
|
92
83
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
93
84
|
commandtxt = '' # (String) SMTP Command name begin with the string '>>>'
|
@@ -101,12 +92,13 @@ module Sisimai
|
|
101
92
|
|
102
93
|
hasdivided.each do |e|
|
103
94
|
# Save the current line for the next loop
|
104
|
-
havepassed << e
|
95
|
+
havepassed << e
|
96
|
+
p = havepassed[-2]
|
105
97
|
|
106
98
|
if readcursor == 0
|
107
99
|
# Beginning of the bounce message or delivery status part
|
108
100
|
if e =~ Re1[:begin]
|
109
|
-
readcursor |= Indicators[:
|
101
|
+
readcursor |= Indicators[:deliverystatus]
|
110
102
|
next
|
111
103
|
end
|
112
104
|
end
|
@@ -121,30 +113,16 @@ module Sisimai
|
|
121
113
|
|
122
114
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
123
115
|
# After "message/rfc822"
|
124
|
-
if
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
next unless RFC822Head.key?(lhs)
|
129
|
-
|
130
|
-
previousfn = lhs
|
131
|
-
rfc822part += e + "\n"
|
132
|
-
|
133
|
-
elsif e =~ /\A[ \t]+/
|
134
|
-
# Continued line from the previous line
|
135
|
-
next if rfc822next[previousfn]
|
136
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
137
|
-
|
138
|
-
else
|
139
|
-
# Check the end of headers in rfc822 part
|
140
|
-
next unless LongFields.key?(previousfn)
|
141
|
-
next unless e.empty?
|
142
|
-
rfc822next[previousfn] = true
|
116
|
+
if e.empty?
|
117
|
+
blanklines += 1
|
118
|
+
break if blanklines > 1
|
119
|
+
next
|
143
120
|
end
|
121
|
+
rfc822list << e
|
144
122
|
|
145
123
|
else
|
146
124
|
# Before "message/rfc822"
|
147
|
-
next if readcursor & Indicators[:
|
125
|
+
next if readcursor & Indicators[:deliverystatus] == 0
|
148
126
|
next if e.empty?
|
149
127
|
|
150
128
|
if connvalues == connheader.keys.size
|
@@ -159,7 +137,7 @@ module Sisimai
|
|
159
137
|
# Final-Recipient: rfc822; kijitora@example.co.jp
|
160
138
|
if v['recipient']
|
161
139
|
# There are multiple recipient addresses in the message body.
|
162
|
-
dscontents << Sisimai::MTA.DELIVERYSTATUS
|
140
|
+
dscontents << Sisimai::MTA.DELIVERYSTATUS
|
163
141
|
v = dscontents[-1]
|
164
142
|
end
|
165
143
|
v['recipient'] = cv[1]
|
@@ -250,28 +228,18 @@ module Sisimai
|
|
250
228
|
end
|
251
229
|
end
|
252
230
|
end
|
253
|
-
|
254
231
|
return nil if recipients == 0
|
255
232
|
require 'sisimai/string'
|
256
|
-
require 'sisimai/smtp/status'
|
257
233
|
|
258
234
|
dscontents.map do |e|
|
259
235
|
# Set default values if each value is empty.
|
260
236
|
connheader.each_key { |a| e[a] ||= connheader[a] || '' }
|
261
237
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
262
238
|
|
263
|
-
if mhead['received'].size > 0
|
264
|
-
# Get localhost and remote host name from Received header.
|
265
|
-
r0 = mhead['received']
|
266
|
-
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
267
|
-
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
268
|
-
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
269
|
-
end
|
270
|
-
|
271
239
|
ReFailure.each_key do |r|
|
272
240
|
# Verify each regular expression of session errors
|
273
241
|
next unless e['diagnosis'] =~ ReFailure[r]
|
274
|
-
e['reason'] = r
|
242
|
+
e['reason'] = r.to_s
|
275
243
|
e['softbounce'] = 0
|
276
244
|
break
|
277
245
|
end
|
@@ -280,23 +248,18 @@ module Sisimai
|
|
280
248
|
ReDelayed.each_key do |r|
|
281
249
|
# Verify each regular expression of session errors
|
282
250
|
next unless e['diagnosis'] =~ ReDelayed[r]
|
283
|
-
e['reason'] = r
|
251
|
+
e['reason'] = r.to_s
|
284
252
|
e['softbounce'] = 1
|
285
253
|
break
|
286
254
|
end
|
287
255
|
end
|
288
256
|
|
289
|
-
if !e['status'] || e['status'] =~ /\d[.]0[.]0\z/
|
290
|
-
# Get the status code from the respnse of remote MTA.
|
291
|
-
f = Sisimai::SMTP::Status.find(e['diagnosis'])
|
292
|
-
e['status'] = f if f.size > 0
|
293
|
-
end
|
294
|
-
e['spec'] = '' unless e['spec'] =~ /\A(?:SMTP|X-UNIX)\z/
|
295
257
|
e['agent'] = Sisimai::MTA::Courier.smtpagent
|
296
258
|
e['command'] ||= commandtxt || ''
|
297
259
|
e.each_key { |a| e[a] ||= '' }
|
298
260
|
end
|
299
261
|
|
262
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
300
263
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
301
264
|
end
|
302
265
|
|
data/lib/sisimai/mta/domino.rb
CHANGED
@@ -17,7 +17,7 @@ module Sisimai
|
|
17
17
|
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
18
18
|
}
|
19
19
|
ReFailure = {
|
20
|
-
|
20
|
+
userunknown: %r{(?>
|
21
21
|
not[ ]listed[ ]in[ ](?:
|
22
22
|
Domino[ ]Directory
|
23
23
|
|public[ ]Name[ ][&][ ]Address[ ]Book
|
@@ -25,16 +25,10 @@ module Sisimai
|
|
25
25
|
|Domino[ ]ディレクトリには見つかりません
|
26
26
|
)
|
27
27
|
}x,
|
28
|
-
|
29
|
-
|
30
|
-
}x,
|
31
|
-
'systemerror' => %r{
|
32
|
-
Several[ ]matches[ ]found[ ]in[ ]Domino[ ]Directory
|
33
|
-
}x,
|
28
|
+
filtered: %r/Cannot[ ]route[ ]mail[ ]to[ ]user/x,
|
29
|
+
systemerror: %r/Several[ ]matches[ ]found[ ]in[ ]Domino[ ]Directory/x,
|
34
30
|
}
|
35
31
|
Indicators = Sisimai::MTA.INDICATORS
|
36
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
37
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
38
32
|
|
39
33
|
def description; return 'IBM Domino Server'; end
|
40
34
|
def smtpagent; return 'Domino'; end
|
@@ -57,25 +51,23 @@ module Sisimai
|
|
57
51
|
return nil unless mbody
|
58
52
|
return nil unless mhead['subject'] =~ Re0[:subject]
|
59
53
|
|
60
|
-
|
54
|
+
require 'sisimai/address'
|
55
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
61
56
|
hasdivided = mbody.split("\n")
|
62
|
-
|
63
|
-
|
64
|
-
previousfn = '' # (String) Previous field name
|
57
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
58
|
+
blanklines = 0 # (Integer) The number of blank lines
|
65
59
|
readcursor = 0 # (Integer) Points the current cursor position
|
66
60
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
67
61
|
subjecttxt = '' # (String) The value of Subject:
|
68
62
|
v = nil
|
69
63
|
|
70
|
-
require 'sisimai/address'
|
71
|
-
|
72
64
|
hasdivided.each do |e|
|
73
65
|
next if e.empty?
|
74
66
|
|
75
67
|
if readcursor == 0
|
76
68
|
# Beginning of the bounce message or delivery status part
|
77
69
|
if e =~ Re1[:begin]
|
78
|
-
readcursor |= Indicators[:
|
70
|
+
readcursor |= Indicators[:deliverystatus]
|
79
71
|
next
|
80
72
|
end
|
81
73
|
end
|
@@ -90,30 +82,16 @@ module Sisimai
|
|
90
82
|
|
91
83
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
92
84
|
# After "message/rfc822"
|
93
|
-
if
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
next unless RFC822Head.key?(lhs)
|
98
|
-
|
99
|
-
previousfn = lhs
|
100
|
-
rfc822part += e + "\n"
|
101
|
-
|
102
|
-
elsif e =~ /\A[ \t]+/
|
103
|
-
# Continued line from the previous line
|
104
|
-
next if rfc822next[previousfn]
|
105
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
106
|
-
|
107
|
-
else
|
108
|
-
# Check the end of headers in rfc822 part
|
109
|
-
next unless LongFields.key?(previousfn)
|
110
|
-
next unless e.empty?
|
111
|
-
rfc822next[previousfn] = true
|
85
|
+
if e.empty?
|
86
|
+
blanklines += 1
|
87
|
+
break if blanklines > 1
|
88
|
+
next
|
112
89
|
end
|
90
|
+
rfc822list << e
|
113
91
|
|
114
92
|
else
|
115
93
|
# Before "message/rfc822"
|
116
|
-
next if readcursor & Indicators[:
|
94
|
+
next if readcursor & Indicators[:deliverystatus] == 0
|
117
95
|
|
118
96
|
# Your message
|
119
97
|
#
|
@@ -167,38 +145,28 @@ module Sisimai
|
|
167
145
|
require 'sisimai/smtp/status'
|
168
146
|
|
169
147
|
dscontents.map do |e|
|
170
|
-
|
171
|
-
e['agent'] = Sisimai::MTA::Domino.smtpagent
|
172
|
-
|
173
|
-
if mhead['received'].size > 0
|
174
|
-
# Get localhost and remote host name from Received header.
|
175
|
-
r0 = mhead['received']
|
176
|
-
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
177
|
-
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
178
|
-
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
179
|
-
end
|
148
|
+
e['agent'] = Sisimai::MTA::Domino.smtpagent
|
180
149
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
181
150
|
e['recipient'] = Sisimai::Address.s3s4(e['recipient'])
|
182
151
|
|
183
152
|
ReFailure.each_key do |r|
|
184
153
|
# Check each regular expression of Domino error messages
|
185
154
|
next unless e['diagnosis'] =~ ReFailure[r]
|
186
|
-
e['reason'] = r
|
187
|
-
pseudostatus = Sisimai::SMTP::Status.code(r, false)
|
155
|
+
e['reason'] = r.to_s
|
156
|
+
pseudostatus = Sisimai::SMTP::Status.code(r.to_s, false)
|
188
157
|
e['status'] = pseudostatus if pseudostatus.size > 0
|
189
158
|
break
|
190
159
|
end
|
191
|
-
|
192
|
-
e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
|
193
|
-
e['action'] = 'failed' if e['status'] =~ /\A[45]/
|
194
|
-
|
195
|
-
unless rfc822part =~ /\bSubject:/
|
196
|
-
# Fallback: Add the value of Subject as a Subject header
|
197
|
-
rfc822part += sprintf("Subject: %s\n", subjecttxt)
|
198
|
-
end
|
199
160
|
e.each_key { |a| e[a] ||= '' }
|
200
161
|
end
|
201
162
|
|
163
|
+
unless rfc822list.find { |a| a =~ /^Subject:/ }
|
164
|
+
# Set the value of $subjecttxt as a Subject if there is no original
|
165
|
+
# message in the bounce mail.
|
166
|
+
rfc822list << sprintf('Subject: %s', subjecttxt)
|
167
|
+
end
|
168
|
+
|
169
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
202
170
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
203
171
|
end
|
204
172
|
|
data/lib/sisimai/mta/exchange.rb
CHANGED
@@ -27,35 +27,33 @@ module Sisimai
|
|
27
27
|
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
28
28
|
}
|
29
29
|
CodeTable = {
|
30
|
-
|
30
|
+
onhold: [
|
31
31
|
'000B099C', # Host Unknown, Message exceeds size limit, ...
|
32
32
|
'000B09AA', # Unable to relay for, Message exceeds size limit,...
|
33
33
|
'000B09B6', # Error messages by remote MTA
|
34
34
|
],
|
35
|
-
|
35
|
+
userunknown: [
|
36
36
|
'000C05A6', # Unknown Recipient,
|
37
37
|
],
|
38
|
-
|
38
|
+
systemerror: [
|
39
39
|
'00010256', # Too many recipients.
|
40
40
|
'000D06B5', # No proxy for recipient (non-smtp mail?)
|
41
41
|
],
|
42
|
-
|
42
|
+
networkerror: [
|
43
43
|
'00120270', # Too Many Hops
|
44
44
|
],
|
45
|
-
|
45
|
+
contenterr: [
|
46
46
|
'00050311', # Conversion to Internet format failed
|
47
47
|
'000502CC', # Conversion to Internet format failed
|
48
48
|
],
|
49
|
-
|
49
|
+
securityerr: [
|
50
50
|
'000B0981', # 502 Server does not support AUTH
|
51
51
|
],
|
52
|
-
|
52
|
+
filtered: [
|
53
53
|
'000C0595', # Ambiguous Recipient
|
54
54
|
],
|
55
55
|
}
|
56
56
|
Indicators = Sisimai::MTA.INDICATORS
|
57
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
58
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
59
57
|
|
60
58
|
def description; return 'Microsoft Exchange Server'; end
|
61
59
|
def smtpagent; return 'Exchange'; end
|
@@ -108,11 +106,10 @@ module Sisimai
|
|
108
106
|
end
|
109
107
|
return nil if match == 0
|
110
108
|
|
111
|
-
dscontents = [
|
109
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
112
110
|
hasdivided = mbody.split("\n")
|
113
|
-
|
114
|
-
|
115
|
-
previousfn = '' # (String) Previous field name
|
111
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
112
|
+
blanklines = 0 # (Integer) The number of blank lines
|
116
113
|
readcursor = 0 # (Integer) Points the current cursor position
|
117
114
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
118
115
|
statuspart = false # (Boolean) Flag, true = have got delivery status part.
|
@@ -128,7 +125,7 @@ module Sisimai
|
|
128
125
|
if readcursor == 0
|
129
126
|
# Beginning of the bounce message or delivery status part
|
130
127
|
if e =~ Re1[:begin]
|
131
|
-
readcursor |= Indicators[:
|
128
|
+
readcursor |= Indicators[:deliverystatus]
|
132
129
|
next
|
133
130
|
end
|
134
131
|
end
|
@@ -143,30 +140,16 @@ module Sisimai
|
|
143
140
|
|
144
141
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
145
142
|
# After "message/rfc822"
|
146
|
-
if
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
next unless RFC822Head.key?(lhs)
|
151
|
-
|
152
|
-
previousfn = lhs
|
153
|
-
rfc822part += e + "\n"
|
154
|
-
|
155
|
-
elsif e =~ /\A[ \t]+/
|
156
|
-
# Continued line from the previous line
|
157
|
-
next if rfc822next[previousfn]
|
158
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
159
|
-
|
160
|
-
else
|
161
|
-
# Check the end of headers in rfc822 part
|
162
|
-
next unless LongFields.key?(previousfn)
|
163
|
-
next unless e.empty?
|
164
|
-
rfc822next[previousfn] = true
|
143
|
+
if e.empty?
|
144
|
+
blanklines += 1
|
145
|
+
break if blanklines > 1
|
146
|
+
next
|
165
147
|
end
|
148
|
+
rfc822list << e
|
166
149
|
|
167
150
|
else
|
168
151
|
# Before "message/rfc822"
|
169
|
-
next if readcursor & Indicators[:
|
152
|
+
next if readcursor & Indicators[:deliverystatus] == 0
|
170
153
|
next if statuspart
|
171
154
|
|
172
155
|
if connvalues == connheader.keys.size
|
@@ -185,7 +168,7 @@ module Sisimai
|
|
185
168
|
v = dscontents[-1]
|
186
169
|
|
187
170
|
if cv = e.match(/\A[ \t]*([^ ]+[@][^ ]+) on[ \t]*.*\z/) ||
|
188
|
-
|
171
|
+
e.match(/\A[ \t]*.+(?:SMTP|smtp)=([^ ]+[@][^ ]+) on[ \t]*.*\z/)
|
189
172
|
# kijitora@example.co.jp on Thu, 29 Apr 2007 16:51:51 -0500
|
190
173
|
# kijitora@example.com on 4/29/99 9:19:59 AM
|
191
174
|
if v['recipient']
|
@@ -254,15 +237,6 @@ module Sisimai
|
|
254
237
|
require 'sisimai/smtp/status'
|
255
238
|
|
256
239
|
dscontents.map do |e|
|
257
|
-
if mhead['received'].size > 0
|
258
|
-
# Get localhost and remote host name from Received header.
|
259
|
-
r0 = mhead['received']
|
260
|
-
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
261
|
-
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
262
|
-
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
263
|
-
end
|
264
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
265
|
-
|
266
240
|
if cv = e['diagnosis'].match(/\AMSEXCH:.+[ \t]*[(]([0-9A-F]{8})[)][ \t]*(.*)\z/)
|
267
241
|
# MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
|
268
242
|
capturedcode = cv[1]
|
@@ -272,8 +246,8 @@ module Sisimai
|
|
272
246
|
CodeTable.each_key do |r|
|
273
247
|
# Find captured code from the error code table
|
274
248
|
next unless CodeTable[r].index(capturedcode)
|
275
|
-
e['reason'] = r
|
276
|
-
pseudostatus = Sisimai::SMTP::Status.code(r)
|
249
|
+
e['reason'] = r.to_s
|
250
|
+
pseudostatus = Sisimai::SMTP::Status.code(r.to_s)
|
277
251
|
e['status'] = pseudostatus if pseudostatus.size > 0
|
278
252
|
break
|
279
253
|
end
|
@@ -289,21 +263,19 @@ module Sisimai
|
|
289
263
|
e.delete('alterrors')
|
290
264
|
end
|
291
265
|
end
|
292
|
-
|
293
|
-
e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
|
294
|
-
e['action'] = 'failed' if e['status'] =~ /\A[45]/
|
295
|
-
e['agent'] = Sisimai::MTA::Exchange.smtpagent
|
266
|
+
e['agent'] = Sisimai::MTA::Exchange.smtpagent
|
296
267
|
e.delete('msexch')
|
297
268
|
e.each_key { |a| e[a] ||= '' }
|
298
269
|
end
|
299
270
|
|
300
|
-
if
|
271
|
+
if rfc822list.empty?
|
301
272
|
# When original message does not included in the bounce message
|
302
|
-
|
303
|
-
|
304
|
-
|
273
|
+
rfc822list << sprintf('From: %s', connheader['to'])
|
274
|
+
rfc822list << sprintf('Date: %s', connheader['date'])
|
275
|
+
rfc822list << sprintf('Subject: %s', connheader['subject'])
|
305
276
|
end
|
306
277
|
|
278
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
307
279
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
308
280
|
end
|
309
281
|
|