sisimai 4.25.16-java → 5.0.2-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/rake-test.yml +55 -0
- data/.travis.yml +3 -3
- data/ANALYTICAL-PRECISION +2 -2
- data/Benchmarks.mk +3 -3
- data/CONTRIBUTING +1 -1
- data/ChangeLog.md +451 -393
- data/Developers.mk +5 -6
- data/Gemfile +1 -1
- data/Makefile +15 -15
- data/README-JA.md +323 -149
- data/README.md +319 -149
- 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 +506 -0
- data/lib/sisimai/lhost/activehunter.rb +12 -14
- data/lib/sisimai/lhost/amavis.rb +11 -14
- data/lib/sisimai/lhost/amazonses.rb +37 -42
- data/lib/sisimai/lhost/amazonworkmail.rb +15 -19
- data/lib/sisimai/lhost/aol.rb +12 -15
- data/lib/sisimai/lhost/apachejames.rb +19 -21
- data/lib/sisimai/lhost/barracuda.rb +10 -12
- data/lib/sisimai/lhost/bigfoot.rb +21 -22
- data/lib/sisimai/lhost/biglobe.rb +15 -16
- data/lib/sisimai/lhost/courier.rb +20 -20
- data/lib/sisimai/lhost/domino.rb +23 -20
- 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 +179 -174
- data/lib/sisimai/lhost/ezweb.rb +31 -56
- data/lib/sisimai/lhost/facebook.rb +21 -34
- 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 +11 -11
- data/lib/sisimai/lhost/gsuite.rb +21 -28
- 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 +37 -40
- data/lib/sisimai/lhost/mcafee.rb +21 -31
- data/lib/sisimai/lhost/messagelabs.rb +17 -21
- data/lib/sisimai/lhost/messagingserver.rb +40 -37
- data/lib/sisimai/lhost/mfilter.rb +16 -17
- data/lib/sisimai/lhost/mxlogic.rb +24 -33
- data/lib/sisimai/lhost/notes.rb +17 -17
- data/lib/sisimai/lhost/office365.rb +64 -28
- data/lib/sisimai/lhost/opensmtpd.rb +12 -13
- data/lib/sisimai/lhost/outlook.rb +12 -16
- data/lib/sisimai/lhost/postfix.rb +179 -130
- data/lib/sisimai/lhost/powermta.rb +12 -14
- data/lib/sisimai/lhost/qmail.rb +44 -47
- data/lib/sisimai/lhost/receivingses.rb +15 -21
- data/lib/sisimai/lhost/sendgrid.rb +34 -34
- data/lib/sisimai/lhost/sendmail.rb +65 -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 -21
- 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 +444 -326
- data/lib/sisimai/order.rb +5 -5
- data/lib/sisimai/reason/authfailure.rb +65 -0
- data/lib/sisimai/reason/badreputation.rb +53 -0
- data/lib/sisimai/reason/blocked.rb +96 -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 +7 -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 +11 -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 +34 -36
- data/lib/sisimai/reason/spamdetected.rb +115 -147
- data/lib/sisimai/reason/speeding.rb +49 -0
- data/lib/sisimai/reason/suspend.rb +12 -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 +177 -146
- 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/google.rb +530 -0
- 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 +51 -42
- 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 +507 -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 +46 -31
- 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/lhost-sendmail-60.eml +85 -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 +48 -26
- 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/lib/sisimai/rhost/googleapps.rb +0 -261
- /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,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
|
@@ -101,20 +98,19 @@ module Sisimai::Lhost
|
|
101
98
|
|
102
99
|
dscontents.each do |e|
|
103
100
|
# Set default values if each value is empty.
|
104
|
-
e['lhost'] ||= permessage['rhost']
|
105
101
|
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
106
102
|
e['command'] = commandset.shift || ''
|
107
103
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
108
104
|
|
109
|
-
|
105
|
+
MessagesOf.each_key do |r|
|
110
106
|
# Verify each regular expression of session errors
|
111
|
-
next unless e['diagnosis']
|
107
|
+
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
112
108
|
e['reason'] = r
|
113
109
|
break
|
114
110
|
end
|
115
111
|
end
|
116
112
|
|
117
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
113
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
118
114
|
end
|
119
115
|
def description; return 'Symantec.cloud http://www.messagelabs.com'; end
|
120
116
|
end
|
@@ -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']
|
@@ -105,13 +104,13 @@ module Sisimai::Lhost
|
|
105
104
|
rhosts = Sisimai::RFC5322.received(rheads[-1])
|
106
105
|
|
107
106
|
e['lhost'] ||= Sisimai::RFC5322.received(rheads[0]).shift
|
108
|
-
|
107
|
+
[rhosts[0], rhosts[1]].each do |ee|
|
109
108
|
# Avoid "... by m-FILTER"
|
110
109
|
next unless ee.include?('.')
|
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,19 @@ 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
|
-
localhost0 = '' # (String) Local MTA
|
100
92
|
v = nil
|
101
93
|
|
102
94
|
while e = bodyslices.shift do
|
103
|
-
# Read error messages and delivery status lines from the head of the email
|
104
|
-
#
|
95
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
96
|
+
# line of the beginning of the original message.
|
105
97
|
if readcursor == 0
|
106
98
|
# Beginning of the bounce message or delivery status part
|
107
99
|
readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
|
@@ -120,7 +112,7 @@ module Sisimai::Lhost
|
|
120
112
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
121
113
|
v = dscontents[-1]
|
122
114
|
|
123
|
-
if
|
115
|
+
if e.start_with?(' <') && e.include?('@') && e.include?('>:')
|
124
116
|
# A message that you have sent could not be delivered to one or more
|
125
117
|
# recipients. This is a permanent error. The following address failed:
|
126
118
|
#
|
@@ -130,8 +122,8 @@ module Sisimai::Lhost
|
|
130
122
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
131
123
|
v = dscontents[-1]
|
132
124
|
end
|
133
|
-
v['recipient'] =
|
134
|
-
v['diagnosis'] =
|
125
|
+
v['recipient'] = e[3, e.index('>:') - 3]
|
126
|
+
v['diagnosis'] = e[e.index('>:') + 3, e.size]
|
135
127
|
recipients += 1
|
136
128
|
|
137
129
|
elsif dscontents.size == recipients
|
@@ -142,25 +134,24 @@ module Sisimai::Lhost
|
|
142
134
|
end
|
143
135
|
return nil unless recipients > 0
|
144
136
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
end
|
137
|
+
# Get the name of the local MTA
|
138
|
+
# Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
|
139
|
+
receivedby = mhead['received'] || []
|
140
|
+
recvdtoken = Sisimai::RFC5322.received(receivedby[-1])
|
150
141
|
|
151
142
|
dscontents.each do |e|
|
152
|
-
|
143
|
+
# Check the error message, the rhost, the lhost, and the smtp command.
|
144
|
+
e['lhost'] = recvdtoken[0]
|
153
145
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].gsub(/[-]{2}.*\z/, ''))
|
154
146
|
|
155
147
|
unless e['rhost']
|
156
148
|
# Get the remote host name
|
157
|
-
|
158
|
-
|
149
|
+
p1 = e['diagnosis'].index('host ') || -1
|
150
|
+
p2 = e['diagnosis'].index(' ', p1 + 5)
|
159
151
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
end
|
152
|
+
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
153
|
+
e['rhost'] = e['diagnosis'][p1 + 5, p2 - p1 - 5] if p1 > -1
|
154
|
+
e['rhost'] ||= recvdtoken[1]
|
164
155
|
end
|
165
156
|
|
166
157
|
unless e['command']
|
@@ -198,7 +189,7 @@ module Sisimai::Lhost
|
|
198
189
|
end
|
199
190
|
end
|
200
191
|
|
201
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
192
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
202
193
|
end
|
203
194
|
def description; return 'McAfee SaaS'; end
|
204
195
|
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
|