sisimai 5.6.0 → 5.7.1
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
data/lib/sisimai/lhost/qmail.rb
CHANGED
|
@@ -4,6 +4,7 @@ module Sisimai::Lhost
|
|
|
4
4
|
# Methods in the module are called from only Sisimai::Message.
|
|
5
5
|
module Qmail
|
|
6
6
|
class << self
|
|
7
|
+
require 'sisimai/eb'
|
|
7
8
|
require 'sisimai/lhost'
|
|
8
9
|
require 'sisimai/string'
|
|
9
10
|
|
|
@@ -49,77 +50,27 @@ module Sisimai::Lhost
|
|
|
49
50
|
}.freeze
|
|
50
51
|
CommandSet = {
|
|
51
52
|
# qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
|
|
52
|
-
|
|
53
|
+
Sisimai::Eb::CeCONN => [" but greeting failed."],
|
|
53
54
|
# qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
|
|
54
|
-
|
|
55
|
+
Sisimai::Eb::CeEHLO => [" but my name was rejected."],
|
|
55
56
|
# qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
|
|
56
57
|
# reason = rejected
|
|
57
|
-
|
|
58
|
+
Sisimai::Eb::CeMAIL => [" but sender was rejected."],
|
|
58
59
|
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
|
59
60
|
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
|
60
61
|
# reason = userunknown
|
|
61
|
-
|
|
62
|
+
Sisimai::Eb::CeRCPT => [" does not like recipient."],
|
|
62
63
|
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
|
63
64
|
# qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
|
|
64
65
|
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
|
65
66
|
# qmail-remote.c:272| if (code >= 400) quit("Z"," failed after I sent the message");
|
|
66
|
-
|
|
67
|
+
Sisimai::Eb::CeDATA => [" failed on DATA command", " failed after I sent the message"],
|
|
67
68
|
}.freeze
|
|
68
69
|
|
|
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
70
|
MessagesOf = {
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
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");
|
|
122
|
-
"userunknown" => ["no mailbox here by that name"],
|
|
71
|
+
# notqmail 1.08 returns the following error message when the destination MX is NullMX
|
|
72
|
+
Sisimai::Eb::Re00MX => ["Sorry, I couldn't find a mail exchanger or IP address"],
|
|
73
|
+
Sisimai::Eb::ReUSER => ["no mailbox here by that name"],
|
|
123
74
|
}.freeze
|
|
124
75
|
|
|
125
76
|
# @abstract Decodes the bounce message from qmail
|
|
@@ -186,7 +137,7 @@ module Sisimai::Lhost
|
|
|
186
137
|
cm = r.size
|
|
187
138
|
p2 = e.index(" ", p1 + cm + 1) || p2 = e.rindex(".")
|
|
188
139
|
|
|
189
|
-
v["rhost"] =
|
|
140
|
+
v["rhost"] = e[p1 + cm, p2 - p1 - cm]
|
|
190
141
|
break
|
|
191
142
|
end
|
|
192
143
|
end
|
|
@@ -194,9 +145,6 @@ module Sisimai::Lhost
|
|
|
194
145
|
return nil if recipients == 0
|
|
195
146
|
|
|
196
147
|
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
148
|
# Get the SMTP command name for the session
|
|
201
149
|
CommandSet.each_key do |r|
|
|
202
150
|
# Get the last SMTP command
|
|
@@ -211,37 +159,23 @@ module Sisimai::Lhost
|
|
|
211
159
|
end
|
|
212
160
|
|
|
213
161
|
# Detect the reason of bounce
|
|
214
|
-
if
|
|
162
|
+
if [Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO].index(e["command"])
|
|
215
163
|
# HELO | Connected to 192.0.2.135 but my name was rejected.
|
|
216
|
-
e["reason"] =
|
|
164
|
+
e["reason"] = Sisimai::Eb::ReBLOC
|
|
217
165
|
else
|
|
218
166
|
# 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)
|
|
167
|
+
# Check that the error message includes any of message patterns or not
|
|
168
|
+
[e["alterrors"], e["diagnosis"]].each do |f|
|
|
169
|
+
# Try to detect an error reason
|
|
170
|
+
break if e["reason"] != ""
|
|
171
|
+
next if f.nil?
|
|
172
|
+
MessagesOf.each_key do |r|
|
|
173
|
+
# The key is a bounce reason name
|
|
174
|
+
next if MessagesOf[r].none? { |a| f.include?(a) }
|
|
175
|
+
e["reason"] = r
|
|
176
|
+
break
|
|
244
177
|
end
|
|
178
|
+
break if e["reason"]
|
|
245
179
|
end
|
|
246
180
|
end
|
|
247
181
|
|
|
@@ -3,6 +3,7 @@ module Sisimai::Lhost
|
|
|
3
3
|
# Methods in the module are called from only Sisimai::Message.
|
|
4
4
|
module Sendmail
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
require 'sisimai/lhost'
|
|
7
8
|
require 'sisimai/rfc1123'
|
|
8
9
|
require 'sisimai/smtp/reply'
|
|
@@ -67,7 +68,8 @@ module Sisimai::Lhost
|
|
|
67
68
|
o = Sisimai::RFC1894.field(e) || next
|
|
68
69
|
v = dscontents[-1]
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
case o[3]
|
|
72
|
+
when "addr"
|
|
71
73
|
# Final-Recipient: rfc822; kijitora@example.jp
|
|
72
74
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
73
75
|
if o[0] == 'final-recipient'
|
|
@@ -83,7 +85,7 @@ module Sisimai::Lhost
|
|
|
83
85
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
84
86
|
v['alias'] = o[2]
|
|
85
87
|
end
|
|
86
|
-
|
|
88
|
+
when "code"
|
|
87
89
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
88
90
|
v['spec'] = o[1]
|
|
89
91
|
v['diagnosis'] = o[2]
|
|
@@ -159,7 +161,7 @@ module Sisimai::Lhost
|
|
|
159
161
|
# Continued line of the value of Diagnostic-Code field
|
|
160
162
|
next if readslices[-2].start_with?('Diagnostic-Code:') == false
|
|
161
163
|
next if e.start_with?(' ') == false
|
|
162
|
-
v['diagnosis'] += "
|
|
164
|
+
v['diagnosis'] += " " + e
|
|
163
165
|
readslices[-1] = "Diagnostic-Code: #{e}"
|
|
164
166
|
end
|
|
165
167
|
end
|
|
@@ -186,10 +188,9 @@ module Sisimai::Lhost
|
|
|
186
188
|
break
|
|
187
189
|
end
|
|
188
190
|
|
|
189
|
-
e[
|
|
190
|
-
e["command"]
|
|
191
|
-
e["command"]
|
|
192
|
-
e["command"] = "EHLO" if e["command"].empty? && esmtpreply.size > 0
|
|
191
|
+
e["command"] = thecommand if e["command"].empty?
|
|
192
|
+
e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
|
|
193
|
+
e["command"] = Sisimai::Eb::CeEHLO if e["command"].empty? && esmtpreply.size > 0
|
|
193
194
|
|
|
194
195
|
while true
|
|
195
196
|
# Check alternative status code and override it
|
|
@@ -4,6 +4,7 @@ module Sisimai::Lhost
|
|
|
4
4
|
# Methods in the module are called from only Sisimai::Message.
|
|
5
5
|
module TrendMicro
|
|
6
6
|
class << self
|
|
7
|
+
require 'sisimai/eb'
|
|
7
8
|
require 'sisimai/lhost'
|
|
8
9
|
Boundaries = ['Content-Type: message/rfc822'].freeze
|
|
9
10
|
|
|
@@ -55,11 +56,12 @@ module Sisimai::Lhost
|
|
|
55
56
|
recipients = dscontents.size
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
case
|
|
60
|
+
when e.start_with?('Sent <<< ')
|
|
59
61
|
# Sent <<< RCPT TO:<kijitora@example.co.jp>
|
|
60
62
|
v['command'] = Sisimai::SMTP::Command.find(e)
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
when e.start_with?('Received >>> ')
|
|
63
65
|
# Received >>> 550 5.1.1 <kijitora@example.co.jp>... user unknown
|
|
64
66
|
v['diagnosis'] = e[e.index(' >>> ') + 4, e.size]
|
|
65
67
|
else
|
|
@@ -72,8 +74,7 @@ module Sisimai::Lhost
|
|
|
72
74
|
return nil if recipients == 0
|
|
73
75
|
|
|
74
76
|
dscontents.each do |e|
|
|
75
|
-
e['
|
|
76
|
-
e['reason'] = 'userunknown' if e['diagnosis'].include?('Unable to deliver')
|
|
77
|
+
e['reason'] = Sisimai::Eb::ReUSER if e['diagnosis'].include?('Unable to deliver')
|
|
77
78
|
end
|
|
78
79
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
79
80
|
end
|
|
@@ -41,6 +41,7 @@ module Sisimai::Lhost
|
|
|
41
41
|
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
42
42
|
return nil if emailparts[1].size == 0
|
|
43
43
|
|
|
44
|
+
require 'sisimai/eb'
|
|
44
45
|
require 'sisimai/rfc1123'
|
|
45
46
|
require 'sisimai/smtp/command'
|
|
46
47
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
@@ -84,7 +85,7 @@ module Sisimai::Lhost
|
|
|
84
85
|
next
|
|
85
86
|
end
|
|
86
87
|
|
|
87
|
-
if cv == v["recipient"] || (curcommand ==
|
|
88
|
+
if cv == v["recipient"] || (curcommand == Sisimai::Eb::CeMAIL && e.start_with?("<<< "))
|
|
88
89
|
# The recipient address is the same address with the last appeared address
|
|
89
90
|
# like "550 <mikeneko@example.co.jp>... User unknown"
|
|
90
91
|
# Append this line to the string which is keeping error messages
|
|
@@ -161,7 +162,6 @@ module Sisimai::Lhost
|
|
|
161
162
|
j = 0; dscontents.each do |e|
|
|
162
163
|
# Tidy up the error message in e.Diagnosis
|
|
163
164
|
e["diagnosis"] = anotherone[j] if e["diagnosis"].empty?
|
|
164
|
-
e["diagnosis"] = Sisimai::String.sweep(e["diagnosis"])
|
|
165
165
|
e["command"] = Sisimai::SMTP::Command.find(e["diagnosis"]) if e["command"].empty?
|
|
166
166
|
e["replycode"] = Sisimai::SMTP::Reply.find(e["diagnosis"])
|
|
167
167
|
e["replycode"] = Sisimai::SMTP::Reply.find(anotherone[j]) if e["replycode"].empty?
|
|
@@ -3,6 +3,7 @@ module Sisimai::Lhost
|
|
|
3
3
|
# Methods in the module are called from only Sisimai::Message.
|
|
4
4
|
module Verizon
|
|
5
5
|
class << self
|
|
6
|
+
require 'sisimai/eb'
|
|
6
7
|
require 'sisimai/lhost'
|
|
7
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
8
9
|
|
|
@@ -37,7 +38,7 @@ module Sisimai::Lhost
|
|
|
37
38
|
markingsof = {message: ['Error: ']}
|
|
38
39
|
messagesof = {
|
|
39
40
|
# The attempted recipient address does not exist.
|
|
40
|
-
|
|
41
|
+
Sisimai::Eb::ReUSER => ['550 - Requested action not taken: no such user here'],
|
|
41
42
|
}
|
|
42
43
|
boundaries = [Sisimai::RFC2045.boundary(mhead['content-type'], 1)]
|
|
43
44
|
emailparts = Sisimai::RFC5322.part(mbody, boundaries)
|
|
@@ -85,7 +86,7 @@ module Sisimai::Lhost
|
|
|
85
86
|
else
|
|
86
87
|
# vzwpix.com
|
|
87
88
|
startingof = {message: ['Message could not be delivered to mobile']}
|
|
88
|
-
messagesof = {
|
|
89
|
+
messagesof = {Sisimai::Eb::ReUSER => ['No valid recipients for this MM']}
|
|
89
90
|
boundaries = [Sisimai::RFC2045.boundary(mhead['content-type'], 1)]
|
|
90
91
|
emailparts = Sisimai::RFC5322.part(mbody, boundaries)
|
|
91
92
|
bodyslices = emailparts[0].split("\n")
|
|
@@ -126,7 +127,7 @@ module Sisimai::Lhost
|
|
|
126
127
|
else
|
|
127
128
|
# Message could not be delivered to mobile.
|
|
128
129
|
# Error: No valid recipients for this MM
|
|
129
|
-
v['diagnosis'] =
|
|
130
|
+
v['diagnosis'] = e[7, e.size] if e.start_with?('Error: ')
|
|
130
131
|
end
|
|
131
132
|
end
|
|
132
133
|
end
|
|
@@ -137,7 +138,6 @@ module Sisimai::Lhost
|
|
|
137
138
|
emailparts[1] += "Subject: #{subjecttxt}\n" if emailparts[1].include?("\nSubject: ") == false
|
|
138
139
|
|
|
139
140
|
dscontents.each do |e|
|
|
140
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
141
141
|
messagesof.each_key do |r|
|
|
142
142
|
# Verify each regular expression of session errors
|
|
143
143
|
next if messagesof[r].none? { |a| e['diagnosis'].include?(a) }
|
data/lib/sisimai/lhost/x1.rb
CHANGED
|
@@ -67,8 +67,7 @@ module Sisimai::Lhost
|
|
|
67
67
|
return nil if recipients == 0
|
|
68
68
|
|
|
69
69
|
dscontents.each do |e|
|
|
70
|
-
e['
|
|
71
|
-
e['date'] = datestring || ''
|
|
70
|
+
e['date'] = datestring || ''
|
|
72
71
|
end
|
|
73
72
|
|
|
74
73
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
data/lib/sisimai/lhost/x2.rb
CHANGED
|
@@ -88,8 +88,6 @@ module Sisimai::Lhost
|
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
return nil if recipients == 0
|
|
91
|
-
|
|
92
|
-
dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
|
|
93
91
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
|
94
92
|
end
|
|
95
93
|
def description; return 'Unknown MTA #2'; end
|
data/lib/sisimai/lhost/x3.rb
CHANGED
|
@@ -64,28 +64,23 @@ module Sisimai::Lhost
|
|
|
64
64
|
recipients += 1
|
|
65
65
|
else
|
|
66
66
|
# Detect error message
|
|
67
|
-
|
|
67
|
+
case
|
|
68
|
+
when e.start_with?('SMTP:')
|
|
68
69
|
# SMTP:RCPT host 192.0.2.8: 553 5.3.0 <kijitora@example.com>... No such user here
|
|
69
70
|
v['command'] = Sisimai::SMTP::Command.find(e)
|
|
70
71
|
v['diagnosis'] = e
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
when e.start_with?('Routing: ')
|
|
73
74
|
# Routing: Could not find a gateway for kijitora@example.co.jp
|
|
74
75
|
v['diagnosis'] = e[9, e.size]
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
when e.start_with?('Diagnostic-Code: smtp; ')
|
|
77
78
|
# Diagnostic-Code: smtp; 552 5.2.2 Over quota
|
|
78
79
|
v['diagnosis'] = e[e.index(';') + 2, e.size]
|
|
79
80
|
end
|
|
80
81
|
end
|
|
81
82
|
end
|
|
82
83
|
return nil if recipients == 0
|
|
83
|
-
|
|
84
|
-
dscontents.each do |e|
|
|
85
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
86
|
-
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
|
87
|
-
end
|
|
88
|
-
|
|
89
84
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
|
90
85
|
end
|
|
91
86
|
def description; return 'Unknown MTA #3'; end
|
data/lib/sisimai/lhost/x6.rb
CHANGED
data/lib/sisimai/lhost/zoho.rb
CHANGED
|
@@ -8,7 +8,6 @@ module Sisimai::Lhost
|
|
|
8
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
9
|
Boundaries = ['Received: from mail.zoho.com by mx.zohomail.com'].freeze
|
|
10
10
|
StartingOf = {message: ['This message was created automatically by mail delivery']}.freeze
|
|
11
|
-
MessagesOf = {'expired' => ['Host not reachable']}.freeze
|
|
12
11
|
|
|
13
12
|
# @abstract Decodes the bounce message from Zoho Mail
|
|
14
13
|
# @param [Hash] mhead Message headers of a bounce email
|
|
@@ -88,17 +87,6 @@ module Sisimai::Lhost
|
|
|
88
87
|
end
|
|
89
88
|
end
|
|
90
89
|
return nil if recipients == 0
|
|
91
|
-
|
|
92
|
-
dscontents.each do |e|
|
|
93
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
|
94
|
-
MessagesOf.each_key do |r|
|
|
95
|
-
# Verify each regular expression of session errors
|
|
96
|
-
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
97
|
-
e['reason'] = r
|
|
98
|
-
break
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
90
|
return {"ds" => dscontents, "rfc822" => emailparts[1]}
|
|
103
91
|
end
|
|
104
92
|
def description; return 'Zoho Mail: https://www.zoho.com'; end
|
data/lib/sisimai/lhost.rb
CHANGED
|
@@ -9,21 +9,20 @@ module Sisimai
|
|
|
9
9
|
# @private
|
|
10
10
|
def DELIVERYSTATUS
|
|
11
11
|
return {
|
|
12
|
-
'spec' => "",
|
|
13
|
-
'date' => "",
|
|
14
|
-
'rhost' => "",
|
|
15
|
-
'lhost' => "",
|
|
16
|
-
'alias' => "",
|
|
17
|
-
'agent' => "",
|
|
18
|
-
'action' => "",
|
|
19
|
-
'status' => "",
|
|
20
|
-
'reason' => "",
|
|
21
|
-
'command' => "",
|
|
22
|
-
'replycode' => "",
|
|
23
|
-
'diagnosis' => "",
|
|
24
|
-
'recipient' => "",
|
|
25
|
-
'feedbacktype' => "",
|
|
26
|
-
'toxic' => false, # EXPERIMENTAL
|
|
12
|
+
'spec' => "", # Protocl specification
|
|
13
|
+
'date' => "", # The value of Last-Attempt-Date header
|
|
14
|
+
'rhost' => "", # The value of Remote-MTA header
|
|
15
|
+
'lhost' => "", # The value of Received-From-MTA header
|
|
16
|
+
'alias' => "", # The value of alias entry(RHS)
|
|
17
|
+
'agent' => "", # MTA module name
|
|
18
|
+
'action' => "", # The value of Action header
|
|
19
|
+
'status' => "", # The value of Status header
|
|
20
|
+
'reason' => "", # Temporary reason of bounce
|
|
21
|
+
'command' => "", # SMTP command in the message body
|
|
22
|
+
'replycode' => "", # SMTP Reply code
|
|
23
|
+
'diagnosis' => "", # The value of Diagnostic-Code header
|
|
24
|
+
'recipient' => "", # The value of Final-Recipient header
|
|
25
|
+
'feedbacktype' => "", # Feedback Type
|
|
27
26
|
}
|
|
28
27
|
end
|
|
29
28
|
|
|
@@ -37,14 +36,34 @@ module Sisimai
|
|
|
37
36
|
}
|
|
38
37
|
end
|
|
39
38
|
|
|
39
|
+
# @abstract Banners defined in Smail 3 and Deutsche Telekom
|
|
40
|
+
# @return [Array] Banner strings
|
|
41
|
+
# @private
|
|
42
|
+
def BannerDTAG
|
|
43
|
+
return [
|
|
44
|
+
# smail-3.2.0.108/src/
|
|
45
|
+
# notify.c:61|static char *log_banner = "\
|
|
46
|
+
# notify.c:62||------------------------- Message log follows: -------------------------|\n";
|
|
47
|
+
# notify.c:63|static char *addr_error_banner = "\
|
|
48
|
+
# notify.c:64||------------------------- Failed addresses follow: ---------------------|\n";
|
|
49
|
+
# notify.c:65|static char *text_banner = "\
|
|
50
|
+
# notify.c:66||------------------------- Message text follows: ------------------------|\n";
|
|
51
|
+
"|------------------------- Message log follows: -------------------------|", # 0. Smail 3
|
|
52
|
+
"|------------------------- Failed addresses follow: ---------------------|", # 1. Smail 3
|
|
53
|
+
"|------------------------- Message text follows: ------------------------|", # 2. Smail 3
|
|
54
|
+
"|------------------------- Message header follows: ----------------------|", # 3. Deutsche Telekom
|
|
55
|
+
# "|----------- Message text follows: (body too large, truncated) ----------|", # 4. Deutsche Telekom
|
|
56
|
+
]
|
|
57
|
+
end
|
|
58
|
+
|
|
40
59
|
# @abstract MTA list
|
|
41
60
|
# @return [Array] MTA list with order
|
|
42
61
|
def index
|
|
43
62
|
return %w[
|
|
44
|
-
Activehunter AmazonSES ApacheJames Biglobe Courier Domino DragonFly EZweb
|
|
45
|
-
Exchange2007 Exim FML GMX GoogleWorkspace GoogleGroups Gmail
|
|
46
|
-
MailMarshal MessagingServer Notes OpenSMTPD Postfix
|
|
47
|
-
X1 X2 X3 X6 Zoho MFILTER Qmail
|
|
63
|
+
Activehunter AmazonSES ApacheJames Biglobe Courier Domino DeutscheTelekom DragonFly EZweb
|
|
64
|
+
EinsUndEins Exchange2003 Exchange2007 Exim FML GMX GoogleWorkspace GoogleGroups Gmail
|
|
65
|
+
IMailServer KDDI MailFoundry Mimecast MailMarshal MessagingServer Notes OpenSMTPD Postfix
|
|
66
|
+
Sendmail TrendMicro V5sendmail Verizon X1 X2 X3 X6 Zoho MFILTER Qmail
|
|
48
67
|
]
|
|
49
68
|
end
|
|
50
69
|
|
data/lib/sisimai/message.rb
CHANGED
|
@@ -66,7 +66,7 @@ module Sisimai
|
|
|
66
66
|
# Remove "Fwd:" string from the Subject: header
|
|
67
67
|
if p1
|
|
68
68
|
# Delete quoted strings, quote symbols(>)
|
|
69
|
-
cq =
|
|
69
|
+
cq = cq[cq.index(':') + 1, cq.size]
|
|
70
70
|
aftersplit[2] = aftersplit[2].gsub(/^[>][ ]/, '').gsub(/^[>]$/, '')
|
|
71
71
|
end
|
|
72
72
|
thing['header']['subject'] = cq
|
data/lib/sisimai/order.rb
CHANGED
|
@@ -11,11 +11,12 @@ module Sisimai
|
|
|
11
11
|
'Sisimai::Lhost::Sendmail',
|
|
12
12
|
'Sisimai::Lhost::Exchange2007',
|
|
13
13
|
'Sisimai::Lhost::Exchange2003',
|
|
14
|
+
'Sisimai::Lhost::AmazonSES',
|
|
14
15
|
'Sisimai::Lhost::TrendMicro',
|
|
16
|
+
'Sisimai::Lhost::DeutscheTelekom',
|
|
15
17
|
'Sisimai::Lhost::KDDI',
|
|
16
18
|
'Sisimai::Lhost::FML',
|
|
17
19
|
'Sisimai::Lhost::Verizon',
|
|
18
|
-
'Sisimai::Lhost::AmazonSES',
|
|
19
20
|
'Sisimai::Lhost::ApacheJames',
|
|
20
21
|
'Sisimai::Lhost::X2',
|
|
21
22
|
].freeze
|
|
@@ -83,8 +84,10 @@ module Sisimai
|
|
|
83
84
|
'Sisimai::Lhost::GMX',
|
|
84
85
|
'Sisimai::Lhost::Zoho',
|
|
85
86
|
'Sisimai::Lhost::EinsUndEins',
|
|
87
|
+
'Sisimai::Lhost::DeutscheTelekom',
|
|
86
88
|
],
|
|
87
89
|
'mail-could' => ['Sisimai::Lhost::TrendMicro'],
|
|
90
|
+
'mail-failed' => ['Sisimai::Lhost::DeutscheTelekom'],
|
|
88
91
|
'mail-failure' => ['Sisimai::Lhost::Exim'],
|
|
89
92
|
'mail-system' => ['Sisimai::Lhost::EZweb'],
|
|
90
93
|
'message-delivery' => ['Sisimai::Lhost::MailFoundry'],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::AuthFailure checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::AuthFailure checks the bounce reason is "AuthFailure" or not. This class is
|
|
4
4
|
# called only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that an authenticaion failure related to SPF, DKIM, or DMARC was detected
|
|
@@ -12,6 +12,7 @@ module Sisimai
|
|
|
12
12
|
# Diagnostic-Code: smtp; 550 5.7.1 Email rejected per DMARC policy for example.org
|
|
13
13
|
module AuthFailure
|
|
14
14
|
class << self
|
|
15
|
+
require 'sisimai/eb'
|
|
15
16
|
Index = [
|
|
16
17
|
"//spf.pobox.com",
|
|
17
18
|
"5322.From address doesn't meet the authentication requirements",
|
|
@@ -23,11 +24,11 @@ module Sisimai
|
|
|
23
24
|
"spf check: fail",
|
|
24
25
|
].freeze
|
|
25
26
|
Pairs = [
|
|
26
|
-
[" is not allowed to send
|
|
27
|
-
["is not allowed to send
|
|
27
|
+
["spf: ", " is not allowed to send "],
|
|
28
|
+
["is not allowed to send ", " spf "],
|
|
28
29
|
].freeze
|
|
29
30
|
|
|
30
|
-
def text; return
|
|
31
|
+
def text; return Sisimai::Eb::ReAUTH; end
|
|
31
32
|
def description; return 'Email rejected due to SPF, DKIM, DMARC failure'; end
|
|
32
33
|
|
|
33
34
|
# Try to match that the given text and regular expressions
|
|
@@ -40,14 +41,14 @@ module Sisimai
|
|
|
40
41
|
return false
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
# The bounce reason is "
|
|
44
|
+
# The bounce reason is "AuthFailure" or not
|
|
44
45
|
# @param [Sisimai::Fact] argvs Object to be detected the reason
|
|
45
46
|
# @return [Boolean] true: is AuthFailure, false: is not AuthFailure
|
|
46
47
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
47
48
|
def true(argvs)
|
|
48
49
|
return false if argvs['deliverystatus'].empty?
|
|
49
|
-
return true if argvs['reason'] ==
|
|
50
|
-
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) ==
|
|
50
|
+
return true if argvs['reason'] == Sisimai::Eb::ReAUTH
|
|
51
|
+
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReAUTH
|
|
51
52
|
return match(argvs['diagnosticcode'].downcase)
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::BadReputation checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::BadReputation checks the bounce reason is "BadReputation" or not. This class
|
|
4
4
|
# is called only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that an email rejected due to a reputation score of the sender IP address.
|
|
@@ -14,6 +14,7 @@ module Sisimai
|
|
|
14
14
|
# visit https://support.google.com/mail/answer/188131 for more information.
|
|
15
15
|
module BadReputation
|
|
16
16
|
class << self
|
|
17
|
+
require 'sisimai/eb'
|
|
17
18
|
Index = [
|
|
18
19
|
"has been temporarily rate limited due to ip reputation",
|
|
19
20
|
"ip/domain reputation problems",
|
|
@@ -23,7 +24,7 @@ module Sisimai
|
|
|
23
24
|
"sending mta's poor reputation",
|
|
24
25
|
"temporarily deferred due to unexpected volume or user complaints", # Yahoo Inc.
|
|
25
26
|
].freeze
|
|
26
|
-
def text; return
|
|
27
|
+
def text; return Sisimai::Eb::ReFAMA; end
|
|
27
28
|
def description; return 'Email rejected due to an IP address reputation'; end
|
|
28
29
|
|
|
29
30
|
# Try to match that the given text and regular expressions
|
|
@@ -35,12 +36,12 @@ module Sisimai
|
|
|
35
36
|
return false
|
|
36
37
|
end
|
|
37
38
|
|
|
38
|
-
# The bounce reason is "
|
|
39
|
+
# The bounce reason is "BadReputation" or not
|
|
39
40
|
# @param [Sisimai::Fact] argvs Object to be detected the reason
|
|
40
41
|
# @return [Boolean] true: is BadReputation, false: is not BadReputation
|
|
41
42
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
42
43
|
def true(argvs)
|
|
43
|
-
return true if argvs['reason'] ==
|
|
44
|
+
return true if argvs['reason'] == Sisimai::Eb::ReFAMA
|
|
44
45
|
return match(argvs['diagnosticcode'].downcase)
|
|
45
46
|
end
|
|
46
47
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
module Sisimai
|
|
2
2
|
module Reason
|
|
3
|
-
# Sisimai::Reason::Blocked checks the bounce reason is "
|
|
3
|
+
# Sisimai::Reason::Blocked checks the bounce reason is "Blocked" or not. This class is called
|
|
4
4
|
# only Sisimai::Reason class.
|
|
5
5
|
#
|
|
6
6
|
# This is the error that SMTP connection was rejected due to a client IP address or a hostname,
|
|
7
7
|
# or the parameter of "HELO/EHLO" command. This reason has added in Sisimai 4.0.0.
|
|
8
8
|
module Blocked
|
|
9
9
|
class << self
|
|
10
|
+
require 'sisimai/eb'
|
|
10
11
|
Index = [
|
|
11
12
|
"bad sender ip address",
|
|
12
13
|
"banned sending ip", # Office365
|
|
@@ -70,7 +71,7 @@ module Sisimai
|
|
|
70
71
|
["your sender's ip address is listed at ", ".abuseat.org"],
|
|
71
72
|
].freeze
|
|
72
73
|
|
|
73
|
-
def text; return
|
|
74
|
+
def text; return Sisimai::Eb::ReBLOC; end
|
|
74
75
|
def description; return 'Email rejected due to client IP address or a hostname'; end
|
|
75
76
|
|
|
76
77
|
# Try to match that the given text and regular expressions
|
|
@@ -85,11 +86,11 @@ module Sisimai
|
|
|
85
86
|
|
|
86
87
|
# Blocked due to client IP address or hostname
|
|
87
88
|
# @param [Hash] argvs Hash to be detected the value of reason
|
|
88
|
-
# @return [Boolean] true: is
|
|
89
|
+
# @return [Boolean] true: is Blocked, false: is not Blocked by the client
|
|
89
90
|
# @see http://www.ietf.org/rfc/rfc2822.txt
|
|
90
91
|
def true(argvs)
|
|
91
|
-
return true if argvs['reason'] ==
|
|
92
|
-
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) ==
|
|
92
|
+
return true if argvs['reason'] == Sisimai::Eb::ReBLOC
|
|
93
|
+
return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == Sisimai::Eb::ReBLOC
|
|
93
94
|
return match(argvs['diagnosticcode'].downcase)
|
|
94
95
|
end
|
|
95
96
|
|