sisimai 5.6.0-java → 5.7.1-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 +47 -0
- data/README-JA.md +19 -16
- data/README.md +23 -21
- data/lib/sisimai/address.rb +8 -31
- data/lib/sisimai/arf.rb +5 -6
- data/lib/sisimai/eb.rb +116 -0
- data/lib/sisimai/fact.rb +33 -51
- data/lib/sisimai/lda.rb +20 -18
- data/lib/sisimai/lhost/activehunter.rb +0 -2
- data/lib/sisimai/lhost/amazonses.rb +17 -18
- data/lib/sisimai/lhost/apachejames.rb +0 -1
- data/lib/sisimai/lhost/biglobe.rb +0 -16
- data/lib/sisimai/lhost/courier.rb +9 -7
- data/lib/sisimai/lhost/deutschetelekom.rb +120 -0
- data/lib/sisimai/lhost/domino.rb +2 -4
- data/lib/sisimai/lhost/dragonfly.rb +0 -27
- data/lib/sisimai/lhost/einsundeins.rb +4 -12
- data/lib/sisimai/lhost/exchange2003.rb +12 -11
- data/lib/sisimai/lhost/exchange2007.rb +17 -17
- data/lib/sisimai/lhost/exim.rb +34 -81
- data/lib/sisimai/lhost/ezweb.rb +15 -51
- data/lib/sisimai/lhost/fml.rb +8 -32
- data/lib/sisimai/lhost/gmail.rb +10 -32
- data/lib/sisimai/lhost/gmx.rb +7 -24
- data/lib/sisimai/lhost/googlegroups.rb +6 -5
- data/lib/sisimai/lhost/googleworkspace.rb +2 -5
- data/lib/sisimai/lhost/imailserver.rb +4 -9
- data/lib/sisimai/lhost/kddi.rb +8 -21
- 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 +3 -3
- data/lib/sisimai/lhost/opensmtpd.rb +0 -40
- data/lib/sisimai/lhost/postfix.rb +14 -14
- data/lib/sisimai/lhost/qmail.rb +23 -89
- data/lib/sisimai/lhost/sendmail.rb +8 -7
- data/lib/sisimai/lhost/trendmicro.rb +5 -4
- data/lib/sisimai/lhost/v5sendmail.rb +2 -2
- data/lib/sisimai/lhost/verizon.rb +4 -4
- 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 +8 -7
- data/lib/sisimai/reason/badreputation.rb +5 -4
- data/lib/sisimai/reason/blocked.rb +6 -5
- data/lib/sisimai/reason/contenterror.rb +8 -5
- data/lib/sisimai/reason/delivered.rb +3 -2
- data/lib/sisimai/reason/emailtoolarge.rb +7 -6
- data/lib/sisimai/reason/expired.rb +16 -4
- data/lib/sisimai/reason/failedstarttls.rb +5 -3
- data/lib/sisimai/reason/feedback.rb +2 -1
- data/lib/sisimai/reason/filtered.rb +9 -8
- data/lib/sisimai/reason/hasmoved.rb +5 -4
- data/lib/sisimai/reason/hostunknown.rb +14 -4
- data/lib/sisimai/reason/mailboxfull.rb +10 -8
- data/lib/sisimai/reason/mailererror.rb +3 -2
- data/lib/sisimai/reason/networkerror.rb +16 -3
- data/lib/sisimai/reason/norelaying.rb +8 -6
- data/lib/sisimai/reason/notaccept.rb +15 -7
- data/lib/sisimai/reason/notcompliantrfc.rb +5 -3
- data/lib/sisimai/reason/onhold.rb +8 -7
- data/lib/sisimai/reason/policyviolation.rb +11 -5
- data/lib/sisimai/reason/ratelimited.rb +5 -4
- data/lib/sisimai/reason/rejected.rb +24 -14
- data/lib/sisimai/reason/requireptr.rb +5 -4
- data/lib/sisimai/reason/securityerror.rb +5 -3
- data/lib/sisimai/reason/spamdetected.rb +6 -5
- data/lib/sisimai/reason/suppressed.rb +4 -3
- data/lib/sisimai/reason/suspend.rb +8 -3
- data/lib/sisimai/reason/syntaxerror.rb +5 -11
- data/lib/sisimai/reason/systemerror.rb +21 -2
- data/lib/sisimai/reason/systemfull.rb +4 -3
- data/lib/sisimai/reason/undefined.rb +2 -1
- data/lib/sisimai/reason/userunknown.rb +15 -9
- data/lib/sisimai/reason/vacation.rb +2 -1
- data/lib/sisimai/reason/virusdetected.rb +6 -5
- data/lib/sisimai/reason.rb +47 -42
- data/lib/sisimai/rfc1123.rb +1 -1
- data/lib/sisimai/rfc1894.rb +15 -8
- data/lib/sisimai/rfc2045.rb +8 -5
- data/lib/sisimai/rfc3464/thirdparty.rb +11 -10
- data/lib/sisimai/rfc3464.rb +10 -14
- data/lib/sisimai/rfc3834.rb +6 -5
- data/lib/sisimai/rfc791.rb +3 -38
- data/lib/sisimai/rhost/aol.rb +3 -2
- data/lib/sisimai/rhost/apple.rb +12 -11
- data/lib/sisimai/rhost/cloudflare.rb +3 -2
- data/lib/sisimai/rhost/cox.rb +38 -37
- data/lib/sisimai/rhost/facebook.rb +17 -16
- data/lib/sisimai/rhost/franceptt.rb +39 -38
- data/lib/sisimai/rhost/godaddy.rb +35 -34
- data/lib/sisimai/rhost/google.rb +22 -21
- data/lib/sisimai/rhost/gsuite.rb +8 -7
- data/lib/sisimai/rhost/iua.rb +11 -10
- data/lib/sisimai/rhost/kddi.rb +3 -2
- data/lib/sisimai/rhost/messagelabs.rb +13 -12
- data/lib/sisimai/rhost/microsoft.rb +37 -32
- data/lib/sisimai/rhost/mimecast.rb +18 -17
- data/lib/sisimai/rhost/nttdocomo.rb +10 -9
- data/lib/sisimai/rhost/outlook.rb +3 -2
- data/lib/sisimai/rhost/spectrum.rb +19 -18
- data/lib/sisimai/rhost/tencent.rb +10 -9
- data/lib/sisimai/rhost/yahooinc.rb +11 -10
- data/lib/sisimai/rhost/zoho.rb +8 -7
- data/lib/sisimai/rhost.rb +1 -1
- data/lib/sisimai/smtp/command.rb +13 -8
- data/lib/sisimai/smtp/failure.rb +9 -8
- data/lib/sisimai/smtp/reply.rb +23 -22
- data/lib/sisimai/smtp/status.rb +164 -159
- data/lib/sisimai/smtp/transcript.rb +3 -2
- data/lib/sisimai/string.rb +0 -12
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +2 -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/maildir/bsd/lhost-postfix-81.eml +130 -0
- data/set-of-emails/should-not-crash/go-423-deeply-nested-mime-parts.eml +20050 -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 +11 -2
|
@@ -14,23 +14,6 @@ module Sisimai::Lhost
|
|
|
14
14
|
# https://github.com/corecode/dma/blob/ffad280aa40c242aa9a2cb9ca5b1b6e8efedd17e/mail.c#L84
|
|
15
15
|
message: ['This is the DragonFly Mail Agent '],
|
|
16
16
|
}.freeze
|
|
17
|
-
MessagesOf = {
|
|
18
|
-
'expired' => [
|
|
19
|
-
# https://github.com/corecode/dma/blob/master/dma.c#L370C1-L374C19
|
|
20
|
-
# dma.c:370| if (gettimeofday(&now, NULL) == 0 &&
|
|
21
|
-
# dma.c:371| (now.tv_sec - st.st_mtim.tv_sec > MAX_TIMEOUT)) {
|
|
22
|
-
# dma.c:372| snprintf(errmsg, sizeof(errmsg),
|
|
23
|
-
# dma.c:373| "Could not deliver for the last %d seconds. Giving up.",
|
|
24
|
-
# dma.c:374| MAX_TIMEOUT);
|
|
25
|
-
# dma.c:375| goto bounce;
|
|
26
|
-
# dma.c:376| }
|
|
27
|
-
'Could not deliver for the last ',
|
|
28
|
-
],
|
|
29
|
-
'hostunknown' => [
|
|
30
|
-
# net.c:663| snprintf(errmsg, sizeof(errmsg), "DNS lookup failure: host %s not found", host);
|
|
31
|
-
'DNS lookup failure: host ',
|
|
32
|
-
],
|
|
33
|
-
}.freeze
|
|
34
17
|
|
|
35
18
|
# @abstract Decodes the bounce message from DMA: DragonFly Mail Agent
|
|
36
19
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -92,16 +75,6 @@ module Sisimai::Lhost
|
|
|
92
75
|
end
|
|
93
76
|
end
|
|
94
77
|
return nil if recipients == 0
|
|
95
|
-
|
|
96
|
-
dscontents.each do |e|
|
|
97
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
98
|
-
MessagesOf.each_key do |r|
|
|
99
|
-
# Verify each regular expression of session errors
|
|
100
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
101
|
-
e['reason'] = r
|
|
102
|
-
break
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
78
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
106
79
|
end
|
|
107
80
|
def description; return 'DragonFly'; end
|
|
@@ -3,6 +3,7 @@ module Sisimai::Lhost
|
|
|
3
3
|
# Methods in the module are called from only Sisimai::Message.
|
|
4
4
|
module EinsUndEins
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
require 'sisimai/lhost'
|
|
7
8
|
|
|
8
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
@@ -11,7 +12,6 @@ module Sisimai::Lhost
|
|
|
11
12
|
message: ['This message was created automatically by mail delivery software'],
|
|
12
13
|
error: ['For the following reason:'],
|
|
13
14
|
}.freeze
|
|
14
|
-
MessagesOf = {'emailtoolarge' => ['Mail size limit exceeded']}.freeze
|
|
15
15
|
|
|
16
16
|
# @abstract Decode the bounce message from 1&1
|
|
17
17
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -90,22 +90,14 @@ module Sisimai::Lhost
|
|
|
90
90
|
p1 = e['diagnosis'].index('host: ')
|
|
91
91
|
p2 = e['diagnosis'].index(' reason:')
|
|
92
92
|
|
|
93
|
-
e['rhost'] =
|
|
94
|
-
e['command'] =
|
|
95
|
-
e['spec'] = 'SMTP'
|
|
93
|
+
e['rhost'] = e['diagnosis'][p1 + 6, p2 - p1 - 6]
|
|
94
|
+
e['command'] = Sisimai::Eb::CeDATA if e['diagnosis'].include?('for TEXT command')
|
|
95
|
+
e['spec'] = 'SMTP' if e['diagnosis'].include?('SMTP error')
|
|
96
96
|
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
|
97
97
|
else
|
|
98
98
|
# For the following reason:
|
|
99
99
|
e['diagnosis'][0, StartingOf[:error][0].size] = ''
|
|
100
100
|
end
|
|
101
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
102
|
-
|
|
103
|
-
MessagesOf.each_key do |r|
|
|
104
|
-
# Verify each regular expression of session errors
|
|
105
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
106
|
-
e['reason'] = r
|
|
107
|
-
break
|
|
108
|
-
end
|
|
109
101
|
end
|
|
110
102
|
|
|
111
103
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
|
@@ -4,6 +4,7 @@ module Sisimai::Lhost
|
|
|
4
4
|
# Methods in the module are called from only Sisimai::Message.
|
|
5
5
|
module Exchange2003
|
|
6
6
|
class << self
|
|
7
|
+
require 'sisimai/eb'
|
|
7
8
|
require 'sisimai/lhost'
|
|
8
9
|
|
|
9
10
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
@@ -13,29 +14,29 @@ module Sisimai::Lhost
|
|
|
13
14
|
error: ['did not reach the following recipient(s):'],
|
|
14
15
|
}.freeze
|
|
15
16
|
ErrorCodes = {
|
|
16
|
-
|
|
17
|
+
Sisimai::Eb::Re___1 => [
|
|
17
18
|
'000B099C', # Host Unknown, Message exceeds size limit, ...
|
|
18
19
|
'000B09AA', # Unable to relay for, Message exceeds size limit,...
|
|
19
20
|
'000B09B6', # Error messages by remote MTA
|
|
20
21
|
],
|
|
21
|
-
|
|
22
|
+
Sisimai::Eb::ReUSER => [
|
|
22
23
|
'000C05A6', # Unknown Recipient,
|
|
23
24
|
],
|
|
24
|
-
|
|
25
|
+
Sisimai::Eb::RePROC => [
|
|
25
26
|
'00010256', # Too many recipients.
|
|
26
27
|
'000D06B5', # No proxy for recipient (non-smtp mail?)
|
|
27
28
|
],
|
|
28
|
-
|
|
29
|
+
Sisimai::Eb::ReINET => [
|
|
29
30
|
'00120270', # Too Many Hops
|
|
30
31
|
],
|
|
31
|
-
|
|
32
|
+
Sisimai::Eb::ReBODY => [
|
|
32
33
|
'00050311', # Conversion to Internet format failed
|
|
33
34
|
'000502CC', # Conversion to Internet format failed
|
|
34
35
|
],
|
|
35
|
-
|
|
36
|
+
Sisimai::Eb::ReSAFE => [
|
|
36
37
|
'000B0981', # 502 Server does not support AUTH
|
|
37
38
|
],
|
|
38
|
-
|
|
39
|
+
Sisimai::Eb::ReFILT => [
|
|
39
40
|
'000C0595', # Ambiguous Recipient
|
|
40
41
|
],
|
|
41
42
|
}.freeze
|
|
@@ -158,19 +159,20 @@ module Sisimai::Lhost
|
|
|
158
159
|
# Subject: ...
|
|
159
160
|
# Sent: Thu, 29 Apr 2010 18:14:35 +0000
|
|
160
161
|
#
|
|
161
|
-
|
|
162
|
+
case
|
|
163
|
+
when e.start_with?(' To: ', ' To: ')
|
|
162
164
|
# To: shironeko@example.jp
|
|
163
165
|
next if connheader['to'].empty? == false
|
|
164
166
|
connheader['to'] = e[e.rindex(' ') + 1, e.size]
|
|
165
167
|
connvalues += 1
|
|
166
168
|
|
|
167
|
-
|
|
169
|
+
when e.start_with?(' Subject: ', ' Subject: ')
|
|
168
170
|
# Subject: ...
|
|
169
171
|
next if connheader['subject'].empty? == false
|
|
170
172
|
connheader['subject'] = e[e.rindex(' ') + 1, e.size]
|
|
171
173
|
connvalues += 1
|
|
172
174
|
|
|
173
|
-
|
|
175
|
+
when e.start_with?(' Sent: ', ' Sent: ')
|
|
174
176
|
# Sent: Thu, 29 Apr 2010 18:14:35 +0000
|
|
175
177
|
# Sent: 4/29/99 9:19:59 AM
|
|
176
178
|
next if connheader['date'].empty? == false
|
|
@@ -207,7 +209,6 @@ module Sisimai::Lhost
|
|
|
207
209
|
|
|
208
210
|
# Copy alternative error message
|
|
209
211
|
e['diagnosis'] = "#{e['alterrors']} #{e['diagnosis']}"
|
|
210
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
211
212
|
e.delete('alterrors')
|
|
212
213
|
end
|
|
213
214
|
end
|
|
@@ -4,6 +4,7 @@ module Sisimai::Lhost
|
|
|
4
4
|
# Methods in the module are called from only Sisimai::Message.
|
|
5
5
|
module Exchange2007
|
|
6
6
|
class << self
|
|
7
|
+
require 'sisimai/eb'
|
|
7
8
|
require 'sisimai/lhost'
|
|
8
9
|
|
|
9
10
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
@@ -32,19 +33,19 @@ module Sisimai::Lhost
|
|
|
32
33
|
]
|
|
33
34
|
}.freeze
|
|
34
35
|
NDRSubject = {
|
|
35
|
-
"SMTPSEND.DNS.NonExistentDomain" =>
|
|
36
|
-
"SMTPSEND.DNS.MxLoopback" =>
|
|
37
|
-
"RESOLVER.ADR.BadPrimary" =>
|
|
38
|
-
"RESOLVER.ADR.RecipNotFound" =>
|
|
39
|
-
"RESOLVER.ADR.RecipientNotFound" =>
|
|
40
|
-
"RESOLVER.ADR.ExRecipNotFound" =>
|
|
41
|
-
"RESOLVER.ADR.RecipLimit" =>
|
|
42
|
-
"RESOLVER.ADR.InvalidInSmtp" =>
|
|
43
|
-
"RESOLVER.ADR.Ambiguous" =>
|
|
44
|
-
"RESOLVER.RST.AuthRequired" =>
|
|
45
|
-
"RESOLVER.RST.NotAuthorized" =>
|
|
46
|
-
"RESOLVER.RST.RecipSizeLimit" =>
|
|
47
|
-
"QUEUE.Expired" =>
|
|
36
|
+
"SMTPSEND.DNS.NonExistentDomain" => Sisimai::Eb::ReHOST, # 554 5.4.4 SMTPSEND.DNS.NonExistentDomain
|
|
37
|
+
"SMTPSEND.DNS.MxLoopback" => Sisimai::Eb::ReINET, # 554 5.4.4 SMTPSEND.DNS.MxLoopback
|
|
38
|
+
"RESOLVER.ADR.BadPrimary" => Sisimai::Eb::RePROC, # 550 5.2.0 RESOLVER.ADR.BadPrimary
|
|
39
|
+
"RESOLVER.ADR.RecipNotFound" => Sisimai::Eb::ReUSER, # 550 5.1.1 RESOLVER.ADR.RecipNotFound
|
|
40
|
+
"RESOLVER.ADR.RecipientNotFound" => Sisimai::Eb::ReUSER, # 550 5.1.1 RESOLVER.ADR.RecipientNotFound
|
|
41
|
+
"RESOLVER.ADR.ExRecipNotFound" => Sisimai::Eb::ReUSER, # 550 5.1.1 RESOLVER.ADR.ExRecipNotFound
|
|
42
|
+
"RESOLVER.ADR.RecipLimit" => Sisimai::Eb::ReRATE, # 550 5.5.3 RESOLVER.ADR.RecipLimit
|
|
43
|
+
"RESOLVER.ADR.InvalidInSmtp" => Sisimai::Eb::RePROC, # 550 5.1.0 RESOLVER.ADR.InvalidInSmtp
|
|
44
|
+
"RESOLVER.ADR.Ambiguous" => Sisimai::Eb::RePROC, # 550 5.1.4 RESOLVER.ADR.Ambiguous, 420 4.2.0 RESOLVER.ADR.Ambiguous
|
|
45
|
+
"RESOLVER.RST.AuthRequired" => Sisimai::Eb::ReSAFE, # 550 5.7.1 RESOLVER.RST.AuthRequired
|
|
46
|
+
"RESOLVER.RST.NotAuthorized" => Sisimai::Eb::ReFROM, # 550 5.7.1 RESOLVER.RST.NotAuthorized
|
|
47
|
+
"RESOLVER.RST.RecipSizeLimit" => Sisimai::Eb::ReSIZE, # 550 5.2.3 RESOLVER.RST.RecipSizeLimit
|
|
48
|
+
"QUEUE.Expired" => Sisimai::Eb::ReTIME, # 550 4.4.7 QUEUE.Expired
|
|
48
49
|
}.freeze
|
|
49
50
|
MailSender = ["postmaster@outlook.com", ".onmicrosoft.com"].freeze
|
|
50
51
|
EmailTitle = [
|
|
@@ -64,7 +65,9 @@ module Sisimai::Lhost
|
|
|
64
65
|
def inquire(mhead, mbody)
|
|
65
66
|
proceedsto = 0
|
|
66
67
|
proceedsto += 1 if EmailTitle.any? { |a| mhead["subject"].include?(a) }
|
|
67
|
-
proceedsto += 1 if MailSender.any? { |a| mhead["from"].include?(a)
|
|
68
|
+
proceedsto += 1 if MailSender.any? { |a| mhead["from"].include?(a) }
|
|
69
|
+
proceedsto += 1 if StartingOf[:error].any? { |a| mbody.include?(a) }
|
|
70
|
+
proceedsto += 1 if StartingOf[:message].any? { |a| mbody.include?(a) }
|
|
68
71
|
proceedsto += 1 if mhead["content-language"]
|
|
69
72
|
return nil if proceedsto < 2
|
|
70
73
|
|
|
@@ -150,9 +153,6 @@ module Sisimai::Lhost
|
|
|
150
153
|
return nil if recipients == 0
|
|
151
154
|
|
|
152
155
|
dscontents.each do |e|
|
|
153
|
-
# Tidy up the error message in $e->{'diagnosis'}, Try to detect the bounce reason.
|
|
154
|
-
e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
|
|
155
|
-
|
|
156
156
|
p0 = -1; StartingOf[:error].each do |r|
|
|
157
157
|
# Try to find the NDR subject string such as "RESOLVER.ADR.RecipientNotFound" from the
|
|
158
158
|
# error message
|
data/lib/sisimai/lhost/exim.rb
CHANGED
|
@@ -3,6 +3,7 @@ module Sisimai::Lhost
|
|
|
3
3
|
# Methods in the module are called from only Sisimai::Message.
|
|
4
4
|
module Exim
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
require 'sisimai/lhost'
|
|
7
8
|
require 'sisimai/rfc1894'
|
|
8
9
|
|
|
@@ -60,69 +61,25 @@ module Sisimai::Lhost
|
|
|
60
61
|
MessagesOf = {
|
|
61
62
|
# find exim/ -type f -exec grep 'message = US' {} /dev/null \;
|
|
62
63
|
# route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
|
|
63
|
-
|
|
64
|
-
# route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
|
|
65
|
-
"userunknown" => ["user not found"],
|
|
66
|
-
# transports/smtp.c:3524| addr->message = US"all host address lookups failed permanently";
|
|
67
|
-
# routers/dnslookup.c:331| addr->message = US"all relevant MX records point to non-existent hosts";
|
|
68
|
-
# route.c:1826| uschar *message = US"Unrouteable address";
|
|
69
|
-
"hostunknown" => [
|
|
70
|
-
"all host address lookups failed permanently",
|
|
71
|
-
"all relevant MX records point to non-existent hosts",
|
|
72
|
-
"Unrouteable address",
|
|
73
|
-
],
|
|
74
|
-
# transports/appendfile.c:2567| addr->user_message = US"mailbox is full";
|
|
75
|
-
# transports/appendfile.c:3049| addr->message = string_sprintf("mailbox is full "
|
|
76
|
-
# transports/appendfile.c:3050| "(quota exceeded while writing to file %s)", filename);
|
|
77
|
-
"mailboxfull" => [
|
|
78
|
-
"mailbox is full",
|
|
79
|
-
"error: quota exceed",
|
|
80
|
-
],
|
|
81
|
-
# routers/dnslookup.c:328| addr->message = US"an MX or SRV record indicated no SMTP service";
|
|
82
|
-
# transports/smtp.c:3502| addr->message = US"no host found for existing SMTP connection";
|
|
83
|
-
"notaccept" => [
|
|
84
|
-
"an MX or SRV record indicated no SMTP service",
|
|
85
|
-
"no host found for existing SMTP connection",
|
|
86
|
-
],
|
|
64
|
+
Sisimai::Eb::ReUSER => ["user not found"],
|
|
87
65
|
# parser.c:666| *errorptr = string_sprintf("%s (expected word or \"<\")", *errorptr);
|
|
88
66
|
# parser.c:701| if(bracket_count++ > 5) FAILED(US"angle-brackets nested too deep");
|
|
89
67
|
# parser.c:738| FAILED(US"domain missing in source-routed address");
|
|
90
68
|
# parser.c:747| : string_sprintf("malformed address: %.32s may not follow %.*s",
|
|
91
|
-
|
|
69
|
+
Sisimai::Eb::ReCOMM => [
|
|
92
70
|
"angle-brackets nested too deep",
|
|
93
71
|
'expected word or "<"',
|
|
94
72
|
"domain missing in source-routed address",
|
|
95
73
|
"malformed address:",
|
|
96
74
|
],
|
|
97
|
-
# deliver.c:5614| addr->message = US"delivery to file forbidden";
|
|
98
|
-
# deliver.c:5624| addr->message = US"delivery to pipe forbidden";
|
|
99
|
-
# transports/pipe.c:1156| addr->user_message = US"local delivery failed";
|
|
100
|
-
"systemerror" => [
|
|
101
|
-
"delivery to file forbidden",
|
|
102
|
-
"delivery to pipe forbidden",
|
|
103
|
-
"local delivery failed",
|
|
104
|
-
"LMTP error after ",
|
|
105
|
-
],
|
|
106
|
-
# deliver.c:5425| new->message = US"Too many \"Received\" headers - suspected mail loop";
|
|
107
|
-
"contenterror" => ['Too many "Received" headers'],
|
|
108
75
|
}.freeze
|
|
109
76
|
DelayedFor = [
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
# smtp.c:3508| US"all hosts have been failing for a long time and were last tried "
|
|
114
|
-
# "after this message arrived";
|
|
115
|
-
# deliver.c:7459| print_address_error(addr, f, US"Delay reason: ");
|
|
116
|
-
# deliver.c:7586| "Message %s has been frozen%s.\nThe sender is <%s>.\n", message_id,
|
|
117
|
-
# receive.c:4021| moan_tell_someone(freeze_tell, NULL, US"Message frozen on arrival",
|
|
118
|
-
# receive.c:4022| "Message %s was frozen on arrival by %s.\nThe sender is <%s>.\n",
|
|
119
|
-
"retry timeout exceeded",
|
|
77
|
+
# deliver.c:7475| "No action is required on your part. Delivery attempts will continue for\n"
|
|
78
|
+
# smtp.c:3508| US"retry time not reached for any host after a long failure period" :
|
|
79
|
+
# deliver.c:7459| print_address_error(addr, f, US"Delay reason: ");
|
|
120
80
|
"No action is required on your part",
|
|
121
81
|
"retry time not reached for any host after a long failure period",
|
|
122
|
-
"all hosts have been failing for a long time and were last tried",
|
|
123
82
|
"Delay reason: ",
|
|
124
|
-
"has been frozen",
|
|
125
|
-
"was frozen on arrival by ",
|
|
126
83
|
].freeze
|
|
127
84
|
|
|
128
85
|
# @abstract Decodes the bounce message from Exim
|
|
@@ -133,6 +90,8 @@ module Sisimai::Lhost
|
|
|
133
90
|
def inquire(mhead, mbody)
|
|
134
91
|
# Message-Id: <E1P1YNN-0003AD-Ga@example.org>
|
|
135
92
|
# X-Failed-Recipients: kijitora@example.ed.jp
|
|
93
|
+
return nil if Sisimai::Lhost.BannerDTAG.any? { |a| mbody.include?(a) }
|
|
94
|
+
|
|
136
95
|
thirdparty = false
|
|
137
96
|
proceedsto = 0
|
|
138
97
|
messageidv = mhead["message-id"] || ""
|
|
@@ -255,7 +214,7 @@ module Sisimai::Lhost
|
|
|
255
214
|
# parser.c:749| goto PARSE_FAILED;
|
|
256
215
|
# parser.c:750| }
|
|
257
216
|
cv = Sisimai::Address.s3s4(e[p1, p2 - p1 - 1])
|
|
258
|
-
v["diagnosis"] =
|
|
217
|
+
v["diagnosis"] = e[p2 + 1, e.size]
|
|
259
218
|
else
|
|
260
219
|
# There is an email address only in the line
|
|
261
220
|
# kijitora@example.jp
|
|
@@ -288,7 +247,8 @@ module Sisimai::Lhost
|
|
|
288
247
|
# "e" matched with any field defined in RFC3464
|
|
289
248
|
next unless o = Sisimai::RFC1894.field(e)
|
|
290
249
|
|
|
291
|
-
|
|
250
|
+
case o[3]
|
|
251
|
+
when "addr"
|
|
292
252
|
# Final-Recipient: rfc822; kijitora@example.jp
|
|
293
253
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
294
254
|
next if o[0] != "final-recipient"
|
|
@@ -296,7 +256,7 @@ module Sisimai::Lhost
|
|
|
296
256
|
v["spec"] = o[2].include?('@') ? "SMTP" : "X-UNIX"
|
|
297
257
|
end
|
|
298
258
|
|
|
299
|
-
|
|
259
|
+
when "code"
|
|
300
260
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
301
261
|
v["spec"] = o[1].upcase
|
|
302
262
|
v["diagnosis"] = o[2]
|
|
@@ -341,24 +301,22 @@ module Sisimai::Lhost
|
|
|
341
301
|
q["recipient"] = q["alias"]
|
|
342
302
|
end
|
|
343
303
|
end
|
|
344
|
-
|
|
304
|
+
elsif mhead["x-failed-recipients"]
|
|
345
305
|
# Fallback for getting recipient addresses
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
recipients = rcptinhead.size
|
|
306
|
+
# X-Failed-Recipients: kijitora@example.jp
|
|
307
|
+
rcptinhead = mhead["x-failed-recipients"].split(",")
|
|
308
|
+
rcptinhead.each do |e|
|
|
309
|
+
# Remove space characters
|
|
310
|
+
e.lstrip!
|
|
311
|
+
e.rstrip!
|
|
312
|
+
end
|
|
313
|
+
recipients = rcptinhead.size
|
|
355
314
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
end
|
|
315
|
+
while e = rcptinhead.shift do
|
|
316
|
+
# Insert each recipient address into dscontents
|
|
317
|
+
dscontents[-1]["recipient"] = e
|
|
318
|
+
next if dscontents.size == recipients
|
|
319
|
+
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
|
362
320
|
end
|
|
363
321
|
end
|
|
364
322
|
return nil if recipients == 0
|
|
@@ -406,7 +364,7 @@ module Sisimai::Lhost
|
|
|
406
364
|
end
|
|
407
365
|
e.delete("alterrors")
|
|
408
366
|
end
|
|
409
|
-
|
|
367
|
+
p1 = e["diagnosis"].index("__") || -1
|
|
410
368
|
e["diagnosis"] = e["diagnosis"][0, p1] if p1 > 1
|
|
411
369
|
|
|
412
370
|
if e["rhost"].empty?
|
|
@@ -429,14 +387,11 @@ module Sisimai::Lhost
|
|
|
429
387
|
end
|
|
430
388
|
|
|
431
389
|
# Detect the reason of bounce
|
|
432
|
-
|
|
433
|
-
# HELO | Connected to 192.0.2.135 but my name was rejected.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
# MAIL | Connected to 192.0.2.135 but sender was rejected.
|
|
438
|
-
e["reason"] = "onhold"
|
|
439
|
-
|
|
390
|
+
case e["command"]
|
|
391
|
+
# - HELO | Connected to 192.0.2.135 but my name was rejected.
|
|
392
|
+
# - MAIL | Connected to 192.0.2.135 but sender was rejected.
|
|
393
|
+
when Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO then e["reason"] = Sisimai::Eb::ReBLOC
|
|
394
|
+
when Sisimai::Eb::CeMAIL then e["reason"] = Sisimai::Eb::Re___1
|
|
440
395
|
else
|
|
441
396
|
# Try to match the error message with each message pattern
|
|
442
397
|
MessagesOf.each_key do |r|
|
|
@@ -447,9 +402,7 @@ module Sisimai::Lhost
|
|
|
447
402
|
end
|
|
448
403
|
|
|
449
404
|
if e["reason"].empty?
|
|
450
|
-
|
|
451
|
-
e["reason"] = "expired" if DelayedFor.any? { |a| e["diagnosis"].include?(a) }
|
|
452
|
-
e["reason"] = "mailererror" if e["reason"].empty? && e["diagnosis"].include?("pipe to |")
|
|
405
|
+
e["reason"] = Sisimai::Eb::ReTIME if DelayedFor.any? { |a| e["diagnosis"].include?(a) }
|
|
453
406
|
end
|
|
454
407
|
end
|
|
455
408
|
end
|
|
@@ -468,7 +421,7 @@ module Sisimai::Lhost
|
|
|
468
421
|
re = e["reason"]
|
|
469
422
|
cv = ""
|
|
470
423
|
|
|
471
|
-
if Sisimai::SMTP::Failure.is_temporary(cr) || re ==
|
|
424
|
+
if Sisimai::SMTP::Failure.is_temporary(cr) || re == Sisimai::Eb::ReTIME
|
|
472
425
|
# Set the pseudo status code as a temporary error
|
|
473
426
|
cv = Sisimai::SMTP::Status.code(re, true) if Sisimai::Reason.is_explicit(re)
|
|
474
427
|
end
|
data/lib/sisimai/lhost/ezweb.rb
CHANGED
|
@@ -3,27 +3,18 @@ module Sisimai::Lhost
|
|
|
3
3
|
# Methods in the module are called from only Sisimai::Message.
|
|
4
4
|
module EZweb
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
require 'sisimai/lhost'
|
|
7
8
|
|
|
8
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
10
|
Boundaries = ["--------------------------------------------------", "Content-Type: message/rfc822"].freeze
|
|
10
11
|
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
|
|
12
|
+
UnpaidUser = [
|
|
13
|
+
# http://www.naruhodo-au.kddi.com/qa3429203.html
|
|
14
|
+
# The recipient may be unpaid user...?
|
|
15
|
+
'The user(s) account is disabled.',
|
|
16
|
+
'The user(s) account is temporarily limited.',
|
|
17
|
+
].freeze
|
|
27
18
|
|
|
28
19
|
# @abstract Decodes the bounce message from au EZweb
|
|
29
20
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -48,7 +39,6 @@ module Sisimai::Lhost
|
|
|
48
39
|
bodyslices = emailparts[0].split("\n")
|
|
49
40
|
readcursor = 0 # (Integer) Points the current cursor position
|
|
50
41
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
|
51
|
-
substrings = []; Messagesof.each_value { |a| substrings << a }; substrings.flatten!
|
|
52
42
|
|
|
53
43
|
while e = bodyslices.shift do
|
|
54
44
|
# Read error messages and delivery status lines from the head of the email to the previous
|
|
@@ -94,57 +84,31 @@ module Sisimai::Lhost
|
|
|
94
84
|
|
|
95
85
|
else
|
|
96
86
|
# Other error messages
|
|
87
|
+
# >>> RCPT TO:<******@ezweb.ne.jp>
|
|
88
|
+
# <<< 550 ...
|
|
97
89
|
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
|
|
90
|
+
v["command"] = Sisimai::SMTP::Command.find(e) if e.include?(" >>> ")
|
|
91
|
+
v["diagnosis"] += " #{e}"
|
|
117
92
|
end
|
|
118
93
|
end
|
|
119
94
|
return nil if recipients == 0
|
|
120
95
|
|
|
121
96
|
dscontents.each do |e|
|
|
122
97
|
# Check each value of DeliveryMatter{}, try to detect the bounce reason.
|
|
123
|
-
e['diagnosis'] =
|
|
98
|
+
e['diagnosis'] = e['diagnosis'].split.join(" ")
|
|
124
99
|
e["command"] = Sisimai::SMTP::Command.find(e["diagnosis"]) if e["command"].empty?
|
|
125
100
|
|
|
126
101
|
if mhead['x-spasign'].to_s == 'NG'
|
|
127
102
|
# Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
|
|
128
103
|
# Filtered recipient returns message that include 'X-SPASIGN' header
|
|
129
|
-
e['reason'] =
|
|
130
|
-
e['toxic'] = true
|
|
104
|
+
e['reason'] = Sisimai::Eb::ReFILT
|
|
131
105
|
else
|
|
132
106
|
# 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
|
|
107
|
+
e['reason'] = Sisimai::Eb::ReQUIT if UnpaidUser.any? { |a| e['diagnosis'].include?(a) }
|
|
144
108
|
end
|
|
145
109
|
next if e['reason'] != ""
|
|
146
110
|
next if e['recipient'].end_with?('@ezweb.ne.jp', '@au.com')
|
|
147
|
-
e["reason"] =
|
|
111
|
+
e["reason"] = Sisimai::Eb::ReUSER if e["diagnosis"].start_with?("<")
|
|
148
112
|
end
|
|
149
113
|
|
|
150
114
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
data/lib/sisimai/lhost/fml.rb
CHANGED
|
@@ -3,39 +3,25 @@ module Sisimai::Lhost
|
|
|
3
3
|
# https://www.fml.org/. Methods in the module are called from only Sisimai::Message.
|
|
4
4
|
module FML
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
require 'sisimai/lhost'
|
|
7
8
|
|
|
8
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
10
|
Boundaries = ['Original mail as follows:'].freeze
|
|
10
11
|
ErrorTitle = {
|
|
11
|
-
|
|
12
|
+
Sisimai::Eb::ReFROM => [
|
|
12
13
|
' are not member',
|
|
13
14
|
'NOT MEMBER article from ',
|
|
14
15
|
'reject mail ',
|
|
15
16
|
'Spam mail from a spammer is rejected',
|
|
16
17
|
],
|
|
17
|
-
|
|
18
|
+
Sisimai::Eb::RePROC => [
|
|
18
19
|
'fml system error message',
|
|
19
20
|
'Loop Alert: ',
|
|
20
21
|
'Loop Back Warning: ',
|
|
21
22
|
'WARNING: UNIX FROM Loop',
|
|
22
23
|
],
|
|
23
|
-
|
|
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
|
-
],
|
|
24
|
+
Sisimai::Eb::ReSAFE => ['Security Alert'],
|
|
39
25
|
}.freeze
|
|
40
26
|
|
|
41
27
|
# @abstract Decodes the bounce message from fml mailling list server/manager
|
|
@@ -84,23 +70,13 @@ module Sisimai::Lhost
|
|
|
84
70
|
return nil if recipients == 0
|
|
85
71
|
|
|
86
72
|
dscontents.each do |e|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# Try to match with
|
|
90
|
-
next if
|
|
73
|
+
# Error messages in the message body did not matched
|
|
74
|
+
ErrorTitle.each_key do |f|
|
|
75
|
+
# Try to match with the Subject string
|
|
76
|
+
next if ErrorTitle[f].none? { |a| mhead["subject"].include?(a) }
|
|
91
77
|
e['reason'] = f
|
|
92
78
|
break
|
|
93
79
|
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
80
|
end
|
|
105
81
|
|
|
106
82
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|