sisimai 4.25.17 → 5.0.0
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 +4 -4
- 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 +41 -21
- 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
data/lib/sisimai/lhost/yandex.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Yandex parses a bounce email which created by Yandex.Mail.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Yandex parses a bounce email which created by Yandex.Mail. Methods in the module
|
3
|
+
# are called from only Sisimai::Message.
|
4
4
|
module Yandex
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Yandex.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: ['This is the mail system at host yandex.ru.'] }.freeze
|
12
11
|
|
13
12
|
# Parse bounce messages from Yandex.Mail
|
@@ -15,7 +14,7 @@ module Sisimai::Lhost
|
|
15
14
|
# @param [String] mbody Message body of a bounce email
|
16
15
|
# @return [Hash] Bounce data list and message/rfc822 part
|
17
16
|
# @return [Nil] it failed to parse or the arguments are missing
|
18
|
-
def
|
17
|
+
def inquire(mhead, mbody)
|
19
18
|
# X-Yandex-Front: mxback1h.mail.yandex.net
|
20
19
|
# X-Yandex-TimeMark: 1417885948
|
21
20
|
# X-Yandex-Uniq: 92309766-f1c8-4bd4-92bc-657c75766587
|
@@ -26,13 +25,12 @@ module Sisimai::Lhost
|
|
26
25
|
return nil unless mhead['x-yandex-uniq']
|
27
26
|
return nil unless mhead['from'] == 'mailer-daemon@yandex.ru'
|
28
27
|
|
29
|
-
require 'sisimai/rfc1894'
|
30
28
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
31
29
|
permessage = {} # (Hash) Store values of each Per-Message field
|
32
30
|
|
33
31
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
34
|
-
|
35
|
-
bodyslices =
|
32
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
33
|
+
bodyslices = emailparts[0].split("\n")
|
36
34
|
readslices = ['']
|
37
35
|
readcursor = 0 # (Integer) Points the current cursor position
|
38
36
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
@@ -40,8 +38,8 @@ module Sisimai::Lhost
|
|
40
38
|
v = nil
|
41
39
|
|
42
40
|
while e = bodyslices.shift do
|
43
|
-
# Read error messages and delivery status lines from the head of the email
|
44
|
-
#
|
41
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
42
|
+
# line of the beginning of the original message.
|
45
43
|
readslices << e # Save the current line for the next loop
|
46
44
|
|
47
45
|
if readcursor == 0
|
@@ -82,23 +80,21 @@ module Sisimai::Lhost
|
|
82
80
|
next unless fieldtable[o[0]]
|
83
81
|
v[fieldtable[o[0]]] = o[2]
|
84
82
|
|
85
|
-
next unless f
|
83
|
+
next unless f
|
86
84
|
permessage[fieldtable[o[0]]] = o[2]
|
87
85
|
end
|
88
86
|
else
|
89
87
|
# The line does not begin with a DSN field defined in RFC3464
|
90
|
-
if
|
88
|
+
if e.include?(' (in reply to ') || e.include?('command)')
|
91
89
|
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
92
|
-
|
90
|
+
cv = Sisimai::SMTP::Command.find(e)
|
91
|
+
commandset << cv if cv
|
93
92
|
|
94
|
-
elsif cv = e.match(/([A-Z]{4})[ \t]*.*command[)]\z/)
|
95
|
-
# to MAIL command)
|
96
|
-
commandset << cv[1]
|
97
93
|
else
|
98
94
|
# Continued line of the value of Diagnostic-Code field
|
99
95
|
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
100
|
-
next unless
|
101
|
-
v['diagnosis'] << ' ' <<
|
96
|
+
next unless e.start_with?(' ')
|
97
|
+
v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
|
102
98
|
readslices[-1] = 'Diagnostic-Code: ' << e
|
103
99
|
end
|
104
100
|
end
|
@@ -110,11 +106,11 @@ module Sisimai::Lhost
|
|
110
106
|
e['lhost'] ||= permessage['rhost']
|
111
107
|
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
112
108
|
|
113
|
-
e['command'] = commandset.shift || ''
|
114
109
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
110
|
+
e['command'] ||= commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis']) || ''
|
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 'Yandex.Mail: https://www.yandex.ru'; end
|
120
116
|
end
|
data/lib/sisimai/lhost/zoho.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Zoho parses a bounce email which created by Zoho Mail.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Zoho parses a bounce email which created by Zoho Mail. Methods in the module are
|
3
|
+
# called from only Sisimai::Message.
|
4
4
|
module Zoho
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Zoho.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Received: from mail.zoho.com by mx.zohomail.com'].freeze
|
11
10
|
StartingOf = { message: ['This message was created automatically by mail delivery'] }.freeze
|
12
11
|
MessagesOf = { 'expired' => ['Host not reachable'] }.freeze
|
13
12
|
|
@@ -16,23 +15,23 @@ module Sisimai::Lhost
|
|
16
15
|
# @param [String] mbody Message body of a bounce email
|
17
16
|
# @return [Hash] Bounce data list and message/rfc822 part
|
18
17
|
# @return [Nil] it failed to parse or the arguments are missing
|
19
|
-
def
|
18
|
+
def inquire(mhead, mbody)
|
20
19
|
# X-ZohoMail: Si CHF_MF_NL SS_10 UW48 UB48 FMWL UW48 UB48 SGR3_1_09124_42
|
21
20
|
# X-Zoho-Virus-Status: 2
|
22
21
|
# X-Mailer: Zoho Mail
|
23
22
|
return nil unless mhead['x-zohomail']
|
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
|
qprintable = false
|
31
30
|
v = nil
|
32
31
|
|
33
32
|
while e = bodyslices.shift do
|
34
|
-
# Read error messages and delivery status lines from the head of the email
|
35
|
-
#
|
33
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
34
|
+
# line of the beginning of the original message.
|
36
35
|
if readcursor == 0
|
37
36
|
# Beginning of the bounce message or delivery status part
|
38
37
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -54,15 +53,15 @@ module Sisimai::Lhost
|
|
54
53
|
# shironeko@example.org Invalid Address, ERROR_CODE :550, ERROR_CODE :Requested action not taken: mailbox unavailable
|
55
54
|
v = dscontents[-1]
|
56
55
|
|
57
|
-
if
|
56
|
+
if Sisimai::String.aligned(e, ['@', ' ', 'ERROR_CODE :'])
|
58
57
|
# kijitora@example.co.jp Invalid Address, ERROR_CODE :550, ERROR_CODE :5.1.=
|
59
58
|
if v['recipient']
|
60
59
|
# There are multiple recipient addresses in the message body.
|
61
60
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
62
61
|
v = dscontents[-1]
|
63
62
|
end
|
64
|
-
v['recipient'] =
|
65
|
-
v['diagnosis'] =
|
63
|
+
v['recipient'] = e[0, e.index(' ')]
|
64
|
+
v['diagnosis'] = e[e.index(' ') + 1, e.size]
|
66
65
|
|
67
66
|
if v['diagnosis'].end_with?('=')
|
68
67
|
# Quoted printable
|
@@ -71,7 +70,7 @@ module Sisimai::Lhost
|
|
71
70
|
end
|
72
71
|
recipients += 1
|
73
72
|
|
74
|
-
elsif
|
73
|
+
elsif e.start_with?('[Status: ')
|
75
74
|
# Expired
|
76
75
|
# [Status: Error, Address: <kijitora@6kaku.example.co.jp>, ResponseCode 421, , Host not reachable.]
|
77
76
|
if v['recipient']
|
@@ -79,7 +78,9 @@ module Sisimai::Lhost
|
|
79
78
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
80
79
|
v = dscontents[-1]
|
81
80
|
end
|
82
|
-
|
81
|
+
p1 = e.index('<')
|
82
|
+
p2 = e.index('>', p1 + 2)
|
83
|
+
v['recipient'] = Sisimai::Address.s3s4(e[p1, p2 - p1])
|
83
84
|
v['diagnosis'] = e
|
84
85
|
recipients += 1
|
85
86
|
else
|
@@ -100,7 +101,7 @@ module Sisimai::Lhost
|
|
100
101
|
end
|
101
102
|
end
|
102
103
|
|
103
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
104
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
104
105
|
end
|
105
106
|
def description; return 'Zoho Mail: https://www.zoho.com'; end
|
106
107
|
end
|
data/lib/sisimai/lhost.rb
CHANGED
@@ -2,7 +2,6 @@ module Sisimai
|
|
2
2
|
# Sisimai::Lhost - Base class for Sisimai::Lhost::*
|
3
3
|
module Lhost
|
4
4
|
class << self
|
5
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost.pm
|
6
5
|
require 'sisimai/rfc5322'
|
7
6
|
|
8
7
|
# Data structure for parsed bounce messages
|
@@ -23,7 +22,7 @@ module Sisimai
|
|
23
22
|
'replycode' => nil, # SMTP Reply code
|
24
23
|
'diagnosis' => nil, # The value of Diagnostic-Code header
|
25
24
|
'recipient' => nil, # The value of Final-Recipient header
|
26
|
-
'
|
25
|
+
'hardbounce' => nil, # Hard bounce or not
|
27
26
|
'feedbacktype' => nil, # Feedback Type
|
28
27
|
}
|
29
28
|
end
|
@@ -42,13 +41,12 @@ module Sisimai
|
|
42
41
|
# @return [Array] MTA list with order
|
43
42
|
def index
|
44
43
|
return %w[
|
45
|
-
Activehunter Amavis AmazonSES AmazonWorkMail Aol ApacheJames Barracuda Bigfoot
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
Qmail
|
44
|
+
Activehunter Amavis AmazonSES AmazonWorkMail Aol ApacheJames Barracuda Bigfoot Biglobe
|
45
|
+
Courier Domino EZweb EinsUndEins Exchange2003 Exchange2007 Exim FML Facebook GMX GSuite
|
46
|
+
GoogleGroups Gmail IMailServer InterScanMSS KDDI MXLogic MailFoundry MailMarshalSMTP
|
47
|
+
MailRu McAfee MessageLabs MessagingServer Notes Office365 OpenSMTPD Outlook Postfix
|
48
|
+
PowerMTA ReceivingSES SendGrid Sendmail SurfControl V5sendmail Verizon X1 X2 X3 X4 X5 X6
|
49
|
+
Yahoo Yandex Zoho MFILTER Qmail
|
52
50
|
]
|
53
51
|
end
|
54
52
|
|
@@ -71,7 +69,7 @@ module Sisimai
|
|
71
69
|
# @param [String] mbody Message body of a bounce email
|
72
70
|
# @return [Hash] Bounce data list and message/rfc822 part
|
73
71
|
# @return [Nil] it failed to parse or the arguments are missing
|
74
|
-
def
|
72
|
+
def inquire; return nil; end
|
75
73
|
def description; return ''; end
|
76
74
|
end
|
77
75
|
end
|
data/lib/sisimai/mail/maildir.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Sisimai
|
2
2
|
class Mail
|
3
|
-
# Sisimai::Mail::Maildir is a reader for getting contents of each email in
|
4
|
-
# the Maildir/ directory.
|
3
|
+
# Sisimai::Mail::Maildir is a reader for getting contents of each email in the Maildir/ directory.
|
5
4
|
class Maildir
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Mail/Maildir.pm
|
7
5
|
# :dir [String] Path to Maildir/
|
8
6
|
# :size [Integer] The number of files/directories in the Maildir/
|
9
7
|
# :path [String] Path to each file
|
data/lib/sisimai/mail/mbox.rb
CHANGED
@@ -2,7 +2,6 @@ module Sisimai
|
|
2
2
|
class Mail
|
3
3
|
# Sisimai::Mail::Mbox is a mailbox file (UNIX mbox) reader.
|
4
4
|
class Mbox
|
5
|
-
# Imported from p5-Sisimail/lib/Sisimai/Mail/Mbox.pm
|
6
5
|
# :dir [String] Directory name of the mbox
|
7
6
|
# :file [String] File name of the mbox
|
8
7
|
# :path [String] Path to mbox
|
@@ -13,9 +12,9 @@ module Sisimai
|
|
13
12
|
attr_accessor :offset, :handle
|
14
13
|
|
15
14
|
# Constructor of Sisimai::Mail::Mbox
|
16
|
-
# @param [String] argv1
|
17
|
-
# @return [Sisimai::Mail::Mbox
|
18
|
-
#
|
15
|
+
# @param [String] argv1 Path to mbox
|
16
|
+
# @return [Sisimai::Mail::Mbox] Object
|
17
|
+
# [Nil] is not specified or does not exist
|
19
18
|
def initialize(argv1)
|
20
19
|
raise Errno::ENOENT unless File.exist?(argv1)
|
21
20
|
raise 'is not a file' unless File.ftype(argv1) == 'file'
|
data/lib/sisimai/mail/memory.rb
CHANGED
@@ -2,7 +2,6 @@ module Sisimai
|
|
2
2
|
class Mail
|
3
3
|
# Sisimai::Mail::Memory is a class for reading an email string
|
4
4
|
class Memory
|
5
|
-
# Imported from p5-Sisimail/lib/Sisimai/Mail/Memory.pm
|
6
5
|
# :path [String] Fixed string "<MEMORY>"
|
7
6
|
# :size [Integer] data size of the email text
|
8
7
|
# :payload [Array] Entire bounce mail message
|
data/lib/sisimai/mail/stdin.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Sisimai
|
2
2
|
class Mail
|
3
|
-
# Sisimai::Mail::STDIN is a reader for getting contents of each email from
|
4
|
-
# STDIN
|
3
|
+
# Sisimai::Mail::STDIN is a reader for getting contents of each email from STDIN
|
5
4
|
class STDIN
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Mail/STDIN.pm
|
7
5
|
# :path [String] Fixed string "<STDIN>"
|
8
6
|
# :size [Integer] Data size which has been read
|
9
7
|
# :offset [Integer] The number of emails which have neen read
|
data/lib/sisimai/mail.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
module Sisimai
|
2
|
-
# Sisimai::Mail is a handler of UNIX mbox or Maildir for reading each mail.
|
3
|
-
#
|
4
|
-
# Sisimai::Mail::Memory classes.
|
2
|
+
# Sisimai::Mail is a handler of UNIX mbox or Maildir for reading each mail. It is a wrapper class
|
3
|
+
# of Sisimai::Mail::Mbox, Sisimai::Mail::Maildir, and Sisimai::Mail::Memory classes.
|
5
4
|
class Mail
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Mail.pm
|
7
|
-
|
8
5
|
# :path [String] path to mbox or Maildir/
|
9
6
|
# :kind [String] Data type: mailbox, maildir, or stdin
|
10
7
|
# :data [Sisimai::Mail::[Mbox,Maildir,Memory,STDIN]] Object
|
@@ -47,8 +44,7 @@ module Sisimai
|
|
47
44
|
end
|
48
45
|
end
|
49
46
|
elsif argv1.is_a?(IO)
|
50
|
-
# Read from STDIN
|
51
|
-
# The argument neither a mailbox nor a Maildir/.
|
47
|
+
# Read from STDIN, The argument neither a mailbox nor a Maildir/.
|
52
48
|
classname = self.class.to_s << '::STDIN'
|
53
49
|
parameter['kind'] = 'stdin'
|
54
50
|
parameter['path'] = '<STDIN>'
|
data/lib/sisimai/mda.rb
CHANGED
@@ -1,25 +1,17 @@
|
|
1
1
|
module Sisimai
|
2
2
|
# Sisimai::MDA - Error message parser for MDA
|
3
3
|
module MDA
|
4
|
-
# Imported from p5-Sisimail/lib/Sisimai/MDA.pm
|
5
4
|
class << self
|
6
5
|
AgentNames = {
|
7
6
|
# dovecot/src/deliver/deliver.c
|
8
7
|
# 11: #define DEFAULT_MAIL_REJECTION_HUMAN_REASON \
|
9
8
|
# 12: "Your message to <%t> was automatically rejected:%n%r"
|
10
|
-
'dovecot' =>
|
11
|
-
'mail.local' =>
|
12
|
-
'procmail' =>
|
13
|
-
'maildrop' =>
|
14
|
-
'vpopmail' =>
|
15
|
-
'vmailmgr' =>
|
16
|
-
}.freeze
|
17
|
-
MarkingsOf = {
|
18
|
-
message: %r{\A(?>
|
19
|
-
Your[ ]message[ ]to[ ][^ ]+[ ]was[ ]automatically[ ]rejected:\z
|
20
|
-
|(?:mail[.]local|procmail|maildrop|vdelivermail|vdeliver):[ ]
|
21
|
-
)
|
22
|
-
}x
|
9
|
+
'dovecot' => ['Your message to ', ' was automatically rejected:'],
|
10
|
+
'mail.local' => ['mail.local: '],
|
11
|
+
'procmail' => ['procmail: '],
|
12
|
+
'maildrop' => ['maildrop: '],
|
13
|
+
'vpopmail' => ['vdelivermail: '],
|
14
|
+
'vmailmgr' => ['vdeliver: '],
|
23
15
|
}.freeze
|
24
16
|
|
25
17
|
# dovecot/src/deliver/mail-send.c:94
|
@@ -79,43 +71,37 @@ module Sisimai
|
|
79
71
|
# @param [String] mbody Message body of a bounce email
|
80
72
|
# @return [Hash] Bounce data list and message/rfc822 part
|
81
73
|
# @return [Nil] it failed to parse or the arguments are missing
|
82
|
-
def
|
74
|
+
def inquire(mhead, mbody)
|
75
|
+
return nil unless mhead
|
76
|
+
return nil unless mbody.size > 0
|
83
77
|
return nil unless mhead['from'].downcase.start_with?('mail delivery subsystem','mailer-daemon', 'postmaster')
|
84
78
|
|
85
|
-
|
79
|
+
deliversby = '' # [String] Mail Delivery Agent name
|
86
80
|
reasonname = '' # [String] Error reason
|
87
81
|
bouncemesg = '' # [String] Error message
|
88
|
-
|
89
|
-
linebuffer = []
|
82
|
+
linebuffer = mbody.split("\n")
|
90
83
|
|
91
|
-
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
next if e.empty?
|
96
|
-
next unless e =~ MarkingsOf[:message]
|
84
|
+
AgentNames.each_key do |e|
|
85
|
+
# Find a mail delivery agent name from the entire message body
|
86
|
+
p = mbody.index(AgentNames[e][0])
|
87
|
+
next unless p
|
97
88
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
89
|
+
if AgentNames[e].size > 1
|
90
|
+
# Try to find the 2nd argument
|
91
|
+
q = mbody.index(AgentNames[e][1])
|
92
|
+
next unless q
|
93
|
+
next if p > q
|
104
94
|
end
|
105
|
-
|
106
|
-
|
107
|
-
linebuffer << e
|
108
|
-
break if e.empty?
|
95
|
+
deliversby = e
|
96
|
+
break
|
109
97
|
end
|
110
|
-
return nil if
|
111
|
-
return nil if linebuffer.empty?
|
98
|
+
return nil if deliversby.empty?
|
112
99
|
|
113
|
-
MessagesOf[
|
100
|
+
MessagesOf[deliversby].each_key do |e|
|
114
101
|
# Detect an error reason from message patterns of the MDA.
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
next unless MessagesOf[agentname0][e].any? { |a| f.downcase.include?(a) }
|
102
|
+
linebuffer.each do |f|
|
103
|
+
# Whether the error message include each message defined in MessagesOf
|
104
|
+
next unless MessagesOf[deliversby][e].any? { |a| f.downcase.include?(a) }
|
119
105
|
reasonname = e
|
120
106
|
bouncemesg = f
|
121
107
|
break
|
@@ -124,7 +110,7 @@ module Sisimai
|
|
124
110
|
end
|
125
111
|
|
126
112
|
return {
|
127
|
-
'mda' =>
|
113
|
+
'mda' => deliversby,
|
128
114
|
'reason' => reasonname || '',
|
129
115
|
'message' => bouncemesg || '',
|
130
116
|
}
|