sisimai 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rake-test.yml +1 -1
- data/ChangeLog.md +102 -0
- data/Makefile +4 -2
- data/README-JA.md +23 -16
- data/README.md +22 -15
- data/lib/sisimai/arf.rb +121 -210
- data/lib/sisimai/fact.rb +208 -158
- data/lib/sisimai/lda.rb +98 -0
- data/lib/sisimai/lhost/activehunter.rb +1 -1
- data/lib/sisimai/lhost/amazonses.rb +185 -301
- data/lib/sisimai/lhost/apachejames.rb +48 -51
- data/lib/sisimai/lhost/biglobe.rb +1 -2
- data/lib/sisimai/lhost/courier.rb +10 -8
- data/lib/sisimai/lhost/domino.rb +25 -25
- data/lib/sisimai/lhost/dragonfly.rb +3 -4
- data/lib/sisimai/lhost/einsundeins.rb +3 -4
- data/lib/sisimai/lhost/exchange2003.rb +6 -8
- data/lib/sisimai/lhost/exchange2007.rb +111 -101
- data/lib/sisimai/lhost/exim.rb +232 -242
- data/lib/sisimai/lhost/ezweb.rb +43 -51
- data/lib/sisimai/lhost/fml.rb +2 -3
- data/lib/sisimai/lhost/gmail.rb +32 -28
- data/lib/sisimai/lhost/gmx.rb +4 -16
- data/lib/sisimai/lhost/googlegroups.rb +9 -8
- data/lib/sisimai/lhost/googleworkspace.rb +94 -0
- data/lib/sisimai/lhost/imailserver.rb +7 -16
- data/lib/sisimai/lhost/interscanmss.rb +1 -1
- data/lib/sisimai/lhost/kddi.rb +3 -4
- data/lib/sisimai/lhost/mailfoundry.rb +2 -5
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +1 -2
- data/lib/sisimai/lhost/messagingserver.rb +14 -13
- data/lib/sisimai/lhost/mfilter.rb +4 -3
- data/lib/sisimai/lhost/notes.rb +2 -4
- data/lib/sisimai/lhost/opensmtpd.rb +2 -2
- data/lib/sisimai/lhost/postfix.rb +25 -27
- data/lib/sisimai/lhost/qmail.rb +130 -106
- data/lib/sisimai/lhost/sendmail.rb +19 -18
- data/lib/sisimai/lhost/v5sendmail.rb +88 -60
- data/lib/sisimai/lhost/verizon.rb +2 -2
- data/lib/sisimai/lhost/x1.rb +1 -1
- data/lib/sisimai/lhost/x2.rb +1 -2
- data/lib/sisimai/lhost/x3.rb +2 -2
- data/lib/sisimai/lhost/x6.rb +1 -1
- data/lib/sisimai/lhost/zoho.rb +2 -2
- data/lib/sisimai/lhost.rb +18 -21
- data/lib/sisimai/message.rb +93 -146
- data/lib/sisimai/order.rb +21 -77
- data/lib/sisimai/reason/authfailure.rb +1 -4
- data/lib/sisimai/reason/badreputation.rb +2 -2
- data/lib/sisimai/reason/blocked.rb +7 -10
- data/lib/sisimai/reason/contenterror.rb +7 -1
- data/lib/sisimai/reason/exceedlimit.rb +1 -4
- data/lib/sisimai/reason/failedstarttls.rb +42 -0
- data/lib/sisimai/reason/filtered.rb +5 -4
- data/lib/sisimai/reason/hasmoved.rb +1 -2
- data/lib/sisimai/reason/hostunknown.rb +3 -3
- data/lib/sisimai/reason/mailboxfull.rb +2 -4
- data/lib/sisimai/reason/mailererror.rb +1 -2
- data/lib/sisimai/reason/mesgtoobig.rb +2 -4
- data/lib/sisimai/reason/norelaying.rb +2 -3
- data/lib/sisimai/reason/notaccept.rb +2 -3
- data/lib/sisimai/reason/notcompliantrfc.rb +10 -4
- data/lib/sisimai/reason/rejected.rb +1 -1
- data/lib/sisimai/reason/requireptr.rb +2 -2
- data/lib/sisimai/reason/securityerror.rb +1 -3
- data/lib/sisimai/reason/spamdetected.rb +6 -8
- data/lib/sisimai/reason/speeding.rb +1 -2
- data/lib/sisimai/reason/suppressed.rb +36 -0
- data/lib/sisimai/reason/suspend.rb +1 -3
- data/lib/sisimai/reason/systemerror.rb +5 -0
- data/lib/sisimai/reason/toomanyconn.rb +1 -2
- data/lib/sisimai/reason/userunknown.rb +1 -1
- data/lib/sisimai/reason/virusdetected.rb +5 -6
- data/lib/sisimai/reason.rb +77 -73
- data/lib/sisimai/rfc1123.rb +152 -0
- data/lib/sisimai/rfc1894.rb +102 -62
- data/lib/sisimai/rfc2045.rb +2 -1
- data/lib/sisimai/rfc3464/thirdparty.rb +102 -0
- data/lib/sisimai/rfc3464.rb +222 -343
- data/lib/sisimai/rfc3834.rb +1 -1
- data/lib/sisimai/rfc5322.rb +7 -17
- data/lib/sisimai/rfc791.rb +69 -0
- data/lib/sisimai/rhost/aol.rb +36 -0
- data/lib/sisimai/rhost/apple.rb +5 -2
- data/lib/sisimai/rhost/cox.rb +3 -2
- data/lib/sisimai/rhost/facebook.rb +100 -0
- data/lib/sisimai/rhost/franceptt.rb +3 -2
- data/lib/sisimai/rhost/godaddy.rb +3 -2
- data/lib/sisimai/rhost/google.rb +19 -17
- data/lib/sisimai/rhost/gsuite.rb +42 -0
- data/lib/sisimai/rhost/iua.rb +3 -3
- data/lib/sisimai/rhost/kddi.rb +3 -2
- data/lib/sisimai/rhost/messagelabs.rb +37 -0
- data/lib/sisimai/rhost/microsoft.rb +56 -49
- data/lib/sisimai/rhost/mimecast.rb +29 -27
- data/lib/sisimai/rhost/nttdocomo.rb +4 -3
- data/lib/sisimai/rhost/outlook.rb +36 -0
- data/lib/sisimai/rhost/spectrum.rb +3 -2
- data/lib/sisimai/rhost/tencent.rb +3 -2
- data/lib/sisimai/rhost/yahooinc.rb +4 -3
- data/lib/sisimai/rhost.rb +69 -39
- data/lib/sisimai/smtp/command.rb +31 -21
- data/lib/sisimai/smtp/failure.rb +103 -0
- data/lib/sisimai/smtp/reply.rb +29 -25
- data/lib/sisimai/smtp/status.rb +36 -19
- data/lib/sisimai/smtp/transcript.rb +15 -15
- data/lib/sisimai/string.rb +0 -46
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/maildir/bsd/lhost-postfix-30.eml +81 -81
- data/set-of-emails/maildir/bsd/{lhost-aol-03.eml → rhost-aol-03.eml} +1264 -1264
- data/set-of-emails/maildir/bsd/{lhost-aol-04.eml → rhost-aol-04.eml} +1260 -1260
- data/set-of-emails/maildir/bsd/{lhost-aol-05.eml → rhost-aol-05.eml} +105 -105
- data/set-of-emails/maildir/bsd/{lhost-aol-06.eml → rhost-aol-06.eml} +105 -105
- data/set-of-emails/maildir/bsd/rhost-gsuite-01.eml +189 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-02.eml +180 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-03.eml +251 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-04.eml +211 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-05.eml +226 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-06.eml +257 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-07.eml +289 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-08.eml +231 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-09.eml +231 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-10.eml +254 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-11.eml +228 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-12.eml +271 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-13.eml +261 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-14.eml +273 -0
- data/set-of-emails/maildir/bsd/rhost-gsuite-15.eml +229 -0
- data/set-of-emails/maildir/bsd/{lhost-messagelabs-01.eml → rhost-messagelabs-01.eml} +93 -93
- data/set-of-emails/maildir/bsd/rhost-outlook-01.eml +72 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-02.eml +72 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-03.eml +72 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-04.eml +79 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-06.eml +75 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-07.eml +70 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-08.eml +70 -0
- data/set-of-emails/maildir/bsd/rhost-outlook-09.eml +56 -0
- data/set-of-emails/maildir/tmp/arf-22.eml +49 -0
- data/set-of-emails/maildir/tmp/arf-23.eml +49 -0
- data/set-of-emails/maildir/tmp/arf-24.eml +50 -0
- data/set-of-emails/maildir/tmp/lhost-exim-07.eml +28 -0
- metadata +73 -56
- data/lib/sisimai/lhost/amavis.rb +0 -163
- data/lib/sisimai/lhost/amazonworkmail.rb +0 -127
- data/lib/sisimai/lhost/aol.rb +0 -125
- data/lib/sisimai/lhost/barracuda.rb +0 -92
- data/lib/sisimai/lhost/bigfoot.rb +0 -125
- data/lib/sisimai/lhost/facebook.rb +0 -188
- data/lib/sisimai/lhost/gsuite.rb +0 -194
- data/lib/sisimai/lhost/mailru.rb +0 -214
- data/lib/sisimai/lhost/mcafee.rb +0 -109
- data/lib/sisimai/lhost/messagelabs.rb +0 -120
- data/lib/sisimai/lhost/mxlogic.rb +0 -198
- data/lib/sisimai/lhost/office365.rb +0 -252
- data/lib/sisimai/lhost/outlook.rb +0 -129
- data/lib/sisimai/lhost/powermta.rb +0 -118
- data/lib/sisimai/lhost/receivingses.rb +0 -126
- data/lib/sisimai/lhost/sendgrid.rb +0 -150
- data/lib/sisimai/lhost/surfcontrol.rb +0 -105
- data/lib/sisimai/lhost/x4.rb +0 -269
- data/lib/sisimai/lhost/x5.rb +0 -112
- data/lib/sisimai/lhost/yahoo.rb +0 -102
- data/lib/sisimai/lhost/yandex.rb +0 -118
- data/lib/sisimai/mda.rb +0 -121
- data/lib/sisimai/smtp/error.rb +0 -119
- /data/set-of-emails/maildir/bsd/{lhost-googlegroups-15.eml → lhost-googleworkspace-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-x4-08.eml → lhost-x2-06.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-01.eml → rfc3464-51.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-03.eml → rfc3464-52.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-04.eml → rfc3464-53.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-05.eml → rfc3464-54.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-06.eml → rfc3464-55.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-07.eml → rfc3464-56.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-08.eml → rfc3464-57.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-09.eml → rfc3464-58.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-10.eml → rfc3464-59.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-11.eml → rfc3464-60.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-12.eml → rfc3464-61.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-13.eml → rfc3464-62.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-14.eml → rfc3464-63.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-15.eml → rfc3464-64.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-gsuite-02.eml → rfc3464-65.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-aol-01.eml → rhost-aol-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-aol-02.eml → rhost-aol-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-facebook-03.eml → rhost-facebook-03.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-facebook-04.eml → rhost-facebook-04.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-messagelabs-02.eml → rhost-messagelabs-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-messagelabs-03.eml → rhost-messagelabs-03.eml} +0 -0
- /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-37.eml +0 -0
- /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-38.eml +0 -0
- /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-39.eml +0 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
module Sisimai
|
2
|
+
module SMTP
|
3
|
+
# Sisimai::SMTP::Failure is utilities for checking SMTP Errors from error message text.
|
4
|
+
module Failure
|
5
|
+
class << self
|
6
|
+
require 'sisimai/smtp/reply'
|
7
|
+
require 'sisimai/smtp/status'
|
8
|
+
|
9
|
+
# Returns true if the given string indicates a permanent error
|
10
|
+
# @param [String] argv1 String including SMTP Status code
|
11
|
+
# @return [Boolean] true: Permanet error
|
12
|
+
# false: Is not a permanent error
|
13
|
+
# @since v4.17.3
|
14
|
+
def is_permanent(argv1 = '')
|
15
|
+
return false unless argv1
|
16
|
+
return false unless argv1.size > 0
|
17
|
+
|
18
|
+
statuscode = Sisimai::SMTP::Status.find(argv1)
|
19
|
+
statuscode = Sisimai::SMTP::Reply.find(argv1) if statuscode.empty?
|
20
|
+
return true if statuscode[0, 1] == "5"
|
21
|
+
return true if argv1.downcase.include?(' permanent ')
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns true if the given string indicates a temporary error
|
26
|
+
# @param [String] argv1 String including SMTP Status code
|
27
|
+
# @return [Boolean] true: Temporary error
|
28
|
+
# false: is not a temporary error
|
29
|
+
# @since v5.2.0
|
30
|
+
def is_temporary(argv1 = '')
|
31
|
+
return false unless argv1
|
32
|
+
return false unless argv1.size > 0
|
33
|
+
|
34
|
+
statuscode = Sisimai::SMTP::Status.find(argv1);
|
35
|
+
statuscode = Sisimai::SMTP::Reply.find(argv1) if statuscode.empty?
|
36
|
+
issuedcode = argv1.downcase
|
37
|
+
|
38
|
+
return true if statuscode[0, 1] == "4"
|
39
|
+
return true if issuedcode.include?(' temporar')
|
40
|
+
return true if issuedcode.include?(' persistent')
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
|
44
|
+
# Checks the reason sisimai detected is a hard bounce or not
|
45
|
+
# @param [String] argv1 Detected bounce reason
|
46
|
+
# @param [String] argv2 String including SMTP Status code
|
47
|
+
# @return [Boolean] true: is a hard bounce
|
48
|
+
def is_hardbounce(argv1 = '', argv2 = '')
|
49
|
+
return false unless argv1
|
50
|
+
return false unless argv1.size > 0
|
51
|
+
|
52
|
+
return false if argv1 == "undefined" || argv1 == "onhold"
|
53
|
+
return false if argv1 == "delivered" || argv1 == "feedback" || argv1 == "vacation"
|
54
|
+
return true if argv1 == "hasmoved" || argv1 == "userunknown" || argv1 == "hostunknown"
|
55
|
+
return false if argv1 != "notaccept"
|
56
|
+
|
57
|
+
# NotAccept: 5xx => hard bounce, 4xx => soft bounce
|
58
|
+
hardbounce = false
|
59
|
+
if argv2.size > 0
|
60
|
+
# Check the 2nd argument(a status code or a reply code)
|
61
|
+
cv = Sisimai::SMTP::Status.find(argv2, "")
|
62
|
+
cv = Sisimai::SMTP::Reply.find(argv2, "") if cv.empty?
|
63
|
+
|
64
|
+
# The SMTP status code or the SMTP reply code starts with "5"
|
65
|
+
# Deal as a hard bounce when the error message does not indicate a temporary error
|
66
|
+
hardbounce = true if cv[0, 1] == "5" || Sisimai::SMTP::Failure.is_temporary(argv2) == false
|
67
|
+
else
|
68
|
+
# Deal "NotAccept" as a hard bounce when the 2nd argument is empty
|
69
|
+
hardbounce = true
|
70
|
+
end
|
71
|
+
return hardbounce
|
72
|
+
end
|
73
|
+
|
74
|
+
# Checks the reason sisimai detected is a soft bounce or not
|
75
|
+
# @param [String] argv1 Detected bounce reason
|
76
|
+
# @param [String] argv2 String including SMTP Status code
|
77
|
+
# @return [Boolean] true: is a soft bounce
|
78
|
+
def is_softbounce(argv1 = '', argv2 = '')
|
79
|
+
return false unless argv1
|
80
|
+
return false unless argv1.size > 0
|
81
|
+
|
82
|
+
return false if argv1 == "delivered" || argv1 == "feedback" || argv1 == "vacation"
|
83
|
+
return false if argv1 == "hasmoved" || argv1 == "userunknown" || argv1 == "hostunknown"
|
84
|
+
return true if argv1 == "undefined" || argv1 == "onhold"
|
85
|
+
return true if argv1 != "notaccept"
|
86
|
+
|
87
|
+
# NotAccept: 5xx => hard bounce, 4xx => soft bounce
|
88
|
+
softbounce = false
|
89
|
+
if argv2.size > 0
|
90
|
+
# Check the 2nd argument(a status code or a reply code)
|
91
|
+
cv = Sisimai::SMTP::Status.find(argv2, "")
|
92
|
+
cv = Sisimai::SMTP::Reply.find(argv2, "") if cv.empty?
|
93
|
+
|
94
|
+
# The SMTP status code or the SMTP reply code starts with "4"
|
95
|
+
softbounce = true if cv[0, 1] == "4"
|
96
|
+
end
|
97
|
+
return softbounce
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/sisimai/smtp/reply.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# http://www.ietf.org/rfc/rfc5321.txt
|
2
|
+
# -------------------------------------------------------------------------------------------------
|
2
3
|
# 4.2.1. Reply Code Severities and Theory
|
3
4
|
#
|
4
5
|
# There are four values for the first digit of the reply code:
|
@@ -103,32 +104,32 @@ module Sisimai
|
|
103
104
|
# 554 Transaction failed (Or, in the case of a connection-opening response, "No SMTP service here")
|
104
105
|
# 555 MAIL FROM/RCPT TO parameters not recognized or not implemented
|
105
106
|
# 556 Domain does not accept mail (See RFC7504)
|
107
|
+
# 557 draft-moore-email-addrquery-01
|
106
108
|
'550', '552', '553', '551', '521', '525', '502', '520', '523', '524', '530', '533', '534',
|
107
|
-
'535', '538', '551', '555', '556', '554', '500', '501', '502', '503', '504',
|
109
|
+
'535', '538', '551', '555', '556', '554', '557', '500', '501', '502', '503', '504',
|
108
110
|
].freeze
|
109
111
|
CodeOfSMTP = { '2' => ReplyCode2, '4' => ReplyCode4, '5' => ReplyCode5 }.freeze
|
110
112
|
|
111
113
|
# Check whether a reply code is a valid code or not
|
112
114
|
# @param [String] argv1 Reply Code(DSN)
|
113
|
-
# @return [Boolean]
|
115
|
+
# @return [Boolean] false = Invalid reply code, true = Valid reply code
|
114
116
|
# @see code
|
115
117
|
# @since v5.0.0
|
116
118
|
def test(argv1 = '')
|
117
|
-
return
|
119
|
+
return false if argv1.empty?
|
118
120
|
|
119
121
|
reply = argv1.to_i
|
120
122
|
first = (reply / 100).to_i
|
121
123
|
|
122
|
-
return false if reply <
|
123
|
-
return false if reply >
|
124
|
+
return false if reply < 211
|
125
|
+
return false if reply > 557
|
124
126
|
return false if reply % 100 > 59
|
125
127
|
|
126
128
|
if first == 2
|
127
129
|
# 2yz
|
128
|
-
return true if reply == 235
|
129
|
-
return false if reply
|
130
|
-
return false if reply >
|
131
|
-
return false if reply > 221 && reply < 250
|
130
|
+
return true if reply == 235 # 235 is a valid code for AUTH (RFC4954)
|
131
|
+
return false if reply > 253 # The maximum code of 2xy is 253 (RFC5248)
|
132
|
+
return false if reply > 221 && reply < 250 # There is no reply code between 221 and 250
|
132
133
|
return true
|
133
134
|
end
|
134
135
|
|
@@ -147,34 +148,37 @@ module Sisimai
|
|
147
148
|
# @return [String] SMTP Reply Code
|
148
149
|
# [Nil] The first argument did not include SMTP Reply Code value
|
149
150
|
def find(argv1 = '', argv2 = '0')
|
150
|
-
return
|
151
|
-
return
|
151
|
+
return "" if argv1.to_s.size < 3
|
152
|
+
return "" if argv1.upcase.include?('X-UNIX')
|
152
153
|
|
154
|
+
esmtperror = ' ' + argv1 + ' '
|
155
|
+
esmtpreply = ''
|
153
156
|
statuscode = argv2[0, 1]
|
154
157
|
replycodes = if statuscode == '5' || statuscode == '4' || statuscode == '2'
|
155
158
|
CodeOfSMTP[statuscode]
|
156
159
|
else
|
157
160
|
[*CodeOfSMTP['5'], *CodeOfSMTP['4'], *CodeOfSMTP['2']]
|
158
161
|
end
|
159
|
-
esmtperror = ' ' + argv1 + ' '
|
160
|
-
esmtpreply = '' # SMTP Reply Code
|
161
|
-
replyindex = 0 # A position of SMTP reply code found by the index()
|
162
|
-
formerchar = 0 # a character that is one character before the SMTP reply code
|
163
|
-
latterchar = 0 # a character that is one character after the SMTP reply code
|
164
162
|
|
165
163
|
replycodes.each do |e|
|
166
164
|
# Try to find an SMTP Reply Code from the given string
|
167
|
-
|
168
|
-
|
169
|
-
|
165
|
+
appearance = esmtperror.index(e); next if appearance.nil?
|
166
|
+
startingat = 1
|
167
|
+
mesglength = esmtperror.size
|
170
168
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
169
|
+
while startingat + 3 < mesglength
|
170
|
+
# Find all the reply code in the error message
|
171
|
+
replyindex = esmtperror.index(e, startingat); break if replyindex.nil?
|
172
|
+
formerchar = esmtperror[replyindex - 1, 1].ord || 0
|
173
|
+
latterchar = esmtperror[replyindex + 3, 1].ord || 0
|
176
174
|
|
177
|
-
|
175
|
+
if formerchar > 45 && formerchar < 58 then startingat += 3; next; end
|
176
|
+
if latterchar > 45 && latterchar < 58 then startingat += 3; next; end
|
177
|
+
esmtpreply = e
|
178
|
+
break
|
179
|
+
end
|
180
|
+
break if esmtpreply != ""
|
181
|
+
end
|
178
182
|
return esmtpreply
|
179
183
|
end
|
180
184
|
|
data/lib/sisimai/smtp/status.rb
CHANGED
@@ -479,6 +479,8 @@ module Sisimai
|
|
479
479
|
# reason from D.S.N. value, and getting D.S.N. from the text including D.S.N.
|
480
480
|
module Status
|
481
481
|
class << self
|
482
|
+
require "sisimai/rfc791"
|
483
|
+
|
482
484
|
CodePatterns = [
|
483
485
|
%r/[ ]?[(][#]([45][.]\d[.]\d+)[)]?[ ]?/, # #5.5.1
|
484
486
|
%r/\b\d{3}[- ][#]?([45][.]\d[.]\d+)\b/, # 550-5.1.1 OR 550 5.5.1
|
@@ -492,7 +494,7 @@ module Sisimai
|
|
492
494
|
'4.1.7' => 'rejected', # Bad sender's mailbox address syntax
|
493
495
|
'4.1.8' => 'rejected', # Bad sender's system address
|
494
496
|
'4.1.9' => 'systemerror', # Message relayed to non-compliant mailer
|
495
|
-
'4.2.1' => '
|
497
|
+
'4.2.1' => 'blocked', # Mailbox disabled, not accepting messages
|
496
498
|
'4.2.2' => 'mailboxfull', # Mailbox full
|
497
499
|
'4.2.3' => 'exceedlimit', # Message length exceeds administrative limit
|
498
500
|
'4.2.4' => 'filtered', # Mailing list expansion problem
|
@@ -595,47 +597,53 @@ module Sisimai
|
|
595
597
|
'5.7.27' => 'notaccept', # MX resource record of a destination host is Null MX: RFC7505
|
596
598
|
'5.7.28' => 'spamdetected', # The message appears to be part of a mail flood of similar abusive messages.
|
597
599
|
'5.7.29' => 'authfailure', # This status code may be returned when a message fails ARC validation.
|
598
|
-
'5.7.30' => '
|
600
|
+
'5.7.30' => 'failedstarttls', # REQUIRETLS support required
|
599
601
|
}.freeze
|
600
602
|
|
601
603
|
InternalCode = {
|
602
604
|
:temporary => {
|
603
|
-
'authfailure' => '4.0.
|
605
|
+
'authfailure' => '4.0.926',
|
604
606
|
'badreputation' => '4.0.975',
|
605
607
|
'blocked' => '4.0.971',
|
606
608
|
'contenterror' => '4.0.960',
|
607
|
-
|
609
|
+
'exceedlimit' => '4.0.923',
|
608
610
|
'expired' => '4.0.947',
|
611
|
+
'failedstarttls' => '4.0.976',
|
609
612
|
'filtered' => '4.0.924',
|
610
613
|
# 'hasmoved' => '4.0.916',
|
611
614
|
# 'hostunknown' => '4.0.912',
|
612
615
|
'mailboxfull' => '4.0.922',
|
613
|
-
|
614
|
-
|
616
|
+
'mailererror' => '4.0.939',
|
617
|
+
'mesgtoobig' => '4.0.934',
|
615
618
|
'networkerror' => '4.0.944',
|
616
|
-
|
619
|
+
'norelaying' => '4.0.909',
|
617
620
|
'notaccept' => '4.0.932',
|
618
621
|
'notcompliantrfc' => '4.0.974',
|
619
622
|
'onhold' => '4.0.901',
|
623
|
+
'policyviolaton' => '4.0.972',
|
620
624
|
'rejected' => '4.0.918',
|
621
625
|
'requireptr' => '4.0.973',
|
622
626
|
'securityerror' => '4.0.970',
|
623
627
|
'spamdetected' => '4.0.980',
|
624
628
|
'speeding' => '4.0.946',
|
625
|
-
|
629
|
+
'suppressed' => '4.0.903',
|
630
|
+
'suspend' => '4.0.921',
|
626
631
|
'systemerror' => '4.0.930',
|
627
632
|
'systemfull' => '4.0.931',
|
633
|
+
'syntaxerror' => '4.0.902',
|
628
634
|
'toomanyconn' => '4.0.945',
|
629
635
|
# 'userunknown' => '4.0.911',
|
630
636
|
'undefined' => '4.0.900',
|
637
|
+
'virusdetected' => '4.0.981',
|
631
638
|
},
|
632
639
|
:permanent => {
|
633
|
-
'authfailure' => '5.0.
|
640
|
+
'authfailure' => '5.0.926',
|
634
641
|
'badreputation' => '5.0.975',
|
635
642
|
'blocked' => '5.0.971',
|
636
643
|
'contenterror' => '5.0.960',
|
637
644
|
'exceedlimit' => '5.0.923',
|
638
645
|
'expired' => '5.0.947',
|
646
|
+
'failedstarttls' => '5.0.976',
|
639
647
|
'filtered' => '5.0.910',
|
640
648
|
'hasmoved' => '5.0.916',
|
641
649
|
'hostunknown' => '5.0.912',
|
@@ -653,6 +661,7 @@ module Sisimai
|
|
653
661
|
'securityerror' => '5.0.970',
|
654
662
|
'spamdetected' => '5.0.980',
|
655
663
|
'speeding' => '5.0.946',
|
664
|
+
'suppressed' => '5.0.903',
|
656
665
|
'suspend' => '5.0.921',
|
657
666
|
'systemerror' => '5.0.930',
|
658
667
|
'systemfull' => '5.0.931',
|
@@ -660,7 +669,7 @@ module Sisimai
|
|
660
669
|
'toomanyconn' => '5.0.945',
|
661
670
|
'userunknown' => '5.0.911',
|
662
671
|
'undefined' => '5.0.900',
|
663
|
-
'virusdetected' => '5.0.
|
672
|
+
'virusdetected' => '5.0.981',
|
664
673
|
},
|
665
674
|
}.freeze
|
666
675
|
|
@@ -696,7 +705,7 @@ module Sisimai
|
|
696
705
|
# @see code
|
697
706
|
# @since v5.0.0
|
698
707
|
def test(argv1 = '')
|
699
|
-
return
|
708
|
+
return false if argv1.to_s.empty?
|
700
709
|
return false if argv1.size < 5
|
701
710
|
return false if argv1.size > 7
|
702
711
|
|
@@ -717,8 +726,8 @@ module Sisimai
|
|
717
726
|
# @param [String] argv2 An SMTP Reply Code or 2 or 4 or 5
|
718
727
|
# @return [String, Nil] An SMTP Status Code
|
719
728
|
def find(argv1 = nil, argv2 = '0')
|
720
|
-
return
|
721
|
-
return
|
729
|
+
return "" if argv1.to_s.empty?
|
730
|
+
return "" if argv1.size < 7
|
722
731
|
|
723
732
|
givenclass = argv2[0, 1]
|
724
733
|
eestatuses = if givenclass == '2' || givenclass == '4' || givenclass == '5'
|
@@ -729,7 +738,7 @@ module Sisimai
|
|
729
738
|
esmtperror = ' ' + argv1 + ' '
|
730
739
|
lookingfor = []
|
731
740
|
|
732
|
-
Sisimai::
|
741
|
+
Sisimai::RFC791.find(esmtperror).each do |e|
|
733
742
|
# Rewrite an IPv4 address in the given string(argv1) with '***.***.***.***'
|
734
743
|
p0 = esmtperror.index(e) || next
|
735
744
|
esmtperror[p0, e.size] = '***.***.***.***'
|
@@ -745,7 +754,7 @@ module Sisimai
|
|
745
754
|
p1 = p0 + 5
|
746
755
|
end
|
747
756
|
end
|
748
|
-
return
|
757
|
+
return "" if lookingfor.size == 0
|
749
758
|
|
750
759
|
statuscode = [] # List of SMTP Status Code, Keep the order of appearances
|
751
760
|
anotherone = '' # Alternative code
|
@@ -811,10 +820,13 @@ module Sisimai
|
|
811
820
|
next if characters[6] > 47 && characters[6] < 58
|
812
821
|
statuscode << readbuffer
|
813
822
|
end
|
814
|
-
|
815
823
|
statuscode << anotherone if anotherone.size > 0
|
816
|
-
return
|
817
|
-
|
824
|
+
return "" if statuscode.size == 0
|
825
|
+
|
826
|
+
# Select one from picked status codes
|
827
|
+
cv = statuscode.shift; statuscode.each { |e| cv = Sisimai::SMTP::Status.prefer(cv, e, "") }
|
828
|
+
|
829
|
+
return cv
|
818
830
|
end
|
819
831
|
|
820
832
|
# Return the preferred value selected from the arguments
|
@@ -860,11 +872,16 @@ module Sisimai
|
|
860
872
|
|
861
873
|
return statuscode if zeroindex2['error'] > 0 # An SMTP status code is "X.0.0"
|
862
874
|
return codeinmesg if statuscode == '4.4.7' # "4.4.7" is an ambiguous code
|
875
|
+
return codeinmesg if statuscode == '4.7.0' # "4.7.0" indicates "too many errors"
|
863
876
|
return codeinmesg if statuscode.start_with?('5.3.') # "5.3.Z" is an error of a system
|
877
|
+
return codeinmesg if statuscode.end_with?('.5.1') # "X.5.1" indicates an invalid command
|
878
|
+
return codeinmesg if statuscode.end_with?('.5.2') # "X.5.2" indicates a syntax error
|
879
|
+
return codeinmesg if statuscode.end_with?('.5.4') # "X.5.4" indicates an invalid command arguments
|
880
|
+
return codeinmesg if statuscode.end_with?('.5.5') # "X.5.5" indicates a wrong protocol version
|
864
881
|
|
865
882
|
if statuscode == '5.1.1'
|
866
883
|
# "5.1.1" is a code of "userunknown"
|
867
|
-
return statuscode if zeroindex1['error'] > 0
|
884
|
+
return statuscode if codeinmesg.start_with?('5.5.') || zeroindex1['error'] > 0
|
868
885
|
return codeinmesg
|
869
886
|
|
870
887
|
elsif statuscode == '5.1.3'
|
@@ -34,18 +34,17 @@ module Sisimai
|
|
34
34
|
}
|
35
35
|
}
|
36
36
|
end
|
37
|
-
parameters = '' # Command parameters of MAIL, RCPT
|
38
|
-
cursession = nil # Current session for $esmtp
|
39
37
|
|
40
38
|
cv = ''
|
41
|
-
|
39
|
+
cx = nil # Current session for esmtp
|
42
40
|
p1 = argv0.index('>>>') || -1 # Sent command
|
43
|
-
|
41
|
+
p2 = argv0.index('<<<') || -1 # Server response
|
42
|
+
if p2 < p1
|
44
43
|
# An SMTP server response starting with '<<<' is the first
|
45
44
|
esmtp << table.call
|
46
|
-
|
47
|
-
|
48
|
-
argv0 = argv0[
|
45
|
+
cx = esmtp[-1]
|
46
|
+
cx['command'] = 'CONN'
|
47
|
+
argv0 = argv0[p2, argv0.size] if p2 > -1
|
49
48
|
else
|
50
49
|
# An SMTP command starting with '>>>' is the first
|
51
50
|
argv0 = argv0[p1, argv0.size] if p1 > -1
|
@@ -63,17 +62,18 @@ module Sisimai
|
|
63
62
|
# >>> SMTP Command
|
64
63
|
thecommand = cv[1]
|
65
64
|
commandarg = cv[2]
|
65
|
+
parameters = ''
|
66
66
|
|
67
67
|
esmtp << table.call
|
68
|
-
|
69
|
-
|
68
|
+
cx = esmtp[-1]
|
69
|
+
cx['command'] = thecommand.upcase
|
70
70
|
|
71
71
|
if thecommand =~ /\A(?:MAIL|RCPT|XFORWARD)/
|
72
72
|
# MAIL or RCPT
|
73
73
|
if cv = commandarg.match(/\A(?:FROM|TO):[ ]*<(.+[@].+)>[ ]*(.*)\z/)
|
74
74
|
# >>> MAIL FROM: <neko@example.com> SIZE=65535
|
75
75
|
# >>> RCPT TO: <kijitora@example.org>
|
76
|
-
|
76
|
+
cx['argument'] = cv[1]
|
77
77
|
parameters = cv[2]
|
78
78
|
|
79
79
|
else
|
@@ -87,11 +87,11 @@ module Sisimai
|
|
87
87
|
|
88
88
|
parameters.split(" ").each do |p|
|
89
89
|
# SIZE=22022, PROTO=SMTP, and so on
|
90
|
-
if cv = p.match(/\A([^ =]+)=([^ =]+)\z/) then
|
90
|
+
if cv = p.match(/\A([^ =]+)=([^ =]+)\z/) then cx['parameter'][cv[1].downcase] = cv[2] end
|
91
91
|
end
|
92
92
|
else
|
93
93
|
# HELO, EHLO, AUTH, DATA, QUIT or Other SMTP command
|
94
|
-
|
94
|
+
cx['argument'] = commandarg
|
95
95
|
end
|
96
96
|
end
|
97
97
|
else
|
@@ -101,9 +101,9 @@ module Sisimai
|
|
101
101
|
e = e[4, e.size]
|
102
102
|
|
103
103
|
e.sub!(/\A<<<[ ]/, '')
|
104
|
-
if cv = e.match(/\A([2-5]\d\d)[ ]/) then
|
105
|
-
if cv = e.match(/\A[245]\d\d[ ]([245][.]\d{1,3}[.]\d{1,3})[ ]/) then
|
106
|
-
|
104
|
+
if cv = e.match(/\A([2-5]\d\d)[ ]/) then cx['response']['reply'] = cv[1] end
|
105
|
+
if cv = e.match(/\A[245]\d\d[ ]([245][.]\d{1,3}[.]\d{1,3})[ ]/) then cx['response']['status'] = cv[1] end
|
106
|
+
cx['response']['text'] << e
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
data/lib/sisimai/string.rb
CHANGED
@@ -75,52 +75,6 @@ module Sisimai
|
|
75
75
|
return false
|
76
76
|
end
|
77
77
|
|
78
|
-
# Find an IPv4 address from the given string
|
79
|
-
# @param [String] argv1 String including an IPv4 address
|
80
|
-
# @return [Array] List of IPv4 addresses
|
81
|
-
# @since v5.0.0
|
82
|
-
def ipv4(argv0)
|
83
|
-
return nil if argv0.to_s.empty?
|
84
|
-
return [] if argv0.size < 7
|
85
|
-
|
86
|
-
ipv4a = []
|
87
|
-
%w|( ) [ ]|.each do |e|
|
88
|
-
# Rewrite: "mx.example.jp[192.0.2.1]" => "mx.example.jp 192.0.2.1"
|
89
|
-
p0 = argv0.index(e); next unless p0
|
90
|
-
argv0[p0, 1] = ' '
|
91
|
-
end
|
92
|
-
|
93
|
-
argv0.split(' ').each do |e|
|
94
|
-
# Find string including an IPv4 address
|
95
|
-
next unless e.index('.') # IPv4 address must include "." character
|
96
|
-
|
97
|
-
lx = e.size; next if lx < 7 || lx > 17 # 0.0.0.0 = 7, [255.255.255.255] = 17
|
98
|
-
cu = 0 # Cursor for seeking each octet of an IPv4 address
|
99
|
-
as = '' # ASCII Code of each character
|
100
|
-
eo = '' # Buffer of each octet of IPv4 Address
|
101
|
-
|
102
|
-
while cu < lx
|
103
|
-
# Check whether each character is a number or "." or not
|
104
|
-
as = e[cu, 1].ord
|
105
|
-
cu += 1
|
106
|
-
|
107
|
-
if as < 48 || as > 57
|
108
|
-
# The character is not a number(0-9)
|
109
|
-
break if as != 46 # The character is not "."
|
110
|
-
next if eo == '' # The current buffer is empty
|
111
|
-
break if eo.to_i > 255 # The current buffer is greater than 255
|
112
|
-
eo = ''
|
113
|
-
next
|
114
|
-
end
|
115
|
-
eo << as.chr
|
116
|
-
break if eo.to_i > 255
|
117
|
-
end
|
118
|
-
ipv4a << e if eo.size > 0 && eo.to_i < 256
|
119
|
-
end
|
120
|
-
|
121
|
-
return ipv4a
|
122
|
-
end
|
123
|
-
|
124
78
|
# Convert given HTML text to plain text
|
125
79
|
# @param [String] argv1 HTML text
|
126
80
|
# @param [Boolean] loose Loose check flag
|
data/lib/sisimai/version.rb
CHANGED