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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake-test.yml +0 -4
  3. data/ChangeLog.md +47 -0
  4. data/README-JA.md +19 -16
  5. data/README.md +23 -21
  6. data/lib/sisimai/address.rb +8 -31
  7. data/lib/sisimai/arf.rb +5 -6
  8. data/lib/sisimai/eb.rb +116 -0
  9. data/lib/sisimai/fact.rb +33 -51
  10. data/lib/sisimai/lda.rb +20 -18
  11. data/lib/sisimai/lhost/activehunter.rb +0 -2
  12. data/lib/sisimai/lhost/amazonses.rb +17 -18
  13. data/lib/sisimai/lhost/apachejames.rb +0 -1
  14. data/lib/sisimai/lhost/biglobe.rb +0 -16
  15. data/lib/sisimai/lhost/courier.rb +9 -7
  16. data/lib/sisimai/lhost/deutschetelekom.rb +120 -0
  17. data/lib/sisimai/lhost/domino.rb +2 -4
  18. data/lib/sisimai/lhost/dragonfly.rb +0 -27
  19. data/lib/sisimai/lhost/einsundeins.rb +4 -12
  20. data/lib/sisimai/lhost/exchange2003.rb +12 -11
  21. data/lib/sisimai/lhost/exchange2007.rb +17 -17
  22. data/lib/sisimai/lhost/exim.rb +34 -81
  23. data/lib/sisimai/lhost/ezweb.rb +15 -51
  24. data/lib/sisimai/lhost/fml.rb +8 -32
  25. data/lib/sisimai/lhost/gmail.rb +10 -32
  26. data/lib/sisimai/lhost/gmx.rb +7 -24
  27. data/lib/sisimai/lhost/googlegroups.rb +6 -5
  28. data/lib/sisimai/lhost/googleworkspace.rb +2 -5
  29. data/lib/sisimai/lhost/imailserver.rb +4 -9
  30. data/lib/sisimai/lhost/kddi.rb +8 -21
  31. data/lib/sisimai/lhost/mailfoundry.rb +0 -2
  32. data/lib/sisimai/lhost/mailmarshal.rb +1 -3
  33. data/lib/sisimai/lhost/messagingserver.rb +4 -15
  34. data/lib/sisimai/lhost/mfilter.rb +0 -1
  35. data/lib/sisimai/lhost/mimecast.rb +0 -1
  36. data/lib/sisimai/lhost/notes.rb +3 -3
  37. data/lib/sisimai/lhost/opensmtpd.rb +0 -40
  38. data/lib/sisimai/lhost/postfix.rb +14 -14
  39. data/lib/sisimai/lhost/qmail.rb +23 -89
  40. data/lib/sisimai/lhost/sendmail.rb +8 -7
  41. data/lib/sisimai/lhost/trendmicro.rb +5 -4
  42. data/lib/sisimai/lhost/v5sendmail.rb +2 -2
  43. data/lib/sisimai/lhost/verizon.rb +4 -4
  44. data/lib/sisimai/lhost/x1.rb +1 -2
  45. data/lib/sisimai/lhost/x2.rb +0 -2
  46. data/lib/sisimai/lhost/x3.rb +4 -9
  47. data/lib/sisimai/lhost/x6.rb +0 -1
  48. data/lib/sisimai/lhost/zoho.rb +0 -12
  49. data/lib/sisimai/lhost.rb +38 -19
  50. data/lib/sisimai/message.rb +1 -1
  51. data/lib/sisimai/order.rb +4 -1
  52. data/lib/sisimai/reason/authfailure.rb +8 -7
  53. data/lib/sisimai/reason/badreputation.rb +5 -4
  54. data/lib/sisimai/reason/blocked.rb +6 -5
  55. data/lib/sisimai/reason/contenterror.rb +8 -5
  56. data/lib/sisimai/reason/delivered.rb +3 -2
  57. data/lib/sisimai/reason/emailtoolarge.rb +7 -6
  58. data/lib/sisimai/reason/expired.rb +16 -4
  59. data/lib/sisimai/reason/failedstarttls.rb +5 -3
  60. data/lib/sisimai/reason/feedback.rb +2 -1
  61. data/lib/sisimai/reason/filtered.rb +9 -8
  62. data/lib/sisimai/reason/hasmoved.rb +5 -4
  63. data/lib/sisimai/reason/hostunknown.rb +14 -4
  64. data/lib/sisimai/reason/mailboxfull.rb +10 -8
  65. data/lib/sisimai/reason/mailererror.rb +3 -2
  66. data/lib/sisimai/reason/networkerror.rb +16 -3
  67. data/lib/sisimai/reason/norelaying.rb +8 -6
  68. data/lib/sisimai/reason/notaccept.rb +15 -7
  69. data/lib/sisimai/reason/notcompliantrfc.rb +5 -3
  70. data/lib/sisimai/reason/onhold.rb +8 -7
  71. data/lib/sisimai/reason/policyviolation.rb +11 -5
  72. data/lib/sisimai/reason/ratelimited.rb +5 -4
  73. data/lib/sisimai/reason/rejected.rb +24 -14
  74. data/lib/sisimai/reason/requireptr.rb +5 -4
  75. data/lib/sisimai/reason/securityerror.rb +5 -3
  76. data/lib/sisimai/reason/spamdetected.rb +6 -5
  77. data/lib/sisimai/reason/suppressed.rb +4 -3
  78. data/lib/sisimai/reason/suspend.rb +8 -3
  79. data/lib/sisimai/reason/syntaxerror.rb +5 -11
  80. data/lib/sisimai/reason/systemerror.rb +21 -2
  81. data/lib/sisimai/reason/systemfull.rb +4 -3
  82. data/lib/sisimai/reason/undefined.rb +2 -1
  83. data/lib/sisimai/reason/userunknown.rb +15 -9
  84. data/lib/sisimai/reason/vacation.rb +2 -1
  85. data/lib/sisimai/reason/virusdetected.rb +6 -5
  86. data/lib/sisimai/reason.rb +47 -42
  87. data/lib/sisimai/rfc1123.rb +1 -1
  88. data/lib/sisimai/rfc1894.rb +15 -8
  89. data/lib/sisimai/rfc2045.rb +8 -5
  90. data/lib/sisimai/rfc3464/thirdparty.rb +11 -10
  91. data/lib/sisimai/rfc3464.rb +10 -14
  92. data/lib/sisimai/rfc3834.rb +6 -5
  93. data/lib/sisimai/rfc791.rb +3 -38
  94. data/lib/sisimai/rhost/aol.rb +3 -2
  95. data/lib/sisimai/rhost/apple.rb +12 -11
  96. data/lib/sisimai/rhost/cloudflare.rb +3 -2
  97. data/lib/sisimai/rhost/cox.rb +38 -37
  98. data/lib/sisimai/rhost/facebook.rb +17 -16
  99. data/lib/sisimai/rhost/franceptt.rb +39 -38
  100. data/lib/sisimai/rhost/godaddy.rb +35 -34
  101. data/lib/sisimai/rhost/google.rb +22 -21
  102. data/lib/sisimai/rhost/gsuite.rb +8 -7
  103. data/lib/sisimai/rhost/iua.rb +11 -10
  104. data/lib/sisimai/rhost/kddi.rb +3 -2
  105. data/lib/sisimai/rhost/messagelabs.rb +13 -12
  106. data/lib/sisimai/rhost/microsoft.rb +37 -32
  107. data/lib/sisimai/rhost/mimecast.rb +18 -17
  108. data/lib/sisimai/rhost/nttdocomo.rb +10 -9
  109. data/lib/sisimai/rhost/outlook.rb +3 -2
  110. data/lib/sisimai/rhost/spectrum.rb +19 -18
  111. data/lib/sisimai/rhost/tencent.rb +10 -9
  112. data/lib/sisimai/rhost/yahooinc.rb +11 -10
  113. data/lib/sisimai/rhost/zoho.rb +8 -7
  114. data/lib/sisimai/rhost.rb +1 -1
  115. data/lib/sisimai/smtp/command.rb +13 -8
  116. data/lib/sisimai/smtp/failure.rb +9 -8
  117. data/lib/sisimai/smtp/reply.rb +23 -22
  118. data/lib/sisimai/smtp/status.rb +164 -159
  119. data/lib/sisimai/smtp/transcript.rb +3 -2
  120. data/lib/sisimai/string.rb +0 -12
  121. data/lib/sisimai/version.rb +1 -1
  122. data/lib/sisimai.rb +2 -1
  123. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-01.eml +66 -0
  124. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-02.eml +68 -0
  125. data/set-of-emails/maildir/bsd/lhost-deutschetelekom-03.eml +50 -0
  126. data/set-of-emails/maildir/bsd/lhost-postfix-81.eml +130 -0
  127. data/set-of-emails/should-not-crash/go-423-deeply-nested-mime-parts.eml +20050 -0
  128. data/set-of-emails/should-not-crash/p5-664-iomart-mail-filter.eml +258 -0
  129. data/set-of-emails/to-be-debugged-because/sisimai-cannot-parse-yet/.gitkeep +0 -0
  130. metadata +11 -2
@@ -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
- "CONN" => [" but greeting failed."],
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
- "EHLO" => [" but my name was rejected."],
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
- "MAIL" => [" but sender was rejected."],
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
- "RCPT" => [" does not like recipient."],
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
- "DATA" => [" failed on DATA command", " failed after I sent the message"],
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
- # qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
99
- # qmail-remote.c:78| Sorry, I couldn't find any host named ");
100
- "hostunknown" => ["Sorry, I couldn't find any host "],
101
- # error_str.c:192| X(EDQUOT,"disk quota exceeded")
102
- "mailboxfull" => ["disk quota exceeded"],
103
- # qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
104
- # qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
105
- "emailtoolarge" => ["Message size exceeds fixed maximum message size:"],
106
- "networkerror" => [
107
- "Sorry, I wasn't able to establish an SMTP connection",
108
- "Sorry. Although I'm listed as a best-preference MX or A for that host",
109
- ],
110
- "notaccept" => [
111
- # notqmail 1.08 returns the following error message when the destination MX is NullMX
112
- "Sorry, I couldn't find a mail exchanger or IP address",
113
- ],
114
- "systemerror" => [
115
- "bad interpreter: No such file or directory",
116
- "system error",
117
- "Unable to",
118
- ],
119
- "systemfull" => ["Requested action not taken: mailbox unavailable (not enough free space)"],
120
- # qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
121
- # qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
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"] = Sisimai::String.sweep(e[p1 + cm, p2 - p1 - cm])
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 %w[HELO EHLO].index(e["command"])
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"] = "blocked"
164
+ e["reason"] = Sisimai::Eb::ReBLOC
217
165
  else
218
166
  # Try to match with each error message in the table
219
- if Sisimai::String.aligned(e["diagnosis"], OnHoldPair)
220
- # To decide the reason require pattern match with Sisimai::Reason::* modules
221
- e["reason"] = "onhold"
222
- else
223
- # Check that the error message includes any of message patterns or not
224
- [e["alterrors"], e["diagnosis"]].each do |f|
225
- # Try to detect an error reason
226
- break if e["reason"] != ""
227
- next if f.nil?
228
- MessagesOf.each_key do |r|
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
- if o[3] == 'addr'
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
- elsif o[3] == 'code'
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'] += " #{Sisimai::String.sweep(e)}"
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['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
190
- e["command"] = thecommand if e["command"].empty?
191
- e["command"] = Sisimai::SMTP::Command.find(e['diagnosis']) if e["command"].empty?
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
- if e.start_with?('Sent <<< ')
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
- elsif e.start_with?('Received >>> ')
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['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
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 == "MAIL" && e.start_with?("<<< "))
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
- 'userunknown' => ['550 - Requested action not taken: no such user here'],
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 = {'userunknown' => ['No valid recipients for this MM']}
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'] = Sisimai::String.sweep(e[7, e.size]) if e.start_with?('Error: ')
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) }
@@ -67,8 +67,7 @@ module Sisimai::Lhost
67
67
  return nil if recipients == 0
68
68
 
69
69
  dscontents.each do |e|
70
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
71
- e['date'] = datestring || ''
70
+ e['date'] = datestring || ''
72
71
  end
73
72
 
74
73
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
@@ -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
@@ -64,28 +64,23 @@ module Sisimai::Lhost
64
64
  recipients += 1
65
65
  else
66
66
  # Detect error message
67
- if e.start_with?('SMTP:')
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
- elsif e.start_with?('Routing: ')
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
- elsif e.start_with?('Diagnostic-Code: smtp; ')
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
@@ -84,7 +84,6 @@ module Sisimai::Lhost
84
84
  # ...(Error following RCPT command).
85
85
  e['command'] = cv
86
86
  end
87
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
88
87
  end
89
88
 
90
89
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
@@ -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' => "", # 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
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 EinsUndEins Exchange2003
45
- Exchange2007 Exim FML GMX GoogleWorkspace GoogleGroups Gmail IMailServer KDDI MailFoundry Mimecast
46
- MailMarshal MessagingServer Notes OpenSMTPD Postfix Sendmail TrendMicro V5sendmail Verizon
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
 
@@ -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 = Sisimai::String.sweep(cq[cq.index(':') + 1, cq.size])
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 "authfailure" or not. This class 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 mail.", "_401"],
27
- ["is not allowed to send from <", " per it's spf record"],
27
+ ["spf: ", " is not allowed to send "],
28
+ ["is not allowed to send ", " spf "],
28
29
  ].freeze
29
30
 
30
- def text; return 'authfailure'; end
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 "authfailure" or not
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'] == 'authfailure'
50
- return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'authfailure'
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 "badreputation" or not. This class
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 'badreputation'; end
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 "badreputation" or not
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'] == 'badreputation'
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 "blocked" or not. This class is called
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 'blocked'; end
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 blocked, false: is not blocked by the client
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'] == 'blocked'
92
- return true if Sisimai::SMTP::Status.name(argvs['deliverystatus']) == 'blocked'
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