sisimai 5.4.0-java → 5.5.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/codecovio.yml +1 -1
- data/.github/workflows/rake-test.yml +1 -1
- data/ChangeLog.md +45 -0
- data/Makefile +2 -4
- data/README-JA.md +23 -20
- data/README.md +23 -20
- data/lib/sisimai/address.rb +92 -44
- data/lib/sisimai/arf.rb +7 -8
- data/lib/sisimai/datetime.rb +2 -2
- data/lib/sisimai/fact/json.rb +1 -2
- data/lib/sisimai/fact/yaml.rb +1 -2
- data/lib/sisimai/fact.rb +60 -35
- data/lib/sisimai/lda.rb +2 -2
- data/lib/sisimai/lhost/activehunter.rb +4 -5
- data/lib/sisimai/lhost/amazonses.rb +3 -4
- data/lib/sisimai/lhost/apachejames.rb +2 -2
- data/lib/sisimai/lhost/biglobe.rb +6 -6
- data/lib/sisimai/lhost/courier.rb +7 -7
- data/lib/sisimai/lhost/domino.rb +6 -6
- data/lib/sisimai/lhost/dragonfly.rb +5 -5
- data/lib/sisimai/lhost/einsundeins.rb +4 -4
- data/lib/sisimai/lhost/exchange2003.rb +7 -7
- data/lib/sisimai/lhost/exchange2007.rb +3 -3
- data/lib/sisimai/lhost/exim.rb +7 -7
- data/lib/sisimai/lhost/ezweb.rb +3 -2
- data/lib/sisimai/lhost/fml.rb +9 -9
- data/lib/sisimai/lhost/gmail.rb +9 -9
- data/lib/sisimai/lhost/gmx.rb +3 -3
- data/lib/sisimai/lhost/googlegroups.rb +6 -7
- data/lib/sisimai/lhost/googleworkspace.rb +5 -6
- data/lib/sisimai/lhost/imailserver.rb +4 -4
- data/lib/sisimai/lhost/kddi.rb +4 -4
- data/lib/sisimai/lhost/mailfoundry.rb +3 -3
- data/lib/sisimai/lhost/{mailmarshalsmtp.rb → mailmarshal.rb} +5 -5
- data/lib/sisimai/lhost/messagingserver.rb +8 -8
- data/lib/sisimai/lhost/mfilter.rb +8 -4
- data/lib/sisimai/lhost/mimecast.rb +105 -0
- data/lib/sisimai/lhost/notes.rb +5 -5
- data/lib/sisimai/lhost/opensmtpd.rb +5 -5
- data/lib/sisimai/lhost/postfix.rb +38 -32
- data/lib/sisimai/lhost/qmail.rb +6 -6
- data/lib/sisimai/lhost/sendmail.rb +13 -13
- data/lib/sisimai/lhost/{interscanmss.rb → trendmicro.rb} +8 -9
- data/lib/sisimai/lhost/v5sendmail.rb +7 -7
- data/lib/sisimai/lhost/verizon.rb +3 -3
- data/lib/sisimai/lhost/x1.rb +7 -4
- data/lib/sisimai/lhost/x2.rb +40 -12
- data/lib/sisimai/lhost/x3.rb +3 -3
- data/lib/sisimai/lhost/x6.rb +2 -2
- data/lib/sisimai/lhost/zoho.rb +5 -5
- data/lib/sisimai/lhost.rb +18 -17
- data/lib/sisimai/mail/maildir.rb +4 -4
- data/lib/sisimai/mail/mbox.rb +4 -4
- data/lib/sisimai/mail/memory.rb +1 -1
- data/lib/sisimai/mail/stdin.rb +2 -2
- data/lib/sisimai/message.rb +34 -34
- data/lib/sisimai/order.rb +5 -4
- data/lib/sisimai/reason/authfailure.rb +1 -1
- data/lib/sisimai/reason/badreputation.rb +1 -1
- data/lib/sisimai/reason/blocked.rb +2 -1
- data/lib/sisimai/reason/contenterror.rb +1 -2
- data/lib/sisimai/reason/exceedlimit.rb +1 -1
- data/lib/sisimai/reason/expired.rb +1 -1
- data/lib/sisimai/reason/failedstarttls.rb +1 -1
- data/lib/sisimai/reason/filtered.rb +1 -1
- data/lib/sisimai/reason/hasmoved.rb +1 -1
- data/lib/sisimai/reason/hostunknown.rb +2 -2
- data/lib/sisimai/reason/mailboxfull.rb +1 -1
- data/lib/sisimai/reason/mailererror.rb +1 -1
- data/lib/sisimai/reason/mesgtoobig.rb +1 -1
- data/lib/sisimai/reason/networkerror.rb +1 -1
- data/lib/sisimai/reason/norelaying.rb +2 -2
- data/lib/sisimai/reason/notaccept.rb +2 -3
- data/lib/sisimai/reason/notcompliantrfc.rb +1 -1
- data/lib/sisimai/reason/policyviolation.rb +2 -4
- data/lib/sisimai/reason/rejected.rb +5 -3
- data/lib/sisimai/reason/requireptr.rb +1 -1
- data/lib/sisimai/reason/securityerror.rb +1 -1
- data/lib/sisimai/reason/spamdetected.rb +1 -1
- data/lib/sisimai/reason/speeding.rb +1 -1
- data/lib/sisimai/reason/suspend.rb +2 -1
- data/lib/sisimai/reason/systemerror.rb +1 -1
- data/lib/sisimai/reason/systemfull.rb +1 -1
- data/lib/sisimai/reason/toomanyconn.rb +1 -1
- data/lib/sisimai/reason/userunknown.rb +4 -3
- data/lib/sisimai/reason/vacation.rb +1 -1
- data/lib/sisimai/reason/virusdetected.rb +1 -1
- data/lib/sisimai/reason.rb +12 -12
- data/lib/sisimai/rfc1123.rb +58 -18
- data/lib/sisimai/rfc1894.rb +6 -8
- data/lib/sisimai/rfc2045.rb +25 -13
- data/lib/sisimai/rfc3464/thirdparty.rb +2 -3
- data/lib/sisimai/rfc3464.rb +6 -6
- data/lib/sisimai/rfc3834.rb +18 -8
- data/lib/sisimai/rfc5322.rb +9 -9
- data/lib/sisimai/rfc791.rb +2 -2
- data/lib/sisimai/rhost/aol.rb +4 -1
- data/lib/sisimai/rhost/apple.rb +11 -7
- data/lib/sisimai/rhost/cox.rb +9 -5
- data/lib/sisimai/rhost/facebook.rb +9 -3
- data/lib/sisimai/rhost/franceptt.rb +86 -37
- data/lib/sisimai/rhost/godaddy.rb +10 -1
- data/lib/sisimai/rhost/google.rb +26 -22
- data/lib/sisimai/rhost/gsuite.rb +1 -1
- data/lib/sisimai/rhost/kddi.rb +1 -1
- data/lib/sisimai/rhost/messagelabs.rb +160 -2
- data/lib/sisimai/rhost/microsoft.rb +80 -29
- data/lib/sisimai/rhost/mimecast.rb +30 -21
- data/lib/sisimai/rhost/nttdocomo.rb +69 -89
- data/lib/sisimai/rhost/outlook.rb +1 -1
- data/lib/sisimai/rhost/spectrum.rb +1 -1
- data/lib/sisimai/rhost/tencent.rb +5 -4
- data/lib/sisimai/rhost/yahooinc.rb +2 -2
- data/lib/sisimai/rhost/zoho.rb +72 -0
- data/lib/sisimai/rhost.rb +5 -4
- data/lib/sisimai/smtp/command.rb +2 -2
- data/lib/sisimai/smtp/reply.rb +11 -4
- data/lib/sisimai/smtp/status.rb +17 -8
- data/lib/sisimai/smtp/transcript.rb +3 -3
- data/lib/sisimai/string.rb +6 -10
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +1 -1
- data/set-of-emails/maildir/bsd/lhost-exim-56.eml +40 -40
- data/set-of-emails/maildir/bsd/lhost-mfilter-05.eml +41 -0
- data/set-of-emails/maildir/bsd/lhost-mimecast-01.eml +46 -0
- data/set-of-emails/maildir/bsd/lhost-mimecast-02.eml +59 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-79.eml +81 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-80.eml +84 -0
- data/set-of-emails/maildir/bsd/lhost-x1-03.eml +26 -0
- data/set-of-emails/maildir/bsd/lhost-x1-04.eml +45 -0
- data/set-of-emails/maildir/bsd/lhost-x2-07.eml +30 -0
- data/set-of-emails/maildir/bsd/rfc3464-66.eml +170 -0
- data/set-of-emails/maildir/bsd/rfc3834-06.eml +59 -0
- data/set-of-emails/maildir/bsd/rhost-apple-05.eml +96 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-01.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-02.eml +86 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-03.eml +87 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-04.eml +86 -0
- data/set-of-emails/maildir/not/rb-issue-368-bug.eml +39 -0
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +27 -9
- /data/set-of-emails/maildir/bsd/{lhost-mailmarshalsmtp-02.eml → lhost-mailmarshal-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-interscanmss-01.eml → lhost-trendmicro-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-interscanmss-02.eml → lhost-trendmicro-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-interscanmss-03.eml → lhost-trendmicro-03.eml} +0 -0
|
@@ -17,7 +17,7 @@ module Sisimai
|
|
|
17
17
|
# @param [String] argv1 String to be matched with regular expressions
|
|
18
18
|
# @return [Boolean] false: Did not match, true: Matched
|
|
19
19
|
def match(argv1)
|
|
20
|
-
return false
|
|
20
|
+
return false if argv1.nil? || argv1.empty?
|
|
21
21
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
22
22
|
return false
|
|
23
23
|
end
|
|
@@ -35,7 +35,7 @@ module Sisimai
|
|
|
35
35
|
# @return [Boolean] false: Did not match, true: Matched
|
|
36
36
|
# @since v4.0.0
|
|
37
37
|
def match(argv1)
|
|
38
|
-
return false
|
|
38
|
+
return false if argv1.nil? || argv1.empty?
|
|
39
39
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
40
40
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
41
41
|
return false
|
|
@@ -55,7 +55,7 @@ module Sisimai
|
|
|
55
55
|
if Sisimai::SMTP::Status.name(statuscode) == 'hostunknown'
|
|
56
56
|
# To prevent classifying DNS errors as "HostUnknown"
|
|
57
57
|
require 'sisimai/reason/networkerror'
|
|
58
|
-
return true
|
|
58
|
+
return true if Sisimai::Reason::NetworkError.match(issuedcode) == false
|
|
59
59
|
else
|
|
60
60
|
# Status: 5.1.2
|
|
61
61
|
# Diagnostic-Code: SMTP; 550 Host unknown
|
|
@@ -66,7 +66,7 @@ module Sisimai
|
|
|
66
66
|
# @param [String] argv1 String to be matched with regular expressions
|
|
67
67
|
# @return [Boolean] false: Did not match, true: Matched
|
|
68
68
|
def match(argv1)
|
|
69
|
-
return false
|
|
69
|
+
return false if argv1.nil? || argv1.empty?
|
|
70
70
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
71
71
|
return false
|
|
72
72
|
end
|
|
@@ -30,7 +30,7 @@ module Sisimai
|
|
|
30
30
|
# @param [String] argv1 String to be matched with regular expressions
|
|
31
31
|
# @return [Boolean] false: Did not match, true: Matched
|
|
32
32
|
def match(argv1)
|
|
33
|
-
return false
|
|
33
|
+
return false if argv1.nil? || argv1.empty?
|
|
34
34
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
35
35
|
return false
|
|
36
36
|
end
|
|
@@ -29,7 +29,7 @@ module Sisimai
|
|
|
29
29
|
# @param [String] argv1 String to be matched with regular expressions
|
|
30
30
|
# @return [Boolean] false: Did not match, true: Matched
|
|
31
31
|
def match(argv1)
|
|
32
|
-
return false
|
|
32
|
+
return false if argv1.nil? || argv1.empty?
|
|
33
33
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
34
34
|
return false
|
|
35
35
|
end
|
|
@@ -36,7 +36,7 @@ module Sisimai
|
|
|
36
36
|
# @param [String] argv1 String to be matched with regular expressions
|
|
37
37
|
# @return [Boolean] false: Did not match, true: Matched
|
|
38
38
|
def match(argv1)
|
|
39
|
-
return false
|
|
39
|
+
return false if argv1.nil? || argv1.empty?
|
|
40
40
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
41
41
|
return false
|
|
42
42
|
end
|
|
@@ -28,7 +28,7 @@ module Sisimai
|
|
|
28
28
|
'specified domain is not allowed',
|
|
29
29
|
"that domain isn't in my list of allowed rcpthost",
|
|
30
30
|
'this system is not configured to relay mail',
|
|
31
|
-
'unable to relay
|
|
31
|
+
'unable to relay ',
|
|
32
32
|
"we don't handle mail for",
|
|
33
33
|
].freeze
|
|
34
34
|
|
|
@@ -39,7 +39,7 @@ module Sisimai
|
|
|
39
39
|
# @param [String] argv1 String to be matched with regular expressions
|
|
40
40
|
# @return [Boolean] false: Did not match, true: Matched
|
|
41
41
|
def match(argv1)
|
|
42
|
-
return false
|
|
42
|
+
return false if argv1.nil? || argv1.empty?
|
|
43
43
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
44
44
|
return false
|
|
45
45
|
end
|
|
@@ -11,9 +11,8 @@ module Sisimai
|
|
|
11
11
|
class << self
|
|
12
12
|
# Destination mail server does not accept any message
|
|
13
13
|
Index = [
|
|
14
|
-
'does not accept mail
|
|
14
|
+
'does not accept mail', # Sendmail
|
|
15
15
|
'host/domain does not accept mail', # iCloud
|
|
16
|
-
'host does not accept mail', # Sendmail
|
|
17
16
|
'mail receiving disabled',
|
|
18
17
|
'name server: .: host not found', # Sendmail
|
|
19
18
|
'no mx record found for domain=', # Oath(Yahoo!)
|
|
@@ -28,7 +27,7 @@ module Sisimai
|
|
|
28
27
|
# @param [String] argv1 String to be matched with regular expressions
|
|
29
28
|
# @return [Boolean] false: Did not match, true: Matched
|
|
30
29
|
def match(argv1)
|
|
31
|
-
return false
|
|
30
|
+
return false if argv1.nil? || argv1.empty?
|
|
32
31
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
33
32
|
return false
|
|
34
33
|
end
|
|
@@ -25,7 +25,7 @@ module Sisimai
|
|
|
25
25
|
# @param [String] argv1 String to be matched with regular expressions
|
|
26
26
|
# @return [Boolean] false: Did not match, true: Matched
|
|
27
27
|
def match(argv1)
|
|
28
|
-
return false
|
|
28
|
+
return false if argv1.nil? || argv1.empty?
|
|
29
29
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
30
30
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
31
31
|
return false
|
|
@@ -19,7 +19,6 @@ module Sisimai
|
|
|
19
19
|
Index = [
|
|
20
20
|
'an illegal attachment on your message',
|
|
21
21
|
'because the recipient is not accepting mail with ', # AOL Phoenix
|
|
22
|
-
'by non-member to a members-only list',
|
|
23
22
|
'closed mailing list',
|
|
24
23
|
'denied by policy',
|
|
25
24
|
'email not accepted for policy reasons',
|
|
@@ -35,9 +34,8 @@ module Sisimai
|
|
|
35
34
|
'messages with multiple addresses',
|
|
36
35
|
'rejected for policy reasons',
|
|
37
36
|
'protocol violation',
|
|
38
|
-
'the email address used to send your message is not subscribed to this group',
|
|
39
37
|
'the message was rejected by organization policy',
|
|
40
|
-
'this message was blocked because its content presents a potential',
|
|
38
|
+
'this message was blocked because its content presents a potential', # https://support.google.com/mail/answer/6590
|
|
41
39
|
'we do not accept messages containing images or other attachments',
|
|
42
40
|
"you're using a mass mailer",
|
|
43
41
|
].freeze
|
|
@@ -53,7 +51,7 @@ module Sisimai
|
|
|
53
51
|
# @return [Boolean] false: Did not match, true: Matched
|
|
54
52
|
# @since 4.22.0
|
|
55
53
|
def match(argv1)
|
|
56
|
-
return false
|
|
54
|
+
return false if argv1.nil? || argv1.empty?
|
|
57
55
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
58
56
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
59
57
|
return false
|
|
@@ -23,11 +23,12 @@ module Sisimai
|
|
|
23
23
|
'access denied (sender blacklisted)',
|
|
24
24
|
'address rejected',
|
|
25
25
|
'administrative prohibition',
|
|
26
|
-
'batv failed to verify', #
|
|
27
|
-
'batv validation failure', #
|
|
26
|
+
'batv failed to verify', # SonicWall
|
|
27
|
+
'batv validation failure', # SonicWall
|
|
28
28
|
'backscatter protection detected an invalid or expired email address', # MDaemon
|
|
29
29
|
"because the sender isn't on the recipient's list of senders to accept mail from",
|
|
30
30
|
'bogus mail from', # IMail - block empty sender
|
|
31
|
+
'by non-member to a members-only list',
|
|
31
32
|
"can't determine purported responsible address",
|
|
32
33
|
'connections not accepted from servers without a valid sender domain',
|
|
33
34
|
'denied [bouncedeny]', # McAfee
|
|
@@ -66,6 +67,7 @@ module Sisimai
|
|
|
66
67
|
'sender was rejected', # qmail
|
|
67
68
|
'spam reporting address', # SendGrid|a message to an address has previously been marked as Spam by the recipient.
|
|
68
69
|
'syntax error: empty email address',
|
|
70
|
+
'the email address used to send your message is not subscribed to this group',
|
|
69
71
|
'the message has been rejected by batv defense',
|
|
70
72
|
'this server does not accept mail from',
|
|
71
73
|
'transaction failed unsigned dsn for',
|
|
@@ -83,7 +85,7 @@ module Sisimai
|
|
|
83
85
|
# @param [String] argv1 String to be matched with regular expressions
|
|
84
86
|
# @return [Boolean] false: Did not match, true: Matched
|
|
85
87
|
def match(argv1)
|
|
86
|
-
return false
|
|
88
|
+
return false if argv1.nil? || argv1.empty?
|
|
87
89
|
return false if IsNot.any? { |a| argv1.include?(a) }
|
|
88
90
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
89
91
|
return false
|
|
@@ -44,7 +44,7 @@ module Sisimai
|
|
|
44
44
|
# @param [String] argv1 String to be matched with regular expressions
|
|
45
45
|
# @return [Boolean] false: Did not match, true: Matched
|
|
46
46
|
def match(argv1)
|
|
47
|
-
return false
|
|
47
|
+
return false if argv1.nil? || argv1.empty?
|
|
48
48
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
49
49
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
50
50
|
return false
|
|
@@ -48,7 +48,7 @@ module Sisimai
|
|
|
48
48
|
# @param [String] argv1 String to be matched with regular expressions
|
|
49
49
|
# @return [Boolean] false: Did not match, true: Matched
|
|
50
50
|
def match(argv1)
|
|
51
|
-
return false
|
|
51
|
+
return false if argv1.nil? || argv1.empty?
|
|
52
52
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
53
53
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
54
54
|
return false
|
|
@@ -122,7 +122,7 @@ module Sisimai
|
|
|
122
122
|
# @param [String] argv1 String to be matched with regular expressions
|
|
123
123
|
# @return [Boolean] false: Did not match, true: Matched
|
|
124
124
|
def match(argv1)
|
|
125
|
-
return false
|
|
125
|
+
return false if argv1.nil? || argv1.empty?
|
|
126
126
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
127
127
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
128
128
|
return false
|
|
@@ -18,7 +18,7 @@ module Sisimai
|
|
|
18
18
|
# @param [String] argv1 String to be matched with regular expressions
|
|
19
19
|
# @return [Boolean] false: Did not match, true: Matched
|
|
20
20
|
def match(argv1)
|
|
21
|
-
return false
|
|
21
|
+
return false if argv1.nil? || argv1.empty?
|
|
22
22
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
23
23
|
return false
|
|
24
24
|
end
|
|
@@ -22,6 +22,7 @@ module Sisimai
|
|
|
22
22
|
'mailbox unavailable or access denied',
|
|
23
23
|
'recipient rejected: temporarily inactive',
|
|
24
24
|
'recipient suspend the service',
|
|
25
|
+
"the email account that you tried to reach is inactive",
|
|
25
26
|
'this account has been disabled or discontinued',
|
|
26
27
|
'this account has been temporarily suspended',
|
|
27
28
|
'this address no longer accepts mail',
|
|
@@ -38,7 +39,7 @@ module Sisimai
|
|
|
38
39
|
# @param [String] argv1 String to be matched with regular expressions
|
|
39
40
|
# @return [Boolean] false: Did not match, true: Matched
|
|
40
41
|
def match(argv1)
|
|
41
|
-
return false
|
|
42
|
+
return false if argv1.nil? || argv1.empty?
|
|
42
43
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
43
44
|
return false
|
|
44
45
|
end
|
|
@@ -45,7 +45,7 @@ module Sisimai
|
|
|
45
45
|
# @param [String] argv1 String to be matched with regular expressions
|
|
46
46
|
# @return [Boolean] false: Did not match, true: Matched
|
|
47
47
|
def match(argv1)
|
|
48
|
-
return false
|
|
48
|
+
return false if argv1.nil? || argv1.empty?
|
|
49
49
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
50
50
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
51
51
|
return false
|
|
@@ -20,7 +20,7 @@ module Sisimai
|
|
|
20
20
|
# @param [String] argv1 String to be matched with regular expressions
|
|
21
21
|
# @return [Boolean] false: Did not match, true: Matched
|
|
22
22
|
def match(argv1)
|
|
23
|
-
return false
|
|
23
|
+
return false if argv1.nil? || argv1.empty?
|
|
24
24
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
25
25
|
return false
|
|
26
26
|
end
|
|
@@ -34,7 +34,7 @@ module Sisimai
|
|
|
34
34
|
# @param [String] argv1 String to be matched with regular expressions
|
|
35
35
|
# @return [Boolean] false: Did not match, true: Matched
|
|
36
36
|
def match(argv1)
|
|
37
|
-
return false
|
|
37
|
+
return false if argv1.nil? || argv1.empty?
|
|
38
38
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
39
39
|
return false
|
|
40
40
|
end
|
|
@@ -112,6 +112,7 @@ module Sisimai
|
|
|
112
112
|
'user unknown',
|
|
113
113
|
'utilisateur inconnu !',
|
|
114
114
|
'vdeliver: invalid or unknown virtual user',
|
|
115
|
+
'weil die adresse nicht gefunden wurde oder keine e-mails empfangen kann',
|
|
115
116
|
'your envelope recipient is in my badrcptto list',
|
|
116
117
|
].freeze
|
|
117
118
|
Pairs = [
|
|
@@ -147,7 +148,7 @@ module Sisimai
|
|
|
147
148
|
# @param [String] argv1 String to be matched with regular expressions
|
|
148
149
|
# @return [Boolean] false: Did not match, true: Matched
|
|
149
150
|
def match(argv1)
|
|
150
|
-
return false
|
|
151
|
+
return false if argv1.nil? || argv1.empty?
|
|
151
152
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
152
153
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
153
154
|
return false
|
|
@@ -183,12 +184,12 @@ module Sisimai
|
|
|
183
184
|
next
|
|
184
185
|
end
|
|
185
186
|
|
|
186
|
-
next
|
|
187
|
+
next if r.match(issuedcode) == false
|
|
187
188
|
# Match with reason defined in Sisimai::Reason::* except UserUnknown.
|
|
188
189
|
matchother = true
|
|
189
190
|
break
|
|
190
191
|
end
|
|
191
|
-
return true
|
|
192
|
+
return true if matchother == false # Did not match with other message patterns
|
|
192
193
|
|
|
193
194
|
elsif argvs['command'] == 'RCPT'
|
|
194
195
|
# When the SMTP command is not "RCPT", the session rejected by other
|
|
@@ -18,7 +18,7 @@ module Sisimai
|
|
|
18
18
|
# @param [String] argv1 String to be matched with regular expressions
|
|
19
19
|
# @return [Boolean] false: Did not match, true: Matched
|
|
20
20
|
def match(argv1)
|
|
21
|
-
return false
|
|
21
|
+
return false if argv1.nil? || argv1.empty?
|
|
22
22
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
23
23
|
return false
|
|
24
24
|
end
|
|
@@ -31,7 +31,7 @@ module Sisimai
|
|
|
31
31
|
# @return [Boolean] false: Did not match, true: Matched
|
|
32
32
|
# @since 4.22.0
|
|
33
33
|
def match(argv1)
|
|
34
|
-
return false
|
|
34
|
+
return false if argv1.nil? || argv1.empty?
|
|
35
35
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
36
36
|
return false
|
|
37
37
|
end
|
data/lib/sisimai/reason.rb
CHANGED
|
@@ -68,11 +68,11 @@ module Sisimai
|
|
|
68
68
|
# @return [String] Bounce reason or an empty string if the argument is missing or not Hash
|
|
69
69
|
# @see anotherone
|
|
70
70
|
def find(argvs)
|
|
71
|
-
return ""
|
|
72
|
-
|
|
71
|
+
return "" if argvs.nil?
|
|
72
|
+
if GetRetried[argvs['reason']].nil?
|
|
73
73
|
# Return reason text already decided except reason match with the regular expression of
|
|
74
74
|
# retry() method.
|
|
75
|
-
return argvs['reason']
|
|
75
|
+
return argvs['reason'] if argvs['reason'].empty? == false
|
|
76
76
|
end
|
|
77
77
|
return 'delivered' if argvs['deliverystatus'].start_with?('2.')
|
|
78
78
|
|
|
@@ -94,7 +94,7 @@ module Sisimai
|
|
|
94
94
|
warn " ***warning: Failed to load #{p}"
|
|
95
95
|
next
|
|
96
96
|
end
|
|
97
|
-
next
|
|
97
|
+
next if r.true(argvs) == false
|
|
98
98
|
reasontext = r.text
|
|
99
99
|
break
|
|
100
100
|
end
|
|
@@ -113,7 +113,7 @@ module Sisimai
|
|
|
113
113
|
# Try to match with message patterns in Sisimai::Reason::Vacation
|
|
114
114
|
require 'sisimai/reason/vacation'
|
|
115
115
|
reasontext = 'vacation' if Sisimai::Reason::Vacation.match(issuedcode.downcase)
|
|
116
|
-
reasontext ||= 'onhold'
|
|
116
|
+
reasontext ||= 'onhold' if issuedcode.empty? == false
|
|
117
117
|
reasontext ||= 'undefined'
|
|
118
118
|
end
|
|
119
119
|
end
|
|
@@ -125,7 +125,7 @@ module Sisimai
|
|
|
125
125
|
# @return [String, Nil] Bounce reason or nli if the argument is missing or not Hash
|
|
126
126
|
# @see find()
|
|
127
127
|
def anotherone(argvs)
|
|
128
|
-
return argvs['reason']
|
|
128
|
+
return argvs['reason'] if argvs['reason'].empty? == false
|
|
129
129
|
|
|
130
130
|
require 'sisimai/smtp/status'
|
|
131
131
|
issuedcode = argvs['diagnosticcode'].downcase || ''
|
|
@@ -150,11 +150,11 @@ module Sisimai
|
|
|
150
150
|
next
|
|
151
151
|
end
|
|
152
152
|
|
|
153
|
-
next
|
|
153
|
+
next if r.match(issuedcode) == false
|
|
154
154
|
reasontext = e.downcase
|
|
155
155
|
break
|
|
156
156
|
end
|
|
157
|
-
break
|
|
157
|
+
break if reasontext.empty? == false
|
|
158
158
|
|
|
159
159
|
# Check the value of Status:
|
|
160
160
|
code2digit = statuscode[0, 3] || ''
|
|
@@ -175,7 +175,7 @@ module Sisimai
|
|
|
175
175
|
require 'sisimai/reason/syntaxerror'
|
|
176
176
|
reasontext = 'syntaxerror' if Sisimai::Reason::SyntaxError.true(argvs)
|
|
177
177
|
end
|
|
178
|
-
break
|
|
178
|
+
break if reasontext.empty? == false
|
|
179
179
|
|
|
180
180
|
# Check the value of Action: field, first
|
|
181
181
|
if actiontext.start_with?('delayed', 'expired')
|
|
@@ -195,7 +195,7 @@ module Sisimai
|
|
|
195
195
|
# @param [String] argv1 Error message
|
|
196
196
|
# @return [String] Bounce reason
|
|
197
197
|
def match(argv1)
|
|
198
|
-
return ""
|
|
198
|
+
return "" if argv1.nil?
|
|
199
199
|
|
|
200
200
|
reasontext = ''
|
|
201
201
|
issuedcode = argv1.downcase
|
|
@@ -214,11 +214,11 @@ module Sisimai
|
|
|
214
214
|
next
|
|
215
215
|
end
|
|
216
216
|
|
|
217
|
-
next
|
|
217
|
+
next if r.match(issuedcode) == false
|
|
218
218
|
reasontext = r.text
|
|
219
219
|
break
|
|
220
220
|
end
|
|
221
|
-
return reasontext
|
|
221
|
+
return reasontext if reasontext.empty? == false
|
|
222
222
|
|
|
223
223
|
if issuedcode.upcase.include?('X-UNIX; ')
|
|
224
224
|
# X-Unix; ...
|
data/lib/sisimai/rfc1123.rb
CHANGED
|
@@ -3,6 +3,7 @@ module Sisimai
|
|
|
3
3
|
module RFC1123
|
|
4
4
|
class << self
|
|
5
5
|
require 'sisimai/string'
|
|
6
|
+
require 'sisimai/rfc791'
|
|
6
7
|
Sandwiched = [
|
|
7
8
|
# (Postfix) postfix/src/smtp/smtp_proto.c: "host %s said: %s (in reply to %s)",
|
|
8
9
|
# - <kijitora@example.com>: host re2.example.com[198.51.100.2] said: 550 ...
|
|
@@ -37,32 +38,72 @@ module Sisimai
|
|
|
37
38
|
# @return [Boolean] false: is not a valid internet host, true: is a valid interneet host
|
|
38
39
|
# @since v5.2.0
|
|
39
40
|
def is_internethost(argv0 = '')
|
|
40
|
-
return false
|
|
41
|
-
return
|
|
41
|
+
return false if argv0.nil? || argv0.size < 4 || argv0.size > 255
|
|
42
|
+
return true if argv0 == 'localhost' || argv0 == 'localhost6'
|
|
42
43
|
return false if argv0.include?(".") == false
|
|
43
44
|
return false if argv0.include?("..") || argv0.include?("--")
|
|
44
45
|
return false if argv0.start_with?(".", "-") || argv0.end_with?("-")
|
|
45
46
|
|
|
46
|
-
hostnameok = true
|
|
47
47
|
characters = argv0.upcase.split("")
|
|
48
48
|
characters.each do |e|
|
|
49
49
|
# Check each characater is a number or an alphabet
|
|
50
50
|
f = e.ord
|
|
51
|
-
if f < 45
|
|
52
|
-
if f == 47
|
|
53
|
-
if f > 57 && f < 65
|
|
54
|
-
if f > 90
|
|
51
|
+
return false if f < 45 # 45 = '-'
|
|
52
|
+
return false if f == 47 # 47 = '/'
|
|
53
|
+
return false if f > 57 && f < 65 # 57 = '9', 65 = 'A'
|
|
54
|
+
return false if f > 90 # 90 = 'Z'
|
|
55
55
|
end
|
|
56
|
-
return false if hostnameok == false
|
|
57
56
|
|
|
58
57
|
p1 = argv0.rindex(".")
|
|
59
58
|
cv = argv0[p1 + 1, argv0.size - p1]; return false if cv.size > 63
|
|
60
59
|
cv.split("").each do |e|
|
|
61
60
|
# The top level domain should not include a number
|
|
62
|
-
f = e.ord
|
|
63
|
-
if f > 47 && f < 58 then hostnameok = false; break; end
|
|
61
|
+
f = e.ord; return false if f > 47 && f < 58
|
|
64
62
|
end
|
|
65
|
-
return
|
|
63
|
+
return true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# returns true if the domain part is [IPv4:...] or [IPv6:...].
|
|
67
|
+
# @param [String] email Email address.
|
|
68
|
+
# @return [Boolean] false: the domain part is not a domain literal.
|
|
69
|
+
# true: the domain part is a domain literal.
|
|
70
|
+
def is_domainliteral(email)
|
|
71
|
+
return false if email.is_a?(::String) == false
|
|
72
|
+
|
|
73
|
+
email = email.delete_prefix('<').delete_suffix('>')
|
|
74
|
+
return false if email.size < 16 # e@[IPv4:0.0.0.0] is 16 characters
|
|
75
|
+
return false if email[-1, 1] != ']'
|
|
76
|
+
|
|
77
|
+
lastb = email.rindex('@[IPv'); return false if lastb == false
|
|
78
|
+
dpart = email.split('@')[-1]
|
|
79
|
+
|
|
80
|
+
if email.include?('@[IPv4:')
|
|
81
|
+
# neko@[IPv4:192.0.2.25]
|
|
82
|
+
ipv4a = email[lastb + 7, 16].delete_suffix(']')
|
|
83
|
+
return Sisimai::RFC791.is_ipv4address(ipv4a)
|
|
84
|
+
|
|
85
|
+
elsif email.include?('@[IPv6:')
|
|
86
|
+
# neko@[IPv6:2001:0DB8:0000:0000:0000:0000:0000:0001]
|
|
87
|
+
# neko@[IPv6:2001:0DB8:0000:0000:0000:0000:0000:0001]
|
|
88
|
+
# IPv6-address-literal = "IPv6:" IPv6-addr
|
|
89
|
+
# IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
|
|
90
|
+
# IPv6-hex = 1*4HEXDIG
|
|
91
|
+
# IPv6-full = IPv6-hex 7(":" IPv6-hex)
|
|
92
|
+
# IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
|
|
93
|
+
# [IPv6-hex *5(":" IPv6-hex)]
|
|
94
|
+
# ; The "::" represents at least 2 16-bit groups of
|
|
95
|
+
# ; zeros. No more than 6 groups in addition to the
|
|
96
|
+
# ; "::" may be present.
|
|
97
|
+
# IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
|
|
98
|
+
# IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
|
|
99
|
+
# [IPv6-hex *3(":" IPv6-hex) ":"]
|
|
100
|
+
# IPv4-address-literal
|
|
101
|
+
# ; The "::" represents at least 2 16-bit groups of
|
|
102
|
+
# ; zeros. No more than 4 groups in addition to the
|
|
103
|
+
# ; "::" and IPv4-address-literal may be present.
|
|
104
|
+
return true if dpart.size > 2 && dpart.rindex(':') > 7
|
|
105
|
+
end
|
|
106
|
+
return false
|
|
66
107
|
end
|
|
67
108
|
|
|
68
109
|
# find() returns a valid internet hostname found from the argument
|
|
@@ -70,8 +111,7 @@ module Sisimai
|
|
|
70
111
|
# @return string A valid internet hostname found in the argument
|
|
71
112
|
# @since v5.2.0
|
|
72
113
|
def find(argv1 = "")
|
|
73
|
-
return ""
|
|
74
|
-
return "" unless argv1.size > 4
|
|
114
|
+
return "" if argv1.nil? || argv1.size < 5
|
|
75
115
|
|
|
76
116
|
sourcetext = argv1.downcase
|
|
77
117
|
sourcelist = []
|
|
@@ -91,7 +131,7 @@ module Sisimai
|
|
|
91
131
|
Sandwiched.each do |e|
|
|
92
132
|
# Check a hostname exists between the $e->[0] and $e->[1] at array "Sandwiched"
|
|
93
133
|
# Each array in Sandwiched have 2 elements
|
|
94
|
-
next
|
|
134
|
+
next if Sisimai::String.aligned(sourcetext, e) == false
|
|
95
135
|
|
|
96
136
|
p1 = sourcetext.index(e[0])
|
|
97
137
|
p2 = sourcetext.index(e[1])
|
|
@@ -112,7 +152,7 @@ module Sisimai
|
|
|
112
152
|
end
|
|
113
153
|
ExistUntil.each do |e|
|
|
114
154
|
# ExistUntil have some strings, not an array
|
|
115
|
-
p1 = sourcetext.index(e); next
|
|
155
|
+
p1 = sourcetext.index(e); next if p1.nil?
|
|
116
156
|
sourcelist = sourcetext[0, p1].split(" ")
|
|
117
157
|
throw :MAKELIST
|
|
118
158
|
end
|
|
@@ -126,9 +166,9 @@ module Sisimai
|
|
|
126
166
|
e.chop! if e[-1, 1] == "." # Remove "." at the end of the string
|
|
127
167
|
e.delete!('[]()<>:;')
|
|
128
168
|
|
|
129
|
-
next
|
|
130
|
-
next
|
|
131
|
-
next
|
|
169
|
+
next if e.size < 4
|
|
170
|
+
next if e.include?(".") == false
|
|
171
|
+
next if Sisimai::RFC1123.is_internethost(e) == false
|
|
132
172
|
foundtoken << e
|
|
133
173
|
end
|
|
134
174
|
return "" if foundtoken.size == 0
|
data/lib/sisimai/rfc1894.rb
CHANGED
|
@@ -59,7 +59,7 @@ module Sisimai
|
|
|
59
59
|
|
|
60
60
|
SubtypeSet = {"addr" => "RFC822", "cdoe" => "SMTP", "host" => "DNS"}.freeze
|
|
61
61
|
ActionList = ["failed", "delayed", "delivered", "relayed", "expanded"].freeze
|
|
62
|
-
Correction = {'deliverable' => 'delivered', 'expired' => '
|
|
62
|
+
Correction = {'deliverable' => 'delivered', 'expired' => 'failed', 'failure' => 'failed'}
|
|
63
63
|
FieldGroup = {
|
|
64
64
|
'original-recipient' => 'addr',
|
|
65
65
|
'final-recipient' => 'addr',
|
|
@@ -114,16 +114,16 @@ module Sisimai
|
|
|
114
114
|
|
|
115
115
|
FieldNames[0].each_key do |e|
|
|
116
116
|
# Per-Message fields
|
|
117
|
-
next
|
|
118
|
-
next
|
|
117
|
+
next if label != e
|
|
118
|
+
next if argv0.include?(FieldNames[0][label]) == false
|
|
119
119
|
match = 1; break
|
|
120
120
|
end
|
|
121
121
|
return match if match > 0
|
|
122
122
|
|
|
123
123
|
FieldNames[1].each_key do |e|
|
|
124
124
|
# Per-Recipient field
|
|
125
|
-
next
|
|
126
|
-
next
|
|
125
|
+
next if label != e
|
|
126
|
+
next if argv0.include?(FieldNames[1][label]) == false
|
|
127
127
|
match = 2; break
|
|
128
128
|
end
|
|
129
129
|
return match
|
|
@@ -147,9 +147,7 @@ module Sisimai
|
|
|
147
147
|
label = Sisimai::RFC1894.label(argv0)
|
|
148
148
|
group = FieldGroup[label] || ''
|
|
149
149
|
parts = argv0.split(":", 2); parts[1] = parts[1].nil? ? "" : Sisimai::String.sweep(parts[1])
|
|
150
|
-
|
|
151
|
-
return nil if group.empty?
|
|
152
|
-
return nil unless CapturesOn[group]
|
|
150
|
+
return nil if group.empty? || CapturesOn[group].nil?
|
|
153
151
|
|
|
154
152
|
# Try to match with each pattern of Per-Message field, Per-Recipient field
|
|
155
153
|
# - 0: Field-Name
|