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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 701bb8a21375a15d4189cc3a3f8929884ab3406483526d009bb1e257b610cf9b
4
- data.tar.gz: 2c319b65b0f72c9351dc099877505b6176c3b980e813fc10e53e67be504cafe1
3
+ metadata.gz: a713d133864ab6845c95ba347b30385f5c564864c9afa3edeb0b5f37aebcda7e
4
+ data.tar.gz: ee3ea2d230b497c8f58c643a387838701118449b6bdb04a23229ff3544e6c782
5
5
  SHA512:
6
- metadata.gz: a9458959a372839a8626a31bf487718338a4942c5a27e9d99e4b7efac8e340263c4dab88c8988a197e3b1e72be15b50cf69fcc07c41b6c2f007d03fba33854b1
7
- data.tar.gz: 5b3c330b2297749b8d4a91d68e8ef898993457129b87fab8e7222efc0c6b0a4251742bc5330ab22077dc915fc786e96acf511e41ac3bf74775ae8664da3aeabf
6
+ metadata.gz: 28936ef912d907d24160bdf111a7f047a85fa7a6aa4f41405d2c3c6aee37bb0ce25a38b5fa21b424bc92af481756a06c608291546db776d96cc4a362f20d9321
7
+ data.tar.gz: 53693d2372481b610b312563f1ebec102572fc8b98435c640c05a0a0a5e5a067e763b339e20d8964d3ace364a10eaa8ad2c34be7f4b9cc3fd547b36008df1b0f
@@ -15,7 +15,7 @@ jobs:
15
15
  - name: Setup CRuby
16
16
  uses: ruby/setup-ruby@v1
17
17
  with:
18
- ruby-version: "3.4.7"
18
+ ruby-version: "3.4.10"
19
19
  - name: Install minitest
20
20
  run: gem install minitest -v 5.15.0
21
21
  - name: Install oj
@@ -11,7 +11,7 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- cruby: ["2.5.9", "3.3.10", "3.4.7"]
14
+ cruby: ["2.5.9", "3.3.10", "3.4.10"]
15
15
  steps:
16
16
  - name: Checkout the repository(CRuby)
17
17
  uses: actions/checkout@v4
data/ChangeLog.md CHANGED
@@ -4,6 +4,31 @@ RELEASE NOTES for Ruby version of Sisimai
4
4
  - download: "https://rubygems.org/gems/sisimai"
5
5
  - document: "https://libsisimai.org/"
6
6
 
7
+ v5.7.2
8
+ ---------------------------------------------------------------------------------------------------
9
+ - release: "Mon, 31 Aug 2026 18:25:22 +0900 (JST)"
10
+ - version: "5.7.2"
11
+ - changes:
12
+ - Fix ReDoS vulnerability in `Sisimai::String.to_plain` method when parsing specific HTML tags
13
+ (GHSA-9j9h-h4vm-p7g4). Thanks to @arpitjain099 for reporting and testing.
14
+ - #455 Resolved quadratic memory allocation in `Sisimai::Message` to improve parsing performance
15
+ and reduce memory usage. Thanks to @azranel.
16
+
17
+ v5.7.1
18
+ ---------------------------------------------------------------------------------------------------
19
+ - release: "Fri, 17 Jul 2026 13:22:22 +0900 (JST)"
20
+ - version: "5.7.1"
21
+ - changes:
22
+ - **Bug fixes**
23
+ - Fix duplicated SMTP command `HELO` in `Sisimai::SMTP::Command`.
24
+ - **Mitigation for potential DoS vectors**
25
+ - #441 Limit the nesting depth of MIME parts in Sisimai::RFC2045 class.
26
+ - **Code improvements**
27
+ - New class `Sisimai::Eb` for keeping constants.
28
+ - #443 `Sisimai::Eb::Re****` Bounce reason names.
29
+ - #447 `Sisimai::Eb::Ce****` SMTP commands.
30
+ - #448 `Sisimai::Eb::Ae****` Action field values.
31
+
7
32
  v5.7.0
8
33
  ---------------------------------------------------------------------------------------------------
9
34
  - release: "Mon, 22 Jun 2026 16:22:22 +0900 (JST)"
data/README-JA.md CHANGED
@@ -11,9 +11,10 @@
11
11
  [^1]: 4系を`clone`する場合は`git clone -b 4-stable https://github.com/sisimai/rb-sisimai.git`
12
12
 
13
13
  > [!CAUTION]
14
- > **Sisimai 4.25.14p11およびそれ以前のバージョンには 正規表現に関する脆弱性
15
- > [ReDoS: CVE-2022-4891](https://jvndb.jvn.jp/ja/contents/2022/JVNDB-2022-005663.html)があります。
16
- > 該当するバージョンをお使いの場合はv4.25.14p12以降へアップグレードしてください。**
14
+ > **Sisimai 4.25.17およびそれ以前の、Sisimai 5.7.1およびそれ以前のバージョンには 正規表現に関する脆弱性
15
+ > [ReDoS: CVE-2022-4891](https://jvndb.jvn.jp/ja/contents/2022/JVNDB-2022-005663.html)
16
+ > [ReDos: CVE-2026-XXXX/番号の発行待ち]()があります。
17
+ > 該当するバージョンをお使いの場合はv4.25.18またはv5.7.2以降へアップグレードしてください。**
17
18
 
18
19
  > [!WARNING]
19
20
  > Sisimai 5はRuby 2.5以上が必要です。インストール/アップグレードを実行する前に`ruby -v`コマンドで
@@ -116,10 +117,10 @@ Install
116
117
  ### From RubyGems.org
117
118
  ```shell
118
119
  $ sudo gem install sisimai
119
- Fetching: sisimai-5.7.0.gem (100%)
120
- Successfully installed sisimai-5.7.0
121
- Parsing documentation for sisimai-5.7.0
122
- Installing ri documentation for sisimai-5.7.0
120
+ Fetching: sisimai-5.7.2.gem (100%)
121
+ Successfully installed sisimai-5.7.2
122
+ Parsing documentation for sisimai-5.7.2
123
+ Installing ri documentation for sisimai-5.7.2
123
124
  Done installing documentation for sisimai after 6 seconds
124
125
  1 gem installed
125
126
  ```
@@ -147,13 +148,13 @@ if [ -d "/usr/local/jr" ]; then \
147
148
  ...
148
149
  3 gems installed
149
150
  /opt/local/bin/rake install
150
- sisimai 5.7.0 built to pkg/sisimai-5.7.0.gem.
151
- sisimai (5.7.0) installed.
151
+ sisimai 5.7.2 built to pkg/sisimai-5.7.2.gem.
152
+ sisimai (5.7.2) installed.
152
153
  if [ -d "/usr/local/jr" ]; then \
153
154
  PATH="/usr/local/jr/bin:$PATH" /usr/local/jr/bin/rake install; \
154
155
  fi
155
- sisimai 5.7.0 built to pkg/sisimai-5.7.0-java.gem.
156
- sisimai (5.7.0) installed.
156
+ sisimai 5.7.2 built to pkg/sisimai-5.7.2-java.gem.
157
+ sisimai (5.7.2) installed.
157
158
  ```
158
159
 
159
160
  Usage
@@ -362,9 +363,9 @@ Sisimai 5.5.0から**Ruby 2.5以上**が必要になります。
362
363
  | 解析エンジン(MTA/ESPモジュール)の数 | 68 | 60 |
363
364
  | 検出可能なバウンス理由の数 | 29 | 34 |
364
365
  | 依存Gem数(Ruby Standard Gemsを除く) | 1 Gem | 1 Gem |
365
- | ソースコードの行数 | 10,800 行 | 9,700 行 |
366
+ | ソースコードの行数 | 10,800 行 | 9,670 行 |
366
367
  | テストフレームワーク | rspec | minitest |
367
- | テスト件数(spec/またはtest/ディレクトリ) | 311,000 件 | 240,000 件 |
368
+ | テスト件数(spec/またはtest/ディレクトリ) | 311,000 件 | 255,000 件 |
368
369
  | 1秒間に解析できるバウンスメール数[^4] | 620 通 | 620 通 |
369
370
  | ライセンス | 2条項BSD | 2条項BSD |
370
371
  | 開発会社による商用サポート | 提供中 | 提供中 |
data/README.md CHANGED
@@ -12,9 +12,9 @@
12
12
  [^1]: Specify `-b 4-stable` when you clone Sisimai 4 for example, `git clone -b 4-stable https://github.com/sisimai/rb-sisimai.git`
13
13
 
14
14
  > [!CAUTION]
15
- > **Sisimai versions 4.25.14p11 and earlier contain a regular expression vulnerability
16
- > [ReDoS: CVE-2022-4891](https://nvd.nist.gov/vuln/detail/CVE-2022-4891).
17
- > If you are using one of these versions, please upgrade to v4.25.14p12 or later.**
15
+ > **Sisimai versions 4.25.17 and earlier, as well as 5.7.1 and earlier, contain regular expression vulnerabilities
16
+ > ([ReDoS: CVE-2022-4891](https://nvd.nist.gov/vuln/detail/CVE-2022-4891), ReDoS: CVE Pending).
17
+ > If you are using affected versions, please upgrade to v4.25.18 or v5.7.2 or later.**
18
18
 
19
19
  > [!WARNING]
20
20
  > Sisimai 5 requires Ruby 2.5 or later. Check the version of Ruby in your system before installing/upgrading
@@ -115,10 +115,10 @@ Install
115
115
  ### From RubyGems
116
116
  ```shell
117
117
  $ sudo gem install sisimai
118
- Fetching: sisimai-5.7.0.gem (100%)
119
- Successfully installed sisimai-5.7.0
120
- Parsing documentation for sisimai-5.7.0
121
- Installing ri documentation for sisimai-5.7.0
118
+ Fetching: sisimai-5.7.2.gem (100%)
119
+ Successfully installed sisimai-5.7.2
120
+ Parsing documentation for sisimai-5.7.2
121
+ Installing ri documentation for sisimai-5.7.2
122
122
  Done installing documentation for sisimai after 6 seconds
123
123
  1 gem installed
124
124
  ```
@@ -146,13 +146,13 @@ if [ -d "/usr/local/jr" ]; then \
146
146
  ...
147
147
  3 gems installed
148
148
  /opt/local/bin/rake install
149
- sisimai 5.7.0 built to pkg/sisimai-5.7.0.gem.
150
- sisimai (5.7.0) installed.
149
+ sisimai 5.7.2 built to pkg/sisimai-5.7.2.gem.
150
+ sisimai (5.7.2) installed.
151
151
  if [ -d "/usr/local/jr" ]; then \
152
152
  PATH="/usr/local/jr/bin:$PATH" /usr/local/jr/bin/rake install; \
153
153
  fi
154
- sisimai 5.7.0 built to pkg/sisimai-5.7.0-java.gem.
155
- sisimai (5.7.0) installed.
154
+ sisimai 5.7.2 built to pkg/sisimai-5.7.2-java.gem.
155
+ sisimai (5.7.2) installed.
156
156
  ```
157
157
 
158
158
  Usage
@@ -361,7 +361,7 @@ Beginning with v5.5.0, Sisimai requires **Ruby 2.5.0 or later.**
361
361
  | The number of MTA/ESP modules | 68 | 61 |
362
362
  | The number of detectable bounce reasons | 29 | 34 |
363
363
  | Dependencies (Except Ruby Standard Gems) | 1 gem | 1 gem |
364
- | Source lines of code | 10,300 lines | 9,500 lines |
364
+ | Source lines of code | 10,300 lines | 9,670 lines |
365
365
  | Test frameworks | rspec | minitest |
366
366
  | The number of tests in spec/ or test/ directory | 311,000 tests | 255,000 tests |
367
367
  | The number of bounce emails decoded/sec (CRuby)[^4] | 620 emails | 620 emails |
data/lib/sisimai/arf.rb CHANGED
@@ -2,6 +2,7 @@ module Sisimai
2
2
  # Sisimai::ARF is a decoder for the email returned as a FeedBack Loop report message.
3
3
  module ARF
4
4
  class << self
5
+ require 'sisimai/eb'
5
6
  require 'sisimai/lhost'
6
7
  require 'sisimai/rfc5322'
7
8
 
@@ -220,7 +221,7 @@ module Sisimai
220
221
  # Tidy up the error message in e.Diagnosis, Try to detect the bounce reason.
221
222
  j += 1
222
223
  e["diagnosis"] = e["diagnosis"] + anotherone
223
- e["reason"] = "feedback"
224
+ e["reason"] = Sisimai::Eb::ReFEED
224
225
  e["rhost"] = remotehost
225
226
  e["lhost"] = reportedby
226
227
  e["date"] = timestamp0
data/lib/sisimai/eb.rb ADDED
@@ -0,0 +1,116 @@
1
+ module Sisimai
2
+ # Sisimai::Eb - Package "eb" provides constants for the email bounce.
3
+ module Eb
4
+ # _ ______
5
+ # ___| |__ / / _ \ ___ __ _ ___ ___ _ __
6
+ # / _ \ '_ \ / /| |_) / _ \/ _` / __|/ _ \| '_ \
7
+ # | __/ |_) / / | _ < __/ (_| \__ \ (_) | | | |
8
+ # \___|_.__/_/ |_| \_\___|\__,_|___/\___/|_| |_|
9
+ # bounce reason names
10
+ ReAUTH = "AuthFailure"
11
+ ReFAMA = "BadReputation"
12
+ ReBLOC = "Blocked"
13
+ ReBODY = "ContentError"
14
+ ReSENT = "Delivered"
15
+ ReSIZE = "EmailTooLarge"
16
+ ReTIME = "Expired"
17
+ ReTTLS = "FailedSTARTTLS"
18
+ ReFEED = "Feedback"
19
+ ReFILT = "Filtered"
20
+ ReMOVE = "HasMoved"
21
+ ReHOST = "HostUnknown"
22
+ ReFULL = "MailboxFull"
23
+ ReUNIX = "MailerError"
24
+ ReINET = "NetworkError"
25
+ RePASS = "NoRelaying"
26
+ Re00MX = "NotAccept"
27
+ ReNRFC = "NotCompliantRFC"
28
+ Re___1 = "OnHold"
29
+ ReWONT = "PolicyViolation"
30
+ ReFROM = "Rejected"
31
+ ReQPTR = "RequirePTR"
32
+ ReRATE = "RateLimited"
33
+ ReSAFE = "SecurityError"
34
+ ReSPAM = "SpamDetected"
35
+ ReSTOP = "Suppressed"
36
+ ReQUIT = "Suspend"
37
+ ReCOMM = "SyntaxError"
38
+ RePROC = "SystemError"
39
+ ReDISK = "SystemFull"
40
+ Re___0 = "Undefined"
41
+ ReUSER = "UserUnknown"
42
+ ReAWAY = "Vacation"
43
+ ReEXEC = "VirusDetected"
44
+
45
+ # _ ______ _
46
+ # ___| |__ / / ___|___ _ __ ___ _ __ ___ __ _ _ __ __| |
47
+ # / _ \ '_ \ / / | / _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` |
48
+ # | __/ |_) / /| |__| (_) | | | | | | | | | | | (_| | | | | (_| |
49
+ # \___|_.__/_/ \____\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|
50
+ CeHELO = "HELO"
51
+ CeEHLO = "EHLO"
52
+ CeMAIL = "MAIL"
53
+ CeRCPT = "RCPT"
54
+ CeDATA = "DATA"
55
+ CeQUIT = "QUIT"
56
+ CeRSET = "RSET"
57
+ CeNOOP = "NOOP"
58
+ CeVRFY = "VRFY"
59
+ CeETRN = "ETRN"
60
+ CeEXPN = "EXPN"
61
+ CeHELP = "HELP"
62
+ CeAUTH = "AUTH"
63
+ CeTTLS = "STARTTLS"
64
+ CeXFWD = "XFORWARD"
65
+ CeCONN = "CONN" # CONN is a pseudo SMTP command used only in Sisimai
66
+
67
+ # _ ___ _ _
68
+ # ___| |__ / / \ ___| |_(_) ___ _ __
69
+ # / _ \ '_ \ / / _ \ / __| __| |/ _ \| '_ \
70
+ # | __/ |_) / / ___ \ (__| |_| | (_) | | | |
71
+ # \___|_.__/_/_/ \_\___|\__|_|\___/|_| |_|
72
+ #
73
+ # https://datatracker.ietf.org/doc/html/rfc3464#page-16
74
+ # 2.3.3 Action field
75
+ # The Action field indicates the action performed by the Reporting-MTA as a result of its attempt
76
+ # to deliver the message to this recipient address. This field MUST be present for each recipient
77
+ # named in the DSN.
78
+ #
79
+ # The syntax for the action-field is:
80
+ # action-field = "Action" ":" action-value
81
+ # action-value = "failed" / "delayed" / "delivered" / "relayed" / "expanded"
82
+ #
83
+ # The action-value may be spelled in any combination of upper and lower case characters.
84
+ #
85
+ # "failed" indicates that the message could not be delivered to the recipient.
86
+ # The Reporting MTA has abandoned any attempts to deliver the message to this
87
+ # recipient. No further notifications should be expected.
88
+ #
89
+ # "delayed" indicates that the Reporting MTA has so far been unable to deliver or relay the
90
+ # message, but it will continue to attempt to do so. Additional notification
91
+ # messages may be issued as the message is further delayed or successfully
92
+ # delivered, or if delivery attempts are later abandoned.
93
+ #
94
+ # "delivered" indicates that the message was successfully delivered to the recipient address
95
+ # specified by the sender, which includes "delivery" to a mailing list exploder.
96
+ # It does not indicate that the message has been read. This is a terminal state
97
+ # and no further DSN for this recipient should be expected.
98
+ #
99
+ # "relayed" indicates that the message has been relayed or gatewayed into an environment
100
+ # that does not accept responsibility for generating DSNs upon successful delivery.
101
+ # This action-value SHOULD NOT be used unless the sender has requested notification
102
+ # of successful delivery for this recipient.
103
+ #
104
+ # "expanded" indicates that the message has been successfully delivered to the recipient
105
+ # address as specified by the sender, and forwarded by the Reporting-MTA beyond
106
+ # that destination to multiple additional recipient addresses. An action-value of
107
+ # "expanded" differs from "delivered" in that "expanded" is not a terminal state.
108
+ # Further "failed" and/or "delayed" notifications may be provided.
109
+ AeFAIL = "failed"
110
+ AeSTAY = "delayed"
111
+ AeSENT = "delivered"
112
+ AePASS = "relayed"
113
+ AeEXPN = "expanded"
114
+ end
115
+ end
116
+
data/lib/sisimai/fact.rb CHANGED
@@ -15,6 +15,7 @@ module Sisimai
15
15
  require 'sisimai/string'
16
16
  require 'sisimai/rhost'
17
17
  require 'sisimai/lda'
18
+ require 'sisimai/eb'
18
19
 
19
20
  @@rwaccessors = [
20
21
  :action, # [String] The value of Action: header
@@ -122,7 +123,7 @@ module Sisimai
122
123
  while e = deliveries.shift do
123
124
  # Create parameters for each Sisimai::Fact object
124
125
  next if e['recipient'].size < 5
125
- next if ! argvs[:vacation] && e['reason'] == 'vacation'
126
+ next if ! argvs[:vacation] && e['reason'] == Sisimai::Eb::ReAWAY
126
127
  next if ! argvs[:delivered] && e['status'].start_with?('2.')
127
128
 
128
129
  thing = {} # To be passed to each accessor of Sisimai::Fact
@@ -353,7 +354,7 @@ module Sisimai
353
354
  piece['diagnosticcode'] = piece['diagnosticcode'].force_encoding('UTF-8').scrub('?')
354
355
  end
355
356
 
356
- piece["diagnostictype"] = "X-UNIX" if piece["reason"] == "mailererror"
357
+ piece["diagnostictype"] = "X-UNIX" if piece["reason"] == Sisimai::Eb::ReUNIX
357
358
  if piece["diagnostictype"].empty?
358
359
  piece["diagnostictype"] = "SMTP" if %w[feedback vacation].include?(piece["reason"]) == false
359
360
  end
@@ -363,7 +364,7 @@ module Sisimai
363
364
  # - <<< 503-5.5.1 RCPT first. A mail transaction protocol command was issued ...
364
365
  # - RCPT first (in reply to DATA command)
365
366
  piece['command'] = '' if Sisimai::SMTP::Command.test(piece['command']) == false
366
- piece['command'] = 'RCPT' if piece['diagnosticcode'].include?('RCPT first')
367
+ piece['command'] = Sisimai::Eb::CeRCPT if piece['diagnosticcode'].include?('RCPT first')
367
368
 
368
369
  # Create parameters for the constructor
369
370
  as = Sisimai::Address.new(piece['addresser']) || next; next if as.void
@@ -384,14 +385,14 @@ module Sisimai
384
385
  ea.each { |q| thing[q] = piece[q] if thing[q].nil? || thing[q].empty? }
385
386
 
386
387
  # Other accessors
387
- thing['bogus'] = 0
388
+ thing['bogus'] = -1
388
389
  thing['catch'] = piece['catch'] || nil
389
390
  thing["feedbackid"] = ""
390
391
  thing['hardbounce'] = piece['hardbounce']
391
392
  thing['replycode'] = Sisimai::SMTP::Reply.find(piece['diagnosticcode']) if thing['replycode'].empty?
392
393
  thing['timestamp'] = TimeModule.parse(::Time.at(piece['timestamp']).to_s)
393
394
  thing['timezoneoffset'] = piece['timezoneoffset'] || '+0000'
394
- thing['toxic'] = 0
395
+ thing['toxic'] = -1
395
396
  ea.each { |q| thing[q] = piece[q] if thing[q].empty? }
396
397
 
397
398
  # ALIAS
@@ -422,25 +423,30 @@ module Sisimai
422
423
  while true
423
424
  if thing["reason"].empty? || RetryIndex[thing["reason"]]
424
425
  # The value of "reason" is empty or is needed to check with other values again
425
- re = thing["reason"].empty? ? "undefined" : thing["reason"]
426
+ re = thing["reason"].empty? ? Sisimai::Eb::Re___0 : thing["reason"]
426
427
  cr = Sisimai::LDA.find(thing); if Sisimai::Reason.is_explicit(cr) then thing["reason"] = cr; break; end
427
428
  cr = Sisimai::Rhost.find(thing); if Sisimai::Reason.is_explicit(cr) then thing["reason"] = cr; break; end
428
429
  cr = Sisimai::Reason.find(thing); if Sisimai::Reason.is_explicit(cr) then thing["reason"] = cr; break; end
429
- thing["reason"] = thing["diagnosticcode"].size > 0 ? "onhold" : re
430
+ thing["reason"] = thing["diagnosticcode"].size > 0 ? Sisimai::Eb::Re___1 : re
430
431
  break
431
432
  end
432
433
  break
433
434
  end
434
435
 
435
- # HARDBOUNCE: Set the value of "hardbounce", default value of "bouncebounce" is false
436
- if thing['reason'] == 'delivered' || thing['reason'] == 'feedback' || thing['reason'] == 'vacation'
437
- # Delete the value of ReplyCode when the Reason is "feedback" or "vacation"
438
- thing['replycode'] = '' if thing['reason'] != 'delivered'
439
- else
440
- # The reason is not "delivered", or "feedback", or "vacation"
436
+ while true
437
+ # HARDBOUNCE: Set the value of "hardbounce", default value of "bouncebounce" is false
438
+ break if thing['reason'] == Sisimai::Eb::ReSENT
439
+ if thing['reason'] == Sisimai::Eb::ReFEED || thing['reason'] == Sisimai::Eb::ReAWAY
440
+ # Delete the value of ReplyCode when the Reason is "Feedback" or "Vacation"
441
+ thing['replycode'] = ""
442
+ break
443
+ end
444
+
445
+ # The reason is not "Delivered", or "Feedback", or "Vacation"
441
446
  smtperrors = "#{piece['deliverystatus']} #{piece['diagnosticcode']}"
442
447
  smtperrors = '' if smtperrors.size < 4
443
448
  thing['hardbounce'] = Sisimai::SMTP::Failure.is_hardbounce(thing['reason'], smtperrors)
449
+ break
444
450
  end
445
451
 
446
452
  # DELIVERYSTATUS: Set a pseudo status code if the value of "deliverystatus" is empty
@@ -472,10 +478,10 @@ module Sisimai
472
478
  thing['action'] = ox[2]
473
479
  end
474
480
  end
475
- thing["action"] = "" if thing["action"].nil?
476
- thing["action"] = "delivered" if thing["action"].empty? && thing["reason"] == "delivered"
477
- thing["action"] = "delayed" if thing["action"].empty? && thing["reason"] == "expired"
478
- thing["action"] = "failed" if thing["action"].empty? && cx[0] == "4" || cx[0] == "5"
481
+ thing["action"] = "" if thing["action"].nil?
482
+ thing["action"] = Sisimai::Eb::AeSENT if thing["action"].empty? && thing["reason"] == Sisimai::Eb::ReSENT
483
+ thing["action"] = Sisimai::Eb::AeSTAY if thing["action"].empty? && thing["reason"] == Sisimai::Eb::ReTIME
484
+ thing["action"] = Sisimai::Eb::AeFAIL if thing["action"].empty? && cx[0] == "4" || cx[0] == "5"
479
485
 
480
486
  if thing["replycode"].size > 0
481
487
  # Fill empty values: ["SMTP Command", "DSN", "Reason"]
@@ -489,6 +495,7 @@ module Sisimai
489
495
 
490
496
  # Feedback-ID: 1.us-west-2.QHuyeCQrGtIIMGKQfVdUhP9hCQR2LglVOrRamBc+Prk=:AmazonSES
491
497
  thing["feedbackid"] = rfc822data["feedback-id"] || ""
498
+ thing["reason"] = thing["reason"].downcase
492
499
 
493
500
  listoffact << Sisimai::Fact.new(thing)
494
501
  end
data/lib/sisimai/lda.rb CHANGED
@@ -2,6 +2,8 @@ module Sisimai
2
2
  # Sisimai::LDA - Error message decoder for LDA
3
3
  module LDA
4
4
  class << self
5
+ require 'sisimai/eb'
6
+
5
7
  LocalAgent = {
6
8
  # Each error message should be a lower-cased string
7
9
  # dovecot/src/deliver/deliver.c
@@ -19,20 +21,20 @@ module Sisimai
19
21
  # Each error message should be a lower-cased string
20
22
  "dovecot" => {
21
23
  # dovecot/src/deliver/mail-send.c:94
22
- "mailboxfull" => [
24
+ Sisimai::Eb::ReFULL => [
23
25
  "not enough disk space",
24
26
  "quota exceeded", # Dovecot 1.2 dovecot/src/plugins/quota/quota.c
25
27
  "quota exceeded (mailbox for user is full)", # dovecot/src/plugins/quota/quota.c
26
28
  ],
27
- "userunknown" => ["mailbox doesn't exist: "],
29
+ Sisimai::Eb::ReUSER => ["mailbox doesn't exist: "],
28
30
  },
29
31
  "mail.local" => {
30
- "mailboxfull" => [
32
+ Sisimai::Eb::ReFULL => [
31
33
  "disc quota exceeded",
32
34
  "mailbox full or quota exceeded",
33
35
  ],
34
- "systemerror" => ["temporary file write error"],
35
- "userunknown" => [
36
+ Sisimai::Eb::RePROC => ["temporary file write error"],
37
+ Sisimai::Eb::ReUSER => [
36
38
  ": invalid mailbox path",
37
39
  ": unknown user:",
38
40
  ": user missing home directory",
@@ -40,23 +42,23 @@ module Sisimai
40
42
  ],
41
43
  },
42
44
  "procmail" => {
43
- "mailboxfull" => ["quota exceeded while writing", "user over quota"],
44
- "systemerror" => ["service unavailable"],
45
- "systemfull" => ["no space left to finish writing"],
45
+ Sisimai::Eb::ReFULL => ["quota exceeded while writing", "user over quota"],
46
+ Sisimai::Eb::RePROC => ["service unavailable"],
47
+ Sisimai::Eb::ReDISK => ["no space left to finish writing"],
46
48
  },
47
49
  "maildrop" => {
48
- "userunknown" => ["cannot find system user", "invalid user specified."],
49
- "mailboxfull" => ["maildir over quota."],
50
+ Sisimai::Eb::ReUSER => ["cannot find system user", "invalid user specified."],
51
+ Sisimai::Eb::ReFULL => ["maildir over quota."],
50
52
  },
51
53
  "vpopmail" => {
52
- "filtered" => ["user does not exist, but will deliver to "],
53
- "mailboxfull" => ["domain is over quota", "user is over quota"],
54
- "suspend" => ["account is locked email bounced"],
55
- "userunknown" => ["sorry, no mailbox here by that name."],
54
+ Sisimai::Eb::ReFILT => ["user does not exist, but will deliver to "],
55
+ Sisimai::Eb::ReFULL => ["domain is over quota", "user is over quota"],
56
+ Sisimai::Eb::ReQUIT => ["account is locked email bounced"],
57
+ Sisimai::Eb::ReUSER => ["sorry, no mailbox here by that name."],
56
58
  },
57
59
  "vmailmgr" => {
58
- "mailboxfull" => ["delivery failed due to system quota violation"],
59
- "userunknown" => [
60
+ Sisimai::Eb::ReFULL => ["delivery failed due to system quota violation"],
61
+ Sisimai::Eb::ReUSER => [
60
62
  "invalid or unknown base user or domain",
61
63
  "invalid or unknown virtual user",
62
64
  "user name does not refer to a virtual user",
@@ -70,7 +72,7 @@ module Sisimai
70
72
  def find(argvs)
71
73
  return "" if argvs.nil?
72
74
  return "" if argvs["diagnosticcode"].empty?
73
- return "" if argvs["command"] != "" && argvs["command"] != "DATA"
75
+ return "" if argvs["command"] != "" && argvs["command"] != Sisimai::Eb::CeDATA
74
76
 
75
77
  deliversby = "" # [String] Local Delivery Agent name
76
78
  reasontext = "" # [String] Error reason
@@ -89,7 +91,7 @@ module Sisimai
89
91
  reasontext = e; break
90
92
  end
91
93
 
92
- reasontext = "mailererror" if reasontext.empty?
94
+ reasontext = Sisimai::Eb::ReUNIX if reasontext.empty?
93
95
  return reasontext
94
96
  end
95
97
  end
@@ -42,16 +42,17 @@ module Sisimai::Lhost
42
42
  # Transient/ContentRejected -- message you sent contains content that the provider doesn't allow
43
43
  # Transient/AttachmentRejected the message contained an unacceptable attachment
44
44
  class << self
45
+ require 'sisimai/eb'
45
46
  require 'sisimai/lhost'
46
47
 
47
48
  ReasonPair = {
48
- "Suppressed" => "suppressed",
49
- "OnAccountSuppressionList" => "suppressed",
50
- "General" => "onhold",
51
- "MailboxFull" => "mailboxfull",
52
- "MessageTooLarge" => "emailtoolarge",
53
- "ContentRejected" => "contenterror",
54
- "AttachmentRejected" => "securityerror",
49
+ "Suppressed" => Sisimai::Eb::ReSTOP,
50
+ "OnAccountSuppressionList" => Sisimai::Eb::ReSTOP,
51
+ "General" => Sisimai::Eb::Re___1,
52
+ "MailboxFull" => Sisimai::Eb::ReFULL,
53
+ "MessageTooLarge" => Sisimai::Eb::ReSIZE,
54
+ "ContentRejected" => Sisimai::Eb::ReBODY,
55
+ "AttachmentRejected" => Sisimai::Eb::ReSAFE,
55
56
  }.freeze
56
57
 
57
58
  # @abstract Decodes the bounce message from Amazon SES
@@ -164,7 +165,7 @@ module Sisimai::Lhost
164
165
  v = dscontents[-1]
165
166
  end
166
167
  v["recipient"] = e["emailAddress"]
167
- v["reason"] = "feedback"
168
+ v["reason"] = Sisimai::Eb::ReFEED
168
169
  v["feedbacktype"] = p["complaintFeedbackType"]
169
170
  v["date"] = p["timestamp"]
170
171
  v["diagnosis"] = sprintf('"feedbackid":"%s", "useragent":"%s"}', p["feedbackId"], p["userAgent"])
@@ -181,8 +182,8 @@ module Sisimai::Lhost
181
182
  v = dscontents[-1]
182
183
  end
183
184
  v["recipient"] = e
184
- v["reason"] = "delivered"
185
- v["action"] = "delivered"
185
+ v["reason"] = Sisimai::Eb::ReSENT
186
+ v["action"] = Sisimai::Eb::AeSENT
186
187
  v["date"] = p["timestamp"]
187
188
  v["lhost"] = Sisimai::RFC1123.find(p["reportingMTA"])
188
189
  v["diagnosis"] = p["smtpResponse"]
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Courier
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  # https://www.courier-mta.org/courierdsn.html
@@ -14,12 +15,12 @@ module Sisimai::Lhost
14
15
  }.freeze
15
16
  MessagesOf = {
16
17
  # courier/module.esmtp/esmtpclient.c:526| hard_error(del, ctf, "No such domain.");
17
- 'hostunknown' => ['No such domain.'],
18
+ Sisimai::Eb::ReHOST => ['No such domain.'],
18
19
  # courier/module.esmtp/esmtpclient.c:531| hard_error(del, ctf,
19
20
  # courier/module.esmtp/esmtpclient.c:532| "This domain's DNS violates RFC 1035.");
20
- 'systemerror' => ["This domain's DNS violates RFC 1035."],
21
+ Sisimai::Eb::RePROC => ["This domain's DNS violates RFC 1035."],
21
22
  # courier/module.esmtp/esmtpclient.c:535| soft_error(del, ctf, "DNS lookup failed.");
22
- 'networkerror' => ['DNS lookup failed.'],
23
+ Sisimai::Eb::ReINET => ['DNS lookup failed.'],
23
24
  }.freeze
24
25
 
25
26
  # @abstract Decodes the bounce message from Courier MTA
@@ -3,13 +3,14 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module Domino
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
9
10
  Boundaries = ['Content-Type: message/rfc822'].freeze
10
11
  StartingOf = {message: ['Your message']}.freeze
11
12
  MessagesOf = {
12
- "userunknown" => [
13
+ Sisimai::Eb::ReUSER => [
13
14
  "not listed in Domino Directory",
14
15
  "not listed in public Name & Address Book",
15
16
  "non répertorié dans l'annuaire Domino",
@@ -3,6 +3,7 @@ module Sisimai::Lhost
3
3
  # Methods in the module are called from only Sisimai::Message.
4
4
  module EinsUndEins
5
5
  class << self
6
+ require 'sisimai/eb'
6
7
  require 'sisimai/lhost'
7
8
 
8
9
  Indicators = Sisimai::Lhost.INDICATORS
@@ -90,8 +91,8 @@ module Sisimai::Lhost
90
91
  p2 = e['diagnosis'].index(' reason:')
91
92
 
92
93
  e['rhost'] = e['diagnosis'][p1 + 6, p2 - p1 - 6]
93
- e['command'] = 'DATA' if e['diagnosis'].include?('for TEXT command')
94
- e['spec'] = 'SMTP' if e['diagnosis'].include?('SMTP error')
94
+ e['command'] = Sisimai::Eb::CeDATA if e['diagnosis'].include?('for TEXT command')
95
+ e['spec'] = 'SMTP' if e['diagnosis'].include?('SMTP error')
95
96
  e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
96
97
  else
97
98
  # For the following reason: