sisimai 4.24.1-java → 4.25.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/.travis.yml +3 -2
- data/ANALYTICAL-PRECISION +16 -25
- data/ChangeLog.md +41 -0
- data/Developers.mk +2 -2
- data/README-JA.md +13 -13
- data/README.md +13 -13
- data/lib/sisimai.rb +3 -7
- data/lib/sisimai/address.rb +25 -41
- data/lib/sisimai/arf.rb +58 -59
- data/lib/sisimai/bite.rb +0 -1
- data/lib/sisimai/bite/email.rb +7 -7
- data/lib/sisimai/bite/email/activehunter.rb +4 -3
- data/lib/sisimai/bite/email/amavis.rb +133 -0
- data/lib/sisimai/bite/email/amazonses.rb +53 -87
- data/lib/sisimai/bite/email/amazonworkmail.rb +51 -57
- data/lib/sisimai/bite/email/aol.rb +50 -76
- data/lib/sisimai/bite/email/apachejames.rb +2 -2
- data/lib/sisimai/bite/email/bigfoot.rb +47 -74
- data/lib/sisimai/bite/email/biglobe.rb +8 -9
- data/lib/sisimai/bite/email/courier.rb +56 -101
- data/lib/sisimai/bite/email/domino.rb +7 -8
- data/lib/sisimai/bite/email/einsundeins.rb +4 -5
- data/lib/sisimai/bite/email/exchange2003.rb +21 -22
- data/lib/sisimai/bite/email/exchange2007.rb +26 -28
- data/lib/sisimai/bite/email/exim.rb +48 -47
- data/lib/sisimai/bite/email/ezweb.rb +24 -36
- data/lib/sisimai/bite/email/facebook.rb +54 -79
- data/lib/sisimai/bite/email/fml.rb +10 -10
- data/lib/sisimai/bite/email/gmx.rb +6 -6
- data/lib/sisimai/bite/email/google.rb +12 -13
- data/lib/sisimai/bite/email/gsuite.rb +80 -108
- data/lib/sisimai/bite/email/imailserver.rb +16 -16
- data/lib/sisimai/bite/email/interscanmss.rb +4 -6
- data/lib/sisimai/bite/email/kddi.rb +9 -11
- data/lib/sisimai/bite/email/mailfoundry.rb +2 -2
- data/lib/sisimai/bite/email/mailmarshalsmtp.rb +2 -2
- data/lib/sisimai/bite/email/mailru.rb +12 -13
- data/lib/sisimai/bite/email/mcafee.rb +31 -25
- data/lib/sisimai/bite/email/messagelabs.rb +48 -87
- data/lib/sisimai/bite/email/messagingserver.rb +9 -10
- data/lib/sisimai/bite/email/mfilter.rb +16 -16
- data/lib/sisimai/bite/email/mxlogic.rb +11 -11
- data/lib/sisimai/bite/email/notes.rb +5 -6
- data/lib/sisimai/bite/email/office365.rb +25 -42
- data/lib/sisimai/bite/email/opensmtpd.rb +8 -8
- data/lib/sisimai/bite/email/outlook.rb +49 -67
- data/lib/sisimai/bite/email/postfix.rb +78 -112
- data/lib/sisimai/bite/email/qmail.rb +23 -23
- data/lib/sisimai/bite/email/receivingses.rb +53 -86
- data/lib/sisimai/bite/email/sendgrid.rb +65 -84
- data/lib/sisimai/bite/email/sendmail.rb +89 -117
- data/lib/sisimai/bite/email/surfcontrol.rb +15 -18
- data/lib/sisimai/bite/email/userdefined.rb +1 -1
- data/lib/sisimai/bite/email/v5sendmail.rb +3 -4
- data/lib/sisimai/bite/email/verizon.rb +7 -8
- data/lib/sisimai/bite/email/x1.rb +2 -2
- data/lib/sisimai/bite/email/x2.rb +2 -2
- data/lib/sisimai/bite/email/x3.rb +3 -3
- data/lib/sisimai/bite/email/x4.rb +22 -22
- data/lib/sisimai/bite/email/x5.rb +40 -49
- data/lib/sisimai/bite/email/yahoo.rb +3 -3
- data/lib/sisimai/bite/email/yandex.rb +54 -82
- data/lib/sisimai/bite/email/zoho.rb +6 -6
- data/lib/sisimai/bite/json/amazonses.rb +20 -20
- data/lib/sisimai/bite/json/sendgrid.rb +2 -2
- data/lib/sisimai/data.rb +27 -40
- data/lib/sisimai/datetime.rb +146 -162
- data/lib/sisimai/mda.rb +30 -31
- data/lib/sisimai/message/email.rb +83 -123
- data/lib/sisimai/message/json.rb +2 -4
- data/lib/sisimai/mime.rb +31 -34
- data/lib/sisimai/order/email.rb +23 -22
- data/lib/sisimai/reason.rb +61 -61
- data/lib/sisimai/reason/blocked.rb +139 -135
- data/lib/sisimai/reason/contenterror.rb +11 -10
- data/lib/sisimai/reason/exceedlimit.rb +4 -4
- data/lib/sisimai/reason/expired.rb +20 -20
- data/lib/sisimai/reason/filtered.rb +19 -18
- data/lib/sisimai/reason/hasmoved.rb +3 -3
- data/lib/sisimai/reason/hostunknown.rb +19 -19
- data/lib/sisimai/reason/mailboxfull.rb +49 -49
- data/lib/sisimai/reason/mailererror.rb +16 -16
- data/lib/sisimai/reason/mesgtoobig.rb +17 -17
- data/lib/sisimai/reason/networkerror.rb +19 -19
- data/lib/sisimai/reason/norelaying.rb +16 -16
- data/lib/sisimai/reason/notaccept.rb +9 -10
- data/lib/sisimai/reason/onhold.rb +1 -1
- data/lib/sisimai/reason/policyviolation.rb +21 -20
- data/lib/sisimai/reason/rejected.rb +53 -53
- data/lib/sisimai/reason/securityerror.rb +29 -29
- data/lib/sisimai/reason/spamdetected.rb +127 -127
- data/lib/sisimai/reason/suspend.rb +17 -17
- data/lib/sisimai/reason/systemerror.rb +22 -21
- data/lib/sisimai/reason/systemfull.rb +6 -6
- data/lib/sisimai/reason/toomanyconn.rb +19 -18
- data/lib/sisimai/reason/userunknown.rb +122 -121
- data/lib/sisimai/reason/vacation.rb +8 -8
- data/lib/sisimai/reason/virusdetected.rb +8 -8
- data/lib/sisimai/rfc1894.rb +142 -0
- data/lib/sisimai/rfc3464.rb +70 -70
- data/lib/sisimai/rfc3834.rb +15 -15
- data/lib/sisimai/rfc5322.rb +20 -36
- data/lib/sisimai/rhost.rb +1 -0
- data/lib/sisimai/rhost/exchangeonline.rb +31 -33
- data/lib/sisimai/rhost/franceptt.rb +23 -23
- data/lib/sisimai/rhost/godaddy.rb +28 -28
- data/lib/sisimai/rhost/googleapps.rb +39 -41
- data/lib/sisimai/rhost/kddi.rb +3 -3
- data/lib/sisimai/rhost/tencentqq.rb +51 -0
- data/lib/sisimai/smtp/error.rb +14 -21
- data/lib/sisimai/smtp/reply.rb +14 -13
- data/lib/sisimai/smtp/status.rb +178 -179
- data/lib/sisimai/string.rb +13 -12
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +1 -5
- data/set-of-emails/maildir/bsd/arf-23.eml +49 -0
- data/set-of-emails/maildir/bsd/email-amavis-01.eml +78 -0
- data/set-of-emails/maildir/bsd/email-amavis-02.eml +78 -0
- data/set-of-emails/maildir/bsd/email-exchange2007-04.eml +146 -0
- data/set-of-emails/maildir/bsd/email-exim-60.eml +94 -0
- data/set-of-emails/maildir/bsd/email-ezweb-08.eml +49 -0
- data/set-of-emails/maildir/bsd/email-google-19.eml +67 -0
- data/set-of-emails/maildir/bsd/email-mcafee-05.eml +74 -0
- data/set-of-emails/maildir/bsd/email-messagingserver-12.eml +99 -0
- data/set-of-emails/maildir/bsd/email-postfix-46.eml +81 -0
- data/set-of-emails/maildir/bsd/email-postfix-47.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-48.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-49.eml +141 -0
- data/set-of-emails/maildir/bsd/email-postfix-50.eml +143 -0
- data/set-of-emails/maildir/bsd/email-postfix-51.eml +73 -0
- data/set-of-emails/maildir/bsd/email-postfix-52.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-53.eml +76 -0
- data/set-of-emails/maildir/bsd/email-postfix-54.eml +73 -0
- data/set-of-emails/maildir/bsd/email-postfix-55.eml +74 -0
- data/set-of-emails/maildir/bsd/email-postfix-56.eml +78 -0
- data/set-of-emails/maildir/bsd/email-qmail-10.eml +50 -0
- data/set-of-emails/maildir/bsd/email-x2-05.eml +38 -0
- data/set-of-emails/maildir/bsd/rhost-google-apps-02.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-01.eml +84 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-02.eml +84 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-03.eml +81 -0
- data/set-of-emails/maildir/dos/email-amavis-01.eml +78 -0
- data/set-of-emails/maildir/dos/email-apachejames-01.eml +1 -2
- data/set-of-emails/maildir/dos/email-messagelabs-01.eml +67 -50
- data/set-of-emails/maildir/dos/email-x4-01.eml +31 -76
- data/set-of-emails/maildir/dos/rhost-tencentqq-01.eml +84 -0
- data/set-of-emails/maildir/mac/email-amavis-01.eml +1 -4
- data/set-of-emails/maildir/mac/email-apachejames-01.eml +1 -9
- data/set-of-emails/maildir/mac/email-messagelabs-01.eml +1 -9
- data/set-of-emails/maildir/mac/email-x4-01.eml +1 -5
- data/set-of-emails/maildir/mac/rhost-tencentqq-01.eml +1 -4
- metadata +35 -4
- data/set-of-emails/logo/horizontalversions.png +0 -0
- data/set-of-emails/logo/icon.png +0 -0
data/lib/sisimai/arf.rb
CHANGED
@@ -4,6 +4,7 @@ module Sisimai
|
|
4
4
|
# Imported from p5-Sisimail/lib/Sisimai/ARF.pm
|
5
5
|
class << self
|
6
6
|
require 'sisimai/bite/email'
|
7
|
+
require 'sisimai/rfc5322'
|
7
8
|
|
8
9
|
# http://tools.ietf.org/html/rfc5965
|
9
10
|
# http://en.wikipedia.org/wiki/Feedback_loop_(email)
|
@@ -48,12 +49,13 @@ module Sisimai
|
|
48
49
|
elsif heads['content-type'].start_with?('multipart/mixed')
|
49
50
|
# Microsoft (Hotmail, MSN, Live, Outlook) uses its own report format.
|
50
51
|
# Amazon SES Complaints bounces
|
52
|
+
hfrom = Sisimai::Address.s3s4(heads['from'])
|
51
53
|
mfrom = %r{(?:
|
52
54
|
staff[@]hotmail[.]com
|
53
55
|
|complaints[@]email-abuse[.]amazonses[.]com
|
54
56
|
)\z
|
55
57
|
}x
|
56
|
-
if
|
58
|
+
if hfrom =~ mfrom && heads['subject'].include?('complaint about message from ')
|
57
59
|
# From: staff@hotmail.com
|
58
60
|
# From: complaints@email-abuse.amazonses.com
|
59
61
|
# Subject: complaint about message from 192.0.2.1
|
@@ -85,16 +87,16 @@ module Sisimai
|
|
85
87
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
86
88
|
rcptintext = '' # (String) Recipient address in the message body
|
87
89
|
commondata = {
|
88
|
-
|
89
|
-
|
90
|
-
|
90
|
+
'diagnosis' => '', # Error message
|
91
|
+
'from' => '', # Original-Mail-From:
|
92
|
+
'rhost' => '', # Reporting-MTA:
|
91
93
|
}
|
92
94
|
arfheaders = {
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
95
|
+
'feedbacktype' => nil, # FeedBack-Type:
|
96
|
+
'rhost' => nil, # Source-IP:
|
97
|
+
'agent' => nil, # User-Agent:
|
98
|
+
'date' => nil, # Arrival-Date:
|
99
|
+
'authres' => nil, # Authentication-Results:
|
98
100
|
}
|
99
101
|
v = nil
|
100
102
|
|
@@ -120,7 +122,7 @@ module Sisimai
|
|
120
122
|
#
|
121
123
|
while e = hasdivided.shift do
|
122
124
|
if readcursor == 0
|
123
|
-
# Beginning of the bounce message or delivery
|
125
|
+
# Beginning of the bounce message or message/delivery-status part
|
124
126
|
if e =~ MarkingsOf[:message]
|
125
127
|
readcursor |= Indicators[:deliverystatus]
|
126
128
|
next
|
@@ -136,7 +138,7 @@ module Sisimai
|
|
136
138
|
end
|
137
139
|
|
138
140
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
139
|
-
#
|
141
|
+
# message/rfc822 OR text/rfc822-headers part
|
140
142
|
if cv = e.match(/X-HmXmrOriginalRecipient:[ ]*(.+)\z/)
|
141
143
|
# Microsoft ARF: original recipient.
|
142
144
|
dscontents[-1]['recipient'] = Sisimai::Address.s3s4(cv[1])
|
@@ -145,17 +147,24 @@ module Sisimai
|
|
145
147
|
# The "X-HmXmrOriginalRecipient" header appears only once so
|
146
148
|
# we take this opportunity to hard-code ARF headers missing in
|
147
149
|
# Microsoft's implementation.
|
148
|
-
arfheaders[
|
149
|
-
arfheaders[
|
150
|
+
arfheaders['feedbacktype'] = 'abuse'
|
151
|
+
arfheaders['agent'] = 'Microsoft Junk Mail Reporting Program'
|
150
152
|
|
151
153
|
elsif cv = e.match(/\AFrom:[ ]*(.+)\z/)
|
152
154
|
# Microsoft ARF: original sender.
|
153
|
-
commondata[
|
155
|
+
commondata['from'] = Sisimai::Address.s3s4(cv[1]) if commondata['from'].empty?
|
154
156
|
|
155
|
-
elsif
|
157
|
+
elsif e.start_with?(' ', "\t")
|
158
|
+
# Continued line from the previous line
|
159
|
+
rfc822part << e + "\n" if LongFields.key?(previousfn)
|
160
|
+
next unless e.empty?
|
161
|
+
rcptintext << e if previousfn == 'to'
|
162
|
+
|
163
|
+
else
|
156
164
|
# Get required headers only
|
157
|
-
lhs =
|
158
|
-
|
165
|
+
(lhs, rhs) = e.split(/:[ ]*/, 2)
|
166
|
+
next unless lhs
|
167
|
+
lhs.downcase!
|
159
168
|
|
160
169
|
previousfn = ''
|
161
170
|
next unless RFC822Head.key?(lhs)
|
@@ -163,15 +172,9 @@ module Sisimai
|
|
163
172
|
previousfn = lhs
|
164
173
|
rfc822part << e + "\n"
|
165
174
|
rcptintext = rhs if lhs == 'to'
|
166
|
-
|
167
|
-
elsif e.start_with?(' ', "\t")
|
168
|
-
# Continued line from the previous line
|
169
|
-
rfc822part << e + "\n" if LongFields.key?(previousfn)
|
170
|
-
next unless e.empty?
|
171
|
-
rcptintext << e if previousfn == 'to'
|
172
175
|
end
|
173
176
|
else
|
174
|
-
#
|
177
|
+
# message/delivery-status part
|
175
178
|
next unless readcursor & Indicators[:deliverystatus] > 0
|
176
179
|
next if e.empty?
|
177
180
|
|
@@ -201,7 +204,7 @@ module Sisimai
|
|
201
204
|
elsif cv = e.match(/\AFeedback-Type:[ ]*([^ ]+)\z/)
|
202
205
|
# The header field MUST appear exactly once.
|
203
206
|
# Feedback-Type: abuse
|
204
|
-
arfheaders[
|
207
|
+
arfheaders['feedbacktype'] = cv[1]
|
205
208
|
|
206
209
|
elsif cv = e.match(/\AAuthentication-Results:[ ]*(.+)\z/)
|
207
210
|
# "Authentication-Results" indicates the result of one or more
|
@@ -209,68 +212,68 @@ module Sisimai
|
|
209
212
|
#
|
210
213
|
# Authentication-Results: mail.example.com;
|
211
214
|
# spf=fail smtp.mail=somespammer@example.com
|
212
|
-
arfheaders[
|
215
|
+
arfheaders['authres'] = cv[1]
|
213
216
|
|
214
217
|
elsif cv = e.match(/\AUser-Agent:[ ]*(.+)\z/)
|
215
218
|
# The header field MUST appear exactly once.
|
216
219
|
# User-Agent: SomeGenerator/1.0
|
217
|
-
arfheaders[
|
220
|
+
arfheaders['agent'] = cv[1]
|
218
221
|
|
219
222
|
elsif cv = e.match(/\A(?:Received|Arrival)-Date:[ ]*(.+)\z/)
|
220
223
|
# Arrival-Date header is optional and MUST NOT appear more than
|
221
224
|
# once.
|
222
225
|
# Received-Date: Thu, 29 Apr 2010 00:00:00 JST
|
223
226
|
# Arrival-Date: Thu, 29 Apr 2010 00:00:00 +0000
|
224
|
-
arfheaders[
|
227
|
+
arfheaders['date'] = cv[1]
|
225
228
|
|
226
229
|
elsif cv = e.match(/\AReporting-MTA:[ ]*dns;[ ]*(.+)\z/)
|
227
230
|
# The header is optional and MUST NOT appear more than once.
|
228
231
|
# Reporting-MTA: dns; mx.example.jp
|
229
|
-
commondata[
|
232
|
+
commondata['rhost'] = cv[1]
|
230
233
|
|
231
234
|
elsif cv = e.match(/\ASource-IP:[ ]*(.+)\z/)
|
232
235
|
# The header is optional and MUST NOT appear more than once.
|
233
236
|
# Source-IP: 192.0.2.45
|
234
|
-
arfheaders[
|
237
|
+
arfheaders['rhost'] = cv[1]
|
235
238
|
|
236
239
|
elsif cv = e.match(/\AOriginal-Mail-From:[ ]*(.+)\z/)
|
237
240
|
# the header is optional and MUST NOT appear more than once.
|
238
241
|
# Original-Mail-From: <somespammer@example.net>
|
239
|
-
commondata[
|
242
|
+
commondata['from'] = Sisimai::Address.s3s4(cv[1]) if commondata['from'].empty?
|
240
243
|
|
241
244
|
elsif e =~ MarkingsOf[:message]
|
242
245
|
# This is an email abuse report for an email message with the
|
243
246
|
# message-id of 0000-000000000000000000000000000000000@mx
|
244
247
|
# received from IP address 192.0.2.1 on
|
245
248
|
# Thu, 29 Apr 2010 00:00:00 +0900 (JST)
|
246
|
-
commondata[
|
249
|
+
commondata['diagnosis'] = e
|
247
250
|
end
|
248
251
|
end
|
249
252
|
end
|
250
253
|
|
251
|
-
if arfheaders[
|
254
|
+
if arfheaders['feedbacktype'] == 'auth-failure' && arfheaders['authres']
|
252
255
|
# Append the value of Authentication-Results header
|
253
|
-
commondata[
|
256
|
+
commondata['diagnosis'] << ' ' << arfheaders['authres']
|
254
257
|
end
|
255
258
|
|
256
259
|
unless recipients > 0
|
257
260
|
# Insert pseudo recipient address when there is no valid recipient
|
258
261
|
# address in the message.
|
259
|
-
dscontents[-1]['recipient'] = Sisimai::Address.undisclosed(
|
262
|
+
dscontents[-1]['recipient'] = Sisimai::Address.undisclosed('r')
|
260
263
|
recipients = 1
|
261
264
|
end
|
262
265
|
|
263
266
|
unless rfc822part =~ /\bFrom: [^ ]+[@][^ ]+\b/
|
264
267
|
# There is no "From:" header in the original message
|
265
268
|
# Append the value of "Original-Mail-From" value as a sender address.
|
266
|
-
rfc822part << 'From: ' << commondata[
|
269
|
+
rfc822part << 'From: ' << commondata['from'] + "\n" unless commondata['from'].empty?
|
267
270
|
end
|
268
271
|
|
269
272
|
if cv = mhead['subject'].match(/complaint about message from (\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3})/)
|
270
273
|
# Microsoft ARF: remote host address.
|
271
|
-
arfheaders[
|
272
|
-
commondata[
|
273
|
-
'This is a Microsoft email abuse report for an email message received from IP' << arfheaders[
|
274
|
+
arfheaders['rhost'] = cv[1]
|
275
|
+
commondata['diagnosis'] =
|
276
|
+
'This is a Microsoft email abuse report for an email message received from IP' << arfheaders['rhost'] + ' on ' << mhead['date']
|
274
277
|
end
|
275
278
|
|
276
279
|
dscontents.each do |e|
|
@@ -278,32 +281,28 @@ module Sisimai
|
|
278
281
|
# AOL = http://forums.cpanel.net/f43/aol-brutal-work-71473.html
|
279
282
|
e['recipient'] = Sisimai::Address.s3s4(rcptintext)
|
280
283
|
end
|
281
|
-
arfheaders.each_key { |a| e[a
|
284
|
+
arfheaders.each_key { |a| e[a] ||= arfheaders[a] || '' }
|
282
285
|
e.delete('authres')
|
283
286
|
|
284
287
|
e['softbounce'] = -1
|
285
|
-
e['diagnosis'] = commondata[
|
288
|
+
e['diagnosis'] = commondata['diagnosis'] unless e['diagnosis']
|
286
289
|
e['date'] = mhead['date'] if e['date'].empty?
|
287
|
-
|
288
|
-
if e['
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
290
|
+
e['reason'] = 'feedback'
|
291
|
+
e['agent'] = self.smtpagent if e['agent'].empty?
|
292
|
+
%w[command action status alias].each { |a| e[a] = '' }
|
293
|
+
|
294
|
+
# Get the remote IP address from the message body
|
295
|
+
next unless e['rhost'].empty?
|
296
|
+
if commondata['rhost'].size > 0
|
297
|
+
# The value of "Reporting-MTA" header
|
298
|
+
e['rhost'] = commondata['rhost']
|
299
|
+
|
300
|
+
elsif cv = e['diagnosis'].match(/\breceived from IP address ([^ ]+)/)
|
301
|
+
# This is an email abuse report for an email message received
|
302
|
+
# from IP address 24.64.1.1 on Thu, 29 Apr 2010 00:00:00 +0000
|
303
|
+
e['rhost'] = cv[1]
|
299
304
|
end
|
300
305
|
|
301
|
-
e['reason'] = 'feedback'
|
302
|
-
e['command'] = ''
|
303
|
-
e['action'] = ''
|
304
|
-
e['status'] = ''
|
305
|
-
e['alias'] = ''
|
306
|
-
e['agent'] = self.smtpagent if e['agent'].empty?
|
307
306
|
end
|
308
307
|
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
309
308
|
end
|
data/lib/sisimai/bite.rb
CHANGED
data/lib/sisimai/bite/email.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Sisimai
|
1
|
+
module Sisimai
|
2
2
|
module Bite
|
3
3
|
# Sisimai::Bite::Email- Base class for Sisimai::Bite::Email::*
|
4
4
|
module Email
|
@@ -21,23 +21,23 @@ module Sisimai
|
|
21
21
|
# @return [Array] MTA list with order
|
22
22
|
def index
|
23
23
|
return %w[
|
24
|
-
Sendmail Postfix Qmail Exim Courier OpenSMTPD
|
25
|
-
|
24
|
+
Sendmail Postfix Qmail Exim Courier OpenSMTPD Office365 Outlook
|
25
|
+
Exchange2007 Exchange2003 Yahoo GSuite Aol SendGrid AmazonSES MailRu
|
26
26
|
Yandex MessagingServer Domino Notes ReceivingSES AmazonWorkMail Verizon
|
27
27
|
GMX Bigfoot Facebook Zoho EinsUndEins MessageLabs EZweb KDDI Biglobe
|
28
|
-
ApacheJames McAfee MXLogic MailFoundry IMailServer
|
28
|
+
Amavis ApacheJames McAfee MXLogic MailFoundry IMailServer
|
29
29
|
MFILTER Activehunter InterScanMSS SurfControl MailMarshalSMTP
|
30
|
-
X1 X2 X3 X4 X5 V5sendmail FML]
|
30
|
+
X1 X2 X3 X4 X5 V5sendmail FML Google]
|
31
31
|
end
|
32
32
|
|
33
33
|
# @abstract MTA list which have one or more extra headers
|
34
34
|
# @return [Array] MTA list (have extra headers)
|
35
35
|
def heads
|
36
36
|
return %w[
|
37
|
-
Exim Exchange2007 Exchange2003
|
37
|
+
Exim Office365 Outlook Exchange2007 Exchange2003 GSuite SendGrid
|
38
38
|
AmazonSES ReceivingSES AmazonWorkMail Aol GMX MailRu MessageLabs Yahoo
|
39
39
|
Yandex Zoho EinsUndEins MXLogic McAfee MFILTER EZweb Activehunter IMailServer
|
40
|
-
SurfControl FML
|
40
|
+
SurfControl FML Google
|
41
41
|
]
|
42
42
|
end
|
43
43
|
|
@@ -15,7 +15,7 @@ module Sisimai::Bite::Email
|
|
15
15
|
|
16
16
|
def description; return 'TransWARE Active!hunter'; end
|
17
17
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
18
|
-
def headerlist; return [
|
18
|
+
def headerlist; return %w[x-ahmailid]; end
|
19
19
|
|
20
20
|
# Parse bounce messages from TransWARE Active!hunter
|
21
21
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -59,7 +59,7 @@ module Sisimai::Bite::Email
|
|
59
59
|
end
|
60
60
|
|
61
61
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
62
|
-
#
|
62
|
+
# Inside of the original message part
|
63
63
|
if e.empty?
|
64
64
|
blanklines += 1
|
65
65
|
break if blanklines > 1
|
@@ -67,7 +67,7 @@ module Sisimai::Bite::Email
|
|
67
67
|
end
|
68
68
|
rfc822list << e
|
69
69
|
else
|
70
|
-
#
|
70
|
+
# Error message part
|
71
71
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
72
72
|
next if e.empty?
|
73
73
|
|
@@ -100,6 +100,7 @@ module Sisimai::Bite::Email
|
|
100
100
|
end
|
101
101
|
return nil unless recipients > 0
|
102
102
|
|
103
|
+
require 'sisimai/string'
|
103
104
|
dscontents.each do |e|
|
104
105
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
105
106
|
e['agent'] = self.smtpagent
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Sisimai::Bite::Email
|
2
|
+
# Sisimai::Bite::Email::Amavis parses a bounce email which created by
|
3
|
+
# amavsid-new. Methods in the module are called from only Sisimai::Message.
|
4
|
+
module Amavis
|
5
|
+
class << self
|
6
|
+
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Amavis.pm
|
7
|
+
require 'sisimai/bite/email'
|
8
|
+
|
9
|
+
Indicators = Sisimai::Bite::Email.INDICATORS
|
10
|
+
StartingOf = {
|
11
|
+
message: ['The message '],
|
12
|
+
rfc822: ['Content-Type: text/rfc822-headers'],
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
def description; return 'amavisd-new: https://www.amavis.org/'; end
|
16
|
+
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
17
|
+
|
18
|
+
# Parse bounce messages from amavisd-new
|
19
|
+
# @param [Hash] mhead Message headers of a bounce email
|
20
|
+
# @options mhead [String] from From header
|
21
|
+
# @options mhead [String] date Date header
|
22
|
+
# @options mhead [String] subject Subject header
|
23
|
+
# @options mhead [Array] received Received headers
|
24
|
+
# @options mhead [String] others Other required headers
|
25
|
+
# @param [String] mbody Message body of a bounce email
|
26
|
+
# @return [Hash, Nil] Bounce data list and message/rfc822
|
27
|
+
# part or nil if it failed to parse or
|
28
|
+
# the arguments are missing
|
29
|
+
def scan(mhead, mbody)
|
30
|
+
# From: "Content-filter at neko1.example.jp" <postmaster@neko1.example.jp>
|
31
|
+
# Subject: Undeliverable mail, MTA-BLOCKED
|
32
|
+
return nil unless mhead['from'].to_s.start_with?('"Content-filter at ')
|
33
|
+
|
34
|
+
require 'sisimai/rfc1894'
|
35
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
36
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
37
|
+
|
38
|
+
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
39
|
+
hasdivided = mbody.split("\n")
|
40
|
+
havepassed = ['']
|
41
|
+
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
42
|
+
blanklines = 0 # (Integer) The number of blank lines
|
43
|
+
readcursor = 0 # (Integer) Points the current cursor position
|
44
|
+
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
45
|
+
v = nil
|
46
|
+
|
47
|
+
while e = hasdivided.shift do
|
48
|
+
# Save the current line for the next loop
|
49
|
+
havepassed << e
|
50
|
+
p = havepassed[-2]
|
51
|
+
|
52
|
+
if readcursor == 0
|
53
|
+
# Beginning of the bounce message or message/delivery-status part
|
54
|
+
if e.start_with?(StartingOf[:message][0])
|
55
|
+
readcursor |= Indicators[:deliverystatus]
|
56
|
+
next
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
if (readcursor & Indicators[:'message-rfc822']) == 0
|
61
|
+
# Beginning of the original message part(message/rfc822)
|
62
|
+
if e == StartingOf[:rfc822][0]
|
63
|
+
readcursor |= Indicators[:'message-rfc822']
|
64
|
+
next
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if readcursor & Indicators[:'message-rfc822'] > 0
|
69
|
+
# message/rfc822 OR text/rfc822-headers part
|
70
|
+
if e.empty?
|
71
|
+
blanklines += 1
|
72
|
+
break if blanklines > 1
|
73
|
+
next
|
74
|
+
end
|
75
|
+
rfc822list << e
|
76
|
+
else
|
77
|
+
# message/delivery-status part
|
78
|
+
next if (readcursor & Indicators[:deliverystatus]) == 0
|
79
|
+
next if e.empty?
|
80
|
+
next unless f = Sisimai::RFC1894.match(e)
|
81
|
+
|
82
|
+
# "e" matched with any field defined in RFC3464
|
83
|
+
next unless o = Sisimai::RFC1894.field(e)
|
84
|
+
v = dscontents[-1]
|
85
|
+
|
86
|
+
if o[-1] == 'addr'
|
87
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
88
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
89
|
+
if o[0] == 'final-recipient'
|
90
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
91
|
+
if v['recipient']
|
92
|
+
# There are multiple recipient addresses in the message body.
|
93
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
94
|
+
v = dscontents[-1]
|
95
|
+
end
|
96
|
+
v['recipient'] = o[2]
|
97
|
+
recipients += 1
|
98
|
+
else
|
99
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
100
|
+
v['alias'] = o[2]
|
101
|
+
end
|
102
|
+
elsif o[-1] == 'code'
|
103
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
104
|
+
v['spec'] = o[1]
|
105
|
+
v['diagnosis'] = o[2]
|
106
|
+
else
|
107
|
+
# Other DSN fields defined in RFC3464
|
108
|
+
next unless fieldtable.key?(o[0])
|
109
|
+
v[fieldtable[o[0]]] = o[2]
|
110
|
+
|
111
|
+
next unless f == 1
|
112
|
+
permessage[fieldtable[o[0]]] = o[2]
|
113
|
+
end
|
114
|
+
end # End of message/delivery-status
|
115
|
+
end
|
116
|
+
return nil unless recipients > 0
|
117
|
+
|
118
|
+
dscontents.each do |e|
|
119
|
+
# Set default values if each value is empty.
|
120
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
121
|
+
|
122
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.tr("\n", ' '))
|
123
|
+
e['agent'] = self.smtpagent
|
124
|
+
end
|
125
|
+
|
126
|
+
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
127
|
+
return { 'ds' => dscontents, 'rfc822' => rfc822part }
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|