sisimai 4.22.3-java → 4.22.4-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/.travis.yml +1 -1
- data/Benchmarks.mk +54 -0
- data/ChangeLog.md +23 -2
- data/Developers.mk +42 -35
- data/Makefile +10 -0
- data/README-JA.md +13 -13
- data/README.md +14 -14
- data/lib/sisimai.rb +12 -18
- data/lib/sisimai/address.rb +64 -82
- data/lib/sisimai/arf.rb +27 -42
- data/lib/sisimai/bite/email.rb +2 -4
- data/lib/sisimai/bite/email/activehunter.rb +12 -17
- data/lib/sisimai/bite/email/amazonses.rb +30 -48
- data/lib/sisimai/bite/email/amazonworkmail.rb +20 -27
- data/lib/sisimai/bite/email/aol.rb +27 -35
- data/lib/sisimai/bite/email/apachejames.rb +17 -28
- data/lib/sisimai/bite/email/bigfoot.rb +20 -33
- data/lib/sisimai/bite/email/biglobe.rb +15 -24
- data/lib/sisimai/bite/email/courier.rb +37 -61
- data/lib/sisimai/bite/email/domino.rb +19 -28
- data/lib/sisimai/bite/email/einsundeins.rb +20 -34
- data/lib/sisimai/bite/email/exchange2003.rb +25 -43
- data/lib/sisimai/bite/email/exchange2007.rb +15 -23
- data/lib/sisimai/bite/email/exim.rb +101 -120
- data/lib/sisimai/bite/email/ezweb.rb +28 -44
- data/lib/sisimai/bite/email/facebook.rb +26 -37
- data/lib/sisimai/bite/email/fml.rb +11 -20
- data/lib/sisimai/bite/email/gmx.rb +17 -27
- data/lib/sisimai/bite/email/google.rb +19 -29
- data/lib/sisimai/bite/email/gsuite.rb +39 -48
- data/lib/sisimai/bite/email/imailserver.rb +25 -39
- data/lib/sisimai/bite/email/interscanmss.rb +19 -26
- data/lib/sisimai/bite/email/kddi.rb +20 -33
- data/lib/sisimai/bite/email/mailfoundry.rb +14 -24
- data/lib/sisimai/bite/email/mailmarshalsmtp.rb +15 -24
- data/lib/sisimai/bite/email/mailru.rb +40 -59
- data/lib/sisimai/bite/email/mcafee.rb +21 -35
- data/lib/sisimai/bite/email/messagelabs.rb +23 -38
- data/lib/sisimai/bite/email/messagingserver.rb +15 -27
- data/lib/sisimai/bite/email/mfilter.rb +19 -28
- data/lib/sisimai/bite/email/mxlogic.rb +31 -49
- data/lib/sisimai/bite/email/notes.rb +16 -24
- data/lib/sisimai/bite/email/office365.rb +29 -38
- data/lib/sisimai/bite/email/opensmtpd.rb +50 -67
- data/lib/sisimai/bite/email/outlook.rb +24 -36
- data/lib/sisimai/bite/email/postfix.rb +33 -42
- data/lib/sisimai/bite/email/qmail.rb +44 -59
- data/lib/sisimai/bite/email/receivingses.rb +28 -36
- data/lib/sisimai/bite/email/sendgrid.rb +28 -37
- data/lib/sisimai/bite/email/sendmail.rb +35 -51
- data/lib/sisimai/bite/email/surfcontrol.rb +17 -25
- data/lib/sisimai/bite/email/userdefined.rb +17 -28
- data/lib/sisimai/bite/email/v5sendmail.rb +32 -41
- data/lib/sisimai/bite/email/verizon.rb +31 -56
- data/lib/sisimai/bite/email/x1.rb +11 -18
- data/lib/sisimai/bite/email/x2.rb +11 -23
- data/lib/sisimai/bite/email/x3.rb +10 -19
- data/lib/sisimai/bite/email/x4.rb +46 -65
- data/lib/sisimai/bite/email/x5.rb +26 -37
- data/lib/sisimai/bite/email/yahoo.rb +11 -19
- data/lib/sisimai/bite/email/yandex.rb +19 -30
- data/lib/sisimai/bite/email/zoho.rb +21 -30
- data/lib/sisimai/bite/json.rb +1 -2
- data/lib/sisimai/bite/json/amazonses.rb +20 -25
- data/lib/sisimai/bite/json/sendgrid.rb +1 -1
- data/lib/sisimai/data.rb +36 -55
- data/lib/sisimai/data/json.rb +3 -3
- data/lib/sisimai/data/yaml.rb +1 -1
- data/lib/sisimai/datetime.rb +5 -21
- data/lib/sisimai/mail.rb +4 -6
- data/lib/sisimai/mail/maildir.rb +1 -1
- data/lib/sisimai/mda.rb +41 -44
- data/lib/sisimai/message.rb +2 -3
- data/lib/sisimai/message/email.rb +42 -52
- data/lib/sisimai/message/json.rb +7 -7
- data/lib/sisimai/mime.rb +25 -23
- data/lib/sisimai/order/email.rb +2 -2
- data/lib/sisimai/order/json.rb +2 -7
- data/lib/sisimai/reason.rb +41 -46
- data/lib/sisimai/reason/blocked.rb +60 -71
- data/lib/sisimai/reason/contenterror.rb +4 -8
- data/lib/sisimai/reason/delivered.rb +1 -3
- data/lib/sisimai/reason/exceedlimit.rb +10 -20
- data/lib/sisimai/reason/expired.rb +5 -9
- data/lib/sisimai/reason/feedback.rb +1 -3
- data/lib/sisimai/reason/filtered.rb +19 -38
- data/lib/sisimai/reason/hasmoved.rb +5 -8
- data/lib/sisimai/reason/hostunknown.rb +11 -18
- data/lib/sisimai/reason/mailboxfull.rb +14 -24
- data/lib/sisimai/reason/mailererror.rb +3 -5
- data/lib/sisimai/reason/mesgtoobig.rb +15 -25
- data/lib/sisimai/reason/networkerror.rb +8 -10
- data/lib/sisimai/reason/norelaying.rb +9 -14
- data/lib/sisimai/reason/notaccept.rb +9 -21
- data/lib/sisimai/reason/onhold.rb +3 -8
- data/lib/sisimai/reason/policyviolation.rb +8 -10
- data/lib/sisimai/reason/rejected.rb +36 -49
- data/lib/sisimai/reason/securityerror.rb +11 -13
- data/lib/sisimai/reason/spamdetected.rb +23 -37
- data/lib/sisimai/reason/suspend.rb +9 -10
- data/lib/sisimai/reason/syntaxerror.rb +3 -4
- data/lib/sisimai/reason/systemerror.rb +7 -9
- data/lib/sisimai/reason/systemfull.rb +2 -4
- data/lib/sisimai/reason/toomanyconn.rb +17 -30
- data/lib/sisimai/reason/undefined.rb +1 -3
- data/lib/sisimai/reason/userunknown.rb +28 -38
- data/lib/sisimai/reason/vacation.rb +4 -6
- data/lib/sisimai/reason/virusdetected.rb +4 -6
- data/lib/sisimai/rfc2606.rb +1 -2
- data/lib/sisimai/rfc3464.rb +87 -101
- data/lib/sisimai/rfc3834.rb +29 -39
- data/lib/sisimai/rfc5322.rb +17 -24
- data/lib/sisimai/rhost.rb +10 -7
- data/lib/sisimai/rhost/exchangeonline.rb +124 -255
- data/lib/sisimai/rhost/franceptt.rb +2 -2
- data/lib/sisimai/rhost/godaddy.rb +12 -25
- data/lib/sisimai/rhost/googleapps.rb +82 -183
- data/lib/sisimai/smtp.rb +4 -4
- data/lib/sisimai/smtp/error.rb +8 -8
- data/lib/sisimai/smtp/reply.rb +1 -1
- data/lib/sisimai/smtp/status.rb +1 -0
- data/lib/sisimai/string.rb +5 -7
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +1 -1
- data/set-of-emails/maildir/bsd/README.md +50 -50
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +4 -4
- data/lib/sisimai/skeleton.rb +0 -43
@@ -6,27 +6,21 @@ module Sisimai::Bite::Email
|
|
6
6
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Sendmail.pm
|
7
7
|
require 'sisimai/bite/email'
|
8
8
|
|
9
|
-
Re0 = {
|
10
|
-
:from => %r/\AMail Delivery Subsystem/,
|
11
|
-
:subject => %r/(?:see transcript for details\z|\AWarning: )/,
|
12
|
-
}.freeze
|
13
|
-
# Error text regular expressions which defined in sendmail/savemail.c
|
14
|
-
# savemail.c:1040|if (printheader && !putline(" ----- Transcript of session follows -----\n",
|
15
|
-
# savemail.c:1041| mci))
|
16
|
-
# savemail.c:1042| goto writeerr;
|
17
|
-
#
|
18
|
-
Re1 = {
|
19
|
-
:begin => %r/\A[ \t]+[-]+ Transcript of session follows [-]+\z/,
|
20
|
-
:error => %r/\A[.]+ while talking to .+[:]\z/,
|
21
|
-
:rfc822 => %r{\AContent-Type:[ ]*(?:message/rfc822|text/rfc822-headers)\z},
|
22
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
23
|
-
}.freeze
|
24
9
|
Indicators = Sisimai::Bite::Email.INDICATORS
|
10
|
+
StartingOf = {
|
11
|
+
# Error text regular expressions which defined in sendmail/savemail.c
|
12
|
+
# savemail.c:1040|if (printheader && !putline(" ----- Transcript of session follows -----\n",
|
13
|
+
# savemail.c:1041| mci))
|
14
|
+
# savemail.c:1042| goto writeerr;
|
15
|
+
#
|
16
|
+
rfc822: ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'],
|
17
|
+
message: [' ----- Transcript of session follows -----'],
|
18
|
+
error: ['... while talking to '],
|
19
|
+
}.freeze
|
25
20
|
|
26
21
|
def description; return 'V8Sendmail: /usr/sbin/sendmail'; end
|
27
22
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
28
23
|
def headerlist; return []; end
|
29
|
-
def pattern; return Re0; end
|
30
24
|
|
31
25
|
# Parse bounce messages from Sendmail
|
32
26
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -42,12 +36,12 @@ module Sisimai::Bite::Email
|
|
42
36
|
def scan(mhead, mbody)
|
43
37
|
return nil unless mhead
|
44
38
|
return nil unless mbody
|
45
|
-
return nil unless mhead['subject'] =~ Re0[:subject]
|
46
39
|
|
47
|
-
unless mhead['subject'] =~
|
40
|
+
return nil unless mhead['subject'] =~ /(?:see transcript for details\z|\AWarning: )/
|
41
|
+
unless mhead['subject'].downcase =~ /\A[ \t]*fwd?:/
|
48
42
|
# Fwd: Returned mail: see transcript for details
|
49
43
|
# Do not execute this code if the bounce mail is a forwarded message.
|
50
|
-
return nil unless mhead['from']
|
44
|
+
return nil unless mhead['from'].start_with?('Mail Delivery Subsystem')
|
51
45
|
end
|
52
46
|
|
53
47
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
@@ -68,14 +62,14 @@ module Sisimai::Bite::Email
|
|
68
62
|
anotherset = {} # Another error information
|
69
63
|
v = nil
|
70
64
|
|
71
|
-
hasdivided.
|
65
|
+
while e = hasdivided.shift do
|
72
66
|
# Save the current line for the next loop
|
73
67
|
havepassed << e
|
74
68
|
p = havepassed[-2]
|
75
69
|
|
76
70
|
if readcursor.zero?
|
77
71
|
# Beginning of the bounce message or delivery status part
|
78
|
-
if e
|
72
|
+
if e.start_with?(StartingOf[:message][0])
|
79
73
|
readcursor |= Indicators[:deliverystatus]
|
80
74
|
next
|
81
75
|
end
|
@@ -83,7 +77,7 @@ module Sisimai::Bite::Email
|
|
83
77
|
|
84
78
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
85
79
|
# Beginning of the original message part
|
86
|
-
if e
|
80
|
+
if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
|
87
81
|
readcursor |= Indicators[:'message-rfc822']
|
88
82
|
next
|
89
83
|
end
|
@@ -97,7 +91,6 @@ module Sisimai::Bite::Email
|
|
97
91
|
next
|
98
92
|
end
|
99
93
|
rfc822list << e
|
100
|
-
|
101
94
|
else
|
102
95
|
# Before "message/rfc822"
|
103
96
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -113,7 +106,7 @@ module Sisimai::Bite::Email
|
|
113
106
|
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
114
107
|
v = dscontents[-1]
|
115
108
|
|
116
|
-
if cv = e.match(/\
|
109
|
+
if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
117
110
|
# Final-Recipient: RFC822; userunknown@example.jp
|
118
111
|
if v['recipient']
|
119
112
|
# There are multiple recipient addresses in the message body.
|
@@ -123,43 +116,40 @@ module Sisimai::Bite::Email
|
|
123
116
|
v['recipient'] = cv[1]
|
124
117
|
recipients += 1
|
125
118
|
|
126
|
-
elsif cv = e.match(/\
|
119
|
+
elsif cv = e.match(/\AX-Actual-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
127
120
|
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
128
121
|
v['alias'] = cv[1]
|
129
122
|
|
130
|
-
elsif cv = e.match(/\
|
123
|
+
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
131
124
|
# Action: failed
|
132
125
|
v['action'] = cv[1].downcase
|
133
126
|
|
134
|
-
elsif cv = e.match(/\
|
127
|
+
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
135
128
|
# Status: 5.1.1
|
136
129
|
# Status:5.2.0
|
137
130
|
# Status: 5.1.0 (permanent failure)
|
138
131
|
v['status'] = cv[1]
|
139
132
|
|
140
|
-
elsif cv = e.match(/\
|
133
|
+
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
141
134
|
# Remote-MTA: DNS; mx.example.jp
|
142
135
|
v['rhost'] = cv[1].downcase
|
143
136
|
v['rhost'] = '' if v['rhost'] =~ /\A\s+\z/ # Remote-MTA: DNS;
|
144
137
|
|
145
|
-
elsif cv = e.match(/\
|
138
|
+
elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
|
146
139
|
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
147
140
|
v['date'] = cv[1]
|
148
|
-
|
149
141
|
else
|
150
|
-
if cv = e.match(/\
|
142
|
+
if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
|
151
143
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
152
144
|
v['spec'] = cv[1].upcase
|
153
145
|
v['diagnosis'] = cv[2]
|
154
146
|
|
155
|
-
elsif p
|
147
|
+
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
156
148
|
# Continued line of the value of Diagnostic-Code header
|
157
|
-
v['diagnosis']
|
158
|
-
|
159
|
-
havepassed[-1] = 'Diagnostic-Code: ' + e
|
149
|
+
v['diagnosis'] << ' ' << cv[1]
|
150
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
160
151
|
end
|
161
152
|
end
|
162
|
-
|
163
153
|
else
|
164
154
|
# ----- Transcript of session follows -----
|
165
155
|
# ... while talking to mta.example.org.:
|
@@ -178,13 +168,13 @@ module Sisimai::Bite::Email
|
|
178
168
|
# <<< Response
|
179
169
|
esmtpreply = cv[1]
|
180
170
|
|
181
|
-
elsif cv = e.match(/\
|
171
|
+
elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
182
172
|
# Reporting-MTA: dns; mx.example.jp
|
183
173
|
next if connheader['rhost'].size > 0
|
184
174
|
connheader['rhost'] = cv[1].downcase
|
185
175
|
connvalues += 1
|
186
176
|
|
187
|
-
elsif cv = e.match(/\
|
177
|
+
elsif cv = e.match(/\AReceived-From-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
188
178
|
# Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
|
189
179
|
next if connheader['lhost']
|
190
180
|
|
@@ -192,16 +182,15 @@ module Sisimai::Bite::Email
|
|
192
182
|
connheader['lhost'] = cv[1].downcase
|
193
183
|
connvalues += 1
|
194
184
|
|
195
|
-
elsif cv = e.match(/\
|
185
|
+
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
196
186
|
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
197
187
|
next if connheader['date'].size > 0
|
198
188
|
connheader['date'] = cv[1]
|
199
189
|
connvalues += 1
|
200
|
-
|
201
190
|
else
|
202
191
|
# Detect SMTP session error or connection error
|
203
192
|
next if sessionerr
|
204
|
-
if e
|
193
|
+
if e.start_with?(StartingOf[:error][0])
|
205
194
|
# ----- Transcript of session follows -----
|
206
195
|
# ... while talking to mta.example.org.:
|
207
196
|
sessionerr = true
|
@@ -212,7 +201,6 @@ module Sisimai::Bite::Email
|
|
212
201
|
# <kijitora@example.co.jp>... Deferred: Name server: example.co.jp.: host name lookup failure
|
213
202
|
anotherset['recipient'] = cv[1]
|
214
203
|
anotherset['diagnosis'] = cv[2]
|
215
|
-
|
216
204
|
else
|
217
205
|
# ----- Transcript of session follows -----
|
218
206
|
# Message could not be delivered for too long
|
@@ -225,13 +213,13 @@ module Sisimai::Bite::Email
|
|
225
213
|
# 554 5.3.0 unknown mailer error 255
|
226
214
|
anotherset['status'] = cv[1]
|
227
215
|
anotherset['diagnosis'] ||= ''
|
228
|
-
anotherset['diagnosis']
|
216
|
+
anotherset['diagnosis'] << ' ' << e
|
229
217
|
|
230
|
-
elsif e
|
218
|
+
elsif e.start_with?('Message ', 'Warning: ')
|
231
219
|
# Message could not be delivered for too long
|
232
220
|
# Warning: message still undelivered after 4 hours
|
233
221
|
anotherset['diagnosis'] ||= ''
|
234
|
-
anotherset['diagnosis']
|
222
|
+
anotherset['diagnosis'] << ' ' << e
|
235
223
|
end
|
236
224
|
end
|
237
225
|
end
|
@@ -239,8 +227,8 @@ module Sisimai::Bite::Email
|
|
239
227
|
end
|
240
228
|
end
|
241
229
|
return nil if recipients.zero?
|
242
|
-
require 'sisimai/string'
|
243
230
|
|
231
|
+
require 'sisimai/string'
|
244
232
|
dscontents.map do |e|
|
245
233
|
# Set default values if each value is empty.
|
246
234
|
connheader.each_key { |a| e[a] ||= connheader[a] || '' }
|
@@ -255,11 +243,7 @@ module Sisimai::Bite::Email
|
|
255
243
|
# Copy alternative error message
|
256
244
|
e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'] =~ /\A[ \t]+\z/
|
257
245
|
e['diagnosis'] = anotherset['diagnosis'] unless e['diagnosis']
|
258
|
-
|
259
|
-
if e['diagnosis'] =~ /\A\d+\z/
|
260
|
-
# Override the value of diagnostic code message
|
261
|
-
e['diagnosis'] = anotherset['diagnosis']
|
262
|
-
end
|
246
|
+
e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'] =~ /\A\d+\z/
|
263
247
|
end
|
264
248
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
265
249
|
|
@@ -7,17 +7,11 @@ module Sisimai::Bite::Email
|
|
7
7
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/SurfControl.pm
|
8
8
|
require 'sisimai/bite/email'
|
9
9
|
|
10
|
-
Re0 = {
|
11
|
-
:'from' => %r/ [(]Mail Delivery System[)]\z/,
|
12
|
-
:'x-mailer' => %r/\ASurfControl E-mail Filter\z/,
|
13
|
-
}.freeze
|
14
|
-
Re1 = {
|
15
|
-
:begin => %r/\AYour message could not be sent[.]\z/,
|
16
|
-
:error => %r/\AFailed to send to identified host,\z/,
|
17
|
-
:rfc822 => %r|\AContent-Type: message/rfc822\z|,
|
18
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
19
|
-
}.freeze
|
20
10
|
Indicators = Sisimai::Bite::Email.INDICATORS
|
11
|
+
StartingOf = {
|
12
|
+
message: ['Your message could not be sent.'],
|
13
|
+
rfc822: ['Content-Type: message/rfc822'],
|
14
|
+
}.freeze
|
21
15
|
|
22
16
|
def description; return 'WebSense SurfControl'; end
|
23
17
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
@@ -25,7 +19,6 @@ module Sisimai::Bite::Email
|
|
25
19
|
# X-SEF-Processed: 0_0_0_000__2010_04_29_23_34_45
|
26
20
|
# X-Mailer: SurfControl E-mail Filter
|
27
21
|
def headerlist; return ['X-SEF-Processed', 'X-Mailer']; end
|
28
|
-
def pattern; return Re0; end
|
29
22
|
|
30
23
|
# Parse bounce messages from SurfControl
|
31
24
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -41,9 +34,11 @@ module Sisimai::Bite::Email
|
|
41
34
|
def scan(mhead, mbody)
|
42
35
|
return nil unless mhead
|
43
36
|
return nil unless mbody
|
37
|
+
|
38
|
+
# :'from' => %r/ [(]Mail Delivery System[)]\z/,
|
44
39
|
return nil unless mhead['x-sef-processed']
|
45
40
|
return nil unless mhead['x-mailer']
|
46
|
-
return nil unless mhead['x-mailer']
|
41
|
+
return nil unless mhead['x-mailer'] == 'SurfControl E-mail Filter'
|
47
42
|
|
48
43
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
49
44
|
hasdivided = mbody.split("\n")
|
@@ -54,14 +49,14 @@ module Sisimai::Bite::Email
|
|
54
49
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
55
50
|
v = nil
|
56
51
|
|
57
|
-
hasdivided.
|
52
|
+
while e = hasdivided.shift do
|
58
53
|
# Save the current line for the next loop
|
59
54
|
havepassed << e
|
60
55
|
p = havepassed[-2]
|
61
56
|
|
62
57
|
if readcursor.zero?
|
63
58
|
# Beginning of the bounce message or delivery status part
|
64
|
-
if e
|
59
|
+
if e == StartingOf[:message][0]
|
65
60
|
readcursor |= Indicators[:deliverystatus]
|
66
61
|
next
|
67
62
|
end
|
@@ -69,7 +64,7 @@ module Sisimai::Bite::Email
|
|
69
64
|
|
70
65
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
71
66
|
# Beginning of the original message part
|
72
|
-
if e
|
67
|
+
if e == StartingOf[:rfc822][0]
|
73
68
|
readcursor |= Indicators[:'message-rfc822']
|
74
69
|
next
|
75
70
|
end
|
@@ -83,7 +78,6 @@ module Sisimai::Bite::Email
|
|
83
78
|
next
|
84
79
|
end
|
85
80
|
rfc822list << e
|
86
|
-
|
87
81
|
else
|
88
82
|
# Before "message/rfc822"
|
89
83
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -118,25 +112,23 @@ module Sisimai::Bite::Email
|
|
118
112
|
# kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
|
119
113
|
v['rhost'] = cv[1]
|
120
114
|
v['diagnosis'] = cv[2]
|
121
|
-
|
122
115
|
else
|
123
116
|
# Fallback, parse RFC3464 headers.
|
124
|
-
if cv = e.match(/\
|
117
|
+
if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
|
125
118
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
126
119
|
v['spec'] = cv[1].upcase
|
127
120
|
v['diagnosis'] = cv[2]
|
128
121
|
|
129
|
-
elsif p
|
122
|
+
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ ]+(.+)\z/)
|
130
123
|
# Continued line of the value of Diagnostic-Code header
|
131
|
-
v['diagnosis']
|
132
|
-
|
133
|
-
havepassed[-1] = 'Diagnostic-Code: ' + e
|
124
|
+
v['diagnosis'] << ' ' << cv[1]
|
125
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
134
126
|
|
135
|
-
elsif cv = e.match(/\
|
127
|
+
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
136
128
|
# Action: failed
|
137
129
|
v['action'] = cv[1].downcase
|
138
130
|
|
139
|
-
elsif cv = e.match(/\
|
131
|
+
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
140
132
|
# Status: 5.0.-
|
141
133
|
v['status'] = cv[1]
|
142
134
|
end
|
@@ -144,8 +136,8 @@ module Sisimai::Bite::Email
|
|
144
136
|
end
|
145
137
|
end
|
146
138
|
return nil if recipients.zero?
|
147
|
-
require 'sisimai/string'
|
148
139
|
|
140
|
+
require 'sisimai/string'
|
149
141
|
dscontents.map do |e|
|
150
142
|
e['agent'] = self.smtpagent
|
151
143
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
@@ -6,31 +6,22 @@ module Sisimai::Bite::Email
|
|
6
6
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/UserDefined.pm
|
7
7
|
require 'sisimai/bite/email'
|
8
8
|
|
9
|
-
# Re0 is a regular expression to match with message headers which are
|
10
|
-
# given as the first argument of scan() method.
|
11
|
-
Re0 = {
|
12
|
-
:from => %r/\AMail Sysmet/,
|
13
|
-
:subject => %r/\AError Mail Report/,
|
14
|
-
}.freeze
|
15
|
-
|
16
|
-
# Re1 is delimiter set of these sections:
|
17
|
-
# begin: The first line of a bounce message to be parsed.
|
18
|
-
# error: The first line of an error message to get an error reason, recipient
|
19
|
-
# addresses, or other bounce information.
|
20
|
-
# rfc822: The first line of the original message.
|
21
|
-
# endof: Fixed string ``__END_OF_EMAIL_MESSAGE__''
|
22
|
-
Re1 = {
|
23
|
-
:begin => %r/\A[ \t]+[-]+ Transcript of session follows [-]+\z/,
|
24
|
-
:error => %r/\A[.]+ while talking to .+[:]\z/,
|
25
|
-
:rfc822 => %r{\AContent-Type:[ ]*(?:message/rfc822|text/rfc822-headers)\z},
|
26
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
27
|
-
}.freeze
|
28
9
|
Indicators = Sisimai::Bite::Email.INDICATORS
|
10
|
+
MarkingsOf = {
|
11
|
+
# MarkingsOf is a delimiter set of these sections:
|
12
|
+
# message: The first line of a bounce message to be parsed.
|
13
|
+
# error: The first line of an error message to get an error reason, recipient
|
14
|
+
# addresses, or other bounce information.
|
15
|
+
# rfc822: The first line of the original message.
|
16
|
+
# endof: Fixed string ``__END_OF_EMAIL_MESSAGE__''
|
17
|
+
message: %r/\A[ \t]+[-]+ Transcript of session follows [-]+\z/,
|
18
|
+
error: %r/\A[.]+ while talking to .+[:]\z/,
|
19
|
+
rfc822: %r{\AContent-Type:[ ]*(?:message/rfc822|text/rfc822-headers)\z},
|
20
|
+
}.freeze
|
29
21
|
|
30
22
|
def description; return 'Module description'; end
|
31
23
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
32
24
|
def headerlist; return ['X-Some-UserDefined-Header']; end
|
33
|
-
def pattern; return Re0; end
|
34
25
|
|
35
26
|
# @abstract Template for User-Defined MTA module
|
36
27
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -47,14 +38,14 @@ module Sisimai::Bite::Email
|
|
47
38
|
return nil unless mhead
|
48
39
|
return nil unless mbody
|
49
40
|
|
50
|
-
match = 0
|
51
41
|
# 1. Check some value in mhead using regular expression or "==" operator
|
52
42
|
# whether the bounce message should be parsed by this module or not.
|
53
43
|
# - Matched 1 or more values: Proceed to the step 2.
|
54
44
|
# - Did not matched: return nil
|
55
45
|
#
|
56
|
-
match
|
57
|
-
match += 1 if mhead['
|
46
|
+
match = 0
|
47
|
+
match += 1 if mhead['subject'].start_with?('Error Mail Report')
|
48
|
+
match += 1 if mhead['from'].include?('Mail System')
|
58
49
|
match += 1 if mhead['x-some-userdefined-header']
|
59
50
|
return nil if match.zero?
|
60
51
|
|
@@ -67,10 +58,10 @@ module Sisimai::Bite::Email
|
|
67
58
|
readcursor = 0 # (Integer) Points the current cursor position
|
68
59
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
69
60
|
|
70
|
-
hasdivided.
|
61
|
+
while e = hasdivided.shift do
|
71
62
|
if readcursor.zero?
|
72
63
|
# Beginning of the bounce message or delivery status part
|
73
|
-
if e =~
|
64
|
+
if e =~ MarkingsOf[:message]
|
74
65
|
readcursor |= Indicators[:deliverystatus]
|
75
66
|
next
|
76
67
|
end
|
@@ -78,7 +69,7 @@ module Sisimai::Bite::Email
|
|
78
69
|
|
79
70
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
80
71
|
# Beginning of the original message part
|
81
|
-
if e =~
|
72
|
+
if e =~ MarkingsOf[:rfc822]
|
82
73
|
readcursor |= Indicators[:'message-rfc822']
|
83
74
|
next
|
84
75
|
end
|
@@ -92,12 +83,10 @@ module Sisimai::Bite::Email
|
|
92
83
|
next
|
93
84
|
end
|
94
85
|
rfc822list << e
|
95
|
-
|
96
86
|
else
|
97
87
|
# Before "message/rfc822"
|
98
88
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
99
89
|
next if e.empty?
|
100
|
-
|
101
90
|
end
|
102
91
|
end
|
103
92
|
|
@@ -7,42 +7,36 @@ module Sisimai::Bite::Email
|
|
7
7
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/V5sendmail.pm
|
8
8
|
require 'sisimai/bite/email'
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
:begin => %r/\A[ \t]+[-]+ Transcript of session follows [-]+\z/,
|
32
|
-
:error => %r/\A[.]+ while talking to .+[:]\z/,
|
33
|
-
:rfc822 => %r{\A[ \t]+-----[ ](?:
|
10
|
+
Indicators = Sisimai::Bite::Email.INDICATORS
|
11
|
+
StartingOf = { message: ['----- Transcript of session follows -----'] };
|
12
|
+
MarkingsOf = {
|
13
|
+
# Error text regular expressions which defined in src/savemail.c
|
14
|
+
# savemail.c:485| (void) fflush(stdout);
|
15
|
+
# savemail.c:486| p = queuename(e->e_parent, 'x');
|
16
|
+
# savemail.c:487| if ((xfile = fopen(p, "r")) == NULL)
|
17
|
+
# savemail.c:488| {
|
18
|
+
# savemail.c:489| syserr("Cannot open %s", p);
|
19
|
+
# savemail.c:490| fprintf(fp, " ----- Transcript of session is unavailable -----\n");
|
20
|
+
# savemail.c:491| }
|
21
|
+
# savemail.c:492| else
|
22
|
+
# savemail.c:493| {
|
23
|
+
# savemail.c:494| fprintf(fp, " ----- Transcript of session follows -----\n");
|
24
|
+
# savemail.c:495| if (e->e_xfp != NULL)
|
25
|
+
# savemail.c:496| (void) fflush(e->e_xfp);
|
26
|
+
# savemail.c:497| while (fgets(buf, sizeof buf, xfile) != NULL)
|
27
|
+
# savemail.c:498| putline(buf, fp, m);
|
28
|
+
# savemail.c:499| (void) fclose(xfile);
|
29
|
+
error: %r/\A[.]+ while talking to .+[:]\z/,
|
30
|
+
rfc822: %r{\A[ \t]+-----[ ](?:
|
34
31
|
Unsent[ ]message[ ]follows
|
35
32
|
|No[ ]message[ ]was[ ]collected
|
36
33
|
)[ ]-----
|
37
34
|
}x,
|
38
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
39
35
|
}.freeze
|
40
|
-
Indicators = Sisimai::Bite::Email.INDICATORS
|
41
36
|
|
42
37
|
def description; return 'Sendmail version 5'; end
|
43
38
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
44
39
|
def headerlist; return []; end
|
45
|
-
def pattern; return Re0; end
|
46
40
|
|
47
41
|
# Parse bounce messages from Sendmail version 5
|
48
42
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -58,7 +52,9 @@ module Sisimai::Bite::Email
|
|
58
52
|
def scan(mhead, mbody)
|
59
53
|
return nil unless mhead
|
60
54
|
return nil unless mbody
|
61
|
-
|
55
|
+
|
56
|
+
# :from => %r/\AMail Delivery Subsystem/,
|
57
|
+
return nil unless mhead['subject'] =~ /\AReturned mail: [A-Z]/
|
62
58
|
|
63
59
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
64
60
|
hasdivided = mbody.split("\n")
|
@@ -72,10 +68,10 @@ module Sisimai::Bite::Email
|
|
72
68
|
errorindex = -1 # (Integer)
|
73
69
|
v = nil
|
74
70
|
|
75
|
-
hasdivided.
|
71
|
+
while e = hasdivided.shift do
|
76
72
|
if readcursor.zero?
|
77
73
|
# Beginning of the bounce message or delivery status part
|
78
|
-
if e
|
74
|
+
if e.include?(StartingOf[:message][0])
|
79
75
|
readcursor |= Indicators[:deliverystatus]
|
80
76
|
next
|
81
77
|
end
|
@@ -83,7 +79,7 @@ module Sisimai::Bite::Email
|
|
83
79
|
|
84
80
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
85
81
|
# Beginning of the original message part
|
86
|
-
if e =~
|
82
|
+
if e =~ MarkingsOf[:rfc822]
|
87
83
|
readcursor |= Indicators[:'message-rfc822']
|
88
84
|
next
|
89
85
|
end
|
@@ -97,7 +93,6 @@ module Sisimai::Bite::Email
|
|
97
93
|
next
|
98
94
|
end
|
99
95
|
rfc822list << e
|
100
|
-
|
101
96
|
else
|
102
97
|
# Before "message/rfc822"
|
103
98
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -121,11 +116,8 @@ module Sisimai::Bite::Email
|
|
121
116
|
v['recipient'] = cv[1]
|
122
117
|
v['diagnosis'] = cv[2]
|
123
118
|
|
124
|
-
|
125
|
-
|
126
|
-
v['diagnosis'] ||= ''
|
127
|
-
v['diagnosis'] += ': ' + responding[recipients]
|
128
|
-
end
|
119
|
+
# Concatenate the response of the server and error message
|
120
|
+
v['diagnosis'] << ': ' << responding[recipients] if responding[recipients]
|
129
121
|
recipients += 1
|
130
122
|
|
131
123
|
elsif cv = e.match(/\A[>]{3}[ ]*([A-Z]{4})[ ]*/)
|
@@ -137,12 +129,11 @@ module Sisimai::Bite::Email
|
|
137
129
|
# <<< 501 <shironeko@example.co.jp>... no access from mail server [192.0.2.55] which is an open relay.
|
138
130
|
# <<< 550 Requested User Mailbox not found. No such user here.
|
139
131
|
responding[recipients] = cv[1]
|
140
|
-
|
141
132
|
else
|
142
133
|
# Detect SMTP session error or connection error
|
143
134
|
next if v['sessionerr']
|
144
135
|
|
145
|
-
if e =~
|
136
|
+
if e =~ MarkingsOf[:error]
|
146
137
|
# ----- Transcript of session follows -----
|
147
138
|
# ... while talking to mta.example.org.:
|
148
139
|
v['sessionerr'] = true
|
@@ -170,14 +161,14 @@ module Sisimai::Bite::Email
|
|
170
161
|
end
|
171
162
|
end
|
172
163
|
return nil if recipients.zero?
|
173
|
-
require 'sisimai/string'
|
174
164
|
|
165
|
+
require 'sisimai/string'
|
175
166
|
dscontents.map do |e|
|
176
167
|
errorindex += 1
|
177
168
|
e['agent'] = self.smtpagent
|
178
169
|
e['command'] = commandset[errorindex] || ''
|
179
170
|
|
180
|
-
e['diagnosis'] ||= if anotherset['diagnosis']
|
171
|
+
e['diagnosis'] ||= if anotherset['diagnosis'].to_s.size > 0
|
181
172
|
# Copy alternative error message
|
182
173
|
anotherset['diagnosis']
|
183
174
|
else
|