sisimai 4.25.16 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/ANALYTICAL-PRECISION +2 -2
- data/Benchmarks.mk +3 -3
- data/CONTRIBUTING +1 -1
- data/ChangeLog.md +412 -393
- data/Developers.mk +5 -6
- data/Gemfile +1 -1
- data/Makefile +15 -15
- data/README-JA.md +140 -78
- data/README.md +290 -143
- data/Rakefile +9 -3
- data/Repository.mk +2 -3
- data/lib/sisimai/address.rb +118 -74
- data/lib/sisimai/arf.rb +84 -82
- data/lib/sisimai/datetime.rb +5 -52
- data/lib/sisimai/{data → fact}/json.rb +7 -9
- data/lib/sisimai/fact/yaml.rb +31 -0
- data/lib/sisimai/fact.rb +468 -0
- data/lib/sisimai/lhost/activehunter.rb +12 -14
- data/lib/sisimai/lhost/amavis.rb +11 -14
- data/lib/sisimai/lhost/amazonses.rb +37 -41
- data/lib/sisimai/lhost/amazonworkmail.rb +15 -18
- data/lib/sisimai/lhost/aol.rb +12 -14
- data/lib/sisimai/lhost/apachejames.rb +19 -21
- data/lib/sisimai/lhost/barracuda.rb +10 -12
- data/lib/sisimai/lhost/bigfoot.rb +21 -21
- data/lib/sisimai/lhost/biglobe.rb +15 -16
- data/lib/sisimai/lhost/courier.rb +20 -20
- data/lib/sisimai/lhost/domino.rb +23 -19
- data/lib/sisimai/lhost/einsundeins.rb +23 -18
- data/lib/sisimai/lhost/exchange2003.rb +30 -29
- data/lib/sisimai/lhost/exchange2007.rb +70 -58
- data/lib/sisimai/lhost/exim.rb +175 -161
- data/lib/sisimai/lhost/ezweb.rb +31 -56
- data/lib/sisimai/lhost/facebook.rb +21 -33
- data/lib/sisimai/lhost/fml.rb +43 -48
- data/lib/sisimai/lhost/gmail.rb +29 -29
- data/lib/sisimai/lhost/gmx.rb +18 -17
- data/lib/sisimai/lhost/googlegroups.rb +9 -10
- data/lib/sisimai/lhost/gsuite.rb +21 -27
- data/lib/sisimai/lhost/imailserver.rb +25 -39
- data/lib/sisimai/lhost/interscanmss.rb +28 -31
- data/lib/sisimai/lhost/kddi.rb +22 -28
- data/lib/sisimai/lhost/mailfoundry.rb +11 -12
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
- data/lib/sisimai/lhost/mailru.rb +33 -27
- data/lib/sisimai/lhost/mcafee.rb +21 -31
- data/lib/sisimai/lhost/messagelabs.rb +17 -20
- data/lib/sisimai/lhost/messagingserver.rb +40 -37
- data/lib/sisimai/lhost/mfilter.rb +15 -16
- data/lib/sisimai/lhost/mxlogic.rb +24 -23
- data/lib/sisimai/lhost/notes.rb +17 -17
- data/lib/sisimai/lhost/office365.rb +63 -27
- data/lib/sisimai/lhost/opensmtpd.rb +12 -13
- data/lib/sisimai/lhost/outlook.rb +12 -15
- data/lib/sisimai/lhost/postfix.rb +179 -129
- data/lib/sisimai/lhost/powermta.rb +12 -14
- data/lib/sisimai/lhost/qmail.rb +44 -47
- data/lib/sisimai/lhost/receivingses.rb +15 -20
- data/lib/sisimai/lhost/sendgrid.rb +34 -32
- data/lib/sisimai/lhost/sendmail.rb +66 -53
- data/lib/sisimai/lhost/surfcontrol.rb +19 -19
- data/lib/sisimai/lhost/v5sendmail.rb +45 -39
- data/lib/sisimai/lhost/verizon.rb +35 -39
- data/lib/sisimai/lhost/x1.rb +18 -17
- data/lib/sisimai/lhost/x2.rb +17 -14
- data/lib/sisimai/lhost/x3.rb +19 -19
- data/lib/sisimai/lhost/x4.rb +72 -57
- data/lib/sisimai/lhost/x5.rb +17 -19
- data/lib/sisimai/lhost/x6.rb +41 -17
- data/lib/sisimai/lhost/yahoo.rb +17 -16
- data/lib/sisimai/lhost/yandex.rb +16 -20
- data/lib/sisimai/lhost/zoho.rb +16 -15
- data/lib/sisimai/lhost.rb +8 -10
- data/lib/sisimai/mail/maildir.rb +1 -3
- data/lib/sisimai/mail/mbox.rb +3 -4
- data/lib/sisimai/mail/memory.rb +0 -1
- data/lib/sisimai/mail/stdin.rb +1 -3
- data/lib/sisimai/mail.rb +3 -7
- data/lib/sisimai/mda.rb +28 -42
- data/lib/sisimai/message.rb +435 -326
- data/lib/sisimai/order.rb +5 -5
- data/lib/sisimai/reason/authfailure.rb +64 -0
- data/lib/sisimai/reason/badreputation.rb +53 -0
- data/lib/sisimai/reason/blocked.rb +94 -160
- data/lib/sisimai/reason/contenterror.rb +8 -9
- data/lib/sisimai/reason/delivered.rb +4 -6
- data/lib/sisimai/reason/exceedlimit.rb +10 -12
- data/lib/sisimai/reason/expired.rb +6 -8
- data/lib/sisimai/reason/feedback.rb +2 -3
- data/lib/sisimai/reason/filtered.rb +17 -19
- data/lib/sisimai/reason/hasmoved.rb +9 -10
- data/lib/sisimai/reason/hostunknown.rb +15 -15
- data/lib/sisimai/reason/mailboxfull.rb +10 -12
- data/lib/sisimai/reason/mailererror.rb +18 -20
- data/lib/sisimai/reason/mesgtoobig.rb +9 -11
- data/lib/sisimai/reason/networkerror.rb +5 -8
- data/lib/sisimai/reason/norelaying.rb +8 -11
- data/lib/sisimai/reason/notaccept.rb +13 -14
- data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
- data/lib/sisimai/reason/onhold.rb +6 -9
- data/lib/sisimai/reason/policyviolation.rb +14 -12
- data/lib/sisimai/reason/rejected.rb +26 -24
- data/lib/sisimai/reason/requireptr.rb +69 -0
- data/lib/sisimai/reason/securityerror.rb +33 -36
- data/lib/sisimai/reason/spamdetected.rb +114 -147
- data/lib/sisimai/reason/speeding.rb +49 -0
- data/lib/sisimai/reason/suspend.rb +11 -11
- data/lib/sisimai/reason/syntaxerror.rb +11 -10
- data/lib/sisimai/reason/systemerror.rb +7 -9
- data/lib/sisimai/reason/systemfull.rb +7 -8
- data/lib/sisimai/reason/toomanyconn.rb +9 -11
- data/lib/sisimai/reason/undefined.rb +2 -3
- data/lib/sisimai/reason/userunknown.rb +129 -146
- data/lib/sisimai/reason/vacation.rb +3 -4
- data/lib/sisimai/reason/virusdetected.rb +10 -11
- data/lib/sisimai/reason.rb +59 -64
- data/lib/sisimai/rfc1894.rb +55 -28
- data/lib/sisimai/rfc2045.rb +373 -0
- data/lib/sisimai/rfc3464.rb +250 -308
- data/lib/sisimai/rfc3834.rb +42 -45
- data/lib/sisimai/rfc5322.rb +75 -100
- data/lib/sisimai/rfc5965.rb +31 -0
- data/lib/sisimai/rhost/cox.rb +5 -6
- data/lib/sisimai/rhost/franceptt.rb +6 -8
- data/lib/sisimai/rhost/godaddy.rb +12 -12
- data/lib/sisimai/rhost/{googleapps.rb → google.rb} +80 -72
- data/lib/sisimai/rhost/iua.rb +9 -10
- data/lib/sisimai/rhost/kddi.rb +6 -8
- data/lib/sisimai/rhost/{exchangeonline.rb → microsoft.rb} +115 -114
- data/lib/sisimai/rhost/mimecast.rb +42 -40
- data/lib/sisimai/rhost/nttdocomo.rb +12 -12
- data/lib/sisimai/rhost/spectrum.rb +10 -12
- data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
- data/lib/sisimai/rhost.rb +23 -31
- data/lib/sisimai/smtp/command.rb +59 -0
- data/lib/sisimai/smtp/error.rb +4 -7
- data/lib/sisimai/smtp/reply.rb +161 -74
- data/lib/sisimai/smtp/status.rb +504 -393
- data/lib/sisimai/smtp/transcript.rb +124 -0
- data/lib/sisimai/smtp.rb +0 -1
- data/lib/sisimai/string.rb +74 -5
- data/lib/sisimai/time.rb +1 -2
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +35 -21
- data/set-of-emails/maildir/bsd/lhost-domino-02.eml +6 -3
- data/set-of-emails/maildir/bsd/lhost-googlegroups-15.eml +174 -0
- data/set-of-emails/maildir/bsd/lhost-gsuite-15.eml +229 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-75.eml +51 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-76.eml +101 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-77.eml +74 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-78.eml +91 -0
- data/set-of-emails/maildir/bsd/lhost-receivingses-08.eml +88 -0
- data/set-of-emails/maildir/bsd/rfc3464-43.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
- data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
- data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
- data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
- data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
- data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +41 -20
- data/.rspec +0 -2
- data/lib/sisimai/data/yaml.rb +0 -33
- data/lib/sisimai/data.rb +0 -411
- data/lib/sisimai/mime.rb +0 -456
- /data/set-of-emails/maildir/bsd/{rfc3464-41.eml → rfc3834-05.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-googleapps-01.eml → rhost-google-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-googleapps-02.eml → rhost-google-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-01.eml → rhost-microsoft-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-02.eml → rhost-microsoft-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-03.eml → rhost-microsoft-03.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-tencentqq-01.eml → rhost-tencent-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-tencentqq-02.eml → rhost-tencent-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-tencentqq-03.eml → rhost-tencent-03.eml} +0 -0
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::MailFoundry parses a bounce email which created by
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::MailFoundry parses a bounce email which created by MailFoundry. Methods in the
|
3
|
+
# module are called from only Sisimai::Message.
|
4
4
|
module MailFoundry
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/MailFoundry.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Content-Type: message/rfc822'].freeze
|
11
10
|
StartingOf = {
|
12
11
|
message: ['Unable to deliver message to:'],
|
13
12
|
error: ['Delivery failed for the following reason:'],
|
@@ -18,20 +17,20 @@ module Sisimai::Lhost
|
|
18
17
|
# @param [String] mbody Message body of a bounce email
|
19
18
|
# @return [Hash] Bounce data list and message/rfc822 part
|
20
19
|
# @return [Nil] it failed to parse or the arguments are missing
|
21
|
-
def
|
20
|
+
def inquire(mhead, mbody)
|
22
21
|
return nil unless mhead['subject'] == 'Message delivery has failed'
|
23
22
|
return nil unless mhead['received'].any? { |a| a.include?('(MAILFOUNDRY) id ') }
|
24
23
|
|
25
24
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
26
|
-
|
27
|
-
bodyslices =
|
25
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
26
|
+
bodyslices = emailparts[0].split("\n")
|
28
27
|
readcursor = 0 # (Integer) Points the current cursor position
|
29
28
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
30
29
|
v = nil
|
31
30
|
|
32
31
|
while e = bodyslices.shift do
|
33
|
-
# Read error messages and delivery status lines from the head of the email
|
34
|
-
#
|
32
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
33
|
+
# line of the beginning of the original message.
|
35
34
|
if readcursor == 0
|
36
35
|
# Beginning of the bounce message or delivery status part
|
37
36
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -46,14 +45,14 @@ module Sisimai::Lhost
|
|
46
45
|
# This has been a permanent failure. No further delivery attempts will be made.
|
47
46
|
v = dscontents[-1]
|
48
47
|
|
49
|
-
if
|
48
|
+
if e.start_with?('Unable to deliver message to: <') && e.index('@') > 1
|
50
49
|
# Unable to deliver message to: <kijitora@example.org>
|
51
50
|
if v['recipient']
|
52
51
|
# There are multiple recipient addresses in the message body.
|
53
52
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
54
53
|
v = dscontents[-1]
|
55
54
|
end
|
56
|
-
v['recipient'] =
|
55
|
+
v['recipient'] = e[e.index('<'), e.size]
|
57
56
|
recipients += 1
|
58
57
|
else
|
59
58
|
# Error message
|
@@ -74,7 +73,7 @@ module Sisimai::Lhost
|
|
74
73
|
return nil unless recipients > 0
|
75
74
|
|
76
75
|
dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
|
77
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
76
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
78
77
|
end
|
79
78
|
def description; return 'MailFoundry'; end
|
80
79
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::MailMarshalSMTP parses a bounce email which created
|
3
|
-
#
|
4
|
-
# the module are called from only Sisimai::Message.
|
2
|
+
# Sisimai::Lhost::MailMarshalSMTP parses a bounce email which created by Trustwave Secure Email
|
3
|
+
# Gateway: formerly MailMarshal SMTP. Methods in the module are called from only Sisimai::Message.
|
5
4
|
module MailMarshalSMTP
|
6
5
|
class << self
|
7
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/MailMarshalSMTP.pm
|
8
6
|
require 'sisimai/lhost'
|
9
7
|
|
10
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
9
|
+
Boundaries = ['+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++']
|
12
10
|
StartingOf = {
|
13
11
|
message: ['Your message:'],
|
14
12
|
error: ['Could not be delivered because of'],
|
@@ -20,26 +18,19 @@ module Sisimai::Lhost
|
|
20
18
|
# @param [String] mbody Message body of a bounce email
|
21
19
|
# @return [Hash] Bounce data list and message/rfc822 part
|
22
20
|
# @return [Nil] it failed to parse or the arguments are missing
|
23
|
-
def
|
21
|
+
def inquire(mhead, mbody)
|
24
22
|
return nil unless mhead['subject'].start_with?('Undeliverable Mail: "')
|
25
23
|
|
26
24
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
27
|
-
|
28
|
-
bodyslices =
|
25
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
26
|
+
bodyslices = emailparts[0].split("\n")
|
29
27
|
readcursor = 0 # (Integer) Points the current cursor position
|
30
28
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
31
29
|
endoferror = false # (Boolean) Flag for the end of error message
|
32
30
|
regularexp = nil
|
31
|
+
q = Sisimai::RFC2045.boundary(mhead['content-type'], 1); Boundaries << q if q
|
33
32
|
v = nil
|
34
33
|
|
35
|
-
boundary00 = Sisimai::MIME.boundary(mhead['content-type'], 1) || ''
|
36
|
-
regularexp = if boundary00.size > 0
|
37
|
-
# Convert to regular expression
|
38
|
-
Regexp.new('\A' << Regexp.escape(boundary00) << '\z')
|
39
|
-
else
|
40
|
-
regularexp = %r/\A[ \t]*[+]+[ \t]*\z/
|
41
|
-
end
|
42
|
-
|
43
34
|
while e = bodyslices.shift do
|
44
35
|
# Read error messages and delivery status lines from the head of the email
|
45
36
|
# to the previous line of the beginning of the original message.
|
@@ -61,7 +52,7 @@ module Sisimai::Lhost
|
|
61
52
|
# dummyuser@blabla.xxxxxxxxxxxx.com
|
62
53
|
v = dscontents[-1]
|
63
54
|
|
64
|
-
if
|
55
|
+
if e.start_with?(' ') && e.index('@') > 1
|
65
56
|
# The following recipients were affected:
|
66
57
|
# dummyuser@blabla.xxxxxxxxxxxx.com
|
67
58
|
if v['recipient']
|
@@ -69,7 +60,7 @@ module Sisimai::Lhost
|
|
69
60
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
70
61
|
v = dscontents[-1]
|
71
62
|
end
|
72
|
-
v['recipient'] =
|
63
|
+
v['recipient'] = e[4, e.size]
|
73
64
|
recipients += 1
|
74
65
|
else
|
75
66
|
# Get error message lines
|
@@ -93,24 +84,29 @@ module Sisimai::Lhost
|
|
93
84
|
# Reporting-MTA: <relay.xxxxxxxxxxxx.com>
|
94
85
|
# MessageName: <B549996730000.000000000001.0003.mml>
|
95
86
|
# Last-Attempt-Date: <16:21:07 seg, 22 Dezembro 2014>
|
96
|
-
|
87
|
+
p1 = e.index('<')
|
88
|
+
p2 = e.index('>')
|
89
|
+
if e.start_with?('Original Sender: ')
|
97
90
|
# Original Sender: <originalsender@example.com>
|
98
|
-
# Use this line instead of "From" header of the original
|
99
|
-
|
100
|
-
emailsteak[1] << ('From: ' << cv[1] << "\n")
|
91
|
+
# Use this line instead of "From" header of the original message.
|
92
|
+
emailparts[1] << ('From: ' << e[p1 + 1, p2 - p1 - 1] << "\n")
|
101
93
|
|
102
|
-
elsif
|
94
|
+
elsif e.start_with?('Sender-MTA: ')
|
103
95
|
# Sender-MTA: <10.11.12.13>
|
104
|
-
v['lhost'] =
|
96
|
+
v['lhost'] = e[p1 + 1, p2 - p1 - 1]
|
105
97
|
|
106
|
-
elsif
|
98
|
+
elsif e.start_with?('Reporting-MTA: ')
|
107
99
|
# Reporting-MTA: <relay.xxxxxxxxxxxx.com>
|
108
|
-
v['rhost'] =
|
100
|
+
v['rhost'] = e[p1 + 1, p2 - p1 - 1]
|
109
101
|
|
110
|
-
elsif
|
102
|
+
elsif e.include?(' From:') || e.include?(' Subject:')
|
111
103
|
# From: originalsender@example.com
|
112
104
|
# Subject: ...
|
113
|
-
|
105
|
+
p1 = e.index(' From:') || e.index(' Subject:')
|
106
|
+
p2 = e.index(':')
|
107
|
+
cf = e[p1 + 1, p2 - p1 - 1]
|
108
|
+
cv = Sisimai::String.sweep(e[p2 + 1, e.size])
|
109
|
+
emailparts[1] << sprintf("%s: %s\n", cf, cv)
|
114
110
|
end
|
115
111
|
end
|
116
112
|
end
|
@@ -118,7 +114,7 @@ module Sisimai::Lhost
|
|
118
114
|
return nil unless recipients > 0
|
119
115
|
|
120
116
|
dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
|
121
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
117
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
122
118
|
end
|
123
119
|
def description; return 'Trustwave Secure Email Gateway'; end
|
124
120
|
end
|
data/lib/sisimai/lhost/mailru.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::MailRu parses a bounce email which created by @mail.ru.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::MailRu parses a bounce email which created by @mail.ru. Methods in the module are
|
3
|
+
# called from only Sisimai::Message.
|
4
4
|
module MailRu
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/MailRu.pm
|
7
6
|
# Based on Sisimai::Lhost::Exim
|
8
7
|
require 'sisimai/lhost'
|
9
8
|
|
10
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
10
|
+
Boundaries = ['------ This is a copy of the message, including all the headers. ------'].freeze
|
12
11
|
StartingOf = { message: ['This message was created automatically by mail delivery software.'] }.freeze
|
13
12
|
ReCommands = [
|
14
13
|
%r/SMTP error from remote (?:mail server|mailer) after ([A-Za-z]{4})/,
|
@@ -50,30 +49,32 @@ module Sisimai::Lhost
|
|
50
49
|
# @param [String] mbody Message body of a bounce email
|
51
50
|
# @return [Hash] Bounce data list and message/rfc822 part
|
52
51
|
# @return [Nil] it failed to parse or the arguments are missing
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
52
|
+
def inquire(mhead, mbody)
|
53
|
+
mfrom = mhead['from'].downcase
|
54
|
+
msgid = mhead['message-id'] ? mhead['message-id'].downcase : ''
|
55
|
+
match = 0
|
56
|
+
match += 1 if mfrom.include?('mailer-daemon@') && mfrom.include?('mail.ru')
|
57
|
+
match += 1 if msgid.end_with?('.mail.ru>', 'smailru.net>')
|
58
|
+
match += 1 if [
|
59
|
+
'Delivery Status Notification',
|
60
|
+
'Mail delivery failed',
|
61
|
+
'Mail failure',
|
62
|
+
'Message frozen',
|
63
|
+
'Warning: message ',
|
64
|
+
'error(s) in forwarding or filtering'].any? { |a| mhead['subject'].include?(a) }
|
65
|
+
return nil unless match > 2
|
65
66
|
|
66
67
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
67
|
-
|
68
|
-
bodyslices =
|
68
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
69
|
+
bodyslices = emailparts[0].split("\n")
|
69
70
|
readcursor = 0 # (Integer) Points the current cursor position
|
70
71
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
71
72
|
localhost0 = '' # (String) Local MTA
|
72
73
|
v = nil
|
73
74
|
|
74
75
|
while e = bodyslices.shift do
|
75
|
-
# Read error messages and delivery status lines from the head of the email
|
76
|
-
#
|
76
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
77
|
+
# line of the beginning of the original message.
|
77
78
|
if readcursor == 0
|
78
79
|
# Beginning of the bounce message or delivery status part
|
79
80
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -102,14 +103,14 @@ module Sisimai::Lhost
|
|
102
103
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
103
104
|
v = dscontents[-1]
|
104
105
|
|
105
|
-
if
|
106
|
+
if e.start_with?(' ') && e.include?(' ') == false && e.index('@') > 1
|
106
107
|
# kijitora@example.jp
|
107
108
|
if v['recipient']
|
108
109
|
# There are multiple recipient addresses in the message body.
|
109
110
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
110
111
|
v = dscontents[-1]
|
111
112
|
end
|
112
|
-
v['recipient'] =
|
113
|
+
v['recipient'] = e[2, e.size]
|
113
114
|
recipients += 1
|
114
115
|
|
115
116
|
elsif dscontents.size == recipients
|
@@ -120,7 +121,7 @@ module Sisimai::Lhost
|
|
120
121
|
else
|
121
122
|
# Error message when email address above does not include '@'
|
122
123
|
# and domain part.
|
123
|
-
next unless e.start_with?(' '
|
124
|
+
next unless e.start_with?(' ')
|
124
125
|
v['alterrors'] ||= ''
|
125
126
|
v['alterrors'] << e + ' '
|
126
127
|
end
|
@@ -147,7 +148,9 @@ module Sisimai::Lhost
|
|
147
148
|
unless mhead['received'].empty?
|
148
149
|
# Get the name of local MTA
|
149
150
|
# Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
|
150
|
-
|
151
|
+
p1 = mhead['received'][-1].index('from ') || -1
|
152
|
+
p2 = mhead['received'][-1].index(' ', p1 + 5) || -1
|
153
|
+
localhost0 = mhead['received'][-1][p1 + 5, p2 - p1 - 5] if p1 > -1
|
151
154
|
end
|
152
155
|
|
153
156
|
dscontents.each do |e|
|
@@ -164,12 +167,15 @@ module Sisimai::Lhost
|
|
164
167
|
e.delete('alterrors')
|
165
168
|
end
|
166
169
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
167
|
-
e['diagnosis'].
|
170
|
+
p1 = e['diagnosis'].rindex('__') || -1
|
171
|
+
e['diagnosis'] = e['diagnosis'][0, p1 - 1] if p1 > 2
|
168
172
|
|
169
173
|
unless e['rhost']
|
170
174
|
# Get the remote host name
|
171
175
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
172
|
-
|
176
|
+
p1 = e['diagnosis'].index('host ') || -1
|
177
|
+
p2 = e['diagnosis'].index(' ', p1 + 5) || -1
|
178
|
+
e['rhost'] = e['diagnosis'][p1 + 5, p2 - p1 - 5] if p1 > -1
|
173
179
|
|
174
180
|
unless e['rhost']
|
175
181
|
# Get localhost and remote host name from Received header.
|
@@ -208,7 +214,7 @@ module Sisimai::Lhost
|
|
208
214
|
e['command'] ||= ''
|
209
215
|
end
|
210
216
|
|
211
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
217
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
212
218
|
end
|
213
219
|
def description; return '@mail.ru: https://mail.ru'; end
|
214
220
|
end
|
data/lib/sisimai/lhost/mcafee.rb
CHANGED
@@ -1,49 +1,39 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::McAfee parses a bounce email which created by McAfee
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::McAfee parses a bounce email which created by McAfee Email Appliance. Methods in
|
3
|
+
# the module are called from only Sisimai::Message.
|
4
4
|
module McAfee
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/McAfee.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Content-Type: message/rfc822'].freeze
|
11
10
|
StartingOf = { message: ['--- The following addresses had delivery problems ---'] }.freeze
|
12
|
-
|
13
|
-
'userunknown' => %r{(?:
|
14
|
-
[ ]User[ ][(].+[@].+[)][ ]unknown[.][ ]
|
15
|
-
|550[ ]Unknown[ ]user[ ][^ ]+[@][^ ]+
|
16
|
-
|550[ ][<].+?[@].+?[>][.]+[ ]User[ ]not[ ]exist
|
17
|
-
|No[ ]such[ ]user
|
18
|
-
)
|
19
|
-
}x,
|
20
|
-
}.freeze
|
11
|
+
MessagesOf = { 'userunknown' => [' User not exist', ' unknown.', '550 Unknown user ', 'No such user'] }.freeze
|
21
12
|
|
22
13
|
# Parse bounce messages from McAfee Email Appliance
|
23
14
|
# @param [Hash] mhead Message headers of a bounce email
|
24
15
|
# @param [String] mbody Message body of a bounce email
|
25
16
|
# @return [Hash] Bounce data list and message/rfc822 part
|
26
17
|
# @return [Nil] it failed to parse or the arguments are missing
|
27
|
-
def
|
18
|
+
def inquire(mhead, mbody)
|
28
19
|
# X-NAI-Header: Modified by McAfee Email and Web Security Virtual Appliance
|
29
20
|
return nil unless mhead['x-nai-header']
|
30
21
|
return nil unless mhead['x-nai-header'].start_with?('Modified by McAfee ')
|
31
22
|
return nil unless mhead['subject'] == 'Delivery Status'
|
32
23
|
|
33
|
-
require 'sisimai/rfc1894'
|
34
24
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
35
25
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
36
|
-
|
37
|
-
bodyslices =
|
26
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
27
|
+
bodyslices = emailparts[0].split("\n")
|
38
28
|
readslices = ['']
|
39
29
|
readcursor = 0 # (Integer) Points the current cursor position
|
40
30
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
41
|
-
|
31
|
+
issuedcode = '' # (String) Alternative diagnostic message
|
42
32
|
v = nil
|
43
33
|
|
44
34
|
while e = bodyslices.shift do
|
45
|
-
# Read error messages and delivery status lines from the head of the email
|
46
|
-
#
|
35
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
36
|
+
# line of the beginning of the original message.
|
47
37
|
readslices << e # Save the current line for the next loop
|
48
38
|
|
49
39
|
if readcursor == 0
|
@@ -65,15 +55,15 @@ module Sisimai::Lhost
|
|
65
55
|
#
|
66
56
|
v = dscontents[-1]
|
67
57
|
|
68
|
-
if
|
58
|
+
if Sisimai::String.aligned(e, ['<', '@', '>', '(', ')'])
|
69
59
|
# <kijitora@example.co.jp> (Unknown user kijitora@example.co.jp)
|
70
60
|
if v['recipient']
|
71
61
|
# There are multiple recipient addresses in the message body.
|
72
62
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
73
63
|
v = dscontents[-1]
|
74
64
|
end
|
75
|
-
v['recipient'] =
|
76
|
-
|
65
|
+
v['recipient'] = Sisimai::Address.s3s4(e[e.index('<'), e.index('>')])
|
66
|
+
issuedcode = e[e.index('(') + 1, e.size]
|
77
67
|
recipients += 1
|
78
68
|
|
79
69
|
elsif f = Sisimai::RFC1894.match(e)
|
@@ -82,8 +72,8 @@ module Sisimai::Lhost
|
|
82
72
|
unless o
|
83
73
|
# Fallback code for empty value or invalid formatted value
|
84
74
|
# - Original-Recipient: <kijitora@example.co.jp>
|
85
|
-
if
|
86
|
-
v['alias'] = Sisimai::Address.s3s4(
|
75
|
+
if e.start_with?('Original-Recipient: ')
|
76
|
+
v['alias'] = Sisimai::Address.s3s4(e[e.index(':') + 1, e.size])
|
87
77
|
end
|
88
78
|
next
|
89
79
|
end
|
@@ -93,24 +83,24 @@ module Sisimai::Lhost
|
|
93
83
|
else
|
94
84
|
# Continued line of the value of Diagnostic-Code field
|
95
85
|
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
96
|
-
next unless
|
97
|
-
v['diagnosis'] << ' ' <<
|
86
|
+
next unless e.start_with?(' ')
|
87
|
+
v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
|
98
88
|
readslices[-1] = 'Diagnostic-Code: ' << e
|
99
89
|
end
|
100
90
|
end
|
101
91
|
return nil unless recipients > 0
|
102
92
|
|
103
93
|
dscontents.each do |e|
|
104
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'] ||
|
105
|
-
|
94
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'] || issuedcode)
|
95
|
+
MessagesOf.each_key do |r|
|
106
96
|
# Verify each regular expression of session errors
|
107
|
-
next unless e['diagnosis']
|
97
|
+
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
108
98
|
e['reason'] = r
|
109
99
|
break
|
110
100
|
end
|
111
101
|
end
|
112
102
|
|
113
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
103
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
114
104
|
end
|
115
105
|
def description; return 'McAfee Email Appliance'; end
|
116
106
|
end
|
@@ -1,18 +1,16 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::MessageLabs parses a bounce email which created by
|
3
|
-
#
|
4
|
-
# from only Sisimai::Message.
|
2
|
+
# Sisimai::Lhost::MessageLabs parses a bounce email which created by Symantec.cloud: formerly MessageLabs.
|
3
|
+
# Methods in the module are called from only Sisimai::Message.
|
5
4
|
module MessageLabs
|
6
5
|
class << self
|
7
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/MessageLabs.pm
|
8
6
|
require 'sisimai/lhost'
|
9
7
|
|
10
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
9
|
+
Boundaries = ['Content-Type: text/rfc822-headers'].freeze
|
12
10
|
StartingOf = { message: ['Content-Type: message/delivery-status'] }.freeze
|
13
|
-
|
14
|
-
'userunknown' =>
|
15
|
-
'securityerror' =>
|
11
|
+
MessagesOf = {
|
12
|
+
'userunknown' => ['542 ', ' Rejected', 'No such user'],
|
13
|
+
'securityerror' => ['Please turn on SMTP Authentication in your mail client'],
|
16
14
|
}.freeze
|
17
15
|
|
18
16
|
# Parse bounce messages from Symantec.cloud(MessageLabs)
|
@@ -20,7 +18,7 @@ module Sisimai::Lhost
|
|
20
18
|
# @param [String] mbody Message body of a bounce email
|
21
19
|
# @return [Hash] Bounce data list and message/rfc822 part
|
22
20
|
# @return [Nil] it failed to parse or the arguments are missing
|
23
|
-
def
|
21
|
+
def inquire(mhead, mbody)
|
24
22
|
# X-Msg-Ref: server-11.tower-143.messagelabs.com!1419367175!36473369!1
|
25
23
|
# X-Originating-IP: [10.245.230.38]
|
26
24
|
# X-StarScan-Received:
|
@@ -30,13 +28,12 @@ module Sisimai::Lhost
|
|
30
28
|
return nil unless mhead['from'].include?('MAILER-DAEMON@messagelabs.com')
|
31
29
|
return nil unless mhead['subject'].start_with?('Mail Delivery Failure')
|
32
30
|
|
33
|
-
require 'sisimai/rfc1894'
|
34
31
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
35
32
|
permessage = {} # (Hash) Store values of each Per-Message field
|
36
33
|
|
37
34
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
38
|
-
|
39
|
-
bodyslices =
|
35
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
36
|
+
bodyslices = emailparts[0].split("\n")
|
40
37
|
readslices = ['']
|
41
38
|
readcursor = 0 # (Integer) Points the current cursor position
|
42
39
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
@@ -44,8 +41,8 @@ module Sisimai::Lhost
|
|
44
41
|
v = nil
|
45
42
|
|
46
43
|
while e = bodyslices.shift do
|
47
|
-
# Read error messages and delivery status lines from the head of the email
|
48
|
-
#
|
44
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
45
|
+
# line of the beginning of the original message.
|
49
46
|
readslices << e # Save the current line for the next loop
|
50
47
|
|
51
48
|
if readcursor == 0
|
@@ -86,14 +83,14 @@ module Sisimai::Lhost
|
|
86
83
|
next unless fieldtable[o[0]]
|
87
84
|
v[fieldtable[o[0]]] = o[2]
|
88
85
|
|
89
|
-
next unless f
|
86
|
+
next unless f
|
90
87
|
permessage[fieldtable[o[0]]] = o[2]
|
91
88
|
end
|
92
89
|
else
|
93
90
|
# Continued line of the value of Diagnostic-Code field
|
94
91
|
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
95
|
-
next unless
|
96
|
-
v['diagnosis'] << ' ' <<
|
92
|
+
next unless e.start_with?(' ')
|
93
|
+
v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
|
97
94
|
readslices[-1] = 'Diagnostic-Code: ' << e
|
98
95
|
end
|
99
96
|
end
|
@@ -106,15 +103,15 @@ module Sisimai::Lhost
|
|
106
103
|
e['command'] = commandset.shift || ''
|
107
104
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
108
105
|
|
109
|
-
|
106
|
+
MessagesOf.each_key do |r|
|
110
107
|
# Verify each regular expression of session errors
|
111
|
-
next unless e['diagnosis']
|
108
|
+
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
112
109
|
e['reason'] = r
|
113
110
|
break
|
114
111
|
end
|
115
112
|
end
|
116
113
|
|
117
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
114
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
118
115
|
end
|
119
116
|
def description; return 'Symantec.cloud http://www.messagelabs.com'; end
|
120
117
|
end
|