sisimai 5.5.0 → 5.7.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 +0 -4
- data/ChangeLog.md +53 -0
- data/LICENSE +1 -1
- data/README-JA.md +26 -20
- data/README.md +30 -25
- data/lib/sisimai/address.rb +8 -31
- data/lib/sisimai/arf.rb +3 -5
- data/lib/sisimai/fact.rb +26 -36
- data/lib/sisimai/lhost/activehunter.rb +0 -2
- data/lib/sisimai/lhost/amazonses.rb +7 -9
- 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 +5 -6
- data/lib/sisimai/lhost/exim.rb +35 -85
- 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 +3 -1
- data/lib/sisimai/order.rb +4 -1
- data/lib/sisimai/reason/authfailure.rb +9 -13
- data/lib/sisimai/reason/badreputation.rb +7 -7
- data/lib/sisimai/reason/blocked.rb +57 -83
- data/lib/sisimai/reason/contenterror.rb +16 -8
- data/lib/sisimai/reason/{mesgtoobig.rb → emailtoolarge.rb} +22 -25
- data/lib/sisimai/reason/expired.rb +27 -23
- data/lib/sisimai/reason/filtered.rb +13 -17
- data/lib/sisimai/reason/hasmoved.rb +2 -1
- data/lib/sisimai/reason/hostunknown.rb +25 -19
- data/lib/sisimai/reason/mailboxfull.rb +28 -49
- data/lib/sisimai/reason/networkerror.rb +28 -16
- data/lib/sisimai/reason/norelaying.rb +21 -20
- data/lib/sisimai/reason/notaccept.rb +13 -8
- data/lib/sisimai/reason/notcompliantrfc.rb +6 -9
- data/lib/sisimai/reason/policyviolation.rb +17 -26
- data/lib/sisimai/reason/ratelimited.rb +62 -0
- data/lib/sisimai/reason/rejected.rb +51 -59
- data/lib/sisimai/reason/requireptr.rb +13 -25
- data/lib/sisimai/reason/securityerror.rb +14 -19
- data/lib/sisimai/reason/spamdetected.rb +51 -101
- data/lib/sisimai/reason/suspend.rb +30 -24
- data/lib/sisimai/reason/syntaxerror.rb +1 -8
- data/lib/sisimai/reason/systemerror.rb +37 -23
- data/lib/sisimai/reason/systemfull.rb +1 -1
- data/lib/sisimai/reason/userunknown.rb +81 -112
- data/lib/sisimai/reason/virusdetected.rb +6 -8
- data/lib/sisimai/reason.rb +15 -15
- 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/apple.rb +5 -5
- data/lib/sisimai/rhost/cloudflare.rb +2 -0
- data/lib/sisimai/rhost/cox.rb +22 -20
- data/lib/sisimai/rhost/facebook.rb +16 -16
- data/lib/sisimai/rhost/franceptt.rb +8 -3
- data/lib/sisimai/rhost/godaddy.rb +33 -15
- data/lib/sisimai/rhost/google.rb +63 -64
- data/lib/sisimai/rhost/iua.rb +1 -1
- data/lib/sisimai/rhost/messagelabs.rb +12 -12
- data/lib/sisimai/rhost/microsoft.rb +86 -86
- data/lib/sisimai/rhost/mimecast.rb +34 -34
- data/lib/sisimai/rhost/nttdocomo.rb +2 -2
- data/lib/sisimai/rhost/spectrum.rb +7 -7
- data/lib/sisimai/rhost/tencent.rb +9 -11
- data/lib/sisimai/rhost/yahooinc.rb +7 -8
- data/lib/sisimai/rhost.rb +1 -1
- data/lib/sisimai/smtp/command.rb +2 -0
- data/lib/sisimai/smtp/status.rb +73 -109
- data/lib/sisimai/string.rb +0 -27
- 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 +10 -6
- data/lib/sisimai/reason/exceedlimit.rb +0 -47
- data/lib/sisimai/reason/speeding.rb +0 -47
- data/lib/sisimai/reason/toomanyconn.rb +0 -59
data/lib/sisimai/lhost/ezweb.rb
CHANGED
|
@@ -8,22 +8,12 @@ module Sisimai::Lhost
|
|
|
8
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
9
|
Boundaries = ["--------------------------------------------------", "Content-Type: message/rfc822"].freeze
|
|
10
10
|
StartingOf = {message: ['The user(s) ', 'Your message ', 'Each of the following', '<']}.freeze
|
|
11
|
-
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
],
|
|
18
|
-
'mailboxfull' => ['The user(s) account is temporarily over quota'],
|
|
19
|
-
'onhold' => ['Each of the following recipients was rejected by a remote mail server'],
|
|
20
|
-
'suspend' => [
|
|
21
|
-
# http://www.naruhodo-au.kddi.com/qa3429203.html
|
|
22
|
-
# The recipient may be unpaid user...?
|
|
23
|
-
'The user(s) account is disabled.',
|
|
24
|
-
'The user(s) account is temporarily limited.',
|
|
25
|
-
],
|
|
26
|
-
}.freeze
|
|
11
|
+
UnpaidUser = [
|
|
12
|
+
# http://www.naruhodo-au.kddi.com/qa3429203.html
|
|
13
|
+
# The recipient may be unpaid user...?
|
|
14
|
+
'The user(s) account is disabled.',
|
|
15
|
+
'The user(s) account is temporarily limited.',
|
|
16
|
+
].freeze
|
|
27
17
|
|
|
28
18
|
# @abstract Decodes the bounce message from au EZweb
|
|
29
19
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -48,7 +38,6 @@ module Sisimai::Lhost
|
|
|
48
38
|
bodyslices = emailparts[0].split("\n")
|
|
49
39
|
readcursor = 0 # (Integer) Points the current cursor position
|
|
50
40
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
|
51
|
-
substrings = []; Messagesof.each_value { |a| substrings << a }; substrings.flatten!
|
|
52
41
|
|
|
53
42
|
while e = bodyslices.shift do
|
|
54
43
|
# Read error messages and delivery status lines from the head of the email to the previous
|
|
@@ -94,53 +83,27 @@ module Sisimai::Lhost
|
|
|
94
83
|
|
|
95
84
|
else
|
|
96
85
|
# Other error messages
|
|
86
|
+
# >>> RCPT TO:<******@ezweb.ne.jp>
|
|
87
|
+
# <<< 550 ...
|
|
97
88
|
next if Sisimai::String.is_8bit(e)
|
|
98
|
-
if e.include?(" >>> ")
|
|
99
|
-
|
|
100
|
-
v["command"] = Sisimai::SMTP::Command.find(e)
|
|
101
|
-
v["diagnosis"] += " #{e}"
|
|
102
|
-
|
|
103
|
-
elsif e.include?(" <<< ")
|
|
104
|
-
# <<< 550 ...
|
|
105
|
-
v["diagnosis"] += " #{e}"
|
|
106
|
-
|
|
107
|
-
else
|
|
108
|
-
# Check error message
|
|
109
|
-
isincluded = false
|
|
110
|
-
if substrings.any? { |a| e.include?(a) }
|
|
111
|
-
# Check with regular expressions of each error
|
|
112
|
-
v["diagnosis"] += " #{e}"
|
|
113
|
-
isincluded = true
|
|
114
|
-
end
|
|
115
|
-
v["diagnosis"] += " #{e}" if isincluded
|
|
116
|
-
end
|
|
89
|
+
v["command"] = Sisimai::SMTP::Command.find(e) if e.include?(" >>> ")
|
|
90
|
+
v["diagnosis"] += " #{e}"
|
|
117
91
|
end
|
|
118
92
|
end
|
|
119
93
|
return nil if recipients == 0
|
|
120
94
|
|
|
121
95
|
dscontents.each do |e|
|
|
122
96
|
# Check each value of DeliveryMatter{}, try to detect the bounce reason.
|
|
123
|
-
e['diagnosis'] =
|
|
97
|
+
e['diagnosis'] = e['diagnosis'].split.join(" ")
|
|
124
98
|
e["command"] = Sisimai::SMTP::Command.find(e["diagnosis"]) if e["command"].empty?
|
|
125
99
|
|
|
126
100
|
if mhead['x-spasign'].to_s == 'NG'
|
|
127
101
|
# Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
|
|
128
102
|
# Filtered recipient returns message that include 'X-SPASIGN' header
|
|
129
103
|
e['reason'] = 'filtered'
|
|
130
|
-
e['toxic'] = true
|
|
131
104
|
else
|
|
132
105
|
# There is no X-SPASIGN header or the value of the header is not "NG"
|
|
133
|
-
|
|
134
|
-
Messagesof.each_key do |r|
|
|
135
|
-
# Try to match with each session error message
|
|
136
|
-
Messagesof[r].each do |f|
|
|
137
|
-
# Check each error message pattern
|
|
138
|
-
next if e['diagnosis'].include?(f) == false
|
|
139
|
-
e['reason'] = r
|
|
140
|
-
throw :FINDREASON
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
106
|
+
e['reason'] = "suspend" if UnpaidUser.any? { |a| e['diagnosis'].include?(a) }
|
|
144
107
|
end
|
|
145
108
|
next if e['reason'] != ""
|
|
146
109
|
next if e['recipient'].end_with?('@ezweb.ne.jp', '@au.com')
|
data/lib/sisimai/lhost/fml.rb
CHANGED
|
@@ -22,21 +22,6 @@ module Sisimai::Lhost
|
|
|
22
22
|
],
|
|
23
23
|
'securityerror' => ['Security Alert'],
|
|
24
24
|
}.freeze
|
|
25
|
-
ErrorTable = {
|
|
26
|
-
'rejected' => [
|
|
27
|
-
' header may cause mail loop',
|
|
28
|
-
'NOT MEMBER article from ',
|
|
29
|
-
'reject mail from ',
|
|
30
|
-
'reject spammers:',
|
|
31
|
-
'You are not a member of this mailing list',
|
|
32
|
-
],
|
|
33
|
-
'notcompliantrfc' => ['Duplicated Message-ID'],
|
|
34
|
-
'securityerror' => ['Security alert:'],
|
|
35
|
-
'systemerror' => [
|
|
36
|
-
' has detected a loop condition so that',
|
|
37
|
-
'Loop Back Warning:',
|
|
38
|
-
],
|
|
39
|
-
}.freeze
|
|
40
25
|
|
|
41
26
|
# @abstract Decodes the bounce message from fml mailling list server/manager
|
|
42
27
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -84,23 +69,13 @@ module Sisimai::Lhost
|
|
|
84
69
|
return nil if recipients == 0
|
|
85
70
|
|
|
86
71
|
dscontents.each do |e|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# Try to match with
|
|
90
|
-
next if
|
|
72
|
+
# Error messages in the message body did not matched
|
|
73
|
+
ErrorTitle.each_key do |f|
|
|
74
|
+
# Try to match with the Subject string
|
|
75
|
+
next if ErrorTitle[f].none? { |a| mhead["subject"].include?(a) }
|
|
91
76
|
e['reason'] = f
|
|
92
77
|
break
|
|
93
78
|
end
|
|
94
|
-
|
|
95
|
-
if e['reason'].nil?
|
|
96
|
-
# Error messages in the message body did not matched
|
|
97
|
-
ErrorTitle.each_key do |f|
|
|
98
|
-
# Try to match with the Subject string
|
|
99
|
-
next if ErrorTitle[f].none? { |a| mhead["subject"].include?(a) }
|
|
100
|
-
e['reason'] = f
|
|
101
|
-
break
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
79
|
end
|
|
105
80
|
|
|
106
81
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
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:'])
|