sisimai 4.25.6 → 4.25.11
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sisimai might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/ANALYTICAL-PRECISION +1 -1
- data/Benchmarks.mk +1 -1
- data/ChangeLog.md +71 -2
- data/Developers.mk +2 -2
- data/Makefile +1 -1
- data/README-JA.md +16 -16
- data/README.md +16 -16
- data/Repository.mk +1 -1
- data/lib/sisimai.rb +3 -3
- data/lib/sisimai/address.rb +6 -3
- data/lib/sisimai/arf.rb +25 -21
- data/lib/sisimai/data.rb +8 -29
- data/lib/sisimai/datetime.rb +18 -17
- data/lib/sisimai/lhost/amazonses.rb +1 -1
- data/lib/sisimai/lhost/domino.rb +29 -4
- data/lib/sisimai/lhost/einsundeins.rb +1 -1
- data/lib/sisimai/lhost/exchange2007.rb +1 -1
- data/lib/sisimai/lhost/exim.rb +12 -8
- data/lib/sisimai/lhost/ezweb.rb +1 -1
- data/lib/sisimai/lhost/fml.rb +0 -2
- data/lib/sisimai/lhost/gsuite.rb +5 -0
- data/lib/sisimai/lhost/imailserver.rb +1 -1
- data/lib/sisimai/lhost/mailfoundry.rb +3 -4
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +2 -2
- data/lib/sisimai/lhost/mxlogic.rb +1 -1
- data/lib/sisimai/lhost/notes.rb +1 -1
- data/lib/sisimai/lhost/office365.rb +1 -1
- data/lib/sisimai/lhost/postfix.rb +3 -10
- data/lib/sisimai/lhost/qmail.rb +7 -7
- data/lib/sisimai/lhost/sendgrid.rb +2 -2
- data/lib/sisimai/lhost/sendmail.rb +1 -1
- data/lib/sisimai/lhost/verizon.rb +4 -4
- data/lib/sisimai/lhost/x3.rb +4 -0
- data/lib/sisimai/lhost/x4.rb +8 -8
- data/lib/sisimai/lhost/x5.rb +7 -3
- data/lib/sisimai/mail.rb +2 -21
- data/lib/sisimai/mda.rb +2 -2
- data/lib/sisimai/message.rb +47 -83
- data/lib/sisimai/reason/blocked.rb +40 -26
- data/lib/sisimai/reason/exceedlimit.rb +4 -1
- data/lib/sisimai/reason/expired.rb +2 -0
- data/lib/sisimai/reason/filtered.rb +1 -0
- data/lib/sisimai/reason/hostunknown.rb +3 -0
- data/lib/sisimai/reason/mailererror.rb +1 -1
- data/lib/sisimai/reason/norelaying.rb +5 -0
- data/lib/sisimai/reason/notaccept.rb +2 -0
- data/lib/sisimai/reason/policyviolation.rb +4 -0
- data/lib/sisimai/reason/rejected.rb +5 -1
- data/lib/sisimai/reason/securityerror.rb +5 -6
- data/lib/sisimai/reason/spamdetected.rb +17 -15
- data/lib/sisimai/reason/suspend.rb +1 -0
- data/lib/sisimai/reason/systemerror.rb +2 -0
- data/lib/sisimai/reason/userunknown.rb +25 -21
- data/lib/sisimai/rfc1894.rb +24 -22
- data/lib/sisimai/rfc3464.rb +4 -5
- data/lib/sisimai/rfc3834.rb +1 -1
- data/lib/sisimai/rfc5322.rb +8 -4
- data/lib/sisimai/rhost.rb +6 -8
- data/lib/sisimai/rhost/cox.rb +112 -0
- data/lib/sisimai/rhost/exchangeonline.rb +8 -1
- data/lib/sisimai/rhost/googleapps.rb +4 -1
- data/lib/sisimai/rhost/spectrum.rb +73 -0
- data/lib/sisimai/smtp/error.rb +8 -6
- data/lib/sisimai/smtp/reply.rb +1 -1
- data/lib/sisimai/smtp/status.rb +1 -1
- data/lib/sisimai/time.rb +1 -2
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +5 -4
- data/set-of-emails/maildir/bsd/arf-25.eml +61 -0
- data/set-of-emails/maildir/bsd/lhost-aol-04.eml +23 -23
- data/set-of-emails/maildir/bsd/lhost-domino-02.eml +1 -2
- data/set-of-emails/maildir/bsd/lhost-exim-61.eml +40 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-38.eml +1 -1
- data/set-of-emails/maildir/bsd/lhost-postfix-66.eml +80 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-67.eml +80 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-68.eml +82 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-69.eml +80 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-70.eml +87 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-71.eml +81 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-72.eml +81 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-73.eml +79 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-74.eml +83 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-08.eml +1 -1
- data/set-of-emails/maildir/bsd/lhost-sendmail-11.eml +1 -1
- data/set-of-emails/maildir/bsd/lhost-sendmail-57.eml +59 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-58.eml +70 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-59.eml +68 -0
- data/set-of-emails/maildir/bsd/lhost-x3-06.eml +53 -0
- data/set-of-emails/maildir/bsd/rhost-cox-01.eml +192 -0
- data/set-of-emails/maildir/bsd/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-exchange-online-02.eml → rhost-exchangeonline-02.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-exchange-online-03.eml → rhost-exchangeonline-03.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-google-apps-02.eml → rhost-googleapps-02.eml} +0 -0
- data/set-of-emails/maildir/bsd/rhost-spectrum-01.eml +111 -0
- data/set-of-emails/maildir/dos/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
- data/set-of-emails/maildir/dos/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
- data/set-of-emails/maildir/mac/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
- data/set-of-emails/maildir/mac/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
- data/sisimai-java.gemspec +4 -4
- data/sisimai.gemspec +4 -4
- metadata +39 -20
@@ -25,17 +25,20 @@ module Sisimai
|
|
25
25
|
'Sisimai::Reason::Rejected' => 'sisimai/reason/rejected',
|
26
26
|
}
|
27
27
|
Regex = %r{(?>
|
28
|
-
|
29
|
-
|[
|
30
|
-
|[<]
|
31
|
-
|[
|
28
|
+
[#]5[.]1[.]1[ ]bad[ ]address
|
29
|
+
|[<][^ ]+[>][ ]not[ ]found
|
30
|
+
|[<][^ ]+[@][^ ]+[>][.][.][.][ ]blocked[ ]by[ ]
|
31
|
+
|550[ ]address[ ]invalid
|
32
32
|
|5[.]0[.]0[.][ ]mail[ ]rejected[.]
|
33
33
|
|5[.]1[.]0[ ]address[ ]rejected[.]
|
34
|
-
|
|
34
|
+
|account[ ][^ ]+[ ]does[ ]not[ ]exist[ ]at[ ]the[ ]organization
|
35
|
+
|adresse[ ]d[ ]au[ ]moins[ ]un[ ]destinataire[ ]invalide[.][ ]invalid[ ]recipient[.][0-9a-z_]+41[68]
|
35
36
|
|address[ ](?:does[ ]not[ ]exist|unknown)
|
37
|
+
|address[ ](?:does[ ]not[ ]exist|not[ ]present[ ]in[ ]directory|unknown)
|
36
38
|
|archived[ ]recipient
|
37
39
|
|bad[-_ ]recipient
|
38
40
|
|can[']t[ ]accept[ ]user
|
41
|
+
|does[ ]not[ ]exist[.]
|
39
42
|
|destination[ ](?:
|
40
43
|
addresses[ ]were[ ]unknown
|
41
44
|
|server[ ]rejected[ ]recipients
|
@@ -43,7 +46,7 @@ module Sisimai
|
|
43
46
|
|email[ ]address[ ](?:does[ ]not[ ]exist|could[ ]not[ ]be[ ]found)
|
44
47
|
|invalid[ ](?:
|
45
48
|
address
|
46
|
-
|mailbox
|
49
|
+
|mailbox:?
|
47
50
|
|mailbox[ ]path
|
48
51
|
|recipient
|
49
52
|
)
|
@@ -53,16 +56,17 @@ module Sisimai
|
|
53
56
|
|an[ ]active[ ]address[ ]at[ ]this[ ]host
|
54
57
|
)
|
55
58
|
|mailbox[ ](?:
|
56
|
-
|
57
|
-
|
59
|
+
[^ ]+[ ]does[ ]not[ ]exist
|
60
|
+
|[^ ]+[@][^ ]+[ ]unavailable
|
58
61
|
|does[ ]not[ ]exist
|
59
62
|
|invalid
|
60
63
|
|is[ ](?:inactive|unavailable)
|
61
64
|
|not[ ](?:present|found)
|
62
65
|
|unavailable
|
63
66
|
)
|
67
|
+
|nessun[ ]utente[ ]simile[ ]in[ ]questo[ ]indirizzo
|
64
68
|
|no[ ](?:
|
65
|
-
[ ]
|
69
|
+
[ ][^ ]+[ ]in[ ]name[ ]directory
|
66
70
|
|account[ ]by[ ]that[ ]name[ ]here
|
67
71
|
|existe[ ](?:dicha[ ]persona|ese[ ]usuario[ ])
|
68
72
|
|mail[ ]box[ ]available[ ]for[ ]this[ ]user
|
@@ -79,7 +83,7 @@ module Sisimai
|
|
79
83
|
|user(?:[ ]here)?
|
80
84
|
)
|
81
85
|
|thank[ ]you[ ]rejected:[ ]account[ ]unavailable:
|
82
|
-
|valid[ ]recipients
|
86
|
+
|valid[ ]recipients,[ ]bye
|
83
87
|
)
|
84
88
|
|non[- ]?existent[ ]user
|
85
89
|
|not[ ](?:
|
@@ -87,15 +91,15 @@ module Sisimai
|
|
87
91
|
|a[ ]local[ ]address
|
88
92
|
|email[ ]addresses
|
89
93
|
)
|
90
|
-
|rcpt[ ][<]
|
94
|
+
|rcpt[ ][<][^ ]+[>][ ]does[ ]not[ ]exist
|
91
95
|
|recipient[ ]address[ ]rejected[.][ ][(]in[ ]reply[ ]to[ ]rcpt[ ]to[ ]command[)]
|
92
|
-
|
|
93
|
-
|
96
|
+
|recipient[ ](?:
|
97
|
+
[^ ]+[ ]was[ ]not[ ]found[ ]in
|
94
98
|
|address[ ]rejected:[ ](?:
|
95
99
|
access[ ]denied
|
96
100
|
|invalid[ ]user
|
97
|
-
|user[ ]
|
98
|
-
|user[ ]unknown[ ]in[ ]
|
101
|
+
|user[ ][^ ]+[ ]does[ ]not[ ]exist
|
102
|
+
|user[ ]unknown[ ]in[ ][^ ]+[ ]table
|
99
103
|
|unknown[ ]user
|
100
104
|
)
|
101
105
|
|does[ ]not[ ]exist(?:[ ]on[ ]this[ ]system)?
|
@@ -104,9 +108,8 @@ module Sisimai
|
|
104
108
|
|unknown
|
105
109
|
)
|
106
110
|
|requested[ ]action[ ]not[ ]taken:[ ]mailbox[ ]unavailable
|
107
|
-
|resolver[.]adr[.]
|
108
|
-
|said:[ ]550[-[ ]]5[.]1[.]1[ ]
|
109
|
-
|smtp[ ]error[ ]from[ ]remote[ ]mail[ ]server[ ]after[ ]end[ ]of[ ]data:[ ]553.+does[ ]not[ ]exist
|
111
|
+
|resolver[.]adr[.]recipient notfound
|
112
|
+
|said:[ ]550[-[ ]]5[.]1[.]1[ ][^ ]+[ ]user[ ]unknown[ ]
|
110
113
|
|sorry,[ ](?:
|
111
114
|
user[ ]unknown
|
112
115
|
|badrcptto
|
@@ -122,7 +125,7 @@ module Sisimai
|
|
122
125
|
address[ ]no[ ]longer[ ]accepts[ ]mail
|
123
126
|
|email[ ]address[ ]is[ ]wrong[ ]or[ ]no[ ]longer[ ]valid
|
124
127
|
|spectator[ ]does[ ]not[ ]exist
|
125
|
-
|user[ ]doesn[']?t[ ]have[ ]a[ ]
|
128
|
+
|user[ ]doesn[']?t[ ]have[ ]a[ ][^ ]+[ ]account
|
126
129
|
)
|
127
130
|
|unknown[ ](?:
|
128
131
|
e[-]?mail[ ]address
|
@@ -132,13 +135,14 @@ module Sisimai
|
|
132
135
|
|user
|
133
136
|
)
|
134
137
|
|user[ ](?:
|
135
|
-
|
136
|
-
|
138
|
+
[^ ]+[ ]was[ ]not[ ]found
|
139
|
+
|[^ ]+[ ]does[ ]not[ ]exist
|
137
140
|
|does[ ]not[ ]exist
|
138
141
|
|missing[ ]home[ ]directory
|
139
142
|
|not[ ](?:active|exist|found|known)
|
140
143
|
|unknown
|
141
144
|
)
|
145
|
+
|utilisateur[ ]inconnu[ ]!
|
142
146
|
|vdeliver:[ ]invalid[ ]or[ ]unknown[ ]virtual[ ]user
|
143
147
|
|your[ ]envelope[ ]recipient[ ]is[ ]in[ ]my[ ]badrcptto[ ]list
|
144
148
|
)
|
data/lib/sisimai/rfc1894.rb
CHANGED
@@ -38,14 +38,14 @@ module Sisimai
|
|
38
38
|
'addr' => %r/\A((?:Original|Final|X-Actual)-Recipient):[ ]*(.+?);[ ]*(.+)/,
|
39
39
|
'code' => %r/\A(Diagnostic-Code):[ ]*(.+?);[ ]*(.*)/,
|
40
40
|
'date' => %r/\A((?:Arrival|Last-Attempt)-Date):[ ]*(.+)/,
|
41
|
-
'host' => %r/\A((?:
|
42
|
-
'list' => %r/\A(Action):[ ]*(
|
41
|
+
'host' => %r/\A((?:Received-From|Remote|Reporting)-MTA):[ ]*(.+?);[ ]*(.+)/,
|
42
|
+
'list' => %r/\A(Action):[ ]*(delayed|deliverable|delivered|expanded|expired|failed|failure|relayed)/i,
|
43
43
|
'stat' => %r/\A(Status):[ ]*([245][.]\d+[.]\d+)/,
|
44
44
|
'text' => %r/\A(X-Original-Message-ID):[ ]*(.+)/,
|
45
|
-
#text
|
45
|
+
#'text' => %r/\A(Final-Log-ID|Original-Envelope-Id):[ ]*(.+)/,
|
46
46
|
}.freeze
|
47
47
|
|
48
|
-
Correction = { action: { '
|
48
|
+
Correction = { action: { 'deliverable' => 'delivered', 'expired' => 'delayed', 'failure' => 'failed' }}
|
49
49
|
FieldGroup = {
|
50
50
|
'original-recipient' => 'addr',
|
51
51
|
'final-recipient' => 'addr',
|
@@ -86,8 +86,8 @@ module Sisimai
|
|
86
86
|
# @since v4.25.0
|
87
87
|
def match(argv0 = '')
|
88
88
|
return nil if argv0.empty?
|
89
|
-
return 1
|
90
|
-
return 2
|
89
|
+
return 1 if FieldNames[0].any? { |a| argv0.start_with?(a) }
|
90
|
+
return 2 if FieldNames[1].any? { |a| argv0.start_with?(a) }
|
91
91
|
return nil
|
92
92
|
end
|
93
93
|
|
@@ -98,42 +98,44 @@ module Sisimai
|
|
98
98
|
def field(argv0 = '')
|
99
99
|
return nil if argv0.empty?
|
100
100
|
group = FieldGroup[argv0.split(':',2).shift.downcase] || ''
|
101
|
-
match = []
|
102
101
|
|
103
102
|
return nil if group.empty?
|
104
103
|
return nil unless CapturesOn[group]
|
105
104
|
|
105
|
+
table = ['', '', '', '']
|
106
|
+
match = false
|
106
107
|
while cv = argv0.match(CapturesOn[group])
|
107
108
|
# Try to match with each pattern of Per-Message field, Per-Recipient field
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
match
|
113
|
-
|
109
|
+
# - 0: Field-Name
|
110
|
+
# - 1: Sub Type: RFC822, DNS, X-Unix, and so on)
|
111
|
+
# - 2: Value
|
112
|
+
# - 3: Field Group(addr, code, date, host, stat, text)
|
113
|
+
match = true
|
114
|
+
table[0] = cv[1].downcase
|
115
|
+
table[3] = group
|
114
116
|
|
115
117
|
if group == 'addr' || group == 'code' || group == 'host'
|
116
118
|
# - Final-Recipient: RFC822; kijitora@nyaan.jp
|
117
119
|
# - Diagnostic-Code: SMTP; 550 5.1.1 <kijitora@example.jp>... User Unknown
|
118
120
|
# - Remote-MTA: DNS; mx.example.jp
|
119
|
-
|
120
|
-
|
121
|
-
|
121
|
+
table[1] = cv[2].upcase
|
122
|
+
table[2] = group == 'host' ? cv[3].downcase : cv[3]
|
123
|
+
table[2] = '' if table[2] =~ /\A\s+\z/ # Remote-MTA: dns;
|
122
124
|
else
|
123
125
|
# - Action: failed
|
124
126
|
# - Status: 5.2.2
|
125
|
-
|
126
|
-
|
127
|
+
table[1] = ''
|
128
|
+
table[2] = group == 'date' ? cv[2] : cv[2].downcase
|
127
129
|
|
128
130
|
# Correct invalid value in Action field:
|
129
131
|
break unless group == 'list'
|
130
|
-
break unless Correction[:action][
|
131
|
-
|
132
|
+
break unless Correction[:action][table[2]]
|
133
|
+
table[2] = Correction[:action][table[2]]
|
132
134
|
end
|
133
135
|
break
|
134
136
|
end
|
135
|
-
return nil
|
136
|
-
return
|
137
|
+
return nil unless match
|
138
|
+
return table
|
137
139
|
end
|
138
140
|
|
139
141
|
end
|
data/lib/sisimai/rfc3464.rb
CHANGED
@@ -98,12 +98,9 @@ module Sisimai
|
|
98
98
|
# @return [Hash] Bounce data list and message/rfc822 part
|
99
99
|
# @return [Nil] it failed to parse or the arguments are missing
|
100
100
|
def make(mhead, mbody)
|
101
|
-
require 'sisimai/mda'
|
102
|
-
|
103
101
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
104
102
|
bodyslices = mbody.scrub('?').split("\n")
|
105
103
|
readslices = ['']
|
106
|
-
mdabounced = Sisimai::MDA.make(mhead, mbody)
|
107
104
|
rfc822text = '' # (String) message/rfc822 part text
|
108
105
|
maybealias = nil # (String) Original-Recipient Field
|
109
106
|
blanklines = 0 # (Integer) The number of blank lines
|
@@ -177,7 +174,7 @@ module Sisimai
|
|
177
174
|
maybealias = cv[2]
|
178
175
|
else
|
179
176
|
# Final-Recipient: ...
|
180
|
-
x = v['
|
177
|
+
x = v['recipient'] || ''
|
181
178
|
y = Sisimai::Address.s3s4(cv[2])
|
182
179
|
y = maybealias unless Sisimai::RFC5322.is_emailaddress(y)
|
183
180
|
|
@@ -287,7 +284,7 @@ module Sisimai
|
|
287
284
|
elsif readslices[-2].start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
288
285
|
# Continued line of the value of Diagnostic-Code header
|
289
286
|
v['diagnosis'] << ' ' << cv[1]
|
290
|
-
|
287
|
+
readslices[-1] = 'Diagnostic-Code: ' << e
|
291
288
|
else
|
292
289
|
if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
293
290
|
# 2.2.2 The Reporting-MTA DSN field
|
@@ -421,6 +418,8 @@ module Sisimai
|
|
421
418
|
end
|
422
419
|
return nil unless recipients > 0
|
423
420
|
|
421
|
+
require 'sisimai/mda'
|
422
|
+
mdabounced = Sisimai::MDA.make(mhead, mbody)
|
424
423
|
dscontents.each do |e|
|
425
424
|
# Set default values if each value is empty.
|
426
425
|
connheader.each_key { |a| e[a] ||= connheader[a] || '' }
|
data/lib/sisimai/rfc3834.rb
CHANGED
@@ -99,7 +99,7 @@ module Sisimai
|
|
99
99
|
if mhead['content-type']
|
100
100
|
# Get the boundary string and set regular expression for matching with
|
101
101
|
# the boundary string.
|
102
|
-
b0 = Sisimai::MIME.boundary(mhead['content-type'], 0)
|
102
|
+
b0 = Sisimai::MIME.boundary(mhead['content-type'], 0) || ''
|
103
103
|
MarkingsOf[:boundary] = %r/\A\Q#{b0}\E\z/ unless b0.empty?
|
104
104
|
end
|
105
105
|
|
data/lib/sisimai/rfc5322.rb
CHANGED
@@ -64,9 +64,8 @@ module Sisimai
|
|
64
64
|
# Fields that might be long
|
65
65
|
# @return [Hash] Long filed(email header) list
|
66
66
|
def LONGFIELDS
|
67
|
-
return { 'to' =>
|
67
|
+
return { 'to' => true, 'from' => true, 'subject' => true, 'message-id' => true }
|
68
68
|
end
|
69
|
-
LongHeaders = Sisimai::RFC5322.LONGFIELDS
|
70
69
|
|
71
70
|
# Check that the argument is an email address or not
|
72
71
|
# @param [String] email Email address string
|
@@ -192,8 +191,13 @@ module Sisimai
|
|
192
191
|
v[1] ||= ''
|
193
192
|
|
194
193
|
unless v[1].empty?
|
195
|
-
|
196
|
-
|
194
|
+
# Remove blank lines, the message body of the original message, and append "\n" at the end
|
195
|
+
# of the original message headers
|
196
|
+
# 1. Remove leading blank lines
|
197
|
+
# 2. Remove text after the first blank line: \n\n
|
198
|
+
# 3. Append "\n" at the end of test block when the last character is not "\n"
|
199
|
+
v[1].sub!(/\A[\r\n\s]+/, '')
|
200
|
+
v[1] = v[1][0, v[1].index("\n\n")] if v[1].include?("\n\n")
|
197
201
|
v[1] << "\n" unless v[1].end_with?("\n")
|
198
202
|
end
|
199
203
|
return v
|
data/lib/sisimai/rhost.rb
CHANGED
@@ -19,15 +19,11 @@ module Sisimai
|
|
19
19
|
'.email.ua' => 'IUA',
|
20
20
|
'lsean.ezweb.ne.jp' => 'KDDI',
|
21
21
|
'msmx.au.com' => 'KDDI',
|
22
|
+
'charter.net' => 'Spectrum',
|
23
|
+
'cox.net' => 'Cox',
|
22
24
|
'.qq.com' => 'TencentQQ',
|
23
25
|
}.freeze
|
24
26
|
|
25
|
-
# Retrun the list of remote hosts Sisimai support
|
26
|
-
# @return [Array] Remote host list
|
27
|
-
def list
|
28
|
-
return RhostClass.keys
|
29
|
-
end
|
30
|
-
|
31
27
|
# The value of "rhost" is listed in RhostClass or not
|
32
28
|
# @param [String] argvs Remote host name
|
33
29
|
# @return [True,False] True: matched
|
@@ -49,9 +45,10 @@ module Sisimai
|
|
49
45
|
|
50
46
|
# Detect the bounce reason from certain remote hosts
|
51
47
|
# @param [Sisimai::Data] argvs Parsed email object
|
48
|
+
# @param [String] proxy The alternative of the "rhost"
|
52
49
|
# @return [String] The value of bounce reason
|
53
|
-
def get(argvs)
|
54
|
-
remotehost = argvs.rhost.downcase
|
50
|
+
def get(argvs, proxy = nil)
|
51
|
+
remotehost = proxy || argvs.rhost.downcase
|
55
52
|
rhostclass = ''
|
56
53
|
modulename = ''
|
57
54
|
|
@@ -62,6 +59,7 @@ module Sisimai
|
|
62
59
|
rhostclass = modulename.gsub('::', '/').downcase
|
63
60
|
break
|
64
61
|
end
|
62
|
+
return nil if rhostclass.empty?
|
65
63
|
|
66
64
|
require rhostclass
|
67
65
|
reasontext = Module.const_get(modulename).get(argvs)
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Sisimai
|
2
|
+
module Rhost
|
3
|
+
# Sisimai::Rhost detects the bounce reason from the content of Sisimai::Data
|
4
|
+
# object as an argument of get() method when the value of "destination" of
|
5
|
+
# the object is "charter.net". This class is called only Sisimai::Data class.
|
6
|
+
module Cox
|
7
|
+
class << self
|
8
|
+
# Imported from p5-Sisimail/lib/Sisimai/Rhost/Cox.pm
|
9
|
+
ErrorCodes = {
|
10
|
+
# https://www.cox.com/residential/support/email-error-codes.html
|
11
|
+
'CXBL' => 'blocked', # The sending IP address has been blocked by Cox due to exhibiting spam-like behavior.
|
12
|
+
'CXTHRT' => 'securityerror', # Email sending limited due to suspicious account activity.
|
13
|
+
'CXMJ' => 'securityerror', # Email sending blocked due to suspicious account activity on primary Cox account.
|
14
|
+
'CXDNS' => 'blocked', # There was an issue with the connecting IP address Domain Name System (DNS).
|
15
|
+
'CXSNDR' => 'rejected', # There was a problem with the sender's domain.
|
16
|
+
'CXSMTP' => 'rejected', # Your email wasn't delivered because Cox was unable to verify that it came from a legitimate email sender.
|
17
|
+
'CXCNCT' => 'toomanyconn', # There is a limit to the number of concurrent SMTP connections per IP address
|
18
|
+
'CXMXRT' => 'toomanyconn', # The email sender has exceeded the maximum number of sent email allowed.
|
19
|
+
'CDRBL' => 'blocked', # The sending IP address has been temporarily blocked by Cox due to exhibiting spam-like behavior.
|
20
|
+
'IPBL0001' => 'blocked', # The sending IP address is listed in the Spamhaus Zen DNSBL.
|
21
|
+
'IPBL0010' => 'blocked', # The sending IP is listed in the Return Path DNSBL.
|
22
|
+
'IPBL0100' => 'blocked', # The sending IP is listed in the Invaluement ivmSIP DNSBL.
|
23
|
+
'IPBL0011' => 'blocked', # The sending IP is in the Spamhaus Zen and Return Path DNSBLs.
|
24
|
+
'IPBL0101' => 'blocked', # The sending IP is in the Spamhaus Zen and Invaluement ivmSIP DNSBLs.
|
25
|
+
'IPBL0110' => 'blocked', # The sending IP is in the Return Path and Invaluement ivmSIP DNSBLs.
|
26
|
+
'IPBL0111' => 'blocked', # The sending IP is in the Spamhaus Zen, Return Path and Invaluement ivmSIP DNSBLs.
|
27
|
+
'IPBL1000' => 'blocked', # The sending IP address is listed on a CSI blacklist. You can check your status on the CSI website.
|
28
|
+
'IPBL1001' => 'blocked', # The sending IP is listed in the Cloudmark CSI and Spamhaus Zen DNSBLs.
|
29
|
+
'IPBL1010' => 'blocked', # The sending IP is listed in the Cloudmark CSI and Return Path DNSBLs.
|
30
|
+
'IPBL1011' => 'blocked', # The sending IP is in the Cloudmark CSI, Spamhaus Zen and Return Path DNSBLs.
|
31
|
+
'IPBL1100' => 'blocked', # The sending IP is listed in the Cloudmark CSI and Invaluement ivmSIP DNSBLs.
|
32
|
+
'IPBL1101' => 'blocked', # The sending IP is in the Cloudmark CSI, Spamhaus Zen and Invaluement IVMsip DNSBLs.
|
33
|
+
'IPBL1110' => 'blocked', # The sending IP is in the Cloudmark CSI, Return Path and Invaluement ivmSIP DNSBLs.
|
34
|
+
'IPBL1111' => 'blocked', # The sending IP is in the Cloudmark CSI, Spamhaus Zen, Return Path and Invaluement ivmSIP DNSBLs.
|
35
|
+
'IPBL00001' => 'blocked', # The sending IP address is listed on a Spamhaus blacklist. Check your status at Spamhaus.
|
36
|
+
'URLBL011' => 'spamdetected', # A URL within the body of the message was found on blocklists SURBL and Spamhaus DBL.
|
37
|
+
'URLBL101' => 'spamdetected', # A URL within the body of the message was found on blocklists SURBL and ivmURI.
|
38
|
+
'URLBL110' => 'spamdetected', # A URL within the body of the message was found on blocklists Spamhaus DBL and ivmURI.
|
39
|
+
'URLBL1001' => 'spamdetected', # The URL is listed on a Spamhaus blacklist. Check your status at Spamhaus.
|
40
|
+
}.freeze
|
41
|
+
MessagesOf = {
|
42
|
+
'blocked' => [
|
43
|
+
# Cox requires that all connecting email servers contain valid reverse DNS PTR records.
|
44
|
+
'rejected - no rDNS',
|
45
|
+
# An email client has repeatedly sent bad commands or invalid passwords resulting in a three-hour block of the client's IP address.
|
46
|
+
'cox too many bad commands from',
|
47
|
+
# The reverse DNS check of the sending server IP address has failed.
|
48
|
+
'DNS check failure - try again later',
|
49
|
+
# The sending IP address has exceeded the threshold of invalid recipients and has been blocked.
|
50
|
+
'Too many invalid recipients',
|
51
|
+
],
|
52
|
+
'notaccept' => [
|
53
|
+
# Our systems are experiencing an issue which is causing a temporary inability to accept new email.
|
54
|
+
'ESMTP server temporarily not available',
|
55
|
+
],
|
56
|
+
'policyviolation' => [
|
57
|
+
# The sending server has attempted to communicate too soon within the SMTP transaction
|
58
|
+
'ESMTP no data before greeting',
|
59
|
+
# The message has been rejected because it contains an attachment with one of the following prohibited
|
60
|
+
# file types, which commonly contain viruses: .shb, .shs, .vbe, .vbs, .wsc, .wsf, .wsh, .pif, .msc,
|
61
|
+
# .msi, .msp, .reg, .sct, .bat, .chm, .isp, .cpl, .js, .jse, .scr, .exe.
|
62
|
+
'attachment extension is forbidden',
|
63
|
+
],
|
64
|
+
'rejected' => [
|
65
|
+
# Cox requires that all sender domains resolve to a valid MX or A-record within DNS.
|
66
|
+
'sender rejected',
|
67
|
+
],
|
68
|
+
'toomanyconn' => [
|
69
|
+
# The sending IP address has exceeded the five maximum concurrent connection limit.
|
70
|
+
'too many sessions from',
|
71
|
+
# The SMTP connection has exceeded the 100 email message threshold and was disconnected.
|
72
|
+
'requested action aborted: try again later',
|
73
|
+
# The sending IP address has exceeded one of these rate limits and has been temporarily blocked.
|
74
|
+
'Message threshold exceeded',
|
75
|
+
],
|
76
|
+
'userunknown' => [
|
77
|
+
'recipient rejected', # The intended recipient is not a valid Cox Email account.
|
78
|
+
],
|
79
|
+
}.freeze
|
80
|
+
|
81
|
+
# Detect bounce reason from https://cox.com/
|
82
|
+
# @param [Sisimai::Data] argvs Parsed email object
|
83
|
+
# @return [String, Nil] The bounce reason at Cox
|
84
|
+
# @since v4.25.8
|
85
|
+
def get(argvs)
|
86
|
+
statusmesg = argvs.diagnosticcode
|
87
|
+
codenumber = 0
|
88
|
+
|
89
|
+
if cv = statusmesg.match(/AUP#([0-9A-Z]+)/)
|
90
|
+
# Capture the numeric part of the error code
|
91
|
+
codenumber = cv[1]
|
92
|
+
end
|
93
|
+
reasontext = ErrorCodes[codenumber] || ''
|
94
|
+
|
95
|
+
if reasontext.empty?
|
96
|
+
# The error code was not found in ErrorCodes
|
97
|
+
MessagesOf.each_key do |e|
|
98
|
+
# Try to find with each error message defined in MessagesOf
|
99
|
+
next unless MessagesOf[e].any? { |a| statusmesg.include?(a) }
|
100
|
+
reasontext = e
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
return reasontext
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
@@ -22,6 +22,7 @@ module Sisimai
|
|
22
22
|
'5.2.2' => [{ reason: 'mailboxfull', string: 'Mailbox full' }],
|
23
23
|
'5.2.3' => [{ reason: 'exceedlimit', string: 'Message too large' }],
|
24
24
|
'5.2.4' => [{ reason: 'systemerror', string: 'Mailing list expansion problem' }],
|
25
|
+
'5.2.14' => [{ reason: 'systemerror', string: 'misconfigured forwarding address' }],
|
25
26
|
'5.2.122' => [{ reason: 'toomanyconn' ,string: 'The recipient has exceeded their limit for' }],
|
26
27
|
'5.3.3' => [{ reason: 'systemfull', string: 'Unrecognized command' }],
|
27
28
|
'5.3.4' => [{ reason: 'mesgtoobig', string: 'Message too big for system' }],
|
@@ -29,6 +30,7 @@ module Sisimai
|
|
29
30
|
'5.4.1' => [{ reason: 'rejected', string: 'Recipient address rejected: Access denied' }],
|
30
31
|
'5.4.11' => [{ reason: 'contenterror',string: 'Agent generated message depth exceeded' }],
|
31
32
|
'5.4.14' => [{ reason: 'networkerror',string: 'Hop count exceeded' }],
|
33
|
+
'5.4.310' => [{ reason: 'systemerror', string: 'does not exist' }], # DNS domain * does not exist
|
32
34
|
'5.5.2' => [{ reason: 'syntaxerror', string: 'Send hello first' }],
|
33
35
|
'5.5.3' => [{ reason: 'syntaxerror', string: 'Too many recipients' }],
|
34
36
|
'5.5.4' => [{ reason: 'filtered', string: 'Invalid domain name' }],
|
@@ -100,7 +102,12 @@ module Sisimai
|
|
100
102
|
'networkerror' => ['SMTPSEND.DNS.MxLoopback'],
|
101
103
|
'rejected' => ['RESOLVER.RST.NotAuthorized'],
|
102
104
|
'securityerror' => ['RESOLVER.RST.AuthRequired'],
|
103
|
-
'systemerror' => [
|
105
|
+
'systemerror' => [
|
106
|
+
'RESOLVER.ADR.Ambiguous',
|
107
|
+
'RESOLVER.ADR.BadPrimary',
|
108
|
+
'RESOLVER.ADR.InvalidInSmtp',
|
109
|
+
'RESOLVER.FWD.NotFound',
|
110
|
+
],
|
104
111
|
'toomanyconn' => ['RESOLVER.ADR.RecipLimit', 'RESOLVER.ADR.RecipientLimit'],
|
105
112
|
'userunknown' => [
|
106
113
|
'RESOLVER.ADR.RecipNotFound',
|