sisimai 5.7.0-java → 5.7.2-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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codecovio.yml +1 -1
  3. data/.github/workflows/rake-test.yml +1 -1
  4. data/ChangeLog.md +25 -0
  5. data/README-JA.md +14 -13
  6. data/README.md +12 -12
  7. data/lib/sisimai/arf.rb +2 -1
  8. data/lib/sisimai/eb.rb +116 -0
  9. data/lib/sisimai/fact.rb +24 -17
  10. data/lib/sisimai/lda.rb +20 -18
  11. data/lib/sisimai/lhost/amazonses.rb +11 -10
  12. data/lib/sisimai/lhost/courier.rb +4 -3
  13. data/lib/sisimai/lhost/domino.rb +2 -1
  14. data/lib/sisimai/lhost/einsundeins.rb +3 -2
  15. data/lib/sisimai/lhost/exchange2003.rb +8 -7
  16. data/lib/sisimai/lhost/exchange2007.rb +14 -13
  17. data/lib/sisimai/lhost/exim.rb +7 -6
  18. data/lib/sisimai/lhost/ezweb.rb +4 -3
  19. data/lib/sisimai/lhost/fml.rb +4 -3
  20. data/lib/sisimai/lhost/gmail.rb +10 -9
  21. data/lib/sisimai/lhost/googlegroups.rb +3 -2
  22. data/lib/sisimai/lhost/googleworkspace.rb +2 -1
  23. data/lib/sisimai/lhost/imailserver.rb +3 -2
  24. data/lib/sisimai/lhost/kddi.rb +4 -3
  25. data/lib/sisimai/lhost/notes.rb +2 -1
  26. data/lib/sisimai/lhost/postfix.rb +7 -6
  27. data/lib/sisimai/lhost/qmail.rb +10 -9
  28. data/lib/sisimai/lhost/sendmail.rb +4 -3
  29. data/lib/sisimai/lhost/trendmicro.rb +2 -1
  30. data/lib/sisimai/lhost/v5sendmail.rb +2 -1
  31. data/lib/sisimai/lhost/verizon.rb +3 -2
  32. data/lib/sisimai/message.rb +5 -6
  33. data/lib/sisimai/reason/authfailure.rb +6 -5
  34. data/lib/sisimai/reason/badreputation.rb +5 -4
  35. data/lib/sisimai/reason/blocked.rb +6 -5
  36. data/lib/sisimai/reason/contenterror.rb +6 -5
  37. data/lib/sisimai/reason/delivered.rb +3 -2
  38. data/lib/sisimai/reason/emailtoolarge.rb +6 -5
  39. data/lib/sisimai/reason/expired.rb +3 -2
  40. data/lib/sisimai/reason/failedstarttls.rb +5 -3
  41. data/lib/sisimai/reason/feedback.rb +2 -1
  42. data/lib/sisimai/reason/filtered.rb +9 -8
  43. data/lib/sisimai/reason/hasmoved.rb +5 -4
  44. data/lib/sisimai/reason/hostunknown.rb +5 -4
  45. data/lib/sisimai/reason/mailboxfull.rb +7 -6
  46. data/lib/sisimai/reason/mailererror.rb +3 -2
  47. data/lib/sisimai/reason/networkerror.rb +3 -2
  48. data/lib/sisimai/reason/norelaying.rb +4 -3
  49. data/lib/sisimai/reason/notaccept.rb +5 -4
  50. data/lib/sisimai/reason/notcompliantrfc.rb +4 -3
  51. data/lib/sisimai/reason/onhold.rb +8 -7
  52. data/lib/sisimai/reason/policyviolation.rb +7 -6
  53. data/lib/sisimai/reason/ratelimited.rb +5 -4
  54. data/lib/sisimai/reason/rejected.rb +18 -14
  55. data/lib/sisimai/reason/requireptr.rb +5 -4
  56. data/lib/sisimai/reason/securityerror.rb +4 -3
  57. data/lib/sisimai/reason/spamdetected.rb +6 -5
  58. data/lib/sisimai/reason/suppressed.rb +4 -3
  59. data/lib/sisimai/reason/suspend.rb +4 -3
  60. data/lib/sisimai/reason/syntaxerror.rb +4 -3
  61. data/lib/sisimai/reason/systemerror.rb +3 -2
  62. data/lib/sisimai/reason/systemfull.rb +4 -3
  63. data/lib/sisimai/reason/undefined.rb +2 -1
  64. data/lib/sisimai/reason/userunknown.rb +13 -9
  65. data/lib/sisimai/reason/vacation.rb +2 -1
  66. data/lib/sisimai/reason/virusdetected.rb +6 -5
  67. data/lib/sisimai/reason.rb +45 -40
  68. data/lib/sisimai/rfc1894.rb +8 -2
  69. data/lib/sisimai/rfc2045.rb +6 -3
  70. data/lib/sisimai/rfc3464/thirdparty.rb +10 -9
  71. data/lib/sisimai/rfc3834.rb +4 -2
  72. data/lib/sisimai/rhost/aol.rb +3 -2
  73. data/lib/sisimai/rhost/apple.rb +12 -11
  74. data/lib/sisimai/rhost/cloudflare.rb +3 -2
  75. data/lib/sisimai/rhost/cox.rb +38 -37
  76. data/lib/sisimai/rhost/facebook.rb +17 -16
  77. data/lib/sisimai/rhost/franceptt.rb +39 -38
  78. data/lib/sisimai/rhost/godaddy.rb +35 -34
  79. data/lib/sisimai/rhost/google.rb +22 -21
  80. data/lib/sisimai/rhost/gsuite.rb +8 -7
  81. data/lib/sisimai/rhost/iua.rb +11 -10
  82. data/lib/sisimai/rhost/kddi.rb +3 -2
  83. data/lib/sisimai/rhost/messagelabs.rb +13 -12
  84. data/lib/sisimai/rhost/microsoft.rb +33 -32
  85. data/lib/sisimai/rhost/mimecast.rb +18 -17
  86. data/lib/sisimai/rhost/nttdocomo.rb +10 -9
  87. data/lib/sisimai/rhost/outlook.rb +3 -2
  88. data/lib/sisimai/rhost/spectrum.rb +19 -18
  89. data/lib/sisimai/rhost/tencent.rb +10 -9
  90. data/lib/sisimai/rhost/yahooinc.rb +11 -10
  91. data/lib/sisimai/rhost/zoho.rb +8 -7
  92. data/lib/sisimai/smtp/command.rb +13 -8
  93. data/lib/sisimai/smtp/failure.rb +9 -8
  94. data/lib/sisimai/smtp/reply.rb +23 -22
  95. data/lib/sisimai/smtp/status.rb +141 -140
  96. data/lib/sisimai/smtp/transcript.rb +3 -2
  97. data/lib/sisimai/string.rb +4 -3
  98. data/lib/sisimai/version.rb +1 -1
  99. data/lib/sisimai.rb +2 -1
  100. data/set-of-emails/maildir/bsd/lhost-postfix-81.eml +130 -0
  101. data/set-of-emails/should-not-crash/go-423-deeply-nested-mime-parts.eml +20050 -0
  102. metadata +5 -2
@@ -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
- 'onhold' => [
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
- 'userunknown' => [
22
+ Sisimai::Eb::ReUSER => [
22
23
  '000C05A6', # Unknown Recipient,
23
24
  ],
24
- 'systemerror' => [
25
+ Sisimai::Eb::RePROC => [
25
26
  '00010256', # Too many recipients.
26
27
  '000D06B5', # No proxy for recipient (non-smtp mail?)
27
28
  ],
28
- 'networkerror' => [
29
+ Sisimai::Eb::ReINET => [
29
30
  '00120270', # Too Many Hops
30
31
  ],
31
- 'contenterror' => [
32
+ Sisimai::Eb::ReBODY => [
32
33
  '00050311', # Conversion to Internet format failed
33
34
  '000502CC', # Conversion to Internet format failed
34
35
  ],
35
- 'securityerror' => [
36
+ Sisimai::Eb::ReSAFE => [
36
37
  '000B0981', # 502 Server does not support AUTH
37
38
  ],
38
- 'filtered' => [
39
+ Sisimai::Eb::ReFILT => [
39
40
  '000C0595', # Ambiguous Recipient
40
41
  ],
41
42
  }.freeze
@@ -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" => "hostunknown", # 554 5.4.4 SMTPSEND.DNS.NonExistentDomain
36
- "SMTPSEND.DNS.MxLoopback" => "networkerror", # 554 5.4.4 SMTPSEND.DNS.MxLoopback
37
- "RESOLVER.ADR.BadPrimary" => "systemerror", # 550 5.2.0 RESOLVER.ADR.BadPrimary
38
- "RESOLVER.ADR.RecipNotFound" => "userunknown", # 550 5.1.1 RESOLVER.ADR.RecipNotFound
39
- "RESOLVER.ADR.RecipientNotFound" => "userunknown", # 550 5.1.1 RESOLVER.ADR.RecipientNotFound
40
- "RESOLVER.ADR.ExRecipNotFound" => "userunknown", # 550 5.1.1 RESOLVER.ADR.ExRecipNotFound
41
- "RESOLVER.ADR.RecipLimit" => "ratelimited", # 550 5.5.3 RESOLVER.ADR.RecipLimit
42
- "RESOLVER.ADR.InvalidInSmtp" => "systemerror", # 550 5.1.0 RESOLVER.ADR.InvalidInSmtp
43
- "RESOLVER.ADR.Ambiguous" => "systemerror", # 550 5.1.4 RESOLVER.ADR.Ambiguous, 420 4.2.0 RESOLVER.ADR.Ambiguous
44
- "RESOLVER.RST.AuthRequired" => "securityerror", # 550 5.7.1 RESOLVER.RST.AuthRequired
45
- "RESOLVER.RST.NotAuthorized" => "rejected", # 550 5.7.1 RESOLVER.RST.NotAuthorized
46
- "RESOLVER.RST.RecipSizeLimit" => "emailtoolarge", # 550 5.2.3 RESOLVER.RST.RecipSizeLimit
47
- "QUEUE.Expired" => "expired", # 550 4.4.7 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 = [
@@ -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,12 +61,12 @@ 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
- "userunknown" => ["user not found"],
64
+ Sisimai::Eb::ReUSER => ["user not found"],
64
65
  # parser.c:666| *errorptr = string_sprintf("%s (expected word or \"<\")", *errorptr);
65
66
  # parser.c:701| if(bracket_count++ > 5) FAILED(US"angle-brackets nested too deep");
66
67
  # parser.c:738| FAILED(US"domain missing in source-routed address");
67
68
  # parser.c:747| : string_sprintf("malformed address: %.32s may not follow %.*s",
68
- "syntaxerror" => [
69
+ Sisimai::Eb::ReCOMM => [
69
70
  "angle-brackets nested too deep",
70
71
  'expected word or "<"',
71
72
  "domain missing in source-routed address",
@@ -389,8 +390,8 @@ module Sisimai::Lhost
389
390
  case e["command"]
390
391
  # - HELO | Connected to 192.0.2.135 but my name was rejected.
391
392
  # - MAIL | Connected to 192.0.2.135 but sender was rejected.
392
- when "HELO", "EHLO" then e["reason"] = "blocked"
393
- when "MAIL" then e["reason"] = "onhold"
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
394
395
  else
395
396
  # Try to match the error message with each message pattern
396
397
  MessagesOf.each_key do |r|
@@ -401,7 +402,7 @@ module Sisimai::Lhost
401
402
  end
402
403
 
403
404
  if e["reason"].empty?
404
- e["reason"] = "expired" if DelayedFor.any? { |a| e["diagnosis"].include?(a) }
405
+ e["reason"] = Sisimai::Eb::ReTIME if DelayedFor.any? { |a| e["diagnosis"].include?(a) }
405
406
  end
406
407
  end
407
408
  end
@@ -420,7 +421,7 @@ module Sisimai::Lhost
420
421
  re = e["reason"]
421
422
  cv = ""
422
423
 
423
- if Sisimai::SMTP::Failure.is_temporary(cr) || re == "expired"
424
+ if Sisimai::SMTP::Failure.is_temporary(cr) || re == Sisimai::Eb::ReTIME
424
425
  # Set the pseudo status code as a temporary error
425
426
  cv = Sisimai::SMTP::Status.code(re, true) if Sisimai::Reason.is_explicit(re)
426
427
  end
@@ -3,6 +3,7 @@ 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
@@ -100,14 +101,14 @@ module Sisimai::Lhost
100
101
  if mhead['x-spasign'].to_s == 'NG'
101
102
  # Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
102
103
  # Filtered recipient returns message that include 'X-SPASIGN' header
103
- e['reason'] = 'filtered'
104
+ e['reason'] = Sisimai::Eb::ReFILT
104
105
  else
105
106
  # There is no X-SPASIGN header or the value of the header is not "NG"
106
- e['reason'] = "suspend" if UnpaidUser.any? { |a| e['diagnosis'].include?(a) }
107
+ e['reason'] = Sisimai::Eb::ReQUIT if UnpaidUser.any? { |a| e['diagnosis'].include?(a) }
107
108
  end
108
109
  next if e['reason'] != ""
109
110
  next if e['recipient'].end_with?('@ezweb.ne.jp', '@au.com')
110
- e["reason"] = "userunknown" if e["diagnosis"].start_with?("<")
111
+ e["reason"] = Sisimai::Eb::ReUSER if e["diagnosis"].start_with?("<")
111
112
  end
112
113
 
113
114
  return {"ds" => dscontents, "rfc822" => emailparts[1]}
@@ -3,24 +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
- 'rejected' => [
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
- 'systemerror' => [
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
- 'securityerror' => ['Security Alert'],
24
+ Sisimai::Eb::ReSAFE => ['Security Alert'],
24
25
  }.freeze
25
26
 
26
27
  # @abstract Decodes the bounce message from fml mailling list server/manager
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Gmail
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
@@ -17,7 +18,7 @@ module Sisimai::Lhost
17
18
  # We recommend contacting the other email provider for further information about the
18
19
  # cause of this error. The error that the other server returned was:
19
20
  # 500 Remote server does not support TLS (state 6).
20
- '6' => { 'command' => 'MAIL', 'reason' => 'failedstarttls' },
21
+ '6' => { 'command' => Sisimai::Eb::CeMAIL, 'reason' => Sisimai::Eb::ReTTLS },
21
22
 
22
23
  # https://www.google.td/support/forum/p/gmail/thread?tid=08a60ebf5db24f7b&hl=en
23
24
  # Technical details of permanent failure:
@@ -25,7 +26,7 @@ module Sisimai::Lhost
25
26
  # We recommend contacting the other email provider for further information about the
26
27
  # cause of this error. The error that the other server returned was:
27
28
  # 535 SMTP AUTH failed with the remote server. (state 8).
28
- '8' => { 'command' => 'AUTH', 'reason' => 'systemerror' },
29
+ '8' => { 'command' => Sisimai::Eb::CeAUTH, 'reason' => Sisimai::Eb::RePROC },
29
30
 
30
31
  # https://www.google.co.nz/support/forum/p/gmail/thread?tid=45208164dbca9d24&hl=en
31
32
  # Technical details of temporary failure:
@@ -33,7 +34,7 @@ module Sisimai::Lhost
33
34
  # We recommend contacting the other email provider for further information about the
34
35
  # cause of this error. The error that the other server returned was:
35
36
  # 454 454 TLS missing certificate: error:0200100D:system library:fopen:Permission denied (#4.3.0) (state 9).
36
- '9' => { 'command' => 'AUTH', 'reason' => 'failedstarttls' },
37
+ '9' => { 'command' => Sisimai::Eb::CeAUTH, 'reason' => Sisimai::Eb::ReTTLS },
37
38
 
38
39
  # https://www.google.com/support/forum/p/gmail/thread?tid=5cfab8c76ec88638&hl=en
39
40
  # Technical details of permanent failure:
@@ -41,14 +42,14 @@ module Sisimai::Lhost
41
42
  # We recommend contacting the other email provider for further information about the
42
43
  # cause of this error. The error that the other server returned was:
43
44
  # 500 Remote server does not support SMTP Authenticated Relay (state 12).
44
- '12' => { 'command' => 'AUTH', 'reason' => 'norelaying' },
45
+ '12' => { 'command' => Sisimai::Eb::CeAUTH, 'reason' => Sisimai::Eb::RePASS },
45
46
 
46
47
  # Technical details of permanent failure:
47
48
  # Google tried to deliver your message, but it was rejected by the recipient domain.
48
49
  # We recommend contacting the other email provider for further information about the
49
50
  # cause of this error. The error that the other server returned was:
50
51
  # 550 550 5.7.1 <****@gmail.com>... Access denied (state 13).
51
- '13' => { 'command' => 'EHLO', 'reason' => 'blocked' },
52
+ '13' => { 'command' => Sisimai::Eb::CeEHLO, 'reason' => Sisimai::Eb::ReBLOC },
52
53
 
53
54
  # Technical details of permanent failure:
54
55
  # Google tried to deliver your message, but it was rejected by the recipient domain.
@@ -57,7 +58,7 @@ module Sisimai::Lhost
57
58
  # 550 550 5.1.1 <******@*********.**>... User Unknown (state 14).
58
59
  # 550 550 5.2.2 <*****@****.**>... Mailbox Full (state 14).
59
60
  #
60
- '14' => { 'command' => 'RCPT', 'reason' => 'userunknown' },
61
+ '14' => { 'command' => Sisimai::Eb::CeRCPT, 'reason' => Sisimai::Eb::ReUSER },
61
62
 
62
63
  # https://www.google.cz/support/forum/p/gmail/thread?tid=7090cbfd111a24f9&hl=en
63
64
  # Technical details of permanent failure:
@@ -66,7 +67,7 @@ module Sisimai::Lhost
66
67
  # cause of this error. The error that the other server returned was:
67
68
  # 550 550 5.7.1 SPF unauthorized mail is prohibited. (state 15).
68
69
  # 554 554 Error: no valid recipients (state 15).
69
- '15' => { 'command' => 'DATA', 'reason' => 'filtered' },
70
+ '15' => { 'command' => Sisimai::Eb::CeDATA, 'reason' => Sisimai::Eb::ReFILT },
70
71
 
71
72
  # https://www.google.com/support/forum/p/Google%20Apps/thread?tid=0aac163bc9c65d8e&hl=en
72
73
  # Technical details of permanent failure:
@@ -75,14 +76,14 @@ module Sisimai::Lhost
75
76
  # cause of this error. The error that the other server returned was:
76
77
  # 550 550 <****@***.**> No such user here (state 17).
77
78
  # 550 550 #5.1.0 Address rejected ***@***.*** (state 17).
78
- '17' => { 'command' => 'DATA', 'reason' => 'filtered' },
79
+ '17' => { 'command' => Sisimai::Eb::CeDATA, 'reason' => Sisimai::Eb::ReFILT },
79
80
 
80
81
  # Technical details of permanent failure:
81
82
  # Google tried to deliver your message, but it was rejected by the recipient domain.
82
83
  # We recommend contacting the other email provider for further information about the
83
84
  # cause of this error. The error that the other server returned was:
84
85
  # 550 550 Unknown user *****@***.**.*** (state 18).
85
- '18' => { 'command' => 'DATA', 'reason' => 'filtered' },
86
+ '18' => { 'command' => Sisimai::Eb::CeDATA, 'reason' => Sisimai::Eb::ReFILT },
86
87
  }.freeze
87
88
 
88
89
  # @abstract Decodes the bounce message from Gmail
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module GoogleGroups
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  Boundaries = ['----- Original message -----', 'Content-Type: message/rfc822'].freeze
8
9
 
@@ -47,10 +48,10 @@ module Sisimai::Lhost
47
48
  receivedby = mhead['received'] || []
48
49
  recordwide = {
49
50
  'diagnosis' => entiremesg,
50
- 'reason' => 'onhold',
51
+ 'reason' => Sisimai::Eb::Re___1,
51
52
  'rhost' => Sisimai::RFC5322.received(receivedby[0])[1],
52
53
  }
53
- recordwide['reason'] = 'rejected' if emailparts[0].scan(/^[ ]?[*][ ]?/).size == 4
54
+ recordwide['reason'] = Sisimai::Eb::ReFROM if emailparts[0].scan(/^[ ]?[*][ ]?/).size == 4
54
55
 
55
56
  mhead['x-failed-recipients'].split(',').each do |e|
56
57
  # X-Failed-Recipients: neko@example.jp, nyaan@example.org, ...
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called only from Sisimai::Message.
4
4
  module GoogleWorkspace
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  require 'sisimai/string'
8
9
  require 'sisimai/address'
@@ -14,7 +15,7 @@ module Sisimai::Lhost
14
15
  error: ["The response was:", "The response from the remote server was:"],
15
16
  }.freeze
16
17
  MessagesOf = {
17
- "userunknown" => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
+ Sisimai::Eb::ReUSER => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
19
  }.freeze
19
20
 
20
21
  # @abstract Decodes the bounce message from Google Workspace
@@ -4,13 +4,14 @@ module Sisimai::Lhost
4
4
  # Methods in the module are called from only Sisimai::Message.
5
5
  module IMailServer
6
6
  class << self
7
+ require 'sisimai/eb'
7
8
  require 'sisimai/lhost'
8
9
 
9
10
  Boundaries = ['Original message follows.'].freeze
10
11
  StartingOf = {error: ['Body of message generated response:']}.freeze
11
12
  MessagesOf = {
12
- 'userunknown' => ['Unknown user', 'Invalid final delivery userid'],
13
- 'expired' => ['Delivery failed '],
13
+ Sisimai::Eb::ReUSER => ['Unknown user', 'Invalid final delivery userid'],
14
+ Sisimai::Eb::ReTIME => ['Delivery failed '],
14
15
  }.freeze
15
16
 
16
17
  # @abstract Decodes the bounce message from Progress iMail Server
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module KDDI
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
@@ -72,11 +73,11 @@ module Sisimai::Lhost
72
73
  if mhead['x-spasign'].to_s == 'NG'
73
74
  # Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by KDDI)
74
75
  # Filtered recipient returns message that include 'X-SPASIGN' header
75
- e['reason'] = 'filtered'
76
+ e['reason'] = Sisimai::Eb::ReFILT
76
77
  else
77
78
  # There is no X-SPASIGN: header in the bounce message
78
- # set "userunknown" when the remote server rejected after RCPT command.
79
- e['reason'] = 'userunknown' if e['command'] == 'RCPT'
79
+ # set "UserUnknown" when the remote server rejected after RCPT command.
80
+ e['reason'] = Sisimai::Eb::ReUSER if e['command'] == Sisimai::Eb::CeRCPT
80
81
  end
81
82
  end
82
83
 
@@ -3,13 +3,14 @@ module Sisimai::Lhost
3
3
  # (formerly Lotus Notes Server)). Methods in the module are called from only Sisimai::Message.
4
4
  module Notes
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
9
10
  Boundaries = ['------- Returned Message --------'].freeze
10
11
  StartingOf = {message: ['------- Failure Reasons ']}.freeze
11
12
  MessagesOf = {
12
- 'userunknown' => [
13
+ Sisimai::Eb::ReUSER => [
13
14
  'User not listed in public Name & Address Book',
14
15
  'ディレクトリのリストにありません',
15
16
  ],
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Postfix
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
  require 'sisimai/rfc1123'
8
9
  require 'sisimai/smtp/reply'
@@ -65,12 +66,12 @@ module Sisimai::Lhost
65
66
 
66
67
  case e["command"]
67
68
  # Use the argument of EHLO/HELO command as a value of "lhost"
68
- when "HELO", "EHLO" then v['lhost'] = e['argument']
69
- when "MAIL"
69
+ when Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO then v['lhost'] = e['argument']
70
+ when Sisimai::Eb::CeMAIL
70
71
  # Set the argument of "MAIL" command to pseudo To: header of the original message
71
72
  emailparts[1] += sprintf("To: %s\n", e['argument']) if emailparts[1].size == 0
72
73
 
73
- when "RCPT"
74
+ when Sisimai::Eb::CeRCPT
74
75
  # RCPT TO: <...>
75
76
  if v["recipient"] != ""
76
77
  # There are multiple recipient addresses in the transcript of session
@@ -277,9 +278,9 @@ module Sisimai::Lhost
277
278
  end
278
279
  end
279
280
 
280
- e['command'] = commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis'])
281
- e['command'] = 'HELO' if e["command"].empty? && e['diagnosis'].include?('refused to talk to me:')
282
- e['spec'] = 'SMTP' if e["spec"].empty? && Sisimai::String.aligned(e['diagnosis'], ['host ', ' said:'])
281
+ e['command'] = commandset.shift || Sisimai::SMTP::Command.find(e['diagnosis'])
282
+ e['command'] = Sisimai::Eb::CeHELO if e["command"].empty? && e['diagnosis'].include?('refused to talk to me:')
283
+ e['spec'] = 'SMTP' if e["spec"].empty? && Sisimai::String.aligned(e['diagnosis'], ['host ', ' said:'])
283
284
  end
284
285
 
285
286
  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 Qmail
6
6
  class << self
7
+ require 'sisimai/eb'
7
8
  require 'sisimai/lhost'
8
9
  require 'sisimai/string'
9
10
 
@@ -49,27 +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
70
  MessagesOf = {
70
71
  # notqmail 1.08 returns the following error message when the destination MX is NullMX
71
- "notaccept" => ["Sorry, I couldn't find a mail exchanger or IP address"],
72
- "userunknown" => ["no mailbox here by that name"],
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"],
73
74
  }.freeze
74
75
 
75
76
  # @abstract Decodes the bounce message from qmail
@@ -158,9 +159,9 @@ module Sisimai::Lhost
158
159
  end
159
160
 
160
161
  # Detect the reason of bounce
161
- if %w[HELO EHLO].index(e["command"])
162
+ if [Sisimai::Eb::CeHELO, Sisimai::Eb::CeEHLO].index(e["command"])
162
163
  # HELO | Connected to 192.0.2.135 but my name was rejected.
163
- e["reason"] = "blocked"
164
+ e["reason"] = Sisimai::Eb::ReBLOC
164
165
  else
165
166
  # Try to match with each error message in the table
166
167
  # Check that the error message includes any of message patterns or not
@@ -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'
@@ -187,9 +188,9 @@ module Sisimai::Lhost
187
188
  break
188
189
  end
189
190
 
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
 
@@ -73,7 +74,7 @@ module Sisimai::Lhost
73
74
  return nil if recipients == 0
74
75
 
75
76
  dscontents.each do |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 == "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
@@ -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")
@@ -202,7 +202,7 @@ module Sisimai
202
202
  def tidy(argv0 = '')
203
203
  return '' if argv0.empty?
204
204
 
205
- email = ''
205
+ email = ::String.new(capacity: argv0.bytesize, encoding: Encoding::UTF_8)
206
206
  lines = argv0.split("\n")
207
207
  index = -1
208
208
  lines.each do |e|
@@ -215,7 +215,7 @@ module Sisimai
215
215
  index += 1
216
216
  if fn == ''
217
217
  # There is neither ":" character nor the field listed in $FieldTable
218
- email += "#{e}\n"
218
+ email << e << "\n"
219
219
  next
220
220
  end
221
221
 
@@ -294,12 +294,12 @@ module Sisimai
294
294
 
295
295
  # 4. Remove redundant space characters
296
296
  bf = bf.squeeze(' ').strip
297
- email += sprintf("%s: %s\n", fn, bf)
297
+ email << sprintf("%s: %s\n", fn, bf)
298
298
  end
299
299
 
300
300
  # 5. Convert the lower-cased SMTP command to the upper-cased.
301
- email = email.gsub("after end of data:", "after end of DATA:")
302
- email += "\n" if email.end_with?("\n\n") == false
301
+ email.gsub!("after end of data:", "after end of DATA:")
302
+ email << "\n" if email.end_with?("\n\n") == false
303
303
  return email
304
304
  end
305
305
 
@@ -428,4 +428,3 @@ module Sisimai
428
428
  end
429
429
  end
430
430
  end
431
-
@@ -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",
@@ -27,7 +28,7 @@ module Sisimai
27
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