sisimai 4.25.17-java → 5.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +3 -3
- data/ANALYTICAL-PRECISION +2 -2
- data/Benchmarks.mk +3 -3
- data/CONTRIBUTING +1 -1
- data/ChangeLog.md +406 -407
- data/Developers.mk +5 -6
- data/Gemfile +1 -1
- data/Makefile +12 -12
- data/README-JA.md +142 -94
- data/README.md +282 -150
- 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 +20 -16
- 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 -325
- 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 +13 -18
- 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 +42 -23
- 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/mac/reported-from-nick4tech-san-01.eml +0 -6
- /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,14 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::MessagingServer parses a bounce email which created
|
3
|
-
#
|
4
|
-
# Server. Methods in the module are called from only Sisimai::Message.
|
2
|
+
# Sisimai::Lhost::MessagingServer parses a bounce email which created by Oracle Communications Messaging
|
3
|
+
# Server and Sun Java System Messaging Server. Methods in the module are called from only Sisimai::Message.
|
5
4
|
module MessagingServer
|
6
5
|
class << self
|
7
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/MessagingServer.pm
|
8
6
|
require 'sisimai/lhost'
|
9
7
|
|
10
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
9
|
+
Boundaries = ['Content-Type: message/rfc822', 'Return-path: '].freeze
|
12
10
|
StartingOf = { message: ['This report relates to a message you sent with the following header fields:'] }.freeze
|
13
11
|
MessagesOf = { 'hostunknown' => ['Illegal host/domain name found'] }.freeze
|
14
12
|
|
@@ -17,23 +15,22 @@ module Sisimai::Lhost
|
|
17
15
|
# @param [String] mbody Message body of a bounce email
|
18
16
|
# @return [Hash] Bounce data list and message/rfc822 part
|
19
17
|
# @return [Nil] it failed to parse or the arguments are missing
|
20
|
-
def
|
21
|
-
# :received => %r/[ ][(]MessagingServer[)][ ]with[ ]/,
|
18
|
+
def inquire(mhead, mbody)
|
22
19
|
match = 0
|
23
20
|
match += 1 if mhead['content-type'].include?('Boundary_(ID_')
|
24
21
|
match += 1 if mhead['subject'].start_with?('Delivery Notification: ')
|
25
22
|
return nil unless match > 0
|
26
23
|
|
27
24
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
28
|
-
|
29
|
-
bodyslices =
|
25
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
26
|
+
bodyslices = emailparts[0].split("\n")
|
30
27
|
readcursor = 0 # (Integer) Points the current cursor position
|
31
28
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
32
29
|
v = nil
|
33
30
|
|
34
31
|
while e = bodyslices.shift do
|
35
|
-
# Read error messages and delivery status lines from the head of the email
|
36
|
-
#
|
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.
|
37
34
|
if readcursor == 0
|
38
35
|
# Beginning of the bounce message or delivery status part
|
39
36
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -62,45 +59,49 @@ module Sisimai::Lhost
|
|
62
59
|
# Remote system: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25) (6jo.example.jp ESMTP SENDMAIL-VM)
|
63
60
|
v = dscontents[-1]
|
64
61
|
|
65
|
-
if
|
62
|
+
if e.start_with?(' Recipient address: ') && e.index('@') > 1
|
66
63
|
# Recipient address: kijitora@example.jp
|
67
64
|
if v['recipient']
|
68
65
|
# There are multiple recipient addresses in the message body.
|
69
66
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
70
67
|
v = dscontents[-1]
|
71
68
|
end
|
72
|
-
v['recipient'] = Sisimai::Address.s3s4(
|
69
|
+
v['recipient'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
|
73
70
|
recipients += 1
|
74
71
|
|
75
|
-
elsif
|
72
|
+
elsif e.start_with?(' Original address: ') && e.index('@') > 1
|
76
73
|
# Original address: kijitora@example.jp
|
77
|
-
v['recipient'] = Sisimai::Address.s3s4(
|
74
|
+
v['recipient'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
|
78
75
|
|
79
|
-
elsif
|
76
|
+
elsif e.start_with?(' Date: ')
|
80
77
|
# Date: Fri, 21 Nov 2014 23:34:45 +0900
|
81
|
-
v['date'] =
|
78
|
+
v['date'] = e[e.index(':') + 2, e.size]
|
82
79
|
|
83
|
-
elsif
|
80
|
+
elsif e.start_with?(' Reason: ')
|
84
81
|
# Reason: Remote SMTP server has rejected address
|
85
|
-
v['diagnosis'] =
|
82
|
+
v['diagnosis'] = e[e.index(':') + 2, e.size]
|
86
83
|
|
87
|
-
elsif
|
84
|
+
elsif e.start_with?(' Diagnostic code: ')
|
88
85
|
# Diagnostic code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
|
89
|
-
|
90
|
-
|
86
|
+
p1 = e.index(':')
|
87
|
+
p2 = e.index(';')
|
88
|
+
v['spec'] = e[p1 + 2, p2 - p1 - 2].upcase
|
89
|
+
v['diagnosis'] = e[p2 + 1, e.size]
|
91
90
|
|
92
|
-
elsif
|
91
|
+
elsif e.start_with?(' Remote system: ')
|
93
92
|
# Remote system: dns;mx.example.jp (TCP|17.111.174.67|47323|192.0.2.225|25)
|
94
93
|
# (6jo.example.jp ESMTP SENDMAIL-VM)
|
95
|
-
|
96
|
-
|
94
|
+
p1 = e.index(';')
|
95
|
+
p2 = e.index('(')
|
96
|
+
remotehost = e[p1 + 1, p2 - p1 - 2]
|
97
|
+
sessionlog = e[p2, e.size].split('|')
|
97
98
|
v['rhost'] = remotehost
|
98
99
|
|
99
100
|
# The value does not include ".", use IP address instead.
|
100
101
|
# (TCP|17.111.174.67|47323|192.0.2.225|25)
|
101
|
-
next unless
|
102
|
-
v['lhost'] =
|
103
|
-
v['rhost'] =
|
102
|
+
next unless sessionlog[0] == '(TCP'
|
103
|
+
v['lhost'] = sessionlog[1]
|
104
|
+
v['rhost'] = sessionlog[3] unless remotehost.index('.') > 1
|
104
105
|
else
|
105
106
|
# Original-envelope-id: 0NFC009FLKOUVMA0@mr21p30im-asmtp004.me.com
|
106
107
|
# Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
|
@@ -114,20 +115,22 @@ module Sisimai::Lhost
|
|
114
115
|
# (6jo.example.jp ESMTP SENDMAIL-VM)
|
115
116
|
# Diagnostic-code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
|
116
117
|
#
|
117
|
-
if
|
118
|
+
if e.start_with?('Status: ')
|
118
119
|
# Status: 5.1.1 (Remote SMTP server has rejected address)
|
119
|
-
|
120
|
-
|
120
|
+
p1 = e.index(':')
|
121
|
+
p2 = e.index('(')
|
122
|
+
v['status'] = e[p1 + 2, p2 - p1 - 3]
|
123
|
+
v['diagnosis'] ||= e[p2 + 1, e[e.index(')') - p2 - 1]]
|
121
124
|
|
122
|
-
elsif
|
125
|
+
elsif e.start_with?('Arrival-Date: ')
|
123
126
|
# Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT)
|
124
|
-
v['date'] ||=
|
127
|
+
v['date'] ||= e[e.index(':') + 2, e.size]
|
125
128
|
|
126
|
-
elsif
|
129
|
+
elsif e.start_with?('Reporting-MTA: ')
|
127
130
|
# Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
|
128
|
-
localhost =
|
131
|
+
localhost = e[e.index(';') + 1, e.size]
|
129
132
|
v['lhost'] ||= localhost
|
130
|
-
v['lhost'] = localhost unless v['lhost']
|
133
|
+
v['lhost'] = localhost unless v['lhost'].index('.') > 0
|
131
134
|
end
|
132
135
|
end
|
133
136
|
end
|
@@ -143,7 +146,7 @@ module Sisimai::Lhost
|
|
143
146
|
end
|
144
147
|
end
|
145
148
|
|
146
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
149
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
147
150
|
end
|
148
151
|
def description; return 'Oracle Communications Messaging Server'; end
|
149
152
|
end
|
@@ -1,44 +1,43 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::mFILTER parses a bounce email which created by
|
3
|
-
#
|
4
|
-
# Methods in the module are called from only Sisimai::Message.
|
2
|
+
# Sisimai::Lhost::mFILTER parses a bounce email which created by Digital Arts m-FILTER. Methods in
|
3
|
+
# the module are called from only Sisimai::Message.
|
5
4
|
module MFILTER
|
6
5
|
class << self
|
7
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/mFILTER.pm
|
8
6
|
require 'sisimai/lhost'
|
9
7
|
|
10
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
9
|
+
Boundaries = ['-------original message', '-------original mail info'].freeze
|
12
10
|
StartingOf = {
|
13
11
|
error: ['-------server message'],
|
14
12
|
command: ['-------SMTP command'],
|
15
13
|
}.freeze
|
16
|
-
MarkingsOf = { message: %r/\A[^ ]+[@][^ ]+[.][a-zA-Z]+\z/ }.freeze
|
17
14
|
|
18
15
|
# Parse bounce messages from Digital Arts m-FILTER
|
19
16
|
# @param [Hash] mhead Message headers of a bounce email
|
20
17
|
# @param [String] mbody Message body of a bounce email
|
21
18
|
# @return [Hash] Bounce data list and message/rfc822 part
|
22
19
|
# @return [Nil] it failed to parse or the arguments are missing
|
23
|
-
def
|
20
|
+
def inquire(mhead, mbody)
|
24
21
|
# X-Mailer: m-FILTER
|
25
22
|
return nil unless mhead['x-mailer'].to_s == 'm-FILTER'
|
26
23
|
return nil unless mhead['subject'] == 'failure notice'
|
27
24
|
|
28
25
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
29
|
-
|
30
|
-
bodyslices =
|
26
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
27
|
+
bodyslices = emailparts[0].split("\n")
|
31
28
|
readcursor = 0 # (Integer) Points the current cursor position
|
32
29
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
33
30
|
markingset = { 'diagnosis' => false, 'command' => false }
|
34
31
|
v = nil
|
35
32
|
|
36
33
|
while e = bodyslices.shift do
|
37
|
-
# Read error messages and delivery status lines from the head of the email
|
38
|
-
#
|
34
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
35
|
+
# line of the beginning of the original message.
|
39
36
|
if readcursor == 0
|
40
37
|
# Beginning of the bounce message or delivery status part
|
41
|
-
|
38
|
+
if e.include?('@') && e.include?(' ') == false && Sisimai::Address.is_emailaddress(e)
|
39
|
+
readcursor |= Indicators[:deliverystatus]
|
40
|
+
end
|
42
41
|
end
|
43
42
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
44
43
|
next if e.empty?
|
@@ -60,7 +59,7 @@ module Sisimai::Lhost
|
|
60
59
|
# -------original message
|
61
60
|
v = dscontents[-1]
|
62
61
|
|
63
|
-
if
|
62
|
+
if e.include?('@') && e.include?(' ') == false
|
64
63
|
# 以下のメールアドレスへの送信に失敗しました。
|
65
64
|
# kijitora@example.jp
|
66
65
|
if v['recipient']
|
@@ -68,10 +67,10 @@ module Sisimai::Lhost
|
|
68
67
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
69
68
|
v = dscontents[-1]
|
70
69
|
end
|
71
|
-
v['recipient'] =
|
70
|
+
v['recipient'] = e
|
72
71
|
recipients += 1
|
73
72
|
|
74
|
-
elsif e
|
73
|
+
elsif e.size == 4 && e.index(' ').nil?
|
75
74
|
# -------SMTP command
|
76
75
|
# DATA
|
77
76
|
next if v['command']
|
@@ -111,7 +110,7 @@ module Sisimai::Lhost
|
|
111
110
|
e['rhost'] = ee
|
112
111
|
end
|
113
112
|
end
|
114
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
113
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
115
114
|
end
|
116
115
|
def description; return 'Digital Arts m-FILTER'; end
|
117
116
|
end
|
@@ -1,22 +1,20 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::MXLogic parses a bounce email which created by
|
3
|
-
# McAfee SaaS (formerly MX Logic).
|
2
|
+
# Sisimai::Lhost::MXLogic parses a bounce email which created by McAfee SaaS (formerly MX Logic).
|
4
3
|
# Methods in the module are called from only Sisimai::Message.
|
5
4
|
module MXLogic
|
6
5
|
class << self
|
7
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/MXLogic.pm
|
8
6
|
# Based on Sisimai::Lhost::Exim
|
9
7
|
require 'sisimai/lhost'
|
10
8
|
|
11
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
12
|
-
|
10
|
+
Boundaries = ['Included is a copy of the message header:'].freeze
|
13
11
|
StartingOf = { message: ['This message was created automatically by mail delivery software.'] }.freeze
|
14
12
|
ReCommands = [
|
15
13
|
%r/SMTP error from remote (?:mail server|mailer) after ([A-Za-z]{4})/,
|
16
14
|
%r/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,
|
17
15
|
].freeze
|
18
16
|
MessagesOf = {
|
19
|
-
# find exim/ -type f -exec grep 'message = US' {} /dev/null \;
|
17
|
+
# % find exim/ -type f -exec grep 'message = US' {} /dev/null \;
|
20
18
|
# route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
|
21
19
|
'userunknown' => ['user not found'],
|
22
20
|
# transports/smtp.c:3524| addr->message = US"all host address lookups failed permanently";
|
@@ -74,7 +72,7 @@ module Sisimai::Lhost
|
|
74
72
|
# @param [String] mbody Message body of a bounce email
|
75
73
|
# @return [Hash] Bounce data list and message/rfc822 part
|
76
74
|
# @return [Nil] it failed to parse or the arguments are missing
|
77
|
-
def
|
75
|
+
def inquire(mhead, mbody)
|
78
76
|
# X-MX-Bounce: mta/src/queue/bounce
|
79
77
|
# X-MXL-NoteHash: ffffffffffffffff-0000000000000000000000000000000000000000
|
80
78
|
# X-MXL-Hash: 4c9d4d411993da17-bbd4212b6c887f6c23bab7db4bd87ef5edc00758
|
@@ -83,25 +81,20 @@ module Sisimai::Lhost
|
|
83
81
|
match += 1 if mhead['x-mxl-hash']
|
84
82
|
match += 1 if mhead['x-mxl-notehash']
|
85
83
|
match += 1 if mhead['from'].start_with?('Mail Delivery System')
|
86
|
-
match += 1 if mhead['subject']
|
87
|
-
Mail[ ]delivery[ ]failed(:[ ]returning[ ]message[ ]to[ ]sender)?
|
88
|
-
|Warning:[ ]message[ ][^ ]+[ ]delayed[ ]+
|
89
|
-
|Delivery[ ]Status[ ]Notification
|
90
|
-
)
|
91
|
-
}x
|
84
|
+
match += 1 if ['Delivery Status Notification', 'Mail delivery failed', 'Warning: message '].any? { |a| mhead['subject'].include?(a) }
|
92
85
|
return nil unless match > 0
|
93
86
|
|
94
87
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
95
|
-
|
96
|
-
bodyslices =
|
88
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
89
|
+
bodyslices = emailparts[0].split("\n")
|
97
90
|
readcursor = 0 # (Integer) Points the current cursor position
|
98
91
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
99
92
|
localhost0 = '' # (String) Local MTA
|
100
93
|
v = nil
|
101
94
|
|
102
95
|
while e = bodyslices.shift do
|
103
|
-
# Read error messages and delivery status lines from the head of the email
|
104
|
-
#
|
96
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
97
|
+
# line of the beginning of the original message.
|
105
98
|
if readcursor == 0
|
106
99
|
# Beginning of the bounce message or delivery status part
|
107
100
|
readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
|
@@ -120,7 +113,7 @@ module Sisimai::Lhost
|
|
120
113
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
121
114
|
v = dscontents[-1]
|
122
115
|
|
123
|
-
if
|
116
|
+
if e.start_with?(' <') && e.include?('@') && e.include?('>:')
|
124
117
|
# A message that you have sent could not be delivered to one or more
|
125
118
|
# recipients. This is a permanent error. The following address failed:
|
126
119
|
#
|
@@ -130,8 +123,8 @@ module Sisimai::Lhost
|
|
130
123
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
131
124
|
v = dscontents[-1]
|
132
125
|
end
|
133
|
-
v['recipient'] =
|
134
|
-
v['diagnosis'] =
|
126
|
+
v['recipient'] = e[3, e.index('>:') - 3]
|
127
|
+
v['diagnosis'] = e[e.index('>:') + 3, e.size]
|
135
128
|
recipients += 1
|
136
129
|
|
137
130
|
elsif dscontents.size == recipients
|
@@ -144,8 +137,13 @@ module Sisimai::Lhost
|
|
144
137
|
|
145
138
|
unless mhead['received'].empty?
|
146
139
|
# Get the name of local MTA
|
147
|
-
|
148
|
-
|
140
|
+
p1 = mhead['received'][-1].downcase.index('from ')
|
141
|
+
p2 = mhead['received'][-1].index(' ', p1 + 5)
|
142
|
+
|
143
|
+
if (p1 + 1) * (p2 + 1) > 0
|
144
|
+
# Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
|
145
|
+
localhost0 = mhead['received'][-1][p1 + 5, p2 - p1 - 5]
|
146
|
+
end
|
149
147
|
end
|
150
148
|
|
151
149
|
dscontents.each do |e|
|
@@ -154,8 +152,11 @@ module Sisimai::Lhost
|
|
154
152
|
|
155
153
|
unless e['rhost']
|
156
154
|
# Get the remote host name
|
155
|
+
p1 = e['diagnosis'].index('host ') || -1
|
156
|
+
p2 = e['diagnosis'].index(' ', p1 + 5)
|
157
|
+
|
157
158
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
158
|
-
|
159
|
+
e['rhost'] = e['diagnosis'][p1 + 5, p2 - p1 - 5] if p1 > -1
|
159
160
|
|
160
161
|
unless e['rhost']
|
161
162
|
# Get localhost and remote host name from Received header.
|
@@ -198,7 +199,7 @@ module Sisimai::Lhost
|
|
198
199
|
end
|
199
200
|
end
|
200
201
|
|
201
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
202
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
202
203
|
end
|
203
204
|
def description; return 'McAfee SaaS'; end
|
204
205
|
end
|
data/lib/sisimai/lhost/notes.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Notes parses a bounce email which created by Lotus
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Notes parses a bounce email which created by Lotus Notes Server. Methods in the
|
3
|
+
# module are called from only Sisimai::Message.
|
4
4
|
module Notes
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Notes.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['------- Returned Message --------'].freeze
|
11
10
|
StartingOf = { message: ['------- Failure Reasons '] }.freeze
|
12
11
|
MessagesOf = {
|
13
12
|
'userunknown' => [
|
@@ -22,12 +21,12 @@ module Sisimai::Lhost
|
|
22
21
|
# @param [String] mbody Message body of a bounce email
|
23
22
|
# @return [Hash] Bounce data list and message/rfc822 part
|
24
23
|
# @return [Nil] it failed to parse or the arguments are missing
|
25
|
-
def
|
24
|
+
def inquire(mhead, mbody)
|
26
25
|
return nil unless mhead['subject'].start_with?('Undeliverable message')
|
27
26
|
|
28
27
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
29
|
-
|
30
|
-
bodyslices =
|
28
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
29
|
+
bodyslices = emailparts[0].split("\n")
|
31
30
|
readcursor = 0 # (Integer) Points the current cursor position
|
32
31
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
33
32
|
characters = '' # (String) Character set name of the bounce mail
|
@@ -35,15 +34,14 @@ module Sisimai::Lhost
|
|
35
34
|
encodedmsg = ''
|
36
35
|
v = nil
|
37
36
|
|
38
|
-
if
|
39
|
-
# Get character set name
|
40
|
-
|
41
|
-
characters = cv[1].downcase
|
37
|
+
if mhead['content-type'].include?('charset=')
|
38
|
+
# Get character set name, Content-Type: text/plain; charset=ISO-2022-JP
|
39
|
+
characters = mhead['content-type'][mhead['content-type'].index('charset=') + 8, mhead['content-type'].size].downcase
|
42
40
|
end
|
43
41
|
|
44
42
|
while e = bodyslices.shift do
|
45
|
-
# Read error messages and delivery status lines from the head of the email
|
46
|
-
#
|
43
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
44
|
+
# line of the beginning of the original message.
|
47
45
|
if readcursor == 0
|
48
46
|
# Beginning of the bounce message or delivery status part
|
49
47
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -58,7 +56,7 @@ module Sisimai::Lhost
|
|
58
56
|
#
|
59
57
|
# ------- Returned Message --------
|
60
58
|
v = dscontents[-1]
|
61
|
-
if e
|
59
|
+
if e.include?('@') && e.index(' ').nil?
|
62
60
|
# kijitora@notes.example.jp
|
63
61
|
if v['recipient']
|
64
62
|
# There are multiple recipient addresses in the message body.
|
@@ -97,8 +95,10 @@ module Sisimai::Lhost
|
|
97
95
|
|
98
96
|
unless recipients > 0
|
99
97
|
# Fallback: Get the recpient address from RFC822 part
|
100
|
-
|
101
|
-
|
98
|
+
p1 = emailparts[1].index("\nTo: ") || -1
|
99
|
+
p2 = emailparts[1].index("\n", p1 + 6) || -1
|
100
|
+
if p1 > 0
|
101
|
+
v['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1 + 5, p2 - p1 - 5]) || ''
|
102
102
|
recipients += 1 unless v['recipient'].empty?
|
103
103
|
end
|
104
104
|
end
|
@@ -117,7 +117,7 @@ module Sisimai::Lhost
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
120
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
121
121
|
end
|
122
122
|
def description; return 'Lotus Notes'; end
|
123
123
|
end
|
@@ -1,25 +1,44 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Office365 parses a bounce email which created by
|
3
|
-
#
|
4
|
-
# Methods in the module are called from only Sisimai::Message.
|
2
|
+
# Sisimai::Lhost::Office365 parses a bounce email which created by Microsoft Office 365. Methods in
|
3
|
+
# the module are called from only Sisimai::Message.
|
5
4
|
module Office365
|
6
5
|
class << self
|
7
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Office365.pm
|
8
6
|
require 'sisimai/lhost'
|
9
7
|
|
10
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
9
|
+
Boundaries = ['Content-Type: message/rfc822', 'Original message headers:'].freeze
|
12
10
|
StartingOf = {
|
13
11
|
error: ['Diagnostic information for administrators:'],
|
14
12
|
eoerr: ['Original message headers:'],
|
15
13
|
}.freeze
|
16
14
|
MarkingsOf = {
|
17
|
-
eoe: %r
|
18
|
-
|
15
|
+
eoe: %r{\A(?:
|
16
|
+
Original[ ][Mm]essage[ ][Hh]eaders:?
|
17
|
+
|Message[ ]Hops
|
18
|
+
|Cabe.+alhos[ ]originais[ ]da[ ]mensagem:
|
19
|
+
|Oorspronkelijke[ ]berichtkoppen:
|
20
|
+
)
|
21
|
+
}x,
|
22
|
+
rfc3464: %r|\AContent-Type:[ ]message/delivery-status|,
|
23
|
+
lhost: %r{\A(?:
|
24
|
+
Generating[ ]server
|
25
|
+
|Bronserver
|
26
|
+
|Servidor[ ]de[ ]origem
|
27
|
+
):[ ](.+)\z
|
28
|
+
}x,
|
29
|
+
error: %r{\A(?:
|
30
|
+
Diagnostic[ ]information[ ]for[ ]administrators:
|
31
|
+
|Error[ ]Details
|
32
|
+
|Diagnostische[ ]gegevens[ ]voor[ ]beheerders:
|
33
|
+
|Informa.+es[ ]de[ ]diagn.+stico[ ]para[ ]administradores:
|
34
|
+
)
|
35
|
+
}x,
|
19
36
|
message: %r{\A(?:
|
20
37
|
Delivery[ ]has[ ]failed[ ]to[ ]these[ ]recipients[ ]or[ ]groups:
|
21
38
|
|Original[ ]Message[ ]Details
|
22
39
|
|.+[ ]rejected[ ]your[ ]message[ ]to[ ]the[ ]following[ ]e[-]?mail[ ]addresses:
|
40
|
+
|Falha[ ]na[ ]entrega[ ]a[ ]estes[ ]destinat.+rios[ ]ou[ ]grupos:
|
41
|
+
|Uw[ ]bericht[ ]kan[ ]niet[ ]worden[ ]bezorgd[ ]bij[ ]de[ ]volgende[ ]geadresseerden[ ]of[ ]groepen:
|
23
42
|
)
|
24
43
|
}x,
|
25
44
|
}.freeze
|
@@ -37,7 +56,7 @@ module Sisimai::Lhost
|
|
37
56
|
%r/\A4[.]4[.]7\z/ => 'expired',
|
38
57
|
%r/\A4[.]4[.]312\z/ => 'networkerror',
|
39
58
|
%r/\A4[.]4[.]316\z/ => 'expired',
|
40
|
-
%r/\A4[.]7[.]26\z/ => '
|
59
|
+
%r/\A4[.]7[.]26\z/ => 'authfailure',
|
41
60
|
%r/\A4[.]7[.][56]\d\d\z/ => 'blocked',
|
42
61
|
%r/\A4[.]7[.]8[5-9]\d\z/ => 'blocked',
|
43
62
|
%r/\A5[.]0[.]350\z/ => 'contenterror',
|
@@ -57,10 +76,10 @@ module Sisimai::Lhost
|
|
57
76
|
%r/\A5[.]7[.]50[4-5]\z/ => 'filtered',
|
58
77
|
%r/\A5[.]7[.]50[6-7]\z/ => 'blocked',
|
59
78
|
%r/\A5[.]7[.]508\z/ => 'toomanyconn',
|
60
|
-
%r/\A5[.]7[.]509\z/ => '
|
79
|
+
%r/\A5[.]7[.]509\z/ => 'authfailure',
|
61
80
|
%r/\A5[.]7[.]510\z/ => 'notaccept',
|
62
81
|
%r/\A5[.]7[.]511\z/ => 'rejected',
|
63
|
-
%r/\A5[.]7[.]512\z/ => '
|
82
|
+
%r/\A5[.]7[.]512\z/ => 'authfailure',
|
64
83
|
%r/\A5[.]7[.]57\z/ => 'securityerror',
|
65
84
|
%r/\A5[.]7[.]60[6-9]\z/ => 'blocked',
|
66
85
|
%r/\A5[.]7[.]6[1-4]\d\z/ => 'blocked',
|
@@ -75,7 +94,7 @@ module Sisimai::Lhost
|
|
75
94
|
# @param [String] mbody Message body of a bounce email
|
76
95
|
# @return [Hash] Bounce data list and message/rfc822 part
|
77
96
|
# @return [Nil] it failed to parse or the arguments are missing
|
78
|
-
def
|
97
|
+
def inquire(mhead, mbody)
|
79
98
|
# X-MS-Exchange-Message-Is-Ndr:
|
80
99
|
# X-Microsoft-Antispam-PRVS: <....@...outlook.com>
|
81
100
|
# X-Exchange-Antispam-Report-Test: UriScan:;
|
@@ -86,6 +105,9 @@ module Sisimai::Lhost
|
|
86
105
|
tryto = %r/.+[.](?:outbound[.]protection|prod)[.]outlook[.]com\b/
|
87
106
|
match = 0
|
88
107
|
match += 1 if mhead['subject'].include?('Undeliverable:')
|
108
|
+
match += 1 if mhead['subject'].include?('Onbestelbaar:')
|
109
|
+
match += 1 if mhead['subject'].include?('Não_entregue:')
|
110
|
+
|
89
111
|
Headers365.each do |e|
|
90
112
|
next if mhead[e].nil?
|
91
113
|
next if mhead[e].empty?
|
@@ -102,8 +124,8 @@ module Sisimai::Lhost
|
|
102
124
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
103
125
|
permessage = {} # (Hash) Store values of each Per-Message field
|
104
126
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
105
|
-
|
106
|
-
bodyslices =
|
127
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
128
|
+
bodyslices = emailparts[0].split("\n")
|
107
129
|
readcursor = 0 # (Integer) Points the current cursor position
|
108
130
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
109
131
|
connheader = {}
|
@@ -112,8 +134,8 @@ module Sisimai::Lhost
|
|
112
134
|
v = nil
|
113
135
|
|
114
136
|
while e = bodyslices.shift do
|
115
|
-
# Read error messages and delivery status lines from the head of the email
|
116
|
-
#
|
137
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
138
|
+
# line of the beginning of the original message.
|
117
139
|
if readcursor == 0
|
118
140
|
# Beginning of the bounce message or delivery status part
|
119
141
|
readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
|
@@ -145,7 +167,7 @@ module Sisimai::Lhost
|
|
145
167
|
v['recipient'] = cv[1]
|
146
168
|
recipients += 1
|
147
169
|
|
148
|
-
elsif cv = e.match(
|
170
|
+
elsif cv = e.match(MarkingsOf[:lhost])
|
149
171
|
# Generating server: FFFFFFFFFFFF.e0.prod.outlook.com
|
150
172
|
connheader['lhost'] = cv[1].downcase
|
151
173
|
else
|
@@ -154,11 +176,20 @@ module Sisimai::Lhost
|
|
154
176
|
next unless f = Sisimai::RFC1894.match(e)
|
155
177
|
next unless o = Sisimai::RFC1894.field(e)
|
156
178
|
next unless fieldtable[o[0]]
|
157
|
-
next if o[0] =~ /\A(?:diagnostic-code|final-recipient)\z/
|
158
|
-
v[fieldtable[o[0]]] = o[2]
|
159
179
|
|
160
|
-
|
161
|
-
|
180
|
+
if v['diagnosis']
|
181
|
+
# Do not capture "Diagnostic-Code:" field because error message have already
|
182
|
+
# been captured
|
183
|
+
next if o[0] =~ /\A(?:diagnostic-code|final-recipient)\z/
|
184
|
+
v[fieldtable[o[0]]] = o[2]
|
185
|
+
|
186
|
+
next unless f
|
187
|
+
permessage[fieldtable[o[0]]] = o[2]
|
188
|
+
else
|
189
|
+
# Capture "Diagnostic-Code:" field because no error messages have been captured
|
190
|
+
v[fieldtable[o[0]]] = o[2]
|
191
|
+
permessage[fieldtable[o[0]]] = o[2]
|
192
|
+
end
|
162
193
|
else
|
163
194
|
if e =~ MarkingsOf[:error]
|
164
195
|
# Diagnostic information for administrators:
|
@@ -167,13 +198,18 @@ module Sisimai::Lhost
|
|
167
198
|
# kijitora@example.com
|
168
199
|
# Remote Server returned '550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipien=
|
169
200
|
# t not found by SMTP address lookup'
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
201
|
+
if v['diagnosis']
|
202
|
+
# The error message text have already captured
|
203
|
+
if e =~ MarkingsOf[:eoe]
|
204
|
+
# Original message headers:
|
205
|
+
endoferror = true
|
206
|
+
next
|
207
|
+
end
|
208
|
+
v['diagnosis'] << ' ' << e
|
209
|
+
else
|
210
|
+
# The error message text has not been captured yet
|
211
|
+
endoferror = true if e =~ MarkingsOf[:rfc3464]
|
175
212
|
end
|
176
|
-
v['diagnosis'] << ' ' << e
|
177
213
|
end
|
178
214
|
end
|
179
215
|
end
|
@@ -207,7 +243,7 @@ module Sisimai::Lhost
|
|
207
243
|
end
|
208
244
|
end
|
209
245
|
|
210
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
246
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
211
247
|
end
|
212
248
|
def description; return 'Microsoft Office 365: https://office.microsoft.com/'; end
|
213
249
|
end
|