sisimai 5.7.0 → 5.7.1
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/ChangeLog.md +15 -0
- data/README-JA.md +8 -8
- data/README.md +8 -8
- data/lib/sisimai/arf.rb +2 -1
- data/lib/sisimai/eb.rb +116 -0
- data/lib/sisimai/fact.rb +24 -17
- data/lib/sisimai/lda.rb +20 -18
- data/lib/sisimai/lhost/amazonses.rb +11 -10
- data/lib/sisimai/lhost/courier.rb +4 -3
- data/lib/sisimai/lhost/domino.rb +2 -1
- data/lib/sisimai/lhost/einsundeins.rb +3 -2
- data/lib/sisimai/lhost/exchange2003.rb +8 -7
- data/lib/sisimai/lhost/exchange2007.rb +14 -13
- data/lib/sisimai/lhost/exim.rb +7 -6
- data/lib/sisimai/lhost/ezweb.rb +4 -3
- data/lib/sisimai/lhost/fml.rb +4 -3
- data/lib/sisimai/lhost/gmail.rb +10 -9
- data/lib/sisimai/lhost/googlegroups.rb +3 -2
- data/lib/sisimai/lhost/googleworkspace.rb +2 -1
- data/lib/sisimai/lhost/imailserver.rb +3 -2
- data/lib/sisimai/lhost/kddi.rb +4 -3
- data/lib/sisimai/lhost/notes.rb +2 -1
- data/lib/sisimai/lhost/postfix.rb +7 -6
- data/lib/sisimai/lhost/qmail.rb +10 -9
- data/lib/sisimai/lhost/sendmail.rb +4 -3
- data/lib/sisimai/lhost/trendmicro.rb +2 -1
- data/lib/sisimai/lhost/v5sendmail.rb +2 -1
- data/lib/sisimai/lhost/verizon.rb +3 -2
- data/lib/sisimai/reason/authfailure.rb +6 -5
- data/lib/sisimai/reason/badreputation.rb +5 -4
- data/lib/sisimai/reason/blocked.rb +6 -5
- data/lib/sisimai/reason/contenterror.rb +6 -5
- data/lib/sisimai/reason/delivered.rb +3 -2
- data/lib/sisimai/reason/emailtoolarge.rb +6 -5
- data/lib/sisimai/reason/expired.rb +3 -2
- data/lib/sisimai/reason/failedstarttls.rb +5 -3
- data/lib/sisimai/reason/feedback.rb +2 -1
- data/lib/sisimai/reason/filtered.rb +9 -8
- data/lib/sisimai/reason/hasmoved.rb +5 -4
- data/lib/sisimai/reason/hostunknown.rb +5 -4
- data/lib/sisimai/reason/mailboxfull.rb +7 -6
- data/lib/sisimai/reason/mailererror.rb +3 -2
- data/lib/sisimai/reason/networkerror.rb +3 -2
- data/lib/sisimai/reason/norelaying.rb +4 -3
- data/lib/sisimai/reason/notaccept.rb +5 -4
- data/lib/sisimai/reason/notcompliantrfc.rb +4 -3
- data/lib/sisimai/reason/onhold.rb +8 -7
- data/lib/sisimai/reason/policyviolation.rb +7 -6
- data/lib/sisimai/reason/ratelimited.rb +5 -4
- data/lib/sisimai/reason/rejected.rb +18 -14
- data/lib/sisimai/reason/requireptr.rb +5 -4
- data/lib/sisimai/reason/securityerror.rb +4 -3
- data/lib/sisimai/reason/spamdetected.rb +6 -5
- data/lib/sisimai/reason/suppressed.rb +4 -3
- data/lib/sisimai/reason/suspend.rb +4 -3
- data/lib/sisimai/reason/syntaxerror.rb +4 -3
- data/lib/sisimai/reason/systemerror.rb +3 -2
- data/lib/sisimai/reason/systemfull.rb +4 -3
- data/lib/sisimai/reason/undefined.rb +2 -1
- data/lib/sisimai/reason/userunknown.rb +13 -9
- data/lib/sisimai/reason/vacation.rb +2 -1
- data/lib/sisimai/reason/virusdetected.rb +6 -5
- data/lib/sisimai/reason.rb +45 -40
- data/lib/sisimai/rfc1894.rb +8 -2
- data/lib/sisimai/rfc2045.rb +6 -3
- data/lib/sisimai/rfc3464/thirdparty.rb +10 -9
- data/lib/sisimai/rfc3834.rb +4 -2
- data/lib/sisimai/rhost/aol.rb +3 -2
- data/lib/sisimai/rhost/apple.rb +12 -11
- data/lib/sisimai/rhost/cloudflare.rb +3 -2
- data/lib/sisimai/rhost/cox.rb +38 -37
- data/lib/sisimai/rhost/facebook.rb +17 -16
- data/lib/sisimai/rhost/franceptt.rb +39 -38
- data/lib/sisimai/rhost/godaddy.rb +35 -34
- data/lib/sisimai/rhost/google.rb +22 -21
- data/lib/sisimai/rhost/gsuite.rb +8 -7
- data/lib/sisimai/rhost/iua.rb +11 -10
- data/lib/sisimai/rhost/kddi.rb +3 -2
- data/lib/sisimai/rhost/messagelabs.rb +13 -12
- data/lib/sisimai/rhost/microsoft.rb +33 -32
- data/lib/sisimai/rhost/mimecast.rb +18 -17
- data/lib/sisimai/rhost/nttdocomo.rb +10 -9
- data/lib/sisimai/rhost/outlook.rb +3 -2
- data/lib/sisimai/rhost/spectrum.rb +19 -18
- data/lib/sisimai/rhost/tencent.rb +10 -9
- data/lib/sisimai/rhost/yahooinc.rb +11 -10
- data/lib/sisimai/rhost/zoho.rb +8 -7
- data/lib/sisimai/smtp/command.rb +13 -8
- data/lib/sisimai/smtp/failure.rb +9 -8
- data/lib/sisimai/smtp/reply.rb +23 -22
- data/lib/sisimai/smtp/status.rb +141 -140
- data/lib/sisimai/smtp/transcript.rb +3 -2
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +2 -1
- data/set-of-emails/maildir/bsd/lhost-postfix-81.eml +130 -0
- data/set-of-emails/should-not-crash/go-423-deeply-nested-mime-parts.eml +20050 -0
- metadata +5 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::RequirePTR checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::RequirePTR checks the bounce reason is "RequirePTR" or not. This class is
|
|
4
4
|
# called only from Sisimai::Reason class. This is the error that SMTP connection was rejected
|
|
5
5
|
# due to missing PTR record or having invalid PTR record at the source IP address used for the
|
|
6
6
|
# SMTP connection.
|
|
7
7
|
module RequirePTR
|
|
8
8
|
class << self
|
|
9
|
+
require 'sisimai/eb'
|
|
9
10
|
Index = [
|
|
10
11
|
"cannot find your hostname",
|
|
11
12
|
"cannot resolve your address.",
|
|
@@ -25,7 +26,7 @@ module Sisimai
|
|
|
25
26
|
["service permits ", " unverifyable sending ips"],
|
|
26
27
|
].freeze
|
|
27
28
|
|
|
28
|
-
def text; return
|
|
29
|
+
def text; return Sisimai::Eb::ReQPTR; end
|
|
29
30
|
def description; return 'Email rejected due to missing PTR record or having invalid PTR record'; end
|
|
30
31
|
|
|
31
32
|
# Try to match that the given text and regular expressions
|
|
@@ -44,8 +45,8 @@ module Sisimai
|
|
|
44
45
|
# false: is not blocked due to missing PTR record
|
|
45
46
|
# @see http://www.ietf.org/rfc/rfc5322.txt
|
|
46
47
|
def true(argvs)
|
|
47
|
-
return true if argvs['reason'] ==
|
|
48
|
-
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) ==
|
|
48
|
+
return true if argvs['reason'] == Sisimai::Eb::ReQPTR
|
|
49
|
+
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReQPTR
|
|
49
50
|
return match(argvs['diagnosticcode'].downcase)
|
|
50
51
|
end
|
|
51
52
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::SecurityError checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::SecurityError checks the bounce reason is "SecurityError" or not. This class
|
|
4
4
|
# is called only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that a security violation was detected on a destination mail server. Depends
|
|
7
7
|
# on the security policy on the server, a sender's email address is camouflaged address.
|
|
8
8
|
#
|
|
9
|
-
# Sisimai will set "
|
|
9
|
+
# Sisimai will set "SecurityError" to the reason of email bounce if the value of Status: field
|
|
10
10
|
# in a bounce email is "5.7.*".
|
|
11
11
|
#
|
|
12
12
|
# Action: failed
|
|
@@ -17,6 +17,7 @@ module Sisimai
|
|
|
17
17
|
#
|
|
18
18
|
module SecurityError
|
|
19
19
|
class << self
|
|
20
|
+
require 'sisimai/eb'
|
|
20
21
|
Index = [
|
|
21
22
|
"account not subscribed to ses",
|
|
22
23
|
"authentication credentials invalid",
|
|
@@ -36,7 +37,7 @@ module Sisimai
|
|
|
36
37
|
["user ", " is not authorized to perform ses:sendrawemail on resource"],
|
|
37
38
|
].freeze
|
|
38
39
|
|
|
39
|
-
def text; return
|
|
40
|
+
def text; return Sisimai::Eb::ReSAFE; end
|
|
40
41
|
def description; return 'Email rejected due to security violation was detected on a destination host'; end
|
|
41
42
|
|
|
42
43
|
# Try to match that the given text and regular expressions
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::SpamDetected checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::SpamDetected checks the bounce reason is "SpamDetected" due to Spam content
|
|
4
4
|
# in the message or not. This class is called only Sisimai::Reason class. This is the error that
|
|
5
5
|
# the message you sent was rejected by "spam filter" which is running on the remote host.
|
|
6
6
|
#
|
|
@@ -10,6 +10,7 @@ module Sisimai
|
|
|
10
10
|
# Last-Attempt-Date: Thu, 9 Apr 2008 23:34:45 +0900 (JST)
|
|
11
11
|
module SpamDetected
|
|
12
12
|
class << self
|
|
13
|
+
require 'sisimai/eb'
|
|
13
14
|
Index = [
|
|
14
15
|
"blacklisted url in message",
|
|
15
16
|
"block for spam",
|
|
@@ -65,7 +66,7 @@ module Sisimai
|
|
|
65
66
|
["spam ", "score"],
|
|
66
67
|
].freeze
|
|
67
68
|
|
|
68
|
-
def text; return
|
|
69
|
+
def text; return Sisimai::Eb::ReSPAM; end
|
|
69
70
|
def description; return 'Email rejected by spam filter running on the remote host'; end
|
|
70
71
|
|
|
71
72
|
# Try to match that the given text and regular expressions
|
|
@@ -85,10 +86,10 @@ module Sisimai
|
|
|
85
86
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
86
87
|
def true(argvs)
|
|
87
88
|
return false if argvs['deliverystatus'].empty?
|
|
88
|
-
return true if argvs['reason'] ==
|
|
89
|
-
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) ==
|
|
89
|
+
return true if argvs['reason'] == Sisimai::Eb::ReSPAM
|
|
90
|
+
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReSPAM
|
|
90
91
|
|
|
91
|
-
# The value of "reason" isn't "
|
|
92
|
+
# The value of "reason" isn't "SpamDetected" when the value of "command" is an SMTP command
|
|
92
93
|
# to be sent before the SMTP DATA command because all the MTAs read the headers and the
|
|
93
94
|
# entire message body after the DATA command.
|
|
94
95
|
return false if Sisimai::SMTP::Command::ExceptDATA.include?(argvs['command'])
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::Suppressed checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::Suppressed checks the bounce reason is "Suppressed" or not. This class is called
|
|
4
4
|
# only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that the recipient adddress is listed in the suppression list of the relay
|
|
7
7
|
# server, and was not delivered.
|
|
8
8
|
module Suppressed
|
|
9
9
|
class << self
|
|
10
|
-
|
|
10
|
+
require 'sisimai/eb'
|
|
11
|
+
def text; return Sisimai::Eb::ReSTOP; end
|
|
11
12
|
def description; return "Email was not delivered due to being listed in the suppression list of MTA"; end
|
|
12
13
|
|
|
13
14
|
# Try to match that the given text and regular expressions
|
|
@@ -21,7 +22,7 @@ module Sisimai
|
|
|
21
22
|
# false: is not listed in the suppression list
|
|
22
23
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
23
24
|
def true(argvs)
|
|
24
|
-
return true if argvs['reason'] ==
|
|
25
|
+
return true if argvs['reason'] == Sisimai::Eb::ReSTOP
|
|
25
26
|
return match(argvs['diagnosticcode'].downcase)
|
|
26
27
|
end
|
|
27
28
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::Suspend checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::Suspend checks the bounce reason is "Suspend" or not. This class is called
|
|
4
4
|
# only Sisimai::Reason class. This is the error that a recipient account is being suspended
|
|
5
5
|
# due to unpaid or other reasons.
|
|
6
6
|
module Suspend
|
|
7
7
|
class << self
|
|
8
|
+
require 'sisimai/eb'
|
|
8
9
|
Index = [
|
|
9
10
|
" currently suspended",
|
|
10
11
|
" temporary locked",
|
|
@@ -37,7 +38,7 @@ module Sisimai
|
|
|
37
38
|
["not ", "active"],
|
|
38
39
|
].freeze
|
|
39
40
|
|
|
40
|
-
def text; return
|
|
41
|
+
def text; return Sisimai::Eb::ReQUIT; end
|
|
41
42
|
def description; return 'Email rejected due to a recipient account is being suspended'; end
|
|
42
43
|
|
|
43
44
|
# Try to match that the given text and regular expressions
|
|
@@ -56,7 +57,7 @@ module Sisimai
|
|
|
56
57
|
# false: is not suspended
|
|
57
58
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
58
59
|
def true(argvs)
|
|
59
|
-
return true if argvs['reason'] ==
|
|
60
|
+
return true if argvs['reason'] == Sisimai::Eb::ReQUIT || argvs['replycode'].to_i == 525
|
|
60
61
|
return match(argvs['diagnosticcode'].downcase)
|
|
61
62
|
end
|
|
62
63
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::SyntaxError checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::SyntaxError checks the bounce reason is "SyntaxError" or not. This class is
|
|
4
4
|
# called only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that a destination mail server could not recognize SMTP command which is
|
|
7
|
-
# sent from a sender's MTA. Sisimai will set "
|
|
7
|
+
# sent from a sender's MTA. Sisimai will set "SyntaxError" to the reason if the value of
|
|
8
8
|
# "replycode" begins with "50" such as 502, or 503.
|
|
9
9
|
# Action: failed
|
|
10
10
|
# Status: 5.5.0
|
|
@@ -12,7 +12,8 @@ module Sisimai
|
|
|
12
12
|
#
|
|
13
13
|
module SyntaxError
|
|
14
14
|
class << self
|
|
15
|
-
|
|
15
|
+
require 'sisimai/eb'
|
|
16
|
+
def text; return Sisimai::Eb::ReCOMM; end
|
|
16
17
|
def description; return 'Email rejected due to syntax error at sent commands in SMTP session'; end
|
|
17
18
|
def match(*); return false; end
|
|
18
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::SystemError checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::SystemError checks the bounce reason is "SystemError" or not. This class is
|
|
4
4
|
# called only Sisimai::Reason class. This is the error that an email has bounced due to system
|
|
5
5
|
# error on the remote host such as LDAP connection failure or other internal system error.
|
|
6
6
|
#
|
|
@@ -9,6 +9,7 @@ module Sisimai
|
|
|
9
9
|
# message has been in the queue too long.
|
|
10
10
|
module SystemError
|
|
11
11
|
class << self
|
|
12
|
+
require 'sisimai/eb'
|
|
12
13
|
Index = [
|
|
13
14
|
"aliasing/forwarding loop broken",
|
|
14
15
|
"automatic homedir creator crashed", # qmail-ldap-1.03-20040101.patch:19817 - 19866
|
|
@@ -52,7 +53,7 @@ module Sisimai
|
|
|
52
53
|
["unable to connect ", "daemon"],
|
|
53
54
|
].freeze
|
|
54
55
|
|
|
55
|
-
def text; return
|
|
56
|
+
def text; return Sisimai::Eb::RePROC; end
|
|
56
57
|
def description; return 'Email returned due to system error on the remote host'; end
|
|
57
58
|
|
|
58
59
|
# Try to match that the given text and regular expressions
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::SystemFull checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::SystemFull checks the bounce reason is "SystemFull" or not. This class is called
|
|
4
4
|
# only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that a destination mail server's disk (or spool) is full. Sisimai will set
|
|
7
|
-
#
|
|
7
|
+
# "SystemFull" to the reason of email bounce if the value of Status: field in a bounce email is
|
|
8
8
|
# "4.3.1" or "5.3.1".
|
|
9
9
|
module SystemFull
|
|
10
10
|
class << self
|
|
11
|
+
require 'sisimai/eb'
|
|
11
12
|
Index = [
|
|
12
13
|
'exceeded storage allocation', # MS Exchange
|
|
13
14
|
'mail system full',
|
|
14
15
|
].freeze
|
|
15
16
|
|
|
16
|
-
def text; return
|
|
17
|
+
def text; return Sisimai::Eb::ReDISK; end
|
|
17
18
|
def description; return "Email rejected due to a destination mail server's disk is full"; end
|
|
18
19
|
|
|
19
20
|
# Try to match that the given text and regular expressions
|
|
@@ -3,8 +3,9 @@ module Sisimai
|
|
|
3
3
|
# Sisimai::Reason::Undefined is for only returning text and description. This class is called only
|
|
4
4
|
# from Sisimai.reason method.
|
|
5
5
|
module Undefined
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
class << self
|
|
7
|
-
def text; return
|
|
8
|
+
def text; return Sisimai::Eb::Re___0; end
|
|
8
9
|
def description; return 'Sisimai could not detect an error reason'; end
|
|
9
10
|
def match; return false; end
|
|
10
11
|
def true(*); return false; end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::UserUnknown checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::UserUnknown checks the bounce reason is "UserUnknown" or not. This class is
|
|
4
4
|
# called only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that a local part (Left hand side of @ sign) of a recipient's email address
|
|
7
7
|
# does not exist. In many case, a user has changed internet service provider, or has quit company,
|
|
8
|
-
# or the local part is misspelled. Sisimai will set "
|
|
8
|
+
# or the local part is misspelled. Sisimai will set "UserUnknown" to the reason of email bounce
|
|
9
9
|
# if the value of Status: field in a bounce email is "5.1.1", or connection was refused at SMTP
|
|
10
10
|
# RCPT command, or the contents of Diagnostic-Code: field represents that it is unknown user.
|
|
11
11
|
#
|
|
@@ -14,7 +14,11 @@ module Sisimai
|
|
|
14
14
|
# RCPT TO command)
|
|
15
15
|
module UserUnknown
|
|
16
16
|
class << self
|
|
17
|
-
|
|
17
|
+
require 'sisimai/eb'
|
|
18
|
+
PreMatches = [
|
|
19
|
+
Sisimai::Eb::RePASS, Sisimai::Eb::ReBLOC, Sisimai::Eb::ReFULL,
|
|
20
|
+
Sisimai::Eb::ReMOVE, Sisimai::Eb::ReFROM, Sisimai::Eb::Re00MX,
|
|
21
|
+
]
|
|
18
22
|
ModulePath = {
|
|
19
23
|
'Sisimai::Reason::NoRelaying' => 'sisimai/reason/norelaying',
|
|
20
24
|
'Sisimai::Reason::Blocked' => 'sisimai/reason/blocked',
|
|
@@ -109,7 +113,7 @@ module Sisimai
|
|
|
109
113
|
["user <", "> unknown"],
|
|
110
114
|
].freeze
|
|
111
115
|
|
|
112
|
-
def text; return
|
|
116
|
+
def text; return Sisimai::Eb::ReUSER; end
|
|
113
117
|
def description; return "Email rejected due to a local part of a recipient's email address does not exist"; end
|
|
114
118
|
|
|
115
119
|
# Try to match that the given text and regular expressions
|
|
@@ -122,20 +126,20 @@ module Sisimai
|
|
|
122
126
|
return false
|
|
123
127
|
end
|
|
124
128
|
|
|
125
|
-
# Whether the address is "
|
|
129
|
+
# Whether the address is "UserUnknown" or not
|
|
126
130
|
# @param [Sisimai::Fact] argvs Object to be detected the reason
|
|
127
131
|
# @return [Boolean] true: is unknown user
|
|
128
132
|
# false: is not unknown user.
|
|
129
133
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
130
134
|
def true(argvs)
|
|
131
|
-
return true if argvs['reason'] ==
|
|
135
|
+
return true if argvs['reason'] == Sisimai::Eb::ReUSER
|
|
132
136
|
return false if Sisimai::SMTP::Command::BeforeRCPT.include?(argvs['command'])
|
|
133
137
|
|
|
134
138
|
tempreason = Sisimai::SMTP::Status.name(argvs['deliverystatus'])
|
|
135
|
-
return false if tempreason ==
|
|
139
|
+
return false if tempreason == Sisimai::Eb::ReQUIT
|
|
136
140
|
|
|
137
141
|
issuedcode = argvs['diagnosticcode'].downcase
|
|
138
|
-
if tempreason ==
|
|
142
|
+
if tempreason == Sisimai::Eb::ReUSER
|
|
139
143
|
# *.1.1 = 'Bad destination mailbox address'
|
|
140
144
|
# Status: 5.1.1
|
|
141
145
|
# Diagnostic-Code: SMTP; 550 5.1.1 <***@example.jp>:
|
|
@@ -160,7 +164,7 @@ module Sisimai
|
|
|
160
164
|
end
|
|
161
165
|
return true if matchother == false # Did not match with other message patterns
|
|
162
166
|
|
|
163
|
-
elsif argvs['command'] ==
|
|
167
|
+
elsif argvs['command'] == Sisimai::Eb::CeRCPT
|
|
164
168
|
# When the SMTP command is not "RCPT", the session rejected by other
|
|
165
169
|
# reason, maybe.
|
|
166
170
|
return true if match(issuedcode)
|
|
@@ -4,6 +4,7 @@ module Sisimai
|
|
|
4
4
|
# from Sisimai.reason method.
|
|
5
5
|
module Vacation
|
|
6
6
|
class << self
|
|
7
|
+
require 'sisimai/eb'
|
|
7
8
|
Index = [
|
|
8
9
|
'i am away on vacation',
|
|
9
10
|
'i am away until',
|
|
@@ -11,7 +12,7 @@ module Sisimai
|
|
|
11
12
|
'i will be traveling for work on',
|
|
12
13
|
].freeze
|
|
13
14
|
|
|
14
|
-
def text; return
|
|
15
|
+
def text; return Sisimai::Eb::ReAWAY; end
|
|
15
16
|
def description; return 'Email replied automatically due to a recipient is out of office'; end
|
|
16
17
|
|
|
17
18
|
# Try to match that the given text and regular expressions
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::VirusDetected checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::VirusDetected checks the bounce reason is "VirusDetected" or not. This class
|
|
4
4
|
# is called only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
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 "
|
|
7
|
+
# at a destination mail server. This reason has been divided from "SecurityError" at Sisimai 4.22.0.
|
|
8
8
|
#
|
|
9
9
|
# Your message was infected with a virus. You should download a virus
|
|
10
10
|
# scanner and check your computer for viruses.
|
|
@@ -14,13 +14,14 @@ module Sisimai
|
|
|
14
14
|
#
|
|
15
15
|
module VirusDetected
|
|
16
16
|
class << self
|
|
17
|
+
require 'sisimai/eb'
|
|
17
18
|
Index = ["it has a potentially executable attachment"].freeze
|
|
18
19
|
Pairs = [
|
|
19
20
|
["message was ", "ected", " virus"],
|
|
20
21
|
["virus", " detected"],
|
|
21
22
|
].freeze
|
|
22
23
|
|
|
23
|
-
def text; return
|
|
24
|
+
def text; return Sisimai::Eb::ReEXEC; end
|
|
24
25
|
def description; return 'Email rejected due to a virus scanner on a destination host'; end
|
|
25
26
|
|
|
26
27
|
# Try to match that the given text and regular expressions
|
|
@@ -34,7 +35,7 @@ module Sisimai
|
|
|
34
35
|
return false
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
# The bounce reason is "
|
|
38
|
+
# The bounce reason is "VirusDetected" or not
|
|
38
39
|
# @param [Sisimai::Fact] argvs Object to be detected the reason
|
|
39
40
|
# @return [Boolean] true: virus detected
|
|
40
41
|
# false: virus was not detected
|
|
@@ -44,7 +45,7 @@ module Sisimai
|
|
|
44
45
|
# The value of "reason" isn't "visusdetected" when the value of "command" is an SMTP command
|
|
45
46
|
# to be sent before the SMTP DATA command because all the MTAs read the headers and the
|
|
46
47
|
# entire message body after the DATA command.
|
|
47
|
-
return true if argvs['reason'] ==
|
|
48
|
+
return true if argvs['reason'] == Sisimai::Eb::ReEXEC
|
|
48
49
|
return false if Sisimai::SMTP::Command::ExceptDATA.include?(argvs['command'])
|
|
49
50
|
return match(argvs['diagnosticcode'].downcase)
|
|
50
51
|
end
|
data/lib/sisimai/reason.rb
CHANGED
|
@@ -3,24 +3,28 @@ module Sisimai
|
|
|
3
3
|
# Sisimai::Fact object as an argument of find() method. This class is called only Sisimai::Fact.
|
|
4
4
|
module Reason
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
7
|
+
|
|
6
8
|
# All the error reason list Sisimai support
|
|
7
9
|
# @return [Array] Reason list
|
|
8
10
|
def index
|
|
9
|
-
return
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
return [
|
|
12
|
+
Sisimai::Eb::ReAUTH, Sisimai::Eb::ReFAMA, Sisimai::Eb::ReBLOC, Sisimai::Eb::ReBODY, Sisimai::Eb::ReSIZE,
|
|
13
|
+
Sisimai::Eb::ReTIME, Sisimai::Eb::ReTTLS, Sisimai::Eb::ReFILT, Sisimai::Eb::ReMOVE, Sisimai::Eb::ReHOST,
|
|
14
|
+
Sisimai::Eb::ReFULL, Sisimai::Eb::ReUNIX, Sisimai::Eb::ReINET, Sisimai::Eb::Re00MX, Sisimai::Eb::ReNRFC,
|
|
15
|
+
Sisimai::Eb::ReRATE, Sisimai::Eb::Re___1, Sisimai::Eb::ReFROM, Sisimai::Eb::RePASS, Sisimai::Eb::ReSPAM,
|
|
16
|
+
Sisimai::Eb::ReEXEC, Sisimai::Eb::ReWONT, Sisimai::Eb::ReSAFE, Sisimai::Eb::ReQUIT, Sisimai::Eb::ReQPTR,
|
|
17
|
+
Sisimai::Eb::RePROC, Sisimai::Eb::ReDISK, Sisimai::Eb::ReSTOP, Sisimai::Eb::ReUSER, Sisimai::Eb::ReCOMM,
|
|
14
18
|
]
|
|
15
19
|
end
|
|
16
20
|
|
|
17
|
-
# @abstract is_explicit() returns 0 when the argument is empty or is "
|
|
21
|
+
# @abstract is_explicit() returns 0 when the argument is empty or is "Undefined" or is "OnHold"
|
|
18
22
|
# @param string argv1 Reason name
|
|
19
23
|
# @return bool false: The reaosn is not explicit
|
|
20
24
|
def is_explicit(argv1 = '')
|
|
21
25
|
return false if argv1.nil?
|
|
22
26
|
return false if argv1.empty?
|
|
23
|
-
return false if argv1 ==
|
|
27
|
+
return false if argv1 == Sisimai::Eb::Re___0 || argv1 == Sisimai::Eb::Re___1 || argv1.empty?
|
|
24
28
|
return true
|
|
25
29
|
end
|
|
26
30
|
|
|
@@ -38,29 +42,30 @@ module Sisimai
|
|
|
38
42
|
# @return [Hash] Reason list
|
|
39
43
|
def retry
|
|
40
44
|
return {
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
Sisimai::Eb::Re___0 => true, Sisimai::Eb::Re___1 => true, Sisimai::Eb::RePROC => true,
|
|
46
|
+
Sisimai::Eb::ReSAFE => true, Sisimai::Eb::ReTIME => true, Sisimai::Eb::ReINET => true,
|
|
47
|
+
Sisimai::Eb::ReHOST => true, Sisimai::Eb::ReUSER => true,
|
|
43
48
|
}.freeze
|
|
44
49
|
end
|
|
45
50
|
ModulePath = Sisimai::Reason.path
|
|
46
51
|
GetRetried = Sisimai::Reason.retry
|
|
47
52
|
ClassOrder = [
|
|
48
53
|
# 0. true() meethod in the following reasons are called from Reason->find()
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
[Sisimai::Eb::ReFULL, Sisimai::Eb::ReSIZE, Sisimai::Eb::ReQUIT, Sisimai::Eb::ReMOVE, Sisimai::Eb::RePASS,
|
|
55
|
+
Sisimai::Eb::ReAUTH, Sisimai::Eb::ReUSER, Sisimai::Eb::ReFILT, Sisimai::Eb::ReQPTR, Sisimai::Eb::ReNRFC,
|
|
56
|
+
Sisimai::Eb::ReFAMA, Sisimai::Eb::ReBODY, Sisimai::Eb::ReFROM, Sisimai::Eb::ReHOST, Sisimai::Eb::ReSPAM,
|
|
57
|
+
Sisimai::Eb::ReRATE, Sisimai::Eb::ReBLOC, Sisimai::Eb::ReTTLS, Sisimai::Eb::Re00MX, Sisimai::Eb::ReEXEC,
|
|
58
|
+
Sisimai::Eb::ReWONT],
|
|
59
|
+
|
|
53
60
|
# 1. match() method in the following reasons are called from Reason->find()
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
NoRelaying Suppressed SyntaxError OnHold
|
|
63
|
-
]
|
|
61
|
+
[Sisimai::Eb::ReFULL, Sisimai::Eb::ReSPAM, Sisimai::Eb::ReEXEC, Sisimai::Eb::RePASS, Sisimai::Eb::RePROC,
|
|
62
|
+
Sisimai::Eb::ReINET, Sisimai::Eb::ReQUIT, Sisimai::Eb::ReDISK, Sisimai::Eb::ReSTOP, Sisimai::Eb::ReUNIX,
|
|
63
|
+
Sisimai::Eb::ReSAFE, Sisimai::Eb::ReWONT, Sisimai::Eb::ReCOMM, Sisimai::Eb::ReTIME],
|
|
64
|
+
[Sisimai::Eb::ReFULL, Sisimai::Eb::ReSIZE, Sisimai::Eb::ReQUIT, Sisimai::Eb::ReUSER, Sisimai::Eb::ReFILT,
|
|
65
|
+
Sisimai::Eb::ReFROM, Sisimai::Eb::ReHOST, Sisimai::Eb::ReSPAM, Sisimai::Eb::ReRATE, Sisimai::Eb::ReBLOC,
|
|
66
|
+
Sisimai::Eb::ReAUTH, Sisimai::Eb::ReTTLS, Sisimai::Eb::ReSAFE, Sisimai::Eb::RePROC, Sisimai::Eb::ReINET,
|
|
67
|
+
Sisimai::Eb::ReTIME, Sisimai::Eb::ReBODY, Sisimai::Eb::ReMOVE, Sisimai::Eb::ReDISK, Sisimai::Eb::Re00MX,
|
|
68
|
+
Sisimai::Eb::ReUNIX, Sisimai::Eb::RePASS, Sisimai::Eb::ReSTOP, Sisimai::Eb::ReCOMM, Sisimai::Eb::Re___1],
|
|
64
69
|
]
|
|
65
70
|
|
|
66
71
|
# Detect the bounce reason
|
|
@@ -74,7 +79,7 @@ module Sisimai
|
|
|
74
79
|
# retry() method.
|
|
75
80
|
return argvs['reason'] if argvs['reason'].empty? == false
|
|
76
81
|
end
|
|
77
|
-
return
|
|
82
|
+
return Sisimai::Eb::ReSENT if argvs['deliverystatus'].start_with?('2.')
|
|
78
83
|
|
|
79
84
|
reasontext = ''
|
|
80
85
|
issuedcode = argvs['diagnosticcode'] || ''
|
|
@@ -100,21 +105,21 @@ module Sisimai
|
|
|
100
105
|
end
|
|
101
106
|
end
|
|
102
107
|
|
|
103
|
-
if reasontext.empty? || reasontext ==
|
|
108
|
+
if reasontext.empty? || reasontext == Sisimai::Eb::Re___0
|
|
104
109
|
# Bounce reason is not detected yet.
|
|
105
110
|
reasontext = self.anotherone(argvs)
|
|
106
111
|
|
|
107
|
-
if reasontext ==
|
|
112
|
+
if reasontext == Sisimai::Eb::Re___0 || reasontext.empty?
|
|
108
113
|
# Action: delayed => "expired"
|
|
109
114
|
reasontext = nil
|
|
110
|
-
reasontext ||=
|
|
115
|
+
reasontext ||= Sisimai::Eb::ReTIME if argvs['action'] == Sisimai::Eb::AeSTAY
|
|
111
116
|
return reasontext if reasontext
|
|
112
117
|
|
|
113
118
|
# Try to match with message patterns in Sisimai::Reason::Vacation
|
|
114
119
|
require 'sisimai/reason/vacation'
|
|
115
|
-
reasontext =
|
|
116
|
-
reasontext ||=
|
|
117
|
-
reasontext ||=
|
|
120
|
+
reasontext = Sisimai::Eb::ReAWAY if Sisimai::Reason::Vacation.match(issuedcode.downcase)
|
|
121
|
+
reasontext ||= Sisimai::Eb::Re___1 if issuedcode.empty? == false
|
|
122
|
+
reasontext ||= Sisimai::Eb::Re___0
|
|
118
123
|
end
|
|
119
124
|
end
|
|
120
125
|
return reasontext
|
|
@@ -151,7 +156,7 @@ module Sisimai
|
|
|
151
156
|
end
|
|
152
157
|
|
|
153
158
|
next if r.match(issuedcode) == false
|
|
154
|
-
reasontext = e
|
|
159
|
+
reasontext = e
|
|
155
160
|
break
|
|
156
161
|
end
|
|
157
162
|
break if reasontext.empty? == false
|
|
@@ -160,31 +165,31 @@ module Sisimai
|
|
|
160
165
|
code2digit = statuscode[0, 3] || ''
|
|
161
166
|
if code2digit == '5.6' || code2digit == '4.6'
|
|
162
167
|
# X.6.0 Other or undefined media error
|
|
163
|
-
reasontext =
|
|
168
|
+
reasontext = Sisimai::Eb::ReBODY
|
|
164
169
|
|
|
165
170
|
elsif code2digit == '5.7' || code2digit == '4.7'
|
|
166
171
|
# X.7.0 Other or undefined security status
|
|
167
|
-
reasontext =
|
|
172
|
+
reasontext = Sisimai::Eb::ReSAFE
|
|
168
173
|
|
|
169
174
|
elsif codeformat.start_with?('X-UNIX')
|
|
170
175
|
# Diagnostic-Code: X-UNIX; ...
|
|
171
|
-
reasontext =
|
|
176
|
+
reasontext = Sisimai::Eb::ReUNIX
|
|
172
177
|
|
|
173
178
|
else
|
|
174
179
|
# 50X Syntax Error?
|
|
175
180
|
require 'sisimai/reason/syntaxerror'
|
|
176
|
-
reasontext =
|
|
181
|
+
reasontext = Sisimai::Eb::ReCOMM if Sisimai::Reason::SyntaxError.true(argvs)
|
|
177
182
|
end
|
|
178
183
|
break if reasontext.empty? == false
|
|
179
184
|
|
|
180
185
|
# Check the value of Action: field, first
|
|
181
|
-
if actiontext.start_with?(
|
|
186
|
+
if actiontext.start_with?(Sisimai::Eb::AeSTAY, 'expired')
|
|
182
187
|
# Action: delayed, expired
|
|
183
|
-
reasontext =
|
|
188
|
+
reasontext = Sisimai::Eb::ReTIME
|
|
184
189
|
else
|
|
185
190
|
# Rejected at connection or after EHLO|HELO
|
|
186
191
|
thecommand = argvs['command'] || ''
|
|
187
|
-
reasontext =
|
|
192
|
+
reasontext = Sisimai::Eb::ReBLOC if %w[HELO EHLO].index(thecommand)
|
|
188
193
|
end
|
|
189
194
|
break
|
|
190
195
|
end
|
|
@@ -222,12 +227,12 @@ module Sisimai
|
|
|
222
227
|
|
|
223
228
|
if issuedcode.upcase.include?('X-UNIX; ')
|
|
224
229
|
# X-Unix; ...
|
|
225
|
-
reasontext =
|
|
230
|
+
reasontext = Sisimai::Eb::ReUNIX
|
|
226
231
|
else
|
|
227
232
|
# Detect the bounce reason from "Status:" code
|
|
228
233
|
require 'sisimai/smtp/status'
|
|
229
234
|
reasontext = Sisimai::SMTP::Status.name(Sisimai::SMTP::Status.find(argv1))
|
|
230
|
-
reasontext =
|
|
235
|
+
reasontext = Sisimai::Eb::Re___0 if reasontext.empty?
|
|
231
236
|
end
|
|
232
237
|
return reasontext
|
|
233
238
|
end
|
data/lib/sisimai/rfc1894.rb
CHANGED
|
@@ -2,6 +2,7 @@ module Sisimai
|
|
|
2
2
|
# Sisimai::RFC1894 DSN field defined in RFC3464 (obsoletes RFC1894)
|
|
3
3
|
module RFC1894
|
|
4
4
|
class << self
|
|
5
|
+
require 'sisimai/eb'
|
|
5
6
|
require 'sisimai/string'
|
|
6
7
|
FieldNames = [
|
|
7
8
|
# https://tools.ietf.org/html/rfc3464#section-2.2
|
|
@@ -58,8 +59,13 @@ module Sisimai
|
|
|
58
59
|
}.freeze
|
|
59
60
|
|
|
60
61
|
SubtypeSet = {"addr" => "RFC822", "cdoe" => "SMTP", "host" => "DNS"}.freeze
|
|
61
|
-
ActionList = [
|
|
62
|
-
|
|
62
|
+
ActionList = [Sisimai::Eb::AeFAIL, Sisimai::Eb::AeSTAY, Sisimai::Eb::AeSENT,
|
|
63
|
+
Sisimai::Eb::AePASS, Sisimai::Eb::AeEXPN].freeze
|
|
64
|
+
Correction = {
|
|
65
|
+
'deliverable' => Sisimai::Eb::AeSENT,
|
|
66
|
+
'expired' => Sisimai::Eb::AeFAIL,
|
|
67
|
+
'failure' => Sisimai::Eb::AeFAIL,
|
|
68
|
+
}
|
|
63
69
|
FieldGroup = {
|
|
64
70
|
'original-recipient' => 'addr',
|
|
65
71
|
'final-recipient' => 'addr',
|
data/lib/sisimai/rfc2045.rb
CHANGED
|
@@ -213,14 +213,17 @@ module Sisimai
|
|
|
213
213
|
# Split argv1: multipart/* blocks by a boundary string in argv0
|
|
214
214
|
# @param [String] argv0 The value of Content-Type header
|
|
215
215
|
# @param [String] argv1 A pointer to multipart/* message blocks
|
|
216
|
+
# @param [String] depth Depth of MIME parts
|
|
216
217
|
# @return [Array] List of each part of multipart/*
|
|
217
218
|
# @since v5.0.0
|
|
218
|
-
def levelout(argv0 = '', argv1 = '')
|
|
219
|
+
def levelout(argv0 = '', argv1 = '', depth = 0)
|
|
219
220
|
return [] if argv0.empty?
|
|
220
221
|
return [] if argv1.empty?
|
|
222
|
+
return [] if depth > 100
|
|
221
223
|
|
|
222
224
|
boundary01 = boundary(argv0, 0); return [] if boundary01.empty?
|
|
223
225
|
multiparts = argv1.split(Regexp.new(Regexp.escape(boundary01) + "\n"))
|
|
226
|
+
partsdepth = depth + 1
|
|
224
227
|
partstable = []
|
|
225
228
|
|
|
226
229
|
# Remove empty or useless preamble and epilogue of multipart/* block
|
|
@@ -237,7 +240,7 @@ module Sisimai
|
|
|
237
240
|
bodyinside = f[-1].split("\n\n", 2)[-1]
|
|
238
241
|
next if bodyinside.size < 9 || bodyinside.index(boundary02).nil?
|
|
239
242
|
|
|
240
|
-
v = levelout(f[0], bodyinside)
|
|
243
|
+
v = levelout(f[0], bodyinside, partsdepth)
|
|
241
244
|
partstable += v if v.size > 0
|
|
242
245
|
else
|
|
243
246
|
# The part is not a multipart/* block
|
|
@@ -271,7 +274,7 @@ module Sisimai
|
|
|
271
274
|
# - CHARSET=, BOUNDARY= => charset-, boundary=
|
|
272
275
|
# - message/xdelivery-status => message/delivery-status
|
|
273
276
|
iso2022set = %r/charset=["']?(iso-2022-[-a-z0-9]+)['"]?\b/
|
|
274
|
-
multiparts = levelout(argv0, argv1)
|
|
277
|
+
multiparts = levelout(argv0, argv1, 0)
|
|
275
278
|
flattenout = ''
|
|
276
279
|
delimiters = ["/delivery-status", "/rfc822", "/feedback-report", "/partial"]
|
|
277
280
|
|