sisimai 4.25.16 → 5.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/ANALYTICAL-PRECISION +2 -2
- data/Benchmarks.mk +3 -3
- data/CONTRIBUTING +1 -1
- data/ChangeLog.md +424 -393
- data/Developers.mk +5 -6
- data/Gemfile +1 -1
- data/Makefile +15 -15
- data/README-JA.md +323 -149
- data/README.md +319 -148
- data/Rakefile +9 -3
- data/Repository.mk +2 -3
- data/lib/sisimai/address.rb +118 -74
- data/lib/sisimai/arf.rb +84 -82
- data/lib/sisimai/datetime.rb +5 -52
- data/lib/sisimai/{data → fact}/json.rb +7 -9
- data/lib/sisimai/fact/yaml.rb +31 -0
- data/lib/sisimai/fact.rb +468 -0
- data/lib/sisimai/lhost/activehunter.rb +12 -14
- data/lib/sisimai/lhost/amavis.rb +11 -14
- data/lib/sisimai/lhost/amazonses.rb +37 -41
- data/lib/sisimai/lhost/amazonworkmail.rb +15 -18
- data/lib/sisimai/lhost/aol.rb +12 -14
- data/lib/sisimai/lhost/apachejames.rb +19 -21
- data/lib/sisimai/lhost/barracuda.rb +10 -12
- data/lib/sisimai/lhost/bigfoot.rb +21 -21
- data/lib/sisimai/lhost/biglobe.rb +15 -16
- data/lib/sisimai/lhost/courier.rb +20 -20
- data/lib/sisimai/lhost/domino.rb +23 -19
- data/lib/sisimai/lhost/einsundeins.rb +23 -18
- data/lib/sisimai/lhost/exchange2003.rb +30 -29
- data/lib/sisimai/lhost/exchange2007.rb +70 -58
- data/lib/sisimai/lhost/exim.rb +175 -161
- data/lib/sisimai/lhost/ezweb.rb +31 -56
- data/lib/sisimai/lhost/facebook.rb +21 -33
- data/lib/sisimai/lhost/fml.rb +43 -48
- data/lib/sisimai/lhost/gmail.rb +29 -29
- data/lib/sisimai/lhost/gmx.rb +18 -17
- data/lib/sisimai/lhost/googlegroups.rb +9 -10
- data/lib/sisimai/lhost/gsuite.rb +21 -27
- data/lib/sisimai/lhost/imailserver.rb +25 -39
- data/lib/sisimai/lhost/interscanmss.rb +28 -31
- data/lib/sisimai/lhost/kddi.rb +22 -28
- data/lib/sisimai/lhost/mailfoundry.rb +11 -12
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
- data/lib/sisimai/lhost/mailru.rb +33 -27
- data/lib/sisimai/lhost/mcafee.rb +21 -31
- data/lib/sisimai/lhost/messagelabs.rb +17 -20
- data/lib/sisimai/lhost/messagingserver.rb +40 -37
- data/lib/sisimai/lhost/mfilter.rb +15 -16
- data/lib/sisimai/lhost/mxlogic.rb +24 -23
- data/lib/sisimai/lhost/notes.rb +17 -17
- data/lib/sisimai/lhost/office365.rb +63 -27
- data/lib/sisimai/lhost/opensmtpd.rb +12 -13
- data/lib/sisimai/lhost/outlook.rb +12 -15
- data/lib/sisimai/lhost/postfix.rb +179 -129
- data/lib/sisimai/lhost/powermta.rb +12 -14
- data/lib/sisimai/lhost/qmail.rb +44 -47
- data/lib/sisimai/lhost/receivingses.rb +15 -20
- data/lib/sisimai/lhost/sendgrid.rb +34 -32
- data/lib/sisimai/lhost/sendmail.rb +66 -53
- data/lib/sisimai/lhost/surfcontrol.rb +19 -19
- data/lib/sisimai/lhost/v5sendmail.rb +45 -39
- data/lib/sisimai/lhost/verizon.rb +35 -39
- data/lib/sisimai/lhost/x1.rb +18 -17
- data/lib/sisimai/lhost/x2.rb +17 -14
- data/lib/sisimai/lhost/x3.rb +19 -19
- data/lib/sisimai/lhost/x4.rb +72 -57
- data/lib/sisimai/lhost/x5.rb +17 -19
- data/lib/sisimai/lhost/x6.rb +41 -17
- data/lib/sisimai/lhost/yahoo.rb +17 -16
- data/lib/sisimai/lhost/yandex.rb +16 -20
- data/lib/sisimai/lhost/zoho.rb +16 -15
- data/lib/sisimai/lhost.rb +8 -10
- data/lib/sisimai/mail/maildir.rb +1 -3
- data/lib/sisimai/mail/mbox.rb +3 -4
- data/lib/sisimai/mail/memory.rb +0 -1
- data/lib/sisimai/mail/stdin.rb +1 -3
- data/lib/sisimai/mail.rb +3 -7
- data/lib/sisimai/mda.rb +28 -42
- data/lib/sisimai/message.rb +435 -326
- data/lib/sisimai/order.rb +5 -5
- data/lib/sisimai/reason/authfailure.rb +64 -0
- data/lib/sisimai/reason/badreputation.rb +53 -0
- data/lib/sisimai/reason/blocked.rb +94 -160
- data/lib/sisimai/reason/contenterror.rb +8 -9
- data/lib/sisimai/reason/delivered.rb +4 -6
- data/lib/sisimai/reason/exceedlimit.rb +10 -12
- data/lib/sisimai/reason/expired.rb +6 -8
- data/lib/sisimai/reason/feedback.rb +2 -3
- data/lib/sisimai/reason/filtered.rb +17 -19
- data/lib/sisimai/reason/hasmoved.rb +9 -10
- data/lib/sisimai/reason/hostunknown.rb +15 -15
- data/lib/sisimai/reason/mailboxfull.rb +10 -12
- data/lib/sisimai/reason/mailererror.rb +18 -20
- data/lib/sisimai/reason/mesgtoobig.rb +9 -11
- data/lib/sisimai/reason/networkerror.rb +5 -8
- data/lib/sisimai/reason/norelaying.rb +8 -11
- data/lib/sisimai/reason/notaccept.rb +13 -14
- data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
- data/lib/sisimai/reason/onhold.rb +6 -9
- data/lib/sisimai/reason/policyviolation.rb +14 -12
- data/lib/sisimai/reason/rejected.rb +26 -24
- data/lib/sisimai/reason/requireptr.rb +69 -0
- data/lib/sisimai/reason/securityerror.rb +33 -36
- data/lib/sisimai/reason/spamdetected.rb +114 -147
- data/lib/sisimai/reason/speeding.rb +49 -0
- data/lib/sisimai/reason/suspend.rb +11 -11
- data/lib/sisimai/reason/syntaxerror.rb +11 -10
- data/lib/sisimai/reason/systemerror.rb +7 -9
- data/lib/sisimai/reason/systemfull.rb +7 -8
- data/lib/sisimai/reason/toomanyconn.rb +9 -11
- data/lib/sisimai/reason/undefined.rb +2 -3
- data/lib/sisimai/reason/userunknown.rb +129 -146
- data/lib/sisimai/reason/vacation.rb +3 -4
- data/lib/sisimai/reason/virusdetected.rb +10 -11
- data/lib/sisimai/reason.rb +59 -64
- data/lib/sisimai/rfc1894.rb +55 -28
- data/lib/sisimai/rfc2045.rb +373 -0
- data/lib/sisimai/rfc3464.rb +250 -308
- data/lib/sisimai/rfc3834.rb +42 -45
- data/lib/sisimai/rfc5322.rb +75 -100
- data/lib/sisimai/rfc5965.rb +31 -0
- data/lib/sisimai/rhost/cox.rb +5 -6
- data/lib/sisimai/rhost/franceptt.rb +6 -8
- data/lib/sisimai/rhost/godaddy.rb +12 -12
- data/lib/sisimai/rhost/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 +42 -40
- data/lib/sisimai/rhost/nttdocomo.rb +12 -12
- data/lib/sisimai/rhost/spectrum.rb +10 -12
- data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
- data/lib/sisimai/rhost.rb +23 -31
- data/lib/sisimai/smtp/command.rb +59 -0
- data/lib/sisimai/smtp/error.rb +4 -7
- data/lib/sisimai/smtp/reply.rb +161 -74
- data/lib/sisimai/smtp/status.rb +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/rfc3464-43.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
- data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
- data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
- data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
- data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
- data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +41 -20
- data/.rspec +0 -2
- data/lib/sisimai/data/yaml.rb +0 -33
- data/lib/sisimai/data.rb +0 -411
- data/lib/sisimai/mime.rb +0 -456
- data/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,11 +1,10 @@
|
|
1
1
|
module Sisimai
|
2
2
|
module Reason
|
3
|
-
# Sisimai::Reason::VirusDetected checks the bounce reason is "virusdetected"
|
4
|
-
#
|
3
|
+
# Sisimai::Reason::VirusDetected checks the bounce reason is "virusdetected" or not. This class
|
4
|
+
# is called only Sisimai::Reason class.
|
5
5
|
#
|
6
|
-
# This is an error that any virus or trojan horse detected in the message by
|
7
|
-
#
|
8
|
-
# divided from "securityerror" at Sisimai 4.22.0.
|
6
|
+
# This is an error that any virus or trojan horse detected in the message by a virus scanner program
|
7
|
+
# at a destination mail server. This reason has been divided from "securityerror" at Sisimai 4.22.0.
|
9
8
|
#
|
10
9
|
# Your message was infected with a virus. You should download a virus
|
11
10
|
# scanner and check your computer for viruses.
|
@@ -14,15 +13,15 @@ module Sisimai
|
|
14
13
|
# Recipient: <kijitora@example.jp>
|
15
14
|
#
|
16
15
|
module VirusDetected
|
17
|
-
# Imported from p5-Sisimail/lib/Sisimai/Reason/VirusDetected.pm
|
18
16
|
class << self
|
19
17
|
Index = [
|
20
18
|
'it has a potentially executable attachment',
|
21
19
|
'the message was rejected because it contains prohibited virus or spam content',
|
22
20
|
'this form of attachment has been used by recent viruses or other malware',
|
23
21
|
'virus detected',
|
22
|
+
'virus phishing/malicious_url detected',
|
24
23
|
'your message was infected with a virus',
|
25
|
-
]
|
24
|
+
].freeze
|
26
25
|
|
27
26
|
def text; return 'virusdetected'; end
|
28
27
|
def description; return 'Email rejected due to a virus scanner on a destination host'; end
|
@@ -39,7 +38,7 @@ module Sisimai
|
|
39
38
|
end
|
40
39
|
|
41
40
|
# The bounce reason is "virusdetected" or not
|
42
|
-
# @param [Sisimai::
|
41
|
+
# @param [Sisimai::Fact] argvs Object to be detected the reason
|
43
42
|
# @return [True,False] true: virus detected
|
44
43
|
# false: virus was not detected
|
45
44
|
# @since 4.22.0
|
@@ -48,9 +47,9 @@ module Sisimai
|
|
48
47
|
# The value of "reason" isn't "visusdetected" when the value of "smtpcommand" is an SMTP
|
49
48
|
# command to be sent before the SMTP DATA command because all the MTAs read the headers
|
50
49
|
# and the entire message body after the DATA command.
|
51
|
-
return true if argvs
|
52
|
-
return false if %w[CONN EHLO HELO MAIL RCPT].include?(argvs
|
53
|
-
return true if match(argvs
|
50
|
+
return true if argvs['reason'] == 'virusdetected'
|
51
|
+
return false if %w[CONN EHLO HELO MAIL RCPT].include?(argvs['smtpcommand'])
|
52
|
+
return true if match(argvs['diagnosticcode'].downcase)
|
54
53
|
return false
|
55
54
|
end
|
56
55
|
|
data/lib/sisimai/reason.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
module Sisimai
|
2
|
-
# Sisimai::Reason detects the bounce reason from the
|
3
|
-
# object as an argument of get() method. This class is called only Sisimai::
|
4
|
-
# class.
|
2
|
+
# Sisimai::Reason detects the bounce reason from the Hash table which is to be constructed to
|
3
|
+
# Sisimai::Fact object as an argument of get() method. This class is called only Sisimai::Fact class.
|
5
4
|
module Reason
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Reason.pm
|
7
5
|
class << self
|
8
6
|
# All the error reason list Sisimai support
|
9
7
|
# @return [Array] Reason list
|
10
8
|
def index
|
11
9
|
return %w[
|
12
|
-
Blocked ContentError ExceedLimit Expired Filtered HasMoved
|
13
|
-
MailboxFull MailerError MesgTooBig NetworkError NotAccept
|
14
|
-
Rejected NoRelaying SpamDetected VirusDetected PolicyViolation
|
15
|
-
Suspend SystemError SystemFull TooManyConn UserUnknown SyntaxError
|
10
|
+
AuthFailure BadReputation Blocked ContentError ExceedLimit Expired Filtered HasMoved
|
11
|
+
HostUnknown MailboxFull MailerError MesgTooBig NetworkError NotAccept NotCompliantRFC
|
12
|
+
OnHold Rejected NoRelaying Speeding SpamDetected VirusDetected PolicyViolation
|
13
|
+
SecurityError Suspend RequirePTR SystemError SystemFull TooManyConn UserUnknown SyntaxError
|
16
14
|
]
|
17
15
|
end
|
18
16
|
|
@@ -27,55 +25,57 @@ module Sisimai
|
|
27
25
|
end
|
28
26
|
|
29
27
|
# Reason list better to retry detecting an error reason
|
30
|
-
# @return [
|
28
|
+
# @return [Hash] Reason list
|
31
29
|
def retry
|
32
30
|
return {
|
33
|
-
'undefined' =>
|
34
|
-
'
|
31
|
+
'undefined' => true, 'onhold' => true, 'systemerror' => true, 'securityerror' => true,
|
32
|
+
'expired' => true, 'suspend' => true, 'networkerror' => true, 'hostunknown' => true,
|
33
|
+
'userunknown' => true
|
35
34
|
}.freeze
|
36
35
|
end
|
37
36
|
ModulePath = Sisimai::Reason.path
|
38
37
|
GetRetried = Sisimai::Reason.retry
|
39
38
|
ClassOrder = [
|
40
39
|
%w[
|
41
|
-
MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying UserUnknown
|
42
|
-
Filtered Rejected HostUnknown SpamDetected TooManyConn
|
40
|
+
MailboxFull MesgTooBig ExceedLimit Suspend HasMoved NoRelaying AuthFailure UserUnknown
|
41
|
+
Filtered RequirePTR NotCompliantRFC Rejected HostUnknown SpamDetected Speeding TooManyConn
|
42
|
+
Blocked
|
43
43
|
],
|
44
44
|
%w[
|
45
|
-
MailboxFull SpamDetected PolicyViolation VirusDetected NoRelaying
|
46
|
-
SecurityError SystemError NetworkError Suspend Expired ContentError
|
45
|
+
MailboxFull SpamDetected PolicyViolation VirusDetected NoRelaying AuthFailure
|
46
|
+
BadReputation SecurityError SystemError NetworkError Speeding Suspend Expired ContentError
|
47
47
|
SystemFull NotAccept MailerError
|
48
48
|
],
|
49
49
|
%w[
|
50
|
-
MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected
|
51
|
-
|
52
|
-
SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull
|
53
|
-
|
50
|
+
MailboxFull MesgTooBig ExceedLimit Suspend UserUnknown Filtered Rejected HostUnknown
|
51
|
+
SpamDetected Speeding TooManyConn Blocked SpamDetected AuthFailure SecurityError
|
52
|
+
SystemError NetworkError Suspend Expired ContentError HasMoved SystemFull NotAccept
|
53
|
+
MailerError NoRelaying SyntaxError OnHold
|
54
54
|
]
|
55
55
|
]
|
56
56
|
|
57
57
|
# Detect the bounce reason
|
58
|
-
# @param [
|
59
|
-
# @return [String,
|
60
|
-
# is missing or invalid object
|
58
|
+
# @param [Hash] argvs Parsed email object
|
59
|
+
# @return [String, nil] Bounce reason or nil if the argument is missing or not Hash
|
61
60
|
# @see anotherone
|
62
61
|
def get(argvs)
|
63
62
|
return nil unless argvs
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# regular expression of retry() method.
|
69
|
-
return argvs.reason unless argvs.reason.empty?
|
63
|
+
unless GetRetried[argvs['reason']]
|
64
|
+
# Return reason text already decided except reason match with the regular expression of
|
65
|
+
# retry() method.
|
66
|
+
return argvs['reason'] unless argvs['reason'].empty?
|
70
67
|
end
|
71
|
-
return 'delivered' if argvs
|
68
|
+
return 'delivered' if argvs['deliverystatus'].start_with?('2.')
|
72
69
|
|
73
70
|
reasontext = ''
|
74
|
-
|
71
|
+
issuedcode = argvs['diagnosticcode'] || ''
|
72
|
+
codeformat = argvs['diagnostictype'] || ''
|
73
|
+
|
74
|
+
if codeformat == 'SMTP' || codeformat == ''
|
75
75
|
# Diagnostic-Code: SMTP; ... or empty value
|
76
76
|
ClassOrder[0].each do |e|
|
77
|
-
# Check the value of Diagnostic-Code: and the value of Status:, it is a
|
78
|
-
#
|
77
|
+
# Check the value of Diagnostic-Code: and the value of Status:, it is a deliverystats,
|
78
|
+
# with true() method in each Sisimai::Reason::* class.
|
79
79
|
p = 'Sisimai::Reason::' << e
|
80
80
|
r = nil
|
81
81
|
begin
|
@@ -98,13 +98,13 @@ module Sisimai
|
|
98
98
|
if reasontext == 'undefined' || reasontext.empty?
|
99
99
|
# Action: delayed => "expired"
|
100
100
|
reasontext = nil
|
101
|
-
reasontext ||= 'expired' if argvs
|
101
|
+
reasontext ||= 'expired' if argvs['action'] == 'delayed'
|
102
102
|
return reasontext if reasontext
|
103
103
|
|
104
104
|
# Try to match with message patterns in Sisimai::Reason::Vacation
|
105
105
|
require 'sisimai/reason/vacation'
|
106
|
-
reasontext = 'vacation' if Sisimai::Reason::Vacation.match(
|
107
|
-
reasontext ||= 'onhold' unless
|
106
|
+
reasontext = 'vacation' if Sisimai::Reason::Vacation.match(issuedcode.downcase)
|
107
|
+
reasontext ||= 'onhold' unless issuedcode.empty?
|
108
108
|
reasontext ||= 'undefined'
|
109
109
|
end
|
110
110
|
end
|
@@ -112,24 +112,24 @@ module Sisimai
|
|
112
112
|
end
|
113
113
|
|
114
114
|
# Detect the other bounce reason, fall back method for get()
|
115
|
-
# @param [
|
116
|
-
# @return [String, Nil]
|
117
|
-
# is missing or invalid object
|
115
|
+
# @param [Hash] argvs Parsed email object
|
116
|
+
# @return [String, Nil] Bounce reason or nli if the argument is missing or not Hash
|
118
117
|
# @see get
|
119
118
|
def anotherone(argvs)
|
120
|
-
return
|
121
|
-
return argvs.reason unless argvs.reason.empty?
|
119
|
+
return argvs['reason'] unless argvs['reason'].empty?
|
122
120
|
|
123
121
|
require 'sisimai/smtp/status'
|
124
|
-
|
122
|
+
issuedcode = argvs['diagnosticcode'].downcase || ''
|
123
|
+
codeformat = argvs['diagnostictype'] || ''
|
124
|
+
actiontext = argvs['action'] || ''
|
125
|
+
statuscode = argvs['deliverystatus'] || ''
|
125
126
|
reasontext = Sisimai::SMTP::Status.name(statuscode) || ''
|
126
127
|
|
127
128
|
catch :TRY_TO_MATCH do
|
128
129
|
while true
|
129
|
-
diagnostic = argvs.diagnosticcode.downcase || ''
|
130
130
|
trytomatch = reasontext.empty? ? true : false
|
131
131
|
trytomatch ||= true if GetRetried[reasontext]
|
132
|
-
trytomatch ||= true if
|
132
|
+
trytomatch ||= true if codeformat != 'SMTP'
|
133
133
|
throw :TRY_TO_MATCH unless trytomatch
|
134
134
|
|
135
135
|
# Could not decide the reason by the value of Status:
|
@@ -145,25 +145,26 @@ module Sisimai
|
|
145
145
|
next
|
146
146
|
end
|
147
147
|
|
148
|
-
next unless r.match(
|
148
|
+
next unless r.match(issuedcode)
|
149
149
|
reasontext = e.downcase
|
150
150
|
break
|
151
151
|
end
|
152
152
|
throw :TRY_TO_MATCH unless reasontext.empty?
|
153
153
|
|
154
154
|
# Check the value of Status:
|
155
|
-
|
156
|
-
if
|
155
|
+
code2digit = statuscode[0, 3] || ''
|
156
|
+
if code2digit == '5.6' || code2digit == '4.6'
|
157
157
|
# X.6.0 Other or undefined media error
|
158
158
|
reasontext = 'contenterror'
|
159
159
|
|
160
|
-
elsif
|
160
|
+
elsif code2digit == '5.7' || code2digit == '4.7'
|
161
161
|
# X.7.0 Other or undefined security status
|
162
162
|
reasontext = 'securityerror'
|
163
163
|
|
164
|
-
elsif
|
164
|
+
elsif codeformat.start_with?('X-UNIX')
|
165
165
|
# Diagnostic-Code: X-UNIX; ...
|
166
166
|
reasontext = 'mailererror'
|
167
|
+
|
167
168
|
else
|
168
169
|
# 50X Syntax Error?
|
169
170
|
require 'sisimai/reason/syntaxerror'
|
@@ -172,13 +173,13 @@ module Sisimai
|
|
172
173
|
throw :TRY_TO_MATCH unless reasontext.empty?
|
173
174
|
|
174
175
|
# Check the value of Action: field, first
|
175
|
-
if
|
176
|
+
if actiontext.start_with?('delayed', 'expired')
|
176
177
|
# Action: delayed, expired
|
177
178
|
reasontext = 'expired'
|
178
179
|
else
|
179
180
|
# Rejected at connection or after EHLO|HELO
|
180
|
-
|
181
|
-
reasontext = 'blocked' if %w[HELO EHLO].index(
|
181
|
+
thecommand = argvs['smtpcommand'] || ''
|
182
|
+
reasontext = 'blocked' if %w[HELO EHLO].index(thecommand)
|
182
183
|
end
|
183
184
|
throw :TRY_TO_MATCH
|
184
185
|
end
|
@@ -193,12 +194,12 @@ module Sisimai
|
|
193
194
|
return nil unless argv1
|
194
195
|
|
195
196
|
reasontext = ''
|
196
|
-
|
197
|
+
issuedcode = argv1.downcase
|
197
198
|
|
198
199
|
# Diagnostic-Code: SMTP; ... or empty value
|
199
200
|
ClassOrder[2].each do |e|
|
200
|
-
# Check the value of Diagnostic-Code: and the value of Status:, it is a
|
201
|
-
#
|
201
|
+
# Check the value of Diagnostic-Code: and the value of Status:, it is a deliverystats, with
|
202
|
+
# true() method in each Sisimai::Reason::* class.
|
202
203
|
p = 'Sisimai::Reason::' << e
|
203
204
|
r = nil
|
204
205
|
begin
|
@@ -209,26 +210,20 @@ module Sisimai
|
|
209
210
|
next
|
210
211
|
end
|
211
212
|
|
212
|
-
next unless r.match(
|
213
|
+
next unless r.match(issuedcode)
|
213
214
|
reasontext = r.text
|
214
215
|
break
|
215
216
|
end
|
216
217
|
return reasontext unless reasontext.empty?
|
217
218
|
|
218
|
-
|
219
|
-
if cv = argv1.match(/\A(SMTP|X-.+);/i)
|
220
|
-
# Check the value of typestring
|
221
|
-
typestring = cv[1].upcase
|
222
|
-
end
|
223
|
-
|
224
|
-
if typestring == 'X-UNIX'
|
219
|
+
if issuedcode.upcase == 'X-UNIX'
|
225
220
|
# X-Unix; ...
|
226
221
|
reasontext = 'mailererror'
|
227
222
|
else
|
228
223
|
# Detect the bounce reason from "Status:" code
|
229
224
|
require 'sisimai/smtp/status'
|
230
|
-
|
231
|
-
reasontext = Sisimai::SMTP::Status.name(
|
225
|
+
cv = Sisimai::SMTP::Status.find(argv1) || ''
|
226
|
+
reasontext = Sisimai::SMTP::Status.name(cv) || 'undefined'
|
232
227
|
end
|
233
228
|
return reasontext
|
234
229
|
end
|
data/lib/sisimai/rfc1894.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
module Sisimai
|
2
2
|
# Sisimai::RFC1894 DSN field defined in RFC3464 (obsoletes RFC1894)
|
3
3
|
module RFC1894
|
4
|
-
# Imported from p5-Sisimail/lib/Sisimai/RFC1894.pm
|
5
4
|
class << self
|
6
|
-
FieldNames =
|
5
|
+
FieldNames = {
|
7
6
|
# https://tools.ietf.org/html/rfc3464#section-2.2
|
8
|
-
# Some fields of a DSN apply to all of the delivery attempts described by
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
7
|
+
# Some fields of a DSN apply to all of the delivery attempts described by that DSN. At
|
8
|
+
# most, these fields may appear once in any DSN. These fields are used to correlate the
|
9
|
+
# DSN with the original message transaction and to provide additional information which
|
10
|
+
# may be useful to gateways.
|
12
11
|
#
|
13
12
|
# The following fields (not defined in RFC 3464) are used in Sisimai
|
14
13
|
# - X-Original-Message-ID: <....> (GSuite)
|
@@ -16,13 +15,16 @@ module Sisimai
|
|
16
15
|
# The following fields are not used in Sisimai:
|
17
16
|
# - Original-Envelope-Id
|
18
17
|
# - DSN-Gateway
|
19
|
-
|
18
|
+
'arrival-date' => ':',
|
19
|
+
'received-from-mta' => ';',
|
20
|
+
'reporting-mta' => ';',
|
21
|
+
'x-original-message-id' => '@',
|
20
22
|
|
21
23
|
# https://tools.ietf.org/html/rfc3464#section-2.3
|
22
|
-
# A DSN contains information about attempts to deliver a message to one or
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
24
|
+
# A DSN contains information about attempts to deliver a message to one or more recipi-
|
25
|
+
# ents. The delivery information for any particular recipient is contained in a group of
|
26
|
+
# contiguous per-recipient fields. Each group of per-recipient fields is preceded by a
|
27
|
+
# blank line.
|
26
28
|
#
|
27
29
|
# The following fields (not defined in RFC 3464) are used in Sisimai
|
28
30
|
# - X-Actual-Recipient: RFC822; ....
|
@@ -30,18 +32,24 @@ module Sisimai
|
|
30
32
|
# The following fields are not used in Sisimai:
|
31
33
|
# - Will-Retry-Until
|
32
34
|
# - Final-Log-ID
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
'action' => 'e',
|
36
|
+
'diagnostic-code' => ';',
|
37
|
+
'final-recipient' => ';',
|
38
|
+
'last-attempt-date' => ':',
|
39
|
+
'original-recipient' => ';',
|
40
|
+
'remote-mta' => ';',
|
41
|
+
'status' => '.',
|
42
|
+
'x-actual-recipient' => ';',
|
43
|
+
}.freeze
|
36
44
|
|
37
45
|
CapturesOn = {
|
38
|
-
'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ]
|
39
|
-
'code' => %r/\A(Diagnostic-Code):[ ]
|
40
|
-
'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ]
|
41
|
-
'host' => %r/\A((?:Received-From|Remote|Reporting)-MTA):[ ]
|
42
|
-
'list' => %r/\A(Action):[ ]
|
43
|
-
'stat' => %r/\A(Status):[ ]
|
44
|
-
'text' => %r/\A(X-Original-Message-ID):[ ]
|
46
|
+
'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ](.+?);[ ]*(.+)/,
|
47
|
+
'code' => %r/\A(Diagnostic-Code):[ ](.+?);[ ]*(.*)/,
|
48
|
+
'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ](.+)/,
|
49
|
+
'host' => %r/\A((?:Received-From|Remote|Reporting)-MTA):[ ](.+?);[ ]*(.+)/,
|
50
|
+
'list' => %r/\A(Action):[ ](delayed|deliverable|delivered|expanded|expired|failed|failure|relayed)/i,
|
51
|
+
'stat' => %r/\A(Status):[ ]([245][.]\d+[.]\d+)/,
|
52
|
+
'text' => %r/\A(X-Original-Message-ID):[ ](.+)/,
|
45
53
|
#'text' => %r/\A(Final-Log-ID|Original-Envelope-Id):[ ]*(.+)/,
|
46
54
|
}.freeze
|
47
55
|
|
@@ -61,6 +69,13 @@ module Sisimai
|
|
61
69
|
'x-original-message-id' => 'text',
|
62
70
|
}.freeze
|
63
71
|
|
72
|
+
def FIELDINDEX
|
73
|
+
return %w[
|
74
|
+
Action Arrival-Date Diagnostic-Code Final-Recipient Last-Attempt-Date Original-Recipient
|
75
|
+
Received-From-MTA Remote-MTA Reporting-MTA Status X-Actual-Recipienet X-Original-Message-ID
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
64
79
|
# Table to be converted to key name defined in Sisimai::Lhost class
|
65
80
|
# @param [Symbol] group RFC822 Header group name
|
66
81
|
# @return [Array,Hash] RFC822 Header list
|
@@ -81,23 +96,35 @@ module Sisimai
|
|
81
96
|
end
|
82
97
|
|
83
98
|
# Check the argument matches with a field defined in RFC3464
|
84
|
-
# @param [String] argv0 A line
|
85
|
-
# @return [
|
99
|
+
# @param [String] argv0 A line including field and value defined in RFC3464
|
100
|
+
# @return [Boolean] false: did not matched, true: matched
|
86
101
|
# @since v4.25.0
|
87
102
|
def match(argv0 = '')
|
103
|
+
label = Sisimai::RFC1894.label(argv0)
|
104
|
+
|
105
|
+
return false unless label
|
106
|
+
return false unless FieldNames.has_key?(label)
|
107
|
+
return false unless argv0.include?(FieldNames[label])
|
108
|
+
return true
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns a field name as a lqbel from the given string
|
112
|
+
# @param [String] argv0 A line including field and value defined in RFC3464
|
113
|
+
# @return [String] Field name as a label
|
114
|
+
# @since v4.25.15
|
115
|
+
def label(argv0 = '')
|
88
116
|
return nil if argv0.empty?
|
89
|
-
return
|
90
|
-
return 2 if FieldNames[1].any? { |a| argv0.start_with?(a) }
|
91
|
-
return nil
|
117
|
+
return argv0.split(':', 2).shift.downcase
|
92
118
|
end
|
93
119
|
|
94
120
|
# Check the argument is including field defined in RFC3464 and return values
|
95
|
-
# @param [String] argv0 A line
|
121
|
+
# @param [String] argv0 A line including field and value defined in RFC3464
|
96
122
|
# @return [Array] ['field-name', 'value-type', 'Value', 'field-group']
|
97
123
|
# @since v4.25.0
|
98
124
|
def field(argv0 = '')
|
99
125
|
return nil if argv0.empty?
|
100
|
-
|
126
|
+
label = Sisimai::RFC1894.label(argv0)
|
127
|
+
group = FieldGroup[label] || ''
|
101
128
|
|
102
129
|
return nil if group.empty?
|
103
130
|
return nil unless CapturesOn[group]
|