sisimai 5.0.0 → 5.0.2
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 +55 -0
- data/ChangeLog.md +40 -1
- data/README-JA.md +223 -111
- data/README.md +54 -31
- data/lib/sisimai/fact.rb +46 -8
- data/lib/sisimai/lhost/amazonses.rb +0 -1
- data/lib/sisimai/lhost/amazonworkmail.rb +0 -1
- data/lib/sisimai/lhost/aol.rb +0 -1
- data/lib/sisimai/lhost/bigfoot.rb +0 -1
- data/lib/sisimai/lhost/domino.rb +0 -1
- data/lib/sisimai/lhost/exchange2007.rb +1 -1
- data/lib/sisimai/lhost/exim.rb +7 -16
- data/lib/sisimai/lhost/facebook.rb +0 -1
- data/lib/sisimai/lhost/googlegroups.rb +2 -1
- data/lib/sisimai/lhost/gsuite.rb +0 -1
- data/lib/sisimai/lhost/mailru.rb +8 -17
- data/lib/sisimai/lhost/messagelabs.rb +0 -1
- data/lib/sisimai/lhost/mfilter.rb +1 -1
- data/lib/sisimai/lhost/mxlogic.rb +8 -18
- data/lib/sisimai/lhost/office365.rb +1 -1
- data/lib/sisimai/lhost/outlook.rb +0 -1
- data/lib/sisimai/lhost/postfix.rb +0 -1
- data/lib/sisimai/lhost/receivingses.rb +0 -1
- data/lib/sisimai/lhost/sendgrid.rb +1 -3
- data/lib/sisimai/lhost/sendmail.rb +0 -1
- data/lib/sisimai/lhost/yandex.rb +0 -1
- data/lib/sisimai/message.rb +13 -4
- data/lib/sisimai/reason/authfailure.rb +1 -0
- data/lib/sisimai/reason/blocked.rb +2 -0
- data/lib/sisimai/reason/expired.rb +1 -0
- data/lib/sisimai/reason/mailboxfull.rb +1 -0
- data/lib/sisimai/reason/securityerror.rb +1 -0
- data/lib/sisimai/reason/spamdetected.rb +1 -0
- data/lib/sisimai/reason/suspend.rb +1 -0
- data/lib/sisimai/rfc5322.rb +120 -64
- data/lib/sisimai/rhost/google.rb +320 -59
- data/lib/sisimai/rhost/mimecast.rb +9 -2
- data/lib/sisimai/smtp/status.rb +3 -0
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +12 -11
- data/set-of-emails/maildir/bsd/lhost-sendmail-60.eml +85 -0
- metadata +4 -2
@@ -46,6 +46,7 @@ module Sisimai
|
|
46
46
|
'part of their network is on our block list',
|
47
47
|
'please use the smtp server of your isp',
|
48
48
|
'refused - see http',
|
49
|
+
'rejected - multi-blacklist', # junkemailfilter.com
|
49
50
|
'rejected because the sending mta or the sender has not passed validation',
|
50
51
|
'rejecting open proxy', # Sendmail(srvrsmtp.c)
|
51
52
|
'sender ip address rejected',
|
@@ -78,6 +79,7 @@ module Sisimai
|
|
78
79
|
['message from ', ' rejected based on blacklist'],
|
79
80
|
['messages from ', ' temporarily deferred due to user complaints'], # Yahoo!
|
80
81
|
['server ip ', ' listed as abusive'],
|
82
|
+
['sorry! your ip address', ' is blocked by rbl'], # junkemailfilter.com
|
81
83
|
['the domain ', ' is blacklisted'],
|
82
84
|
['the email ', ' is blacklisted'],
|
83
85
|
['the ip', ' is blacklisted'],
|
@@ -18,6 +18,7 @@ module Sisimai
|
|
18
18
|
'has been delayed',
|
19
19
|
'it has not been collected after',
|
20
20
|
'message expired after sitting in queue for',
|
21
|
+
'message expired, cannot connect to remote server',
|
21
22
|
'message expired, connection refulsed',
|
22
23
|
'message timed out',
|
23
24
|
'retry time not reached for any host after a long failure period',
|
@@ -29,6 +29,7 @@ module Sisimai
|
|
29
29
|
'insecure mail relay',
|
30
30
|
'recipient address rejected: access denied',
|
31
31
|
"sorry, you don't authenticate or the domain isn't in my list of allowed rcpthosts",
|
32
|
+
'starttls is required to send mail',
|
32
33
|
'tls required but not supported', # SendGrid:the recipient mailserver does not support TLS or have a valid certificate
|
33
34
|
'unauthenticated senders not allowed',
|
34
35
|
'verification failure',
|
@@ -76,6 +76,7 @@ module Sisimai
|
|
76
76
|
'spam score ',
|
77
77
|
'spambouncer identified spam', # SpamBouncer identified SPAM
|
78
78
|
'spamming not allowed',
|
79
|
+
'too many spam complaints',
|
79
80
|
'too much spam.', # Earthlink
|
80
81
|
'the email message was detected as spam',
|
81
82
|
'the message has been rejected by spam filtering engine',
|
@@ -21,6 +21,7 @@ module Sisimai
|
|
21
21
|
'recipient rejected: temporarily inactive',
|
22
22
|
'recipient suspend the service',
|
23
23
|
'this account has been disabled or discontinued',
|
24
|
+
'this address no longer accepts mail',
|
24
25
|
'this mailbox is disabled',
|
25
26
|
'user suspended', # http://mail.163.com/help/help_spam_16.htm
|
26
27
|
'vdelivermail: account is locked email bounced',
|
data/lib/sisimai/rfc5322.rb
CHANGED
@@ -3,6 +3,7 @@ module Sisimai
|
|
3
3
|
module RFC5322
|
4
4
|
class << self
|
5
5
|
require 'sisimai/string'
|
6
|
+
require 'sisimai/address'
|
6
7
|
HeaderTable = {
|
7
8
|
:messageid => %w[message-id],
|
8
9
|
:subject => %w[subject],
|
@@ -52,79 +53,134 @@ module Sisimai
|
|
52
53
|
# @return [Array] Received header as a structured data
|
53
54
|
def received(argv1)
|
54
55
|
return [] unless argv1.is_a?(::String)
|
56
|
+
return [] if argv1.include?(' invoked by uid')
|
57
|
+
return [] if argv1.include?(' invoked from network')
|
58
|
+
|
59
|
+
# - https://datatracker.ietf.org/doc/html/rfc5322
|
60
|
+
# received = "Received:" *received-token ";" date-time CRLF
|
61
|
+
# received-token = word / angle-addr / addr-spec / domain
|
62
|
+
#
|
63
|
+
# - Appendix A.4. Message with Trace Fields
|
64
|
+
# Received:
|
65
|
+
# from x.y.test
|
66
|
+
# by example.net
|
67
|
+
# via TCP
|
68
|
+
# with ESMTP
|
69
|
+
# id ABC12345
|
70
|
+
# for <mary@example.net>; 21 Nov 1997 10:05:43 -0600
|
71
|
+
recvd = argv1.split(' ')
|
72
|
+
label = %w[from by via with id for]
|
73
|
+
token = {}
|
74
|
+
other = []
|
75
|
+
alter = []
|
76
|
+
right = false
|
77
|
+
range = recvd.size
|
78
|
+
index = -1
|
79
|
+
|
80
|
+
recvd.each do |e|
|
81
|
+
# Look up each label defined in "label" from Received header
|
82
|
+
index += 1
|
83
|
+
break unless index < range; f = e.downcase
|
84
|
+
next unless label.any? { |a| f == a }
|
85
|
+
token[f] = recvd[index + 1] || next
|
86
|
+
token[f] = token[f].downcase.delete('();')
|
87
|
+
|
88
|
+
next unless f == 'from'
|
89
|
+
break unless index + 2 < range
|
90
|
+
next unless recvd[index + 2].start_with?('(')
|
91
|
+
|
92
|
+
# Get and keep a hostname in the comment as follows:
|
93
|
+
# from mx1.example.com (c213502.kyoto.example.ne.jp [192.0.2.135]) by mx.example.jp (V8/cf)
|
94
|
+
# [
|
95
|
+
# "from", # index + 0
|
96
|
+
# "mx1.example.com", # index + 1
|
97
|
+
# "(c213502.kyoto.example.ne.jp", # index + 2
|
98
|
+
# "[192.0.2.135])", # index + 3
|
99
|
+
# "by",
|
100
|
+
# "mx.example.jp",
|
101
|
+
# "(V8/cf)",
|
102
|
+
# ...
|
103
|
+
# ]
|
104
|
+
# The 2nd element after the current element is NOT a continuation of the current element
|
105
|
+
# such as "(c213502.kyoto.example.ne.jp)"
|
106
|
+
other << recvd[index + 2].delete('();')
|
107
|
+
|
108
|
+
# The 2nd element after the current element is a continuation of the current element.
|
109
|
+
# such as "(c213502.kyoto.example.ne.jp", "[192.0.2.135])"
|
110
|
+
break unless index + 3 < range
|
111
|
+
other << recvd[index + 3].delete('();')
|
112
|
+
end
|
55
113
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# Wed, 26 Feb 2014 06:05:48 -0500
|
69
|
-
value['from'] = Sisimai::String.sweep(argv1[p1 + 5, p2 - p1 - 5])
|
70
|
-
value['by'] = Sisimai::String.sweep(argv1[p2 + 3, p3 - p2 - 3])
|
114
|
+
other.each do |e|
|
115
|
+
# Check alternatives in "other", and then delete uninformative values.
|
116
|
+
next if e.nil?
|
117
|
+
next if e.size < 4
|
118
|
+
next if e == 'unknown'
|
119
|
+
next if e == 'localhost'
|
120
|
+
next if e == '[127.0.0.1]'
|
121
|
+
next if e == '[IPv6:::1]'
|
122
|
+
next unless e.include?('.')
|
123
|
+
next if e.include?('=')
|
124
|
+
alter << e
|
125
|
+
end
|
71
126
|
|
72
|
-
|
73
|
-
#
|
74
|
-
|
75
|
-
|
127
|
+
%w[from by].each do |e|
|
128
|
+
# Remove square brackets from the IP address such as "[192.0.2.25]"
|
129
|
+
next if token[e].nil?
|
130
|
+
next if token[e].empty?
|
131
|
+
next unless token[e].start_with?('[')
|
132
|
+
token[e] = Sisimai::String.ipv4(token[e]).shift || ''
|
76
133
|
end
|
134
|
+
token['from'] ||= ''
|
77
135
|
|
78
|
-
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
hostname = ''
|
85
|
-
hostaddr = ''
|
86
|
-
|
87
|
-
while e = received.shift do
|
88
|
-
# Received: from [10.22.22.222] (smtp-gateway.kyoto.ocn.ne.jp [192.0.2.222])
|
89
|
-
cv = Sisimai::String.ipv4(e) || []
|
90
|
-
if cv.size > 0
|
91
|
-
# [192.0.2.1] or (192.0.2.1)
|
92
|
-
addrlist.append(*cv)
|
93
|
-
else
|
94
|
-
# hostname
|
95
|
-
e = e.delete('()').strip
|
96
|
-
namelist << e
|
97
|
-
end
|
98
|
-
end
|
136
|
+
while true do
|
137
|
+
# Prefer hostnames over IP addresses, except for localhost.localdomain and similar.
|
138
|
+
break if token['from'] == 'localhost'
|
139
|
+
break if token['from'] == 'localhost.localdomain'
|
140
|
+
break unless token['from'].include?('.') # A hostname without a domain name
|
141
|
+
break unless Sisimai::String.ipv4(token['from']).empty?
|
99
142
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
break
|
105
|
-
end
|
143
|
+
# No need to rewrite token['from']
|
144
|
+
right = true
|
145
|
+
break
|
146
|
+
end
|
106
147
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
148
|
+
while true do
|
149
|
+
# Try to rewrite uninformative hostnames and IP addresses in token['from']
|
150
|
+
break if right # There is no need to rewrite
|
151
|
+
break if alter.empty? # There is no alternative to rewriting
|
152
|
+
break if alter[0].include?(token['from'])
|
153
|
+
|
154
|
+
if token['from'].start_with?('localhost')
|
155
|
+
# localhost or localhost.localdomain
|
156
|
+
token['from'] = alter[0]
|
157
|
+
elsif token['from'].index('.')
|
158
|
+
# A hostname without a domain name such as "mail", "mx", or "mbox"
|
159
|
+
token['from'] = alter[0] if alter[0].include?('.')
|
160
|
+
else
|
161
|
+
# An IPv4 address
|
162
|
+
token['from'] = alter[0]
|
116
163
|
end
|
117
|
-
|
118
|
-
value['from'] = hostname || hostaddr || addrlist[-1]
|
164
|
+
break
|
119
165
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
166
|
+
token.delete('from') if token['from'].nil?
|
167
|
+
token.delete('by') if token['by'].nil?
|
168
|
+
token['for'] = Sisimai::Address.s3s4(token['for']) if token.has_key?('for')
|
169
|
+
|
170
|
+
token.keys.each do |e|
|
171
|
+
# Delete an invalid value
|
172
|
+
token[e] = '' if token[e].include?(' ')
|
173
|
+
token[e].delete!('[]') # Remove "[]" from the IP address
|
126
174
|
end
|
127
|
-
|
175
|
+
|
176
|
+
return [
|
177
|
+
token['from'] || '',
|
178
|
+
token['by'] || '',
|
179
|
+
token['via'] || '',
|
180
|
+
token['with'] || '',
|
181
|
+
token['id'] || '',
|
182
|
+
token['for'] || '',
|
183
|
+
]
|
128
184
|
end
|
129
185
|
|
130
186
|
# Split given entire message body into error message lines and the original message part only
|