sisimai 4.16.0 → 4.17.0
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
data/lib/sisimai/mta/exim.rb
CHANGED
@@ -78,11 +78,11 @@ module Sisimai
|
|
78
78
|
# find exim/ -type f -exec grep 'message = US' {} /dev/null \;
|
79
79
|
ReFailure = {
|
80
80
|
# route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
|
81
|
-
|
81
|
+
userunknown: %r/user[ ]not[ ]found/x,
|
82
82
|
# transports/smtp.c:3524| addr->message = US"all host address lookups failed permanently";
|
83
83
|
# routers/dnslookup.c:331| addr->message = US"all relevant MX records point to non-existent hosts";
|
84
84
|
# route.c:1826| uschar *message = US"Unrouteable address";
|
85
|
-
|
85
|
+
hostunknown: %r{(?>
|
86
86
|
all[ ](?:
|
87
87
|
host[ ]address[ ]lookups[ ]failed[ ]permanently
|
88
88
|
|relevant[ ]MX[ ]records[ ]point[ ]to[ ]non[-]existent[ ]hosts
|
@@ -93,10 +93,10 @@ module Sisimai
|
|
93
93
|
# transports/appendfile.c:2567| addr->user_message = US"mailbox is full";
|
94
94
|
# transports/appendfile.c:3049| addr->message = string_sprintf("mailbox is full "
|
95
95
|
# transports/appendfile.c:3050| "(quota exceeded while writing to file %s)", filename);
|
96
|
-
|
96
|
+
mailboxfull: %r/(?:mailbox[ ]is[ ]full:?|error:[ ]quota[ ]exceed)/x,
|
97
97
|
# routers/dnslookup.c:328| addr->message = US"an MX or SRV record indicated no SMTP service";
|
98
98
|
# transports/smtp.c:3502| addr->message = US"no host found for existing SMTP connection";
|
99
|
-
|
99
|
+
notaccept: %r{(?:
|
100
100
|
an[ ]MX[ ]or[ ]SRV[ ]record[ ]indicated[ ]no[ ]SMTP[ ]service
|
101
101
|
|no[ ]host[ ]found[ ]for[ ]existing[ ]SMTP[ ]connection
|
102
102
|
)
|
@@ -104,14 +104,14 @@ module Sisimai
|
|
104
104
|
# deliver.c:5614| addr->message = US"delivery to file forbidden";
|
105
105
|
# deliver.c:5624| addr->message = US"delivery to pipe forbidden";
|
106
106
|
# transports/pipe.c:1156| addr->user_message = US"local delivery failed";
|
107
|
-
|
107
|
+
systemerror: %r{(?>
|
108
108
|
delivery[ ]to[ ](?:file|pipe)[ ]forbidden
|
109
109
|
|local[ ]delivery[ ]failed
|
110
110
|
|LMTP[ ]error[ ]after[ ]
|
111
111
|
)
|
112
112
|
}x,
|
113
113
|
# deliver.c:5425| new->message = US"Too many \"Received\" headers - suspected mail loop";
|
114
|
-
|
114
|
+
contenterror: %r/Too[ ]many[ ]["]Received["][ ]headers/x,
|
115
115
|
}
|
116
116
|
|
117
117
|
# retry.c:902| addr->message = (addr->message == NULL)? US"retry timeout exceeded" :
|
@@ -132,10 +132,7 @@ module Sisimai
|
|
132
132
|
|Message[ ].+[ ](?:has[ ]been[ ]frozen|was[ ]frozen[ ]on[ ]arrival[ ]by[ ])
|
133
133
|
)
|
134
134
|
}x
|
135
|
-
|
136
135
|
Indicators = Sisimai::MTA.INDICATORS
|
137
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
138
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
139
136
|
|
140
137
|
def description; return 'Exim'; end
|
141
138
|
def smtpagent; return 'Exim'; end
|
@@ -160,11 +157,10 @@ module Sisimai
|
|
160
157
|
return nil unless mhead['from'] =~ Re0[:from]
|
161
158
|
return nil unless mhead['subject'] =~ Re0[:subject]
|
162
159
|
|
163
|
-
dscontents = [
|
160
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
164
161
|
hasdivided = mbody.split("\n")
|
165
|
-
|
166
|
-
|
167
|
-
previousfn = '' # (String) Previous field name
|
162
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
163
|
+
blanklines = 0 # (Integer) The number of blank lines
|
168
164
|
readcursor = 0 # (Integer) Points the current cursor position
|
169
165
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
170
166
|
localhost0 = '' # (String) Local MTA
|
@@ -184,7 +180,7 @@ module Sisimai
|
|
184
180
|
if readcursor == 0
|
185
181
|
# Beginning of the bounce message or delivery status part
|
186
182
|
if e =~ Re1[:begin]
|
187
|
-
readcursor |= Indicators[:
|
183
|
+
readcursor |= Indicators[:deliverystatus]
|
188
184
|
next unless e =~ Re1[:frozen]
|
189
185
|
end
|
190
186
|
end
|
@@ -199,30 +195,16 @@ module Sisimai
|
|
199
195
|
|
200
196
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
201
197
|
# After "message/rfc822"
|
202
|
-
if
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
next unless RFC822Head.key?(lhs)
|
207
|
-
|
208
|
-
previousfn = lhs
|
209
|
-
rfc822part += e + "\n"
|
210
|
-
|
211
|
-
elsif e =~ /\A[ \t]+/
|
212
|
-
# Continued line from the previous line
|
213
|
-
next if rfc822next[previousfn]
|
214
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
215
|
-
|
216
|
-
else
|
217
|
-
# Check the end of headers in rfc822 part
|
218
|
-
next unless LongFields.key?(previousfn)
|
219
|
-
next unless e.empty?
|
220
|
-
rfc822next[previousfn] = true
|
198
|
+
if e.empty?
|
199
|
+
blanklines += 1
|
200
|
+
break if blanklines > 1
|
201
|
+
next
|
221
202
|
end
|
203
|
+
rfc822list << e
|
222
204
|
|
223
205
|
else
|
224
206
|
# Before "message/rfc822"
|
225
|
-
next if readcursor & Indicators[:
|
207
|
+
next if readcursor & Indicators[:deliverystatus] == 0
|
226
208
|
next if e.empty?
|
227
209
|
|
228
210
|
# This message was created automatically by mail delivery software.
|
@@ -239,8 +221,7 @@ module Sisimai
|
|
239
221
|
# deliver.c:6811| "recipients. This is a permanent error. The following address(es) failed:\n");
|
240
222
|
v['softbounce'] = 0
|
241
223
|
|
242
|
-
elsif cv = e.match(/\A[ ][ ]+([^ \t]+[@][^ \t]+[.][a-zA-Z]+)(:.+)?\z/) ||
|
243
|
-
cv = e.match(Re1[:alias])
|
224
|
+
elsif cv = e.match(/\A[ ][ ]+([^ \t]+[@][^ \t]+[.][a-zA-Z]+)(:.+)?\z/) || e.match(Re1[:alias])
|
244
225
|
# kijitora@example.jp
|
245
226
|
# sabineko@example.jp: forced freeze
|
246
227
|
#
|
@@ -256,7 +237,7 @@ module Sisimai
|
|
256
237
|
recipients += 1
|
257
238
|
|
258
239
|
elsif cv = e.match(/\A[ ]+[(]generated[ ]from[ ](.+)[)]\z/) ||
|
259
|
-
|
240
|
+
e.match(/\A[ ]+generated[ ]by[ ]([^ \t]+[@][^ \t]+)/)
|
260
241
|
# (generated from kijitora@example.jp)
|
261
242
|
# pipe to |/bin/echo "Some pipe output"
|
262
243
|
# generated by userx@myhost.test.ex
|
@@ -457,7 +438,7 @@ module Sisimai
|
|
457
438
|
ReFailure.each_key do |r|
|
458
439
|
# Check each regular expression
|
459
440
|
next unless e['diagnosis'] =~ ReFailure[r]
|
460
|
-
e['reason'] = r
|
441
|
+
e['reason'] = r.to_s
|
461
442
|
break
|
462
443
|
end
|
463
444
|
|
@@ -535,10 +516,10 @@ module Sisimai
|
|
535
516
|
end
|
536
517
|
end
|
537
518
|
e['status'] ||= sv
|
538
|
-
e['action'] ||= 'failed' if e['status'] =~ /\A[45]/
|
539
519
|
e.each_key { |a| e[a] ||= '' }
|
540
520
|
end
|
541
521
|
|
522
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
542
523
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
543
524
|
end
|
544
525
|
|
@@ -9,8 +9,8 @@ module Sisimai
|
|
9
9
|
require 'sisimai/rfc5322'
|
10
10
|
|
11
11
|
Re0 = {
|
12
|
-
:'x-mailer' => %r/\A[<]SMTP32 v[\d.]+[>]
|
13
|
-
:'subject' => %r/\AUndeliverable Mail
|
12
|
+
:'x-mailer' => %r/\A[<]SMTP32 v[\d.]+[>][ ]*\z/,
|
13
|
+
:'subject' => %r/\AUndeliverable Mail[ ]*\z/,
|
14
14
|
}
|
15
15
|
Re1 = {
|
16
16
|
:begin => %r/\A\z/, # Blank line
|
@@ -19,41 +19,25 @@ module Sisimai
|
|
19
19
|
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
20
20
|
}
|
21
21
|
ReSMTP = {
|
22
|
-
|
22
|
+
conn: %r{(?:
|
23
23
|
SMTP[ ]connection[ ]failed,
|
24
24
|
|Unexpected[ ]connection[ ]response[ ]from[ ]server:
|
25
25
|
)
|
26
26
|
},
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
ehlo: %r|Unexpected response to EHLO/HELO:|,
|
28
|
+
mail: %r|Server response to MAIL FROM:|,
|
29
|
+
rcpt: %r|Additional RCPT TO generated following response:|,
|
30
|
+
data: %r|DATA command generated response:|,
|
31
31
|
}
|
32
32
|
ReFailure = {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
)
|
40
|
-
}x,
|
41
|
-
'mailboxfull' => %r{
|
42
|
-
\AUser[ ]mailbox[ ]exceeds[ ]allowed[ ]size
|
43
|
-
}x,
|
44
|
-
'securityerr' => %r{
|
45
|
-
\ARequested[ ]action[ ]not[ ]taken:[ ]virus[ ]detected
|
46
|
-
}x,
|
47
|
-
'undefined' => %r{
|
48
|
-
\Aundeliverable[ ]to[ ]
|
49
|
-
}x,
|
50
|
-
'expired' => %r{
|
51
|
-
\ADelivery[ ]failed[ ]\d+[ ]attempts
|
52
|
-
}x,
|
33
|
+
hostunknown: %r/Unknown[ ]host/x,
|
34
|
+
userunknown: %r/\A(?:Unknown[ ]user|Invalid[ ]final[ ]delivery[ ]userid)/x,
|
35
|
+
mailboxfull: %r/\AUser[ ]mailbox[ ]exceeds[ ]allowed[ ]size/x,
|
36
|
+
securityerr: %r/\ARequested[ ]action[ ]not[ ]taken:[ ]virus[ ]detected/x,
|
37
|
+
undefined: %r/\Aundeliverable[ ]to[ ]/x,
|
38
|
+
expired: %r/\ADelivery[ ]failed[ ]\d+[ ]attempts/x,
|
53
39
|
}
|
54
40
|
Indicators = Sisimai::MTA.INDICATORS
|
55
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
56
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
57
41
|
|
58
42
|
def description; return 'IPSWITCH IMail Server'; end
|
59
43
|
def smtpagent; return 'IMailServer'; end
|
@@ -80,11 +64,10 @@ module Sisimai
|
|
80
64
|
match += 1 if mhead['x-mailer'] && mhead['x-mailer'] =~ Re0[:'x-mailer']
|
81
65
|
return nil if match == 0
|
82
66
|
|
83
|
-
dscontents = [
|
67
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
84
68
|
hasdivided = mbody.split("\n")
|
85
|
-
|
86
|
-
|
87
|
-
previousfn = '' # (String) Previous field name
|
69
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
70
|
+
blanklines = 0 # (Integer) The number of blank lines
|
88
71
|
readcursor = 0 # (Integer) Points the current cursor position
|
89
72
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
90
73
|
v = nil
|
@@ -93,7 +76,7 @@ module Sisimai
|
|
93
76
|
if readcursor == 0
|
94
77
|
# Beginning of the bounce message or delivery status part
|
95
78
|
if e =~ Re1[:begin]
|
96
|
-
readcursor |= Indicators[:
|
79
|
+
readcursor |= Indicators[:deliverystatus]
|
97
80
|
next
|
98
81
|
end
|
99
82
|
end
|
@@ -108,26 +91,12 @@ module Sisimai
|
|
108
91
|
|
109
92
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
110
93
|
# After "message/rfc822"
|
111
|
-
if
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
next unless RFC822Head.key?(lhs)
|
116
|
-
|
117
|
-
previousfn = lhs
|
118
|
-
rfc822part += e + "\n"
|
119
|
-
|
120
|
-
elsif e =~ /\A[ \t]+/
|
121
|
-
# Continued line from the previous line
|
122
|
-
next if rfc822next[previousfn]
|
123
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
124
|
-
|
125
|
-
else
|
126
|
-
# Check the end of headers in rfc822 part
|
127
|
-
next unless LongFields.key?(previousfn)
|
128
|
-
next unless e.empty?
|
129
|
-
rfc822next[previousfn] = true
|
94
|
+
if e.empty?
|
95
|
+
blanklines += 1
|
96
|
+
break if blanklines > 1
|
97
|
+
next
|
130
98
|
end
|
99
|
+
rfc822list << e
|
131
100
|
|
132
101
|
else
|
133
102
|
# Before "message/rfc822"
|
@@ -138,7 +107,7 @@ module Sisimai
|
|
138
107
|
# Original message follows.
|
139
108
|
v = dscontents[-1]
|
140
109
|
|
141
|
-
if cv = e.match(/\A(.+)[ ](.+)[:][ \t]*([^ ]+[@][^ ]+)
|
110
|
+
if cv = e.match(/\A(.+)[ ](.+)[:][ \t]*([^ ]+[@][^ ]+)/)
|
142
111
|
# Unknown user: kijitora@example.com
|
143
112
|
if v['recipient']
|
144
113
|
# There are multiple recipient addresses in the message body.
|
@@ -169,23 +138,12 @@ module Sisimai
|
|
169
138
|
end
|
170
139
|
end
|
171
140
|
end
|
172
|
-
|
173
141
|
return nil if recipients == 0
|
174
142
|
require 'sisimai/string'
|
175
|
-
require 'sisimai/smtp/status'
|
176
143
|
|
177
144
|
dscontents.map do |e|
|
178
|
-
# Set default values if each value is empty.
|
179
145
|
e['agent'] = Sisimai::MTA::IMailServer.smtpagent
|
180
146
|
|
181
|
-
if mhead['received'].size > 0
|
182
|
-
# Get localhost and remote host name from Received header.
|
183
|
-
r0 = mhead['received']
|
184
|
-
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
185
|
-
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
186
|
-
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
187
|
-
end
|
188
|
-
|
189
147
|
if e['alterrors'] && e['alterrors'].size > 0
|
190
148
|
# Copy alternative error message
|
191
149
|
if e['diagnosis']
|
@@ -201,23 +159,20 @@ module Sisimai
|
|
201
159
|
ReSMTP.each_key do |r|
|
202
160
|
# Detect SMTP command from the message
|
203
161
|
next unless e['diagnosis'] =~ ReSMTP[r]
|
204
|
-
e['command'] = r.upcase
|
162
|
+
e['command'] = r.to_s.upcase
|
205
163
|
break
|
206
164
|
end
|
207
165
|
|
208
166
|
ReFailure.each_key do |r|
|
209
167
|
# Verify each regular expression of session errors
|
210
168
|
next unless e['diagnosis'] =~ ReFailure[r]
|
211
|
-
e['reason'] = r
|
169
|
+
e['reason'] = r.to_s
|
212
170
|
break
|
213
171
|
end
|
214
|
-
|
215
|
-
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
216
|
-
e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
|
217
|
-
e['action'] = 'failed' if e['status'] =~ /\A[45]/
|
218
172
|
e.each_key { |a| e[a] ||= '' }
|
219
173
|
end
|
220
174
|
|
175
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
221
176
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
222
177
|
end
|
223
178
|
|
@@ -26,8 +26,6 @@ module Sisimai
|
|
26
26
|
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
27
27
|
}
|
28
28
|
Indicators = Sisimai::MTA.INDICATORS
|
29
|
-
LongFields = Sisimai::RFC5322.LONGFIELDS
|
30
|
-
RFC822Head = Sisimai::RFC5322.HEADERFIELDS
|
31
29
|
|
32
30
|
def description; return 'Trend Micro InterScan Messaging Security Suite'; end
|
33
31
|
def smtpagent; return 'InterScanMSS'; end
|
@@ -54,11 +52,10 @@ module Sisimai
|
|
54
52
|
match += 1 if Re0[:subject].find { |a| mhead['subject'] == a }
|
55
53
|
return nil if match == 0
|
56
54
|
|
57
|
-
dscontents = [
|
55
|
+
dscontents = [Sisimai::MTA.DELIVERYSTATUS]
|
58
56
|
hasdivided = mbody.split("\n")
|
59
|
-
|
60
|
-
|
61
|
-
previousfn = '' # (String) Previous field name
|
57
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
58
|
+
blanklines = 0 # (Integer) The number of blank lines
|
62
59
|
readcursor = 0 # (Integer) Points the current cursor position
|
63
60
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
64
61
|
v = nil
|
@@ -67,7 +64,7 @@ module Sisimai
|
|
67
64
|
if readcursor == 0
|
68
65
|
# Beginning of the bounce message or delivery status part
|
69
66
|
if e =~ Re1[:begin]
|
70
|
-
readcursor |= Indicators[:
|
67
|
+
readcursor |= Indicators[:deliverystatus]
|
71
68
|
next
|
72
69
|
end
|
73
70
|
end
|
@@ -82,30 +79,16 @@ module Sisimai
|
|
82
79
|
|
83
80
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
84
81
|
# After "message/rfc822"
|
85
|
-
if
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
next unless RFC822Head.key?(lhs)
|
90
|
-
|
91
|
-
previousfn = lhs
|
92
|
-
rfc822part += e + "\n"
|
93
|
-
|
94
|
-
elsif e =~ /\A[ \t]+/
|
95
|
-
# Continued line from the previous line
|
96
|
-
next if rfc822next[previousfn]
|
97
|
-
rfc822part += e + "\n" if LongFields.key?(previousfn)
|
98
|
-
|
99
|
-
else
|
100
|
-
# Check the end of headers in rfc822 part
|
101
|
-
next unless LongFields.key?(previousfn)
|
102
|
-
next unless e.empty?
|
103
|
-
rfc822next[previousfn] = true
|
82
|
+
if e.empty?
|
83
|
+
blanklines += 1
|
84
|
+
break if blanklines > 1
|
85
|
+
next
|
104
86
|
end
|
87
|
+
rfc822list << e
|
105
88
|
|
106
89
|
else
|
107
90
|
# Before "message/rfc822"
|
108
|
-
next if readcursor & Indicators[:
|
91
|
+
next if readcursor & Indicators[:deliverystatus] == 0
|
109
92
|
next if e.empty?
|
110
93
|
|
111
94
|
# Sent <<< RCPT TO:<kijitora@example.co.jp>
|
@@ -113,16 +96,15 @@ module Sisimai
|
|
113
96
|
v = dscontents[-1]
|
114
97
|
|
115
98
|
if cv = e.match(/\A.+[<>]{3}[ \t]+.+[<]([^ ]+[@][^ ]+)[>]\z/) ||
|
116
|
-
|
99
|
+
e.match(/\A.+[<>]{3}[ \t]+.+[<]([^ ]+[@][^ ]+)[>]/)
|
117
100
|
# Sent <<< RCPT TO:<kijitora@example.co.jp>
|
118
101
|
# Received >>> 550 5.1.1 <kijitora@example.co.jp>... user unknown
|
119
|
-
|
120
|
-
if v['recipient'] && cr != v['recipient']
|
102
|
+
if v['recipient'] && cv[1] != v['recipient']
|
121
103
|
# There are multiple recipient addresses in the message body.
|
122
104
|
dscontents << Sisimai::MTA.DELIVERYSTATUS
|
123
105
|
v = dscontents[-1]
|
124
106
|
end
|
125
|
-
v['recipient'] =
|
107
|
+
v['recipient'] = cv[1]
|
126
108
|
recipients = dscontents.size
|
127
109
|
end
|
128
110
|
|
@@ -133,30 +115,30 @@ module Sisimai
|
|
133
115
|
elsif cv = e.match(/\AReceived[ ]+[>]{3}[ ]+(\d{3}[ ]+.+)\z/)
|
134
116
|
# Received >>> 550 5.1.1 <kijitora@example.co.jp>... user unknown
|
135
117
|
v['diagnosis'] = cv[1]
|
118
|
+
|
119
|
+
else
|
120
|
+
# Error message in non-English
|
121
|
+
if cv = e.match(/[ ][>]{3}[ ]([A-Z]{4})/)
|
122
|
+
# >>> RCPT TO ...
|
123
|
+
v['command'] = cv[1]
|
124
|
+
|
125
|
+
elsif cv = e.match(/[ ][<]{3}[ ](.+)/)
|
126
|
+
# <<< 550 5.1.1 User unknown
|
127
|
+
v['diagnosis'] = cv[1]
|
128
|
+
end
|
136
129
|
end
|
137
130
|
end
|
138
131
|
end
|
139
|
-
|
140
132
|
return nil if recipients == 0
|
141
133
|
require 'sisimai/string'
|
142
|
-
require 'sisimai/smtp/status'
|
143
134
|
|
144
135
|
dscontents.map do |e|
|
145
|
-
e['agent']
|
146
|
-
if mhead['received'].size > 0
|
147
|
-
# Get localhost and remote host name from Received header.
|
148
|
-
r0 = mhead['received']
|
149
|
-
%w|lhost rhost|.each { |a| e[a] ||= '' }
|
150
|
-
e['lhost'] = Sisimai::RFC5322.received(r0[0]).shift if e['lhost'].empty?
|
151
|
-
e['rhost'] = Sisimai::RFC5322.received(r0[-1]).pop if e['rhost'].empty?
|
152
|
-
end
|
136
|
+
e['agent'] = Sisimai::MTA::InterScanMSS.smtpagent
|
153
137
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
154
|
-
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
155
|
-
e['spec'] = e['reason'] == 'mailererror' ? 'X-UNIX' : 'SMTP'
|
156
|
-
e['action'] = 'failed' if e['status'] =~ /\A[45]/
|
157
138
|
e.each_key { |a| e[a] ||= '' }
|
158
139
|
end
|
159
140
|
|
141
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
160
142
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
161
143
|
end
|
162
144
|
|