sisimai 5.6.0-java → 5.7.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/rake-test.yml +0 -4
- data/ChangeLog.md +32 -0
- data/README-JA.md +19 -16
- data/README.md +23 -21
- data/lib/sisimai/address.rb +8 -31
- data/lib/sisimai/arf.rb +3 -5
- data/lib/sisimai/fact.rb +12 -37
- data/lib/sisimai/lhost/activehunter.rb +0 -2
- data/lib/sisimai/lhost/amazonses.rb +6 -8
- data/lib/sisimai/lhost/apachejames.rb +0 -1
- data/lib/sisimai/lhost/biglobe.rb +0 -16
- data/lib/sisimai/lhost/courier.rb +5 -4
- data/lib/sisimai/lhost/deutschetelekom.rb +120 -0
- data/lib/sisimai/lhost/domino.rb +0 -3
- data/lib/sisimai/lhost/dragonfly.rb +0 -27
- data/lib/sisimai/lhost/einsundeins.rb +1 -10
- data/lib/sisimai/lhost/exchange2003.rb +4 -4
- data/lib/sisimai/lhost/exchange2007.rb +3 -4
- data/lib/sisimai/lhost/exim.rb +30 -78
- data/lib/sisimai/lhost/ezweb.rb +12 -49
- data/lib/sisimai/lhost/fml.rb +4 -29
- data/lib/sisimai/lhost/gmail.rb +0 -23
- data/lib/sisimai/lhost/gmx.rb +7 -24
- data/lib/sisimai/lhost/googlegroups.rb +3 -3
- data/lib/sisimai/lhost/googleworkspace.rb +0 -4
- data/lib/sisimai/lhost/imailserver.rb +3 -9
- data/lib/sisimai/lhost/kddi.rb +6 -20
- data/lib/sisimai/lhost/mailfoundry.rb +0 -2
- data/lib/sisimai/lhost/mailmarshal.rb +1 -3
- data/lib/sisimai/lhost/messagingserver.rb +4 -15
- data/lib/sisimai/lhost/mfilter.rb +0 -1
- data/lib/sisimai/lhost/mimecast.rb +0 -1
- data/lib/sisimai/lhost/notes.rb +1 -2
- data/lib/sisimai/lhost/opensmtpd.rb +0 -40
- data/lib/sisimai/lhost/postfix.rb +10 -11
- data/lib/sisimai/lhost/qmail.rb +14 -81
- data/lib/sisimai/lhost/sendmail.rb +4 -4
- data/lib/sisimai/lhost/trendmicro.rb +3 -3
- data/lib/sisimai/lhost/v5sendmail.rb +0 -1
- data/lib/sisimai/lhost/verizon.rb +1 -2
- data/lib/sisimai/lhost/x1.rb +1 -2
- data/lib/sisimai/lhost/x2.rb +0 -2
- data/lib/sisimai/lhost/x3.rb +4 -9
- data/lib/sisimai/lhost/x6.rb +0 -1
- data/lib/sisimai/lhost/zoho.rb +0 -12
- data/lib/sisimai/lhost.rb +38 -19
- data/lib/sisimai/message.rb +1 -1
- data/lib/sisimai/order.rb +4 -1
- data/lib/sisimai/reason/authfailure.rb +2 -2
- data/lib/sisimai/reason/contenterror.rb +2 -0
- data/lib/sisimai/reason/emailtoolarge.rb +1 -1
- data/lib/sisimai/reason/expired.rb +13 -2
- data/lib/sisimai/reason/hostunknown.rb +9 -0
- data/lib/sisimai/reason/mailboxfull.rb +3 -2
- data/lib/sisimai/reason/networkerror.rb +13 -1
- data/lib/sisimai/reason/norelaying.rb +4 -3
- data/lib/sisimai/reason/notaccept.rb +10 -3
- data/lib/sisimai/reason/notcompliantrfc.rb +1 -0
- data/lib/sisimai/reason/policyviolation.rb +6 -1
- data/lib/sisimai/reason/rejected.rb +6 -0
- data/lib/sisimai/reason/securityerror.rb +1 -0
- data/lib/sisimai/reason/suspend.rb +4 -0
- data/lib/sisimai/reason/syntaxerror.rb +1 -8
- data/lib/sisimai/reason/systemerror.rb +18 -0
- data/lib/sisimai/reason/userunknown.rb +2 -0
- data/lib/sisimai/reason.rb +7 -7
- data/lib/sisimai/rfc1123.rb +1 -1
- data/lib/sisimai/rfc1894.rb +7 -6
- data/lib/sisimai/rfc2045.rb +2 -2
- data/lib/sisimai/rfc3464/thirdparty.rb +1 -1
- data/lib/sisimai/rfc3464.rb +10 -14
- data/lib/sisimai/rfc3834.rb +3 -4
- data/lib/sisimai/rfc791.rb +3 -38
- data/lib/sisimai/rhost/microsoft.rb +4 -0
- data/lib/sisimai/rhost.rb +1 -1
- data/lib/sisimai/smtp/status.rb +23 -19
- data/lib/sisimai/string.rb +0 -12
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/maildir/bsd/lhost-deutschetelekom-01.eml +66 -0
- data/set-of-emails/maildir/bsd/lhost-deutschetelekom-02.eml +68 -0
- data/set-of-emails/maildir/bsd/lhost-deutschetelekom-03.eml +50 -0
- data/set-of-emails/should-not-crash/p5-664-iomart-mail-filter.eml +258 -0
- data/set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yet/.gitkeep +0 -0
- metadata +8 -2
data/lib/sisimai/lhost/gmail.rb
CHANGED
|
@@ -11,17 +11,6 @@ module Sisimai::Lhost
|
|
|
11
11
|
message: ['Delivery to the following recipient'],
|
|
12
12
|
error: ['The error that the other server returned was:'],
|
|
13
13
|
}.freeze
|
|
14
|
-
MessagesOf = {
|
|
15
|
-
'expired' => [
|
|
16
|
-
'DNS Error: Could not contact DNS servers',
|
|
17
|
-
'Delivery to the following recipient has been delayed',
|
|
18
|
-
'The recipient server did not accept our requests to connect',
|
|
19
|
-
],
|
|
20
|
-
'hostunknown' => [
|
|
21
|
-
'DNS Error: Domain name not found',
|
|
22
|
-
'DNS Error: DNS server returned answer with no data',
|
|
23
|
-
],
|
|
24
|
-
}.freeze
|
|
25
14
|
StateTable = {
|
|
26
15
|
# Technical details of permanent failure:
|
|
27
16
|
# Google tried to deliver your message, but it was rejected by the recipient domain.
|
|
@@ -205,8 +194,6 @@ module Sisimai::Lhost
|
|
|
205
194
|
require 'sisimai/string'
|
|
206
195
|
require 'sisimai/rfc1123'
|
|
207
196
|
dscontents.each do |e|
|
|
208
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
209
|
-
|
|
210
197
|
if Sisimai::String.aligned(e['diagnosis'], [' by ', '. [', ']. '])
|
|
211
198
|
# Get the value of remote host
|
|
212
199
|
# Google tried to deliver your message, but it was rejected by the server for the recipient
|
|
@@ -232,16 +219,6 @@ module Sisimai::Lhost
|
|
|
232
219
|
e['command'] = StateTable[cu]['command']
|
|
233
220
|
break
|
|
234
221
|
end
|
|
235
|
-
|
|
236
|
-
if e['reason'].empty?
|
|
237
|
-
# There is no no state code in the error message
|
|
238
|
-
MessagesOf.each_key do |r|
|
|
239
|
-
# Verify each regular expression of session errors
|
|
240
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
241
|
-
e['reason'] = r
|
|
242
|
-
break
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
222
|
next if e['reason'].empty?
|
|
246
223
|
|
|
247
224
|
# Set pseudo status code
|
data/lib/sisimai/lhost/gmx.rb
CHANGED
|
@@ -8,7 +8,6 @@ module Sisimai::Lhost
|
|
|
8
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
9
|
Boundaries = ['--- The header of the original message is following. ---'].freeze
|
|
10
10
|
StartingOf = {message: ['This message was created automatically by mail delivery software']}.freeze
|
|
11
|
-
MessagesOf = {'expired' => ['delivery retry timeout exceeded']}.freeze
|
|
12
11
|
|
|
13
12
|
# @abstract Decodes the bounce message from GMX
|
|
14
13
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -65,33 +64,17 @@ module Sisimai::Lhost
|
|
|
65
64
|
end
|
|
66
65
|
v['recipient'] = Sisimai::Address.s3s4(e)
|
|
67
66
|
recipients += 1
|
|
68
|
-
|
|
69
|
-
elsif e.start_with?('SMTP error ')
|
|
70
|
-
# SMTP error from remote server after RCPT command:
|
|
71
|
-
v['command'] = Sisimai::SMTP::Command.find(e)
|
|
72
|
-
|
|
73
|
-
elsif e.start_with?('host:')
|
|
74
|
-
# host: mx.example.jp
|
|
75
|
-
v['rhost'] = e[6, e.size]
|
|
76
67
|
else
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
# - SMTP error from remote server after RCPT command:
|
|
69
|
+
# - host: mx.example.jp
|
|
70
|
+
case
|
|
71
|
+
when e.start_with?('SMTP error ') then v['command'] = Sisimai::SMTP::Command.find(e)
|
|
72
|
+
when e.start_with?('host:') then v['rhost'] = e[6, e.size]
|
|
73
|
+
else v['diagnosis'] += "#{e }" if e.empty? == false
|
|
74
|
+
end
|
|
80
75
|
end
|
|
81
76
|
end
|
|
82
77
|
return nil if recipients == 0
|
|
83
|
-
|
|
84
|
-
dscontents.each do |e|
|
|
85
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
|
86
|
-
|
|
87
|
-
MessagesOf.each_key do |r|
|
|
88
|
-
# Verify each regular expression of session errors
|
|
89
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
90
|
-
e['reason'] = r
|
|
91
|
-
break
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
78
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
|
96
79
|
end
|
|
97
80
|
def description; return 'GMX: https://www.gmx.net'; end
|
|
@@ -13,10 +13,10 @@ module Sisimai::Lhost
|
|
|
13
13
|
# @return [Nil] it failed to decode or the arguments are missing
|
|
14
14
|
# @since v4.25.6
|
|
15
15
|
def inquire(mhead, mbody)
|
|
16
|
-
return nil if mbody.include?("Google
|
|
16
|
+
return nil if mbody.include?("Google Group") == false
|
|
17
17
|
return nil if mhead['from'].end_with?('<mailer-daemon@googlemail.com>') == false
|
|
18
18
|
return nil if mhead['subject'].start_with?('Delivery Status Notification') == false
|
|
19
|
-
return nil if mhead['x-failed-recipients'].nil?
|
|
19
|
+
return nil if mhead['x-failed-recipients'].nil?
|
|
20
20
|
|
|
21
21
|
# Hello kijitora@libsisimai.org,
|
|
22
22
|
#
|
|
@@ -46,7 +46,7 @@ module Sisimai::Lhost
|
|
|
46
46
|
entiremesg = emailparts[0].split(/\n\n/, 5).slice(0, 4).join(' ').tr("\n", ' ');
|
|
47
47
|
receivedby = mhead['received'] || []
|
|
48
48
|
recordwide = {
|
|
49
|
-
'diagnosis' =>
|
|
49
|
+
'diagnosis' => entiremesg,
|
|
50
50
|
'reason' => 'onhold',
|
|
51
51
|
'rhost' => Sisimai::RFC5322.received(receivedby[0])[1],
|
|
52
52
|
}
|
|
@@ -15,8 +15,6 @@ module Sisimai::Lhost
|
|
|
15
15
|
}.freeze
|
|
16
16
|
MessagesOf = {
|
|
17
17
|
"userunknown" => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
|
|
18
|
-
"notaccept" => ["Null MX"],
|
|
19
|
-
"networkerror" => [" had no relevant answers.", " responded with code NXDOMAIN"],
|
|
20
18
|
}.freeze
|
|
21
19
|
|
|
22
20
|
# @abstract Decodes the bounce message from Google Workspace
|
|
@@ -73,8 +71,6 @@ module Sisimai::Lhost
|
|
|
73
71
|
|
|
74
72
|
dscontents[0]["diagnosis"] = entiremesg
|
|
75
73
|
dscontents.each do |e|
|
|
76
|
-
# Tidy up the error message in e["diagnosis"], Try to detect the bounce reason.
|
|
77
|
-
e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
|
|
78
74
|
MessagesOf.each_key do |r|
|
|
79
75
|
# Guess an reason of the bounce
|
|
80
76
|
next if MessagesOf[r].none? { |a| e["diagnosis"].include?(a) }
|
|
@@ -9,12 +9,8 @@ module Sisimai::Lhost
|
|
|
9
9
|
Boundaries = ['Original message follows.'].freeze
|
|
10
10
|
StartingOf = {error: ['Body of message generated response:']}.freeze
|
|
11
11
|
MessagesOf = {
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'mailboxfull' => ['User mailbox exceeds allowed size'],
|
|
15
|
-
'virusdetected' => ['Requested action not taken: virus detected'],
|
|
16
|
-
'spamdetected' => ['Blacklisted URL in message'],
|
|
17
|
-
'expired' => ['Delivery failed '],
|
|
12
|
+
'userunknown' => ['Unknown user', 'Invalid final delivery userid'],
|
|
13
|
+
'expired' => ['Delivery failed '],
|
|
18
14
|
}.freeze
|
|
19
15
|
|
|
20
16
|
# @abstract Decodes the bounce message from Progress iMail Server
|
|
@@ -72,11 +68,9 @@ module Sisimai::Lhost
|
|
|
72
68
|
else
|
|
73
69
|
e['alterrors']
|
|
74
70
|
end
|
|
75
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
76
71
|
e.delete('alterrors')
|
|
77
72
|
end
|
|
78
|
-
e['
|
|
79
|
-
e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
|
|
73
|
+
e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
|
|
80
74
|
|
|
81
75
|
MessagesOf.each_key do |r|
|
|
82
76
|
# Verify each regular expression of session errors
|
data/lib/sisimai/lhost/kddi.rb
CHANGED
|
@@ -8,11 +8,6 @@ module Sisimai::Lhost
|
|
|
8
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
9
|
Boundaries = ['Content-Type: message/rfc822'].freeze
|
|
10
10
|
StartingOf = {message: ['Your mail sent on:', 'Your mail attempted to be delivered on:']}.freeze
|
|
11
|
-
MessagesOf = {
|
|
12
|
-
'mailboxfull' => ['As their mailbox is full'],
|
|
13
|
-
'norelaying' => ['Due to the following SMTP relay error'],
|
|
14
|
-
'hostunknown' => ['As the remote domain doesnt exist'],
|
|
15
|
-
}.freeze
|
|
16
11
|
|
|
17
12
|
# @abstract Decodes the bounce message from au by KDDI
|
|
18
13
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -45,7 +40,8 @@ module Sisimai::Lhost
|
|
|
45
40
|
next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
|
|
46
41
|
|
|
47
42
|
v = dscontents[-1]
|
|
48
|
-
|
|
43
|
+
case
|
|
44
|
+
when e.include?(' Could not be delivered to: <')
|
|
49
45
|
# Your mail sent on: Thu, 29 Apr 2010 11:04:47 +0900
|
|
50
46
|
# Could not be delivered to: <******@**.***.**>
|
|
51
47
|
# As their mailbox is full.
|
|
@@ -59,7 +55,7 @@ module Sisimai::Lhost
|
|
|
59
55
|
v['recipient'] = r
|
|
60
56
|
recipients += 1
|
|
61
57
|
|
|
62
|
-
|
|
58
|
+
when e.include?('Your mail sent on: ')
|
|
63
59
|
# Your mail sent on: Thu, 29 Apr 2010 11:04:47 +0900
|
|
64
60
|
v['date'] = e[19, e.size]
|
|
65
61
|
else
|
|
@@ -71,7 +67,6 @@ module Sisimai::Lhost
|
|
|
71
67
|
|
|
72
68
|
require 'sisimai/smtp/command'
|
|
73
69
|
dscontents.each do |e|
|
|
74
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
|
75
70
|
e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
|
|
76
71
|
|
|
77
72
|
if mhead['x-spasign'].to_s == 'NG'
|
|
@@ -79,18 +74,9 @@ module Sisimai::Lhost
|
|
|
79
74
|
# Filtered recipient returns message that include 'X-SPASIGN' header
|
|
80
75
|
e['reason'] = 'filtered'
|
|
81
76
|
else
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
else
|
|
86
|
-
# SMTP command is not RCPT
|
|
87
|
-
MessagesOf.each_key do |r|
|
|
88
|
-
# Verify each regular expression of session errors
|
|
89
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
90
|
-
e['reason'] = r
|
|
91
|
-
break
|
|
92
|
-
end
|
|
93
|
-
end
|
|
77
|
+
# There is no X-SPASIGN: header in the bounce message
|
|
78
|
+
# set "userunknown" when the remote server rejected after RCPT command.
|
|
79
|
+
e['reason'] = 'userunknown' if e['command'] == 'RCPT'
|
|
94
80
|
end
|
|
95
81
|
end
|
|
96
82
|
|
|
@@ -65,8 +65,6 @@ module Sisimai::Lhost
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
return nil if recipients == 0
|
|
68
|
-
|
|
69
|
-
dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
|
|
70
68
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
71
69
|
end
|
|
72
70
|
def description; return 'MailFoundry'; end
|
|
@@ -103,15 +103,13 @@ module Sisimai::Lhost
|
|
|
103
103
|
p1 = e.index(' From:') || e.index(' Subject:')
|
|
104
104
|
p2 = e.index(':')
|
|
105
105
|
cf = e[p1 + 1, p2 - p1 - 1]
|
|
106
|
-
cv =
|
|
106
|
+
cv = e[p2 + 1, e.size]
|
|
107
107
|
emailparts[1] += sprintf("%s: %s\n", cf, cv)
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
return nil if recipients == 0
|
|
113
|
-
|
|
114
|
-
dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
|
|
115
113
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
116
114
|
end
|
|
117
115
|
def description; return 'Trustwave Secure Email Gateway'; end
|
|
@@ -9,7 +9,6 @@ module Sisimai::Lhost
|
|
|
9
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
10
10
|
Boundaries = ['Content-Type: message/rfc822', 'Return-path: '].freeze
|
|
11
11
|
StartingOf = {message: ['This report relates to a message you sent with the following header fields:']}.freeze
|
|
12
|
-
MessagesOf = {'hostunknown' => ['Illegal host/domain name found']}.freeze
|
|
13
12
|
|
|
14
13
|
# @abstract Decodes the bounce message from MessagingServer
|
|
15
14
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -115,18 +114,19 @@ module Sisimai::Lhost
|
|
|
115
114
|
# (6jo.example.jp ESMTP SENDMAIL-VM)
|
|
116
115
|
# Diagnostic-code: smtp;550 5.1.1 <kijitora@example.jp>... User Unknown
|
|
117
116
|
#
|
|
118
|
-
|
|
117
|
+
case
|
|
118
|
+
when e.start_with?('Status: ')
|
|
119
119
|
# Status: 5.1.1 (Remote SMTP server has rejected address)
|
|
120
120
|
p1 = e.index(':')
|
|
121
121
|
p2 = e.index('('); next if p2.nil?
|
|
122
122
|
v['status'] = e[p1 + 2, p2 - p1 - 3]
|
|
123
123
|
v['diagnosis'] = e[p2 + 1, e[e.index(')') - p2 - 1]] if v["diagnosis"].empty?
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
when e.start_with?('Arrival-Date: ')
|
|
126
126
|
# Arrival-date: Thu, 29 Apr 2014 23:34:45 +0000 (GMT)
|
|
127
127
|
v['date'] = e[e.index(':') + 2, e.size] if v["date"].empty?
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
when e.start_with?('Reporting-MTA: ')
|
|
130
130
|
# Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
|
|
131
131
|
localhost = e[e.index(';') + 1, e.size]
|
|
132
132
|
v['lhost'] = localhost if v["lhost"].empty?
|
|
@@ -135,17 +135,6 @@ module Sisimai::Lhost
|
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
137
|
return nil if recipients == 0
|
|
138
|
-
|
|
139
|
-
dscontents.each do |e|
|
|
140
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
141
|
-
MessagesOf.each_key do |r|
|
|
142
|
-
# Verify each regular expression of session errors
|
|
143
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
144
|
-
e['reason'] = r
|
|
145
|
-
break
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
|
|
149
138
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
|
150
139
|
end
|
|
151
140
|
def description; return 'Oracle Communications Messaging Server'; end
|
|
@@ -93,7 +93,6 @@ module Sisimai::Lhost
|
|
|
93
93
|
dscontents.each do |e|
|
|
94
94
|
# Set default values if each value is empty.
|
|
95
95
|
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
|
96
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
|
97
96
|
end
|
|
98
97
|
|
|
99
98
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
data/lib/sisimai/lhost/notes.rb
CHANGED
|
@@ -13,7 +13,6 @@ module Sisimai::Lhost
|
|
|
13
13
|
'User not listed in public Name & Address Book',
|
|
14
14
|
'ディレクトリのリストにありません',
|
|
15
15
|
],
|
|
16
|
-
'networkerror' => ['Message has exceeded maximum hop count'],
|
|
17
16
|
}.freeze
|
|
18
17
|
|
|
19
18
|
# @abstract Decodes the bounce messages from HCL Notes (Formerly IBM Notes (Formerly Lotus Notes))
|
|
@@ -101,7 +100,7 @@ module Sisimai::Lhost
|
|
|
101
100
|
return nil if recipients == 0
|
|
102
101
|
|
|
103
102
|
dscontents.each do |e|
|
|
104
|
-
e['diagnosis'] =
|
|
103
|
+
e['diagnosis'] = e['diagnosis'].split.join(" ")
|
|
105
104
|
e['recipient'] = Sisimai::Address.s3s4(e['recipient'])
|
|
106
105
|
|
|
107
106
|
MessagesOf.each_key do |r|
|
|
@@ -35,36 +35,6 @@ module Sisimai::Lhost
|
|
|
35
35
|
# bounce.c/339:
|
|
36
36
|
message: [' This is the MAILER-DAEMON, please DO NOT REPLY to this '],
|
|
37
37
|
}.freeze
|
|
38
|
-
MessagesOf = {
|
|
39
|
-
# smtpd/queue.c:221| envelope_set_errormsg(&evp, "Envelope expired");
|
|
40
|
-
'expired' => ['Envelope expired'],
|
|
41
|
-
# smtpd/mta.c:976| relay->failstr = "Invalid domain name";
|
|
42
|
-
# smtpd/mta.c:980| relay->failstr = "Domain does not exist";
|
|
43
|
-
'hostunknown' => [
|
|
44
|
-
'Invalid domain name',
|
|
45
|
-
'Domain does not exist',
|
|
46
|
-
],
|
|
47
|
-
# smtp/mta.c:1085| relay->failstr = "Destination seem to reject all mails";
|
|
48
|
-
'notaccept' => [
|
|
49
|
-
'Destination seem to reject all mails',
|
|
50
|
-
'No MX found for domain',
|
|
51
|
-
'No MX found for destination',
|
|
52
|
-
],
|
|
53
|
-
# smtpd/mta.c:972| relay->failstr = "Temporary failure in MX lookup";
|
|
54
|
-
'networkerror' => [
|
|
55
|
-
'Address family mismatch on destination MXs',
|
|
56
|
-
'All routes to destination blocked',
|
|
57
|
-
'bad DNS lookup error code',
|
|
58
|
-
'Could not retrieve source address',
|
|
59
|
-
'Loop detected',
|
|
60
|
-
'Network error on destination MXs',
|
|
61
|
-
'No valid route to remote MX',
|
|
62
|
-
'No valid route to destination',
|
|
63
|
-
'Temporary failure in MX lookup',
|
|
64
|
-
],
|
|
65
|
-
# smtpd/mta.c:1013| relay->failstr = "Could not retrieve credentials";
|
|
66
|
-
'securityerror' => ['Could not retrieve credentials'],
|
|
67
|
-
}.freeze
|
|
68
38
|
|
|
69
39
|
# @abstract Decodes the bounce message from OpenSMTPD
|
|
70
40
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -117,16 +87,6 @@ module Sisimai::Lhost
|
|
|
117
87
|
end
|
|
118
88
|
end
|
|
119
89
|
return nil if recipients == 0
|
|
120
|
-
|
|
121
|
-
dscontents.each do |e|
|
|
122
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
123
|
-
MessagesOf.each_key do |r|
|
|
124
|
-
# Verify each regular expression of session errors
|
|
125
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
126
|
-
e['reason'] = r
|
|
127
|
-
break
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
90
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
131
91
|
end
|
|
132
92
|
def description; return 'OpenSMTPD'; end
|
|
@@ -63,15 +63,14 @@ module Sisimai::Lhost
|
|
|
63
63
|
v ||= dscontents[-1]
|
|
64
64
|
p = e['response']
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
elsif e['command'] == 'MAIL'
|
|
66
|
+
case e["command"]
|
|
67
|
+
# Use the argument of EHLO/HELO command as a value of "lhost"
|
|
68
|
+
when "HELO", "EHLO" then v['lhost'] = e['argument']
|
|
69
|
+
when "MAIL"
|
|
71
70
|
# Set the argument of "MAIL" command to pseudo To: header of the original message
|
|
72
71
|
emailparts[1] += sprintf("To: %s\n", e['argument']) if emailparts[1].size == 0
|
|
73
72
|
|
|
74
|
-
|
|
73
|
+
when "RCPT"
|
|
75
74
|
# RCPT TO: <...>
|
|
76
75
|
if v["recipient"] != ""
|
|
77
76
|
# There are multiple recipient addresses in the transcript of session
|
|
@@ -110,7 +109,8 @@ module Sisimai::Lhost
|
|
|
110
109
|
next unless o = Sisimai::RFC1894.field(e)
|
|
111
110
|
v = dscontents[-1]
|
|
112
111
|
|
|
113
|
-
|
|
112
|
+
case o[3]
|
|
113
|
+
when "addr"
|
|
114
114
|
# Final-Recipient: rfc822; kijitora@example.jp
|
|
115
115
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
116
116
|
if Sisimai::Address.is_emailaddress(o[2])
|
|
@@ -130,7 +130,7 @@ module Sisimai::Lhost
|
|
|
130
130
|
v['alias'] = o[2]
|
|
131
131
|
end
|
|
132
132
|
end
|
|
133
|
-
|
|
133
|
+
when "code"
|
|
134
134
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
135
135
|
v['spec'] = o[1]
|
|
136
136
|
v['spec'] = 'SMTP' if v['spec'].upcase == 'X-POSTFIX'
|
|
@@ -154,7 +154,7 @@ module Sisimai::Lhost
|
|
|
154
154
|
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO command)
|
|
155
155
|
if readslices[-2].start_with?('Diagnostic-Code:') && e.include?(' ')
|
|
156
156
|
# Continued line of the value of Diagnostic-Code header
|
|
157
|
-
v['diagnosis'] += "
|
|
157
|
+
v['diagnosis'] += " " + e.split.join(" ")
|
|
158
158
|
readslices[-1] = "Diagnostic-Code: #{e}"
|
|
159
159
|
|
|
160
160
|
elsif Sisimai::String.aligned(e, ['X-Postfix-Sender:', 'rfc822;', '@'])
|
|
@@ -238,7 +238,7 @@ module Sisimai::Lhost
|
|
|
238
238
|
|
|
239
239
|
if anotherset['diagnosis']
|
|
240
240
|
# Copy alternative error message
|
|
241
|
-
anotherset['diagnosis'] =
|
|
241
|
+
anotherset['diagnosis'] = anotherset['diagnosis'].split.join(" ")
|
|
242
242
|
e['diagnosis'] = anotherset['diagnosis'] if e['diagnosis'].nil? || e['diagnosis'].empty?
|
|
243
243
|
|
|
244
244
|
if e['diagnosis'] =~ /\A\d+\z/
|
|
@@ -277,7 +277,6 @@ module Sisimai::Lhost
|
|
|
277
277
|
end
|
|
278
278
|
end
|
|
279
279
|
|
|
280
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
|
281
280
|
e['command'] = commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis'])
|
|
282
281
|
e['command'] = 'HELO' if e["command"].empty? && e['diagnosis'].include?('refused to talk to me:')
|
|
283
282
|
e['spec'] = 'SMTP' if e["spec"].empty? && Sisimai::String.aligned(e['diagnosis'], ['host ', ' said:'])
|
data/lib/sisimai/lhost/qmail.rb
CHANGED
|
@@ -66,59 +66,9 @@ module Sisimai::Lhost
|
|
|
66
66
|
"DATA" => [" failed on DATA command", " failed after I sent the message"],
|
|
67
67
|
}.freeze
|
|
68
68
|
|
|
69
|
-
# qmail-send.c:922| ... (&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
|
|
70
|
-
# qmail-remote-fallback.patch
|
|
71
|
-
HasExpired = "this message has been in the queue too long.".freeze
|
|
72
|
-
OnHoldPair = [" does not like recipient.", "this message has been in the queue too long."].freeze
|
|
73
|
-
FailOnLDAP = {
|
|
74
|
-
# qmail-ldap-1.03-20040101.patch:19817 - 19866
|
|
75
|
-
"emailtoolarge" => ["The message exeeded the maximum size the user accepts"], # 5.2.3
|
|
76
|
-
"userunknown" => ["Sorry, no mailbox here by that name"], # 5.1.1
|
|
77
|
-
"suspend" => [ # 5.2.1
|
|
78
|
-
"Mailaddress is administrativly disabled",
|
|
79
|
-
"Mailaddress is administrativley disabled",
|
|
80
|
-
"Mailaddress is administratively disabled",
|
|
81
|
-
"Mailaddress is administrativeley disabled",
|
|
82
|
-
],
|
|
83
|
-
"systemerror" => [
|
|
84
|
-
"Automatic homedir creator crashed", # 4.3.0
|
|
85
|
-
"Illegal value in LDAP attribute", # 5.3.5
|
|
86
|
-
"LDAP attribute is not given but mandatory", # 5.3.5
|
|
87
|
-
"Timeout while performing search on LDAP server", # 4.4.3
|
|
88
|
-
"Too many results returned but needs to be unique", # 5.3.5
|
|
89
|
-
"Permanent error while executing qmail-forward", # 5.4.4
|
|
90
|
-
"Temporary error in automatic homedir creation", # 4.3.0 or 5.3.0
|
|
91
|
-
"Temporary error while executing qmail-forward", # 4.4.4
|
|
92
|
-
"Temporary failure in LDAP lookup", # 4.4.3
|
|
93
|
-
"Unable to contact LDAP server", # 4.4.3
|
|
94
|
-
"Unable to login into LDAP server, bad credentials",# 4.4.3
|
|
95
|
-
],
|
|
96
|
-
}.freeze
|
|
97
69
|
MessagesOf = {
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
"hostunknown" => ["Sorry, I couldn't find any host "],
|
|
101
|
-
# error_str.c:192| X(EDQUOT,"disk quota exceeded")
|
|
102
|
-
"mailboxfull" => ["disk quota exceeded"],
|
|
103
|
-
# qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
|
|
104
|
-
# qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
|
|
105
|
-
"emailtoolarge" => ["Message size exceeds fixed maximum message size:"],
|
|
106
|
-
"networkerror" => [
|
|
107
|
-
"Sorry, I wasn't able to establish an SMTP connection",
|
|
108
|
-
"Sorry. Although I'm listed as a best-preference MX or A for that host",
|
|
109
|
-
],
|
|
110
|
-
"notaccept" => [
|
|
111
|
-
# notqmail 1.08 returns the following error message when the destination MX is NullMX
|
|
112
|
-
"Sorry, I couldn't find a mail exchanger or IP address",
|
|
113
|
-
],
|
|
114
|
-
"systemerror" => [
|
|
115
|
-
"bad interpreter: No such file or directory",
|
|
116
|
-
"system error",
|
|
117
|
-
"Unable to",
|
|
118
|
-
],
|
|
119
|
-
"systemfull" => ["Requested action not taken: mailbox unavailable (not enough free space)"],
|
|
120
|
-
# qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
|
|
121
|
-
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
|
70
|
+
# notqmail 1.08 returns the following error message when the destination MX is NullMX
|
|
71
|
+
"notaccept" => ["Sorry, I couldn't find a mail exchanger or IP address"],
|
|
122
72
|
"userunknown" => ["no mailbox here by that name"],
|
|
123
73
|
}.freeze
|
|
124
74
|
|
|
@@ -186,7 +136,7 @@ module Sisimai::Lhost
|
|
|
186
136
|
cm = r.size
|
|
187
137
|
p2 = e.index(" ", p1 + cm + 1) || p2 = e.rindex(".")
|
|
188
138
|
|
|
189
|
-
v["rhost"] =
|
|
139
|
+
v["rhost"] = e[p1 + cm, p2 - p1 - cm]
|
|
190
140
|
break
|
|
191
141
|
end
|
|
192
142
|
end
|
|
@@ -194,9 +144,6 @@ module Sisimai::Lhost
|
|
|
194
144
|
return nil if recipients == 0
|
|
195
145
|
|
|
196
146
|
dscontents.each do |e|
|
|
197
|
-
# Tidy up the error message in e['diagnosis'], Try to detect the bounce reason.
|
|
198
|
-
e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
|
|
199
|
-
|
|
200
147
|
# Get the SMTP command name for the session
|
|
201
148
|
CommandSet.each_key do |r|
|
|
202
149
|
# Get the last SMTP command
|
|
@@ -216,32 +163,18 @@ module Sisimai::Lhost
|
|
|
216
163
|
e["reason"] = "blocked"
|
|
217
164
|
else
|
|
218
165
|
# Try to match with each error message in the table
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
#
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
# The key is a bounce reason name
|
|
230
|
-
next if MessagesOf[r].none? { |a| f.include?(a) }
|
|
231
|
-
e["reason"] = r
|
|
232
|
-
break
|
|
233
|
-
end
|
|
234
|
-
break if e["reason"]
|
|
235
|
-
|
|
236
|
-
FailOnLDAP.each_key do |r|
|
|
237
|
-
# The key is a bounce reason name
|
|
238
|
-
next if FailOnLDAP[r].none? { |a| f.include?(a) }
|
|
239
|
-
e["reason"] = r
|
|
240
|
-
break
|
|
241
|
-
end
|
|
242
|
-
break if e["reason"]
|
|
243
|
-
e["reason"] = "expired" if e["diagnosis"].include?(HasExpired)
|
|
166
|
+
# Check that the error message includes any of message patterns or not
|
|
167
|
+
[e["alterrors"], e["diagnosis"]].each do |f|
|
|
168
|
+
# Try to detect an error reason
|
|
169
|
+
break if e["reason"] != ""
|
|
170
|
+
next if f.nil?
|
|
171
|
+
MessagesOf.each_key do |r|
|
|
172
|
+
# The key is a bounce reason name
|
|
173
|
+
next if MessagesOf[r].none? { |a| f.include?(a) }
|
|
174
|
+
e["reason"] = r
|
|
175
|
+
break
|
|
244
176
|
end
|
|
177
|
+
break if e["reason"]
|
|
245
178
|
end
|
|
246
179
|
end
|
|
247
180
|
|
|
@@ -67,7 +67,8 @@ module Sisimai::Lhost
|
|
|
67
67
|
o = Sisimai::RFC1894.field(e) || next
|
|
68
68
|
v = dscontents[-1]
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
case o[3]
|
|
71
|
+
when "addr"
|
|
71
72
|
# Final-Recipient: rfc822; kijitora@example.jp
|
|
72
73
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
73
74
|
if o[0] == 'final-recipient'
|
|
@@ -83,7 +84,7 @@ module Sisimai::Lhost
|
|
|
83
84
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
84
85
|
v['alias'] = o[2]
|
|
85
86
|
end
|
|
86
|
-
|
|
87
|
+
when "code"
|
|
87
88
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
88
89
|
v['spec'] = o[1]
|
|
89
90
|
v['diagnosis'] = o[2]
|
|
@@ -159,7 +160,7 @@ module Sisimai::Lhost
|
|
|
159
160
|
# Continued line of the value of Diagnostic-Code field
|
|
160
161
|
next if readslices[-2].start_with?('Diagnostic-Code:') == false
|
|
161
162
|
next if e.start_with?(' ') == false
|
|
162
|
-
v['diagnosis'] += "
|
|
163
|
+
v['diagnosis'] += " " + e
|
|
163
164
|
readslices[-1] = "Diagnostic-Code: #{e}"
|
|
164
165
|
end
|
|
165
166
|
end
|
|
@@ -186,7 +187,6 @@ module Sisimai::Lhost
|
|
|
186
187
|
break
|
|
187
188
|
end
|
|
188
189
|
|
|
189
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
190
190
|
e["command"] = thecommand if e["command"].empty?
|
|
191
191
|
e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
|
|
192
192
|
e["command"] = "EHLO" if e["command"].empty? && esmtpreply.size > 0
|
|
@@ -55,11 +55,12 @@ module Sisimai::Lhost
|
|
|
55
55
|
recipients = dscontents.size
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
case
|
|
59
|
+
when e.start_with?('Sent <<< ')
|
|
59
60
|
# Sent <<< RCPT TO:<kijitora@example.co.jp>
|
|
60
61
|
v['command'] = Sisimai::SMTP::Command.find(e)
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
when e.start_with?('Received >>> ')
|
|
63
64
|
# Received >>> 550 5.1.1 <kijitora@example.co.jp>... user unknown
|
|
64
65
|
v['diagnosis'] = e[e.index(' >>> ') + 4, e.size]
|
|
65
66
|
else
|
|
@@ -72,7 +73,6 @@ module Sisimai::Lhost
|
|
|
72
73
|
return nil if recipients == 0
|
|
73
74
|
|
|
74
75
|
dscontents.each do |e|
|
|
75
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
76
76
|
e['reason'] = 'userunknown' if e['diagnosis'].include?('Unable to deliver')
|
|
77
77
|
end
|
|
78
78
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
@@ -161,7 +161,6 @@ module Sisimai::Lhost
|
|
|
161
161
|
j = 0; dscontents.each do |e|
|
|
162
162
|
# Tidy up the error message in e.Diagnosis
|
|
163
163
|
e["diagnosis"] = anotherone[j] if e["diagnosis"].empty?
|
|
164
|
-
e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
|
|
165
164
|
e["command"] = Sisimai::SMTP::Command.find(e["diagnosis"]) if e["command"].empty?
|
|
166
165
|
e["replycode"] = Sisimai::SMTP::Reply.find(e["diagnosis"])
|
|
167
166
|
e["replycode"] = Sisimai::SMTP::Reply.find(anotherone[j]) if e["replycode"].empty?
|