@serve.zone/dcrouter 2.12.4 → 5.0.2

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 (722) hide show
  1. package/.playwright-mcp/dcrouter-scrollbar-issue.png +0 -0
  2. package/.playwright-mcp/page-2026-02-01T23-10-23-737Z.png +0 -0
  3. package/.playwright-mcp/page-2026-02-01T23-11-19-449Z.png +0 -0
  4. package/.playwright-mcp/page-2026-02-01T23-12-03-126Z.png +0 -0
  5. package/.playwright-mcp/page-2026-02-01T23-12-15-576Z.png +0 -0
  6. package/changelog.md +103 -0
  7. package/npmextra.json +36 -2
  8. package/package.json +60 -46
  9. package/readme.hints.md +537 -670
  10. package/readme.md +659 -937
  11. package/test/test.contentscanner.ts +1 -1
  12. package/test/test.dcrouter.email.ts +70 -112
  13. package/test/test.dns-socket-handler.ts +75 -96
  14. package/test/test.errors.ts +3 -137
  15. package/test/test.jwt-auth.ts +1 -0
  16. package/test/test.opsserver-api.ts +1 -0
  17. package/test/test.protected-endpoint.ts +43 -38
  18. package/test_watch/devserver.ts +35 -0
  19. package/ts/00_commitinfo_data.ts +3 -3
  20. package/ts/cache/classes.cache.cleaner.ts +166 -0
  21. package/ts/cache/classes.cached.document.ts +111 -0
  22. package/ts/cache/classes.cachedb.ts +154 -0
  23. package/ts/cache/documents/classes.cached.email.ts +240 -0
  24. package/ts/cache/documents/classes.cached.ip.reputation.ts +247 -0
  25. package/ts/cache/documents/index.ts +2 -0
  26. package/ts/cache/index.ts +7 -0
  27. package/ts/classes.dcrouter.ts +229 -162
  28. package/ts/errors/index.ts +0 -2
  29. package/ts/index.ts +8 -2
  30. package/ts/monitoring/classes.metricscache.ts +75 -0
  31. package/ts/monitoring/classes.metricsmanager.ts +522 -0
  32. package/ts/monitoring/index.ts +1 -0
  33. package/ts/opsserver/classes.opsserver.ts +5 -1
  34. package/ts/opsserver/handlers/admin.handler.ts +1 -1
  35. package/ts/opsserver/handlers/config.handler.ts +16 -58
  36. package/ts/opsserver/handlers/email-ops.handler.ts +318 -0
  37. package/ts/opsserver/handlers/index.ts +3 -1
  38. package/ts/opsserver/handlers/radius.handler.ts +405 -0
  39. package/ts/opsserver/handlers/security.handler.ts +115 -6
  40. package/ts/opsserver/handlers/stats.handler.ts +177 -18
  41. package/ts/paths.ts +9 -9
  42. package/ts/plugins.ts +73 -11
  43. package/ts/radius/classes.accounting.manager.ts +607 -0
  44. package/ts/radius/classes.radius.server.ts +532 -0
  45. package/ts/radius/classes.vlan.manager.ts +363 -0
  46. package/ts/radius/index.ts +14 -0
  47. package/ts/security/classes.contentscanner.ts +2 -2
  48. package/ts/security/classes.ipreputationchecker.ts +2 -2
  49. package/ts/sms/classes.smsservice.ts +7 -9
  50. package/ts/storage/classes.storagemanager.ts +3 -3
  51. package/ts_interfaces/data/stats.ts +30 -0
  52. package/ts_interfaces/readme.md +205 -0
  53. package/ts_interfaces/requests/combined.stats.ts +25 -0
  54. package/ts_interfaces/requests/config.ts +1 -18
  55. package/ts_interfaces/requests/email-ops.ts +239 -0
  56. package/ts_interfaces/requests/index.ts +4 -1
  57. package/ts_interfaces/requests/radius.ts +329 -0
  58. package/ts_web/00_commitinfo_data.ts +3 -3
  59. package/ts_web/appstate.ts +523 -85
  60. package/ts_web/elements/index.ts +2 -1
  61. package/ts_web/elements/ops-dashboard.ts +117 -52
  62. package/ts_web/elements/ops-view-config.ts +236 -118
  63. package/ts_web/elements/ops-view-emails.ts +818 -0
  64. package/ts_web/elements/ops-view-logs.ts +14 -14
  65. package/ts_web/elements/ops-view-network.ts +580 -0
  66. package/ts_web/elements/ops-view-overview.ts +196 -110
  67. package/ts_web/elements/ops-view-security.ts +155 -96
  68. package/ts_web/elements/shared/ops-sectionheading.ts +1 -5
  69. package/ts_web/index.ts +4 -0
  70. package/ts_web/readme.md +211 -0
  71. package/ts_web/router.ts +181 -0
  72. package/tsconfig.json +0 -3
  73. package/dist_ts/00_commitinfo_data.d.ts +0 -8
  74. package/dist_ts/00_commitinfo_data.js +0 -9
  75. package/dist_ts/classes.dcrouter.d.ts +0 -238
  76. package/dist_ts/classes.dcrouter.js +0 -1008
  77. package/dist_ts/config/index.d.ts +0 -1
  78. package/dist_ts/config/index.js +0 -3
  79. package/dist_ts/config/validator.d.ts +0 -104
  80. package/dist_ts/config/validator.js +0 -152
  81. package/dist_ts/deliverability/classes.ipwarmupmanager.d.ts +0 -253
  82. package/dist_ts/deliverability/classes.ipwarmupmanager.js +0 -639
  83. package/dist_ts/deliverability/classes.senderreputationmonitor.d.ts +0 -300
  84. package/dist_ts/deliverability/classes.senderreputationmonitor.js +0 -961
  85. package/dist_ts/deliverability/index.d.ts +0 -2
  86. package/dist_ts/deliverability/index.js +0 -3
  87. package/dist_ts/errors/base.errors.d.ts +0 -224
  88. package/dist_ts/errors/base.errors.js +0 -310
  89. package/dist_ts/errors/email.errors.d.ts +0 -175
  90. package/dist_ts/errors/email.errors.js +0 -265
  91. package/dist_ts/errors/error-handler.d.ts +0 -98
  92. package/dist_ts/errors/error-handler.js +0 -282
  93. package/dist_ts/errors/error.codes.d.ts +0 -115
  94. package/dist_ts/errors/error.codes.js +0 -136
  95. package/dist_ts/errors/index.d.ts +0 -56
  96. package/dist_ts/errors/index.js +0 -138
  97. package/dist_ts/errors/mta.errors.d.ts +0 -259
  98. package/dist_ts/errors/mta.errors.js +0 -472
  99. package/dist_ts/errors/reputation.errors.d.ts +0 -183
  100. package/dist_ts/errors/reputation.errors.js +0 -292
  101. package/dist_ts/index.d.ts +0 -4
  102. package/dist_ts/index.js +0 -6
  103. package/dist_ts/logger.d.ts +0 -17
  104. package/dist_ts/logger.js +0 -77
  105. package/dist_ts/mail/core/classes.bouncemanager.d.ts +0 -200
  106. package/dist_ts/mail/core/classes.bouncemanager.js +0 -778
  107. package/dist_ts/mail/core/classes.email.d.ts +0 -291
  108. package/dist_ts/mail/core/classes.email.js +0 -780
  109. package/dist_ts/mail/core/classes.emailvalidator.d.ts +0 -61
  110. package/dist_ts/mail/core/classes.emailvalidator.js +0 -182
  111. package/dist_ts/mail/core/classes.templatemanager.d.ts +0 -95
  112. package/dist_ts/mail/core/classes.templatemanager.js +0 -239
  113. package/dist_ts/mail/core/index.d.ts +0 -4
  114. package/dist_ts/mail/core/index.js +0 -6
  115. package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +0 -163
  116. package/dist_ts/mail/delivery/classes.delivery.queue.js +0 -485
  117. package/dist_ts/mail/delivery/classes.delivery.system.d.ts +0 -186
  118. package/dist_ts/mail/delivery/classes.delivery.system.js +0 -846
  119. package/dist_ts/mail/delivery/classes.emailsendjob.d.ts +0 -84
  120. package/dist_ts/mail/delivery/classes.emailsendjob.js +0 -362
  121. package/dist_ts/mail/delivery/classes.emailsignjob.d.ts +0 -18
  122. package/dist_ts/mail/delivery/classes.emailsignjob.js +0 -44
  123. package/dist_ts/mail/delivery/classes.mta.config.d.ts +0 -22
  124. package/dist_ts/mail/delivery/classes.mta.config.js +0 -51
  125. package/dist_ts/mail/delivery/classes.ratelimiter.d.ts +0 -98
  126. package/dist_ts/mail/delivery/classes.ratelimiter.js +0 -205
  127. package/dist_ts/mail/delivery/classes.smtp.client.legacy.d.ts +0 -275
  128. package/dist_ts/mail/delivery/classes.smtp.client.legacy.js +0 -973
  129. package/dist_ts/mail/delivery/classes.unified.rate.limiter.d.ts +0 -200
  130. package/dist_ts/mail/delivery/classes.unified.rate.limiter.js +0 -817
  131. package/dist_ts/mail/delivery/index.d.ts +0 -12
  132. package/dist_ts/mail/delivery/index.js +0 -18
  133. package/dist_ts/mail/delivery/interfaces.d.ts +0 -243
  134. package/dist_ts/mail/delivery/interfaces.js +0 -17
  135. package/dist_ts/mail/delivery/smtpclient/auth-handler.d.ts +0 -43
  136. package/dist_ts/mail/delivery/smtpclient/auth-handler.js +0 -188
  137. package/dist_ts/mail/delivery/smtpclient/command-handler.d.ts +0 -67
  138. package/dist_ts/mail/delivery/smtpclient/command-handler.js +0 -276
  139. package/dist_ts/mail/delivery/smtpclient/connection-manager.d.ts +0 -48
  140. package/dist_ts/mail/delivery/smtpclient/connection-manager.js +0 -238
  141. package/dist_ts/mail/delivery/smtpclient/constants.d.ts +0 -129
  142. package/dist_ts/mail/delivery/smtpclient/constants.js +0 -135
  143. package/dist_ts/mail/delivery/smtpclient/create-client.d.ts +0 -22
  144. package/dist_ts/mail/delivery/smtpclient/create-client.js +0 -86
  145. package/dist_ts/mail/delivery/smtpclient/error-handler.d.ts +0 -28
  146. package/dist_ts/mail/delivery/smtpclient/error-handler.js +0 -110
  147. package/dist_ts/mail/delivery/smtpclient/index.d.ts +0 -16
  148. package/dist_ts/mail/delivery/smtpclient/index.js +0 -21
  149. package/dist_ts/mail/delivery/smtpclient/interfaces.d.ts +0 -183
  150. package/dist_ts/mail/delivery/smtpclient/interfaces.js +0 -19
  151. package/dist_ts/mail/delivery/smtpclient/smtp-client.d.ts +0 -58
  152. package/dist_ts/mail/delivery/smtpclient/smtp-client.js +0 -279
  153. package/dist_ts/mail/delivery/smtpclient/tls-handler.d.ts +0 -33
  154. package/dist_ts/mail/delivery/smtpclient/tls-handler.js +0 -202
  155. package/dist_ts/mail/delivery/smtpclient/utils/helpers.d.ts +0 -77
  156. package/dist_ts/mail/delivery/smtpclient/utils/helpers.js +0 -196
  157. package/dist_ts/mail/delivery/smtpclient/utils/logging.d.ts +0 -46
  158. package/dist_ts/mail/delivery/smtpclient/utils/logging.js +0 -153
  159. package/dist_ts/mail/delivery/smtpclient/utils/validation.d.ts +0 -38
  160. package/dist_ts/mail/delivery/smtpclient/utils/validation.js +0 -139
  161. package/dist_ts/mail/delivery/smtpserver/certificate-utils.d.ts +0 -45
  162. package/dist_ts/mail/delivery/smtpserver/certificate-utils.js +0 -345
  163. package/dist_ts/mail/delivery/smtpserver/command-handler.d.ts +0 -156
  164. package/dist_ts/mail/delivery/smtpserver/command-handler.js +0 -1159
  165. package/dist_ts/mail/delivery/smtpserver/connection-manager.d.ts +0 -159
  166. package/dist_ts/mail/delivery/smtpserver/connection-manager.js +0 -894
  167. package/dist_ts/mail/delivery/smtpserver/constants.d.ts +0 -130
  168. package/dist_ts/mail/delivery/smtpserver/constants.js +0 -162
  169. package/dist_ts/mail/delivery/smtpserver/create-server.d.ts +0 -14
  170. package/dist_ts/mail/delivery/smtpserver/create-server.js +0 -28
  171. package/dist_ts/mail/delivery/smtpserver/data-handler.d.ts +0 -123
  172. package/dist_ts/mail/delivery/smtpserver/data-handler.js +0 -1148
  173. package/dist_ts/mail/delivery/smtpserver/index.d.ts +0 -20
  174. package/dist_ts/mail/delivery/smtpserver/index.js +0 -27
  175. package/dist_ts/mail/delivery/smtpserver/interfaces.d.ts +0 -530
  176. package/dist_ts/mail/delivery/smtpserver/interfaces.js +0 -10
  177. package/dist_ts/mail/delivery/smtpserver/secure-server.d.ts +0 -15
  178. package/dist_ts/mail/delivery/smtpserver/secure-server.js +0 -79
  179. package/dist_ts/mail/delivery/smtpserver/security-handler.d.ts +0 -86
  180. package/dist_ts/mail/delivery/smtpserver/security-handler.js +0 -234
  181. package/dist_ts/mail/delivery/smtpserver/session-manager.d.ts +0 -140
  182. package/dist_ts/mail/delivery/smtpserver/session-manager.js +0 -469
  183. package/dist_ts/mail/delivery/smtpserver/smtp-server.d.ts +0 -137
  184. package/dist_ts/mail/delivery/smtpserver/smtp-server.js +0 -666
  185. package/dist_ts/mail/delivery/smtpserver/starttls-handler.d.ts +0 -21
  186. package/dist_ts/mail/delivery/smtpserver/starttls-handler.js +0 -207
  187. package/dist_ts/mail/delivery/smtpserver/tls-handler.d.ts +0 -66
  188. package/dist_ts/mail/delivery/smtpserver/tls-handler.js +0 -261
  189. package/dist_ts/mail/delivery/smtpserver/utils/adaptive-logging.d.ts +0 -117
  190. package/dist_ts/mail/delivery/smtpserver/utils/adaptive-logging.js +0 -411
  191. package/dist_ts/mail/delivery/smtpserver/utils/helpers.d.ts +0 -78
  192. package/dist_ts/mail/delivery/smtpserver/utils/helpers.js +0 -208
  193. package/dist_ts/mail/delivery/smtpserver/utils/logging.d.ts +0 -106
  194. package/dist_ts/mail/delivery/smtpserver/utils/logging.js +0 -181
  195. package/dist_ts/mail/delivery/smtpserver/utils/validation.d.ts +0 -69
  196. package/dist_ts/mail/delivery/smtpserver/utils/validation.js +0 -360
  197. package/dist_ts/mail/index.d.ts +0 -8
  198. package/dist_ts/mail/index.js +0 -13
  199. package/dist_ts/mail/routing/classes.dns.manager.d.ts +0 -65
  200. package/dist_ts/mail/routing/classes.dns.manager.js +0 -413
  201. package/dist_ts/mail/routing/classes.dnsmanager.d.ts +0 -165
  202. package/dist_ts/mail/routing/classes.dnsmanager.js +0 -430
  203. package/dist_ts/mail/routing/classes.domain.registry.d.ts +0 -54
  204. package/dist_ts/mail/routing/classes.domain.registry.js +0 -118
  205. package/dist_ts/mail/routing/classes.email.config.d.ts +0 -64
  206. package/dist_ts/mail/routing/classes.email.config.js +0 -2
  207. package/dist_ts/mail/routing/classes.email.router.d.ts +0 -171
  208. package/dist_ts/mail/routing/classes.email.router.js +0 -491
  209. package/dist_ts/mail/routing/classes.unified.email.server.d.ts +0 -426
  210. package/dist_ts/mail/routing/classes.unified.email.server.js +0 -1454
  211. package/dist_ts/mail/routing/index.d.ts +0 -5
  212. package/dist_ts/mail/routing/index.js +0 -7
  213. package/dist_ts/mail/routing/interfaces.d.ts +0 -187
  214. package/dist_ts/mail/routing/interfaces.js +0 -2
  215. package/dist_ts/mail/security/classes.dkimcreator.d.ts +0 -68
  216. package/dist_ts/mail/security/classes.dkimcreator.js +0 -346
  217. package/dist_ts/mail/security/classes.dkimverifier.d.ts +0 -46
  218. package/dist_ts/mail/security/classes.dkimverifier.js +0 -317
  219. package/dist_ts/mail/security/classes.dmarcverifier.d.ts +0 -123
  220. package/dist_ts/mail/security/classes.dmarcverifier.js +0 -365
  221. package/dist_ts/mail/security/classes.spfverifier.d.ts +0 -103
  222. package/dist_ts/mail/security/classes.spfverifier.js +0 -492
  223. package/dist_ts/mail/security/index.d.ts +0 -4
  224. package/dist_ts/mail/security/index.js +0 -6
  225. package/dist_ts/opsserver/classes.opsserver.d.ts +0 -14
  226. package/dist_ts/opsserver/classes.opsserver.js +0 -37
  227. package/dist_ts/opsserver/index.d.ts +0 -1
  228. package/dist_ts/opsserver/index.js +0 -2
  229. package/dist_ts/paths.d.ts +0 -14
  230. package/dist_ts/paths.js +0 -39
  231. package/dist_ts/plugins.d.ts +0 -43
  232. package/dist_ts/plugins.js +0 -50
  233. package/dist_ts/security/classes.contentscanner.d.ts +0 -160
  234. package/dist_ts/security/classes.contentscanner.js +0 -634
  235. package/dist_ts/security/classes.ipreputationchecker.d.ts +0 -150
  236. package/dist_ts/security/classes.ipreputationchecker.js +0 -508
  237. package/dist_ts/security/classes.securitylogger.d.ts +0 -140
  238. package/dist_ts/security/classes.securitylogger.js +0 -232
  239. package/dist_ts/security/index.d.ts +0 -3
  240. package/dist_ts/security/index.js +0 -4
  241. package/dist_ts/sms/classes.smsservice.d.ts +0 -15
  242. package/dist_ts/sms/classes.smsservice.js +0 -72
  243. package/dist_ts/sms/config/sms.config.d.ts +0 -93
  244. package/dist_ts/sms/config/sms.config.js +0 -2
  245. package/dist_ts/sms/config/sms.schema.d.ts +0 -5
  246. package/dist_ts/sms/config/sms.schema.js +0 -121
  247. package/dist_ts/sms/index.d.ts +0 -1
  248. package/dist_ts/sms/index.js +0 -2
  249. package/dist_ts/storage/classes.storagemanager.d.ts +0 -82
  250. package/dist_ts/storage/classes.storagemanager.js +0 -341
  251. package/dist_ts/storage/index.d.ts +0 -1
  252. package/dist_ts/storage/index.js +0 -3
  253. package/dist_ts/ts/00_commitinfo_data.d.ts +0 -8
  254. package/dist_ts/ts/00_commitinfo_data.js +0 -9
  255. package/dist_ts/ts/classes.dcrouter.d.ts +0 -238
  256. package/dist_ts/ts/classes.dcrouter.js +0 -1008
  257. package/dist_ts/ts/config/index.d.ts +0 -1
  258. package/dist_ts/ts/config/index.js +0 -3
  259. package/dist_ts/ts/config/validator.d.ts +0 -104
  260. package/dist_ts/ts/config/validator.js +0 -152
  261. package/dist_ts/ts/deliverability/classes.ipwarmupmanager.d.ts +0 -253
  262. package/dist_ts/ts/deliverability/classes.ipwarmupmanager.js +0 -639
  263. package/dist_ts/ts/deliverability/classes.senderreputationmonitor.d.ts +0 -300
  264. package/dist_ts/ts/deliverability/classes.senderreputationmonitor.js +0 -961
  265. package/dist_ts/ts/deliverability/index.d.ts +0 -2
  266. package/dist_ts/ts/deliverability/index.js +0 -3
  267. package/dist_ts/ts/errors/base.errors.d.ts +0 -224
  268. package/dist_ts/ts/errors/base.errors.js +0 -310
  269. package/dist_ts/ts/errors/email.errors.d.ts +0 -175
  270. package/dist_ts/ts/errors/email.errors.js +0 -265
  271. package/dist_ts/ts/errors/error-handler.d.ts +0 -98
  272. package/dist_ts/ts/errors/error-handler.js +0 -282
  273. package/dist_ts/ts/errors/error.codes.d.ts +0 -115
  274. package/dist_ts/ts/errors/error.codes.js +0 -136
  275. package/dist_ts/ts/errors/index.d.ts +0 -56
  276. package/dist_ts/ts/errors/index.js +0 -138
  277. package/dist_ts/ts/errors/mta.errors.d.ts +0 -259
  278. package/dist_ts/ts/errors/mta.errors.js +0 -472
  279. package/dist_ts/ts/errors/reputation.errors.d.ts +0 -183
  280. package/dist_ts/ts/errors/reputation.errors.js +0 -292
  281. package/dist_ts/ts/index.d.ts +0 -4
  282. package/dist_ts/ts/index.js +0 -6
  283. package/dist_ts/ts/logger.d.ts +0 -17
  284. package/dist_ts/ts/logger.js +0 -77
  285. package/dist_ts/ts/mail/core/classes.bouncemanager.d.ts +0 -200
  286. package/dist_ts/ts/mail/core/classes.bouncemanager.js +0 -778
  287. package/dist_ts/ts/mail/core/classes.email.d.ts +0 -291
  288. package/dist_ts/ts/mail/core/classes.email.js +0 -780
  289. package/dist_ts/ts/mail/core/classes.emailvalidator.d.ts +0 -61
  290. package/dist_ts/ts/mail/core/classes.emailvalidator.js +0 -182
  291. package/dist_ts/ts/mail/core/classes.templatemanager.d.ts +0 -95
  292. package/dist_ts/ts/mail/core/classes.templatemanager.js +0 -239
  293. package/dist_ts/ts/mail/core/index.d.ts +0 -4
  294. package/dist_ts/ts/mail/core/index.js +0 -6
  295. package/dist_ts/ts/mail/delivery/classes.delivery.queue.d.ts +0 -163
  296. package/dist_ts/ts/mail/delivery/classes.delivery.queue.js +0 -485
  297. package/dist_ts/ts/mail/delivery/classes.delivery.system.d.ts +0 -186
  298. package/dist_ts/ts/mail/delivery/classes.delivery.system.js +0 -846
  299. package/dist_ts/ts/mail/delivery/classes.emailsendjob.d.ts +0 -84
  300. package/dist_ts/ts/mail/delivery/classes.emailsendjob.js +0 -362
  301. package/dist_ts/ts/mail/delivery/classes.emailsignjob.d.ts +0 -18
  302. package/dist_ts/ts/mail/delivery/classes.emailsignjob.js +0 -44
  303. package/dist_ts/ts/mail/delivery/classes.mta.config.d.ts +0 -22
  304. package/dist_ts/ts/mail/delivery/classes.mta.config.js +0 -51
  305. package/dist_ts/ts/mail/delivery/classes.ratelimiter.d.ts +0 -98
  306. package/dist_ts/ts/mail/delivery/classes.ratelimiter.js +0 -205
  307. package/dist_ts/ts/mail/delivery/classes.smtp.client.legacy.d.ts +0 -275
  308. package/dist_ts/ts/mail/delivery/classes.smtp.client.legacy.js +0 -973
  309. package/dist_ts/ts/mail/delivery/classes.unified.rate.limiter.d.ts +0 -200
  310. package/dist_ts/ts/mail/delivery/classes.unified.rate.limiter.js +0 -817
  311. package/dist_ts/ts/mail/delivery/index.d.ts +0 -12
  312. package/dist_ts/ts/mail/delivery/index.js +0 -18
  313. package/dist_ts/ts/mail/delivery/interfaces.d.ts +0 -243
  314. package/dist_ts/ts/mail/delivery/interfaces.js +0 -17
  315. package/dist_ts/ts/mail/delivery/smtpclient/auth-handler.d.ts +0 -43
  316. package/dist_ts/ts/mail/delivery/smtpclient/auth-handler.js +0 -188
  317. package/dist_ts/ts/mail/delivery/smtpclient/command-handler.d.ts +0 -67
  318. package/dist_ts/ts/mail/delivery/smtpclient/command-handler.js +0 -276
  319. package/dist_ts/ts/mail/delivery/smtpclient/connection-manager.d.ts +0 -48
  320. package/dist_ts/ts/mail/delivery/smtpclient/connection-manager.js +0 -238
  321. package/dist_ts/ts/mail/delivery/smtpclient/constants.d.ts +0 -129
  322. package/dist_ts/ts/mail/delivery/smtpclient/constants.js +0 -135
  323. package/dist_ts/ts/mail/delivery/smtpclient/create-client.d.ts +0 -22
  324. package/dist_ts/ts/mail/delivery/smtpclient/create-client.js +0 -86
  325. package/dist_ts/ts/mail/delivery/smtpclient/error-handler.d.ts +0 -28
  326. package/dist_ts/ts/mail/delivery/smtpclient/error-handler.js +0 -110
  327. package/dist_ts/ts/mail/delivery/smtpclient/index.d.ts +0 -16
  328. package/dist_ts/ts/mail/delivery/smtpclient/index.js +0 -21
  329. package/dist_ts/ts/mail/delivery/smtpclient/interfaces.d.ts +0 -183
  330. package/dist_ts/ts/mail/delivery/smtpclient/interfaces.js +0 -19
  331. package/dist_ts/ts/mail/delivery/smtpclient/smtp-client.d.ts +0 -58
  332. package/dist_ts/ts/mail/delivery/smtpclient/smtp-client.js +0 -279
  333. package/dist_ts/ts/mail/delivery/smtpclient/tls-handler.d.ts +0 -33
  334. package/dist_ts/ts/mail/delivery/smtpclient/tls-handler.js +0 -202
  335. package/dist_ts/ts/mail/delivery/smtpclient/utils/helpers.d.ts +0 -77
  336. package/dist_ts/ts/mail/delivery/smtpclient/utils/helpers.js +0 -196
  337. package/dist_ts/ts/mail/delivery/smtpclient/utils/logging.d.ts +0 -46
  338. package/dist_ts/ts/mail/delivery/smtpclient/utils/logging.js +0 -153
  339. package/dist_ts/ts/mail/delivery/smtpclient/utils/validation.d.ts +0 -38
  340. package/dist_ts/ts/mail/delivery/smtpclient/utils/validation.js +0 -139
  341. package/dist_ts/ts/mail/delivery/smtpserver/certificate-utils.d.ts +0 -45
  342. package/dist_ts/ts/mail/delivery/smtpserver/certificate-utils.js +0 -345
  343. package/dist_ts/ts/mail/delivery/smtpserver/command-handler.d.ts +0 -156
  344. package/dist_ts/ts/mail/delivery/smtpserver/command-handler.js +0 -1159
  345. package/dist_ts/ts/mail/delivery/smtpserver/connection-manager.d.ts +0 -159
  346. package/dist_ts/ts/mail/delivery/smtpserver/connection-manager.js +0 -894
  347. package/dist_ts/ts/mail/delivery/smtpserver/constants.d.ts +0 -130
  348. package/dist_ts/ts/mail/delivery/smtpserver/constants.js +0 -162
  349. package/dist_ts/ts/mail/delivery/smtpserver/create-server.d.ts +0 -14
  350. package/dist_ts/ts/mail/delivery/smtpserver/create-server.js +0 -28
  351. package/dist_ts/ts/mail/delivery/smtpserver/data-handler.d.ts +0 -123
  352. package/dist_ts/ts/mail/delivery/smtpserver/data-handler.js +0 -1148
  353. package/dist_ts/ts/mail/delivery/smtpserver/index.d.ts +0 -20
  354. package/dist_ts/ts/mail/delivery/smtpserver/index.js +0 -27
  355. package/dist_ts/ts/mail/delivery/smtpserver/interfaces.d.ts +0 -530
  356. package/dist_ts/ts/mail/delivery/smtpserver/interfaces.js +0 -10
  357. package/dist_ts/ts/mail/delivery/smtpserver/secure-server.d.ts +0 -15
  358. package/dist_ts/ts/mail/delivery/smtpserver/secure-server.js +0 -79
  359. package/dist_ts/ts/mail/delivery/smtpserver/security-handler.d.ts +0 -86
  360. package/dist_ts/ts/mail/delivery/smtpserver/security-handler.js +0 -234
  361. package/dist_ts/ts/mail/delivery/smtpserver/session-manager.d.ts +0 -140
  362. package/dist_ts/ts/mail/delivery/smtpserver/session-manager.js +0 -469
  363. package/dist_ts/ts/mail/delivery/smtpserver/smtp-server.d.ts +0 -137
  364. package/dist_ts/ts/mail/delivery/smtpserver/smtp-server.js +0 -666
  365. package/dist_ts/ts/mail/delivery/smtpserver/starttls-handler.d.ts +0 -21
  366. package/dist_ts/ts/mail/delivery/smtpserver/starttls-handler.js +0 -207
  367. package/dist_ts/ts/mail/delivery/smtpserver/tls-handler.d.ts +0 -66
  368. package/dist_ts/ts/mail/delivery/smtpserver/tls-handler.js +0 -261
  369. package/dist_ts/ts/mail/delivery/smtpserver/utils/adaptive-logging.d.ts +0 -117
  370. package/dist_ts/ts/mail/delivery/smtpserver/utils/adaptive-logging.js +0 -411
  371. package/dist_ts/ts/mail/delivery/smtpserver/utils/helpers.d.ts +0 -78
  372. package/dist_ts/ts/mail/delivery/smtpserver/utils/helpers.js +0 -208
  373. package/dist_ts/ts/mail/delivery/smtpserver/utils/logging.d.ts +0 -106
  374. package/dist_ts/ts/mail/delivery/smtpserver/utils/logging.js +0 -181
  375. package/dist_ts/ts/mail/delivery/smtpserver/utils/validation.d.ts +0 -69
  376. package/dist_ts/ts/mail/delivery/smtpserver/utils/validation.js +0 -360
  377. package/dist_ts/ts/mail/index.d.ts +0 -8
  378. package/dist_ts/ts/mail/index.js +0 -13
  379. package/dist_ts/ts/mail/routing/classes.dns.manager.d.ts +0 -65
  380. package/dist_ts/ts/mail/routing/classes.dns.manager.js +0 -413
  381. package/dist_ts/ts/mail/routing/classes.dnsmanager.d.ts +0 -165
  382. package/dist_ts/ts/mail/routing/classes.dnsmanager.js +0 -430
  383. package/dist_ts/ts/mail/routing/classes.domain.registry.d.ts +0 -54
  384. package/dist_ts/ts/mail/routing/classes.domain.registry.js +0 -118
  385. package/dist_ts/ts/mail/routing/classes.email.config.d.ts +0 -64
  386. package/dist_ts/ts/mail/routing/classes.email.config.js +0 -2
  387. package/dist_ts/ts/mail/routing/classes.email.router.d.ts +0 -171
  388. package/dist_ts/ts/mail/routing/classes.email.router.js +0 -491
  389. package/dist_ts/ts/mail/routing/classes.unified.email.server.d.ts +0 -426
  390. package/dist_ts/ts/mail/routing/classes.unified.email.server.js +0 -1454
  391. package/dist_ts/ts/mail/routing/index.d.ts +0 -5
  392. package/dist_ts/ts/mail/routing/index.js +0 -7
  393. package/dist_ts/ts/mail/routing/interfaces.d.ts +0 -187
  394. package/dist_ts/ts/mail/routing/interfaces.js +0 -2
  395. package/dist_ts/ts/mail/security/classes.dkimcreator.d.ts +0 -68
  396. package/dist_ts/ts/mail/security/classes.dkimcreator.js +0 -346
  397. package/dist_ts/ts/mail/security/classes.dkimverifier.d.ts +0 -46
  398. package/dist_ts/ts/mail/security/classes.dkimverifier.js +0 -317
  399. package/dist_ts/ts/mail/security/classes.dmarcverifier.d.ts +0 -123
  400. package/dist_ts/ts/mail/security/classes.dmarcverifier.js +0 -365
  401. package/dist_ts/ts/mail/security/classes.spfverifier.d.ts +0 -103
  402. package/dist_ts/ts/mail/security/classes.spfverifier.js +0 -492
  403. package/dist_ts/ts/mail/security/index.d.ts +0 -4
  404. package/dist_ts/ts/mail/security/index.js +0 -6
  405. package/dist_ts/ts/opsserver/classes.opsserver.d.ts +0 -20
  406. package/dist_ts/ts/opsserver/classes.opsserver.js +0 -44
  407. package/dist_ts/ts/opsserver/handlers/admin.handler.d.ts +0 -31
  408. package/dist_ts/ts/opsserver/handlers/admin.handler.js +0 -177
  409. package/dist_ts/ts/opsserver/handlers/config.handler.d.ts +0 -10
  410. package/dist_ts/ts/opsserver/handlers/config.handler.js +0 -100
  411. package/dist_ts/ts/opsserver/handlers/index.d.ts +0 -5
  412. package/dist_ts/ts/opsserver/handlers/index.js +0 -6
  413. package/dist_ts/ts/opsserver/handlers/logs.handler.d.ts +0 -10
  414. package/dist_ts/ts/opsserver/handlers/logs.handler.js +0 -121
  415. package/dist_ts/ts/opsserver/handlers/security.handler.d.ts +0 -11
  416. package/dist_ts/ts/opsserver/handlers/security.handler.js +0 -118
  417. package/dist_ts/ts/opsserver/handlers/stats.handler.d.ts +0 -13
  418. package/dist_ts/ts/opsserver/handlers/stats.handler.js +0 -233
  419. package/dist_ts/ts/opsserver/helpers/guards.d.ts +0 -25
  420. package/dist_ts/ts/opsserver/helpers/guards.js +0 -41
  421. package/dist_ts/ts/opsserver/index.d.ts +0 -1
  422. package/dist_ts/ts/opsserver/index.js +0 -2
  423. package/dist_ts/ts/paths.d.ts +0 -14
  424. package/dist_ts/ts/paths.js +0 -39
  425. package/dist_ts/ts/plugins.d.ts +0 -46
  426. package/dist_ts/ts/plugins.js +0 -53
  427. package/dist_ts/ts/security/classes.contentscanner.d.ts +0 -160
  428. package/dist_ts/ts/security/classes.contentscanner.js +0 -634
  429. package/dist_ts/ts/security/classes.ipreputationchecker.d.ts +0 -150
  430. package/dist_ts/ts/security/classes.ipreputationchecker.js +0 -508
  431. package/dist_ts/ts/security/classes.securitylogger.d.ts +0 -140
  432. package/dist_ts/ts/security/classes.securitylogger.js +0 -232
  433. package/dist_ts/ts/security/index.d.ts +0 -3
  434. package/dist_ts/ts/security/index.js +0 -4
  435. package/dist_ts/ts/sms/classes.smsservice.d.ts +0 -15
  436. package/dist_ts/ts/sms/classes.smsservice.js +0 -72
  437. package/dist_ts/ts/sms/config/sms.config.d.ts +0 -93
  438. package/dist_ts/ts/sms/config/sms.config.js +0 -2
  439. package/dist_ts/ts/sms/config/sms.schema.d.ts +0 -5
  440. package/dist_ts/ts/sms/config/sms.schema.js +0 -121
  441. package/dist_ts/ts/sms/index.d.ts +0 -1
  442. package/dist_ts/ts/sms/index.js +0 -2
  443. package/dist_ts/ts/storage/classes.storagemanager.d.ts +0 -82
  444. package/dist_ts/ts/storage/classes.storagemanager.js +0 -341
  445. package/dist_ts/ts/storage/index.d.ts +0 -1
  446. package/dist_ts/ts/storage/index.js +0 -3
  447. package/dist_ts/ts_interfaces/data/auth.d.ts +0 -8
  448. package/dist_ts/ts_interfaces/data/auth.js +0 -2
  449. package/dist_ts/ts_interfaces/data/index.d.ts +0 -2
  450. package/dist_ts/ts_interfaces/data/index.js +0 -3
  451. package/dist_ts/ts_interfaces/data/stats.d.ts +0 -93
  452. package/dist_ts/ts_interfaces/data/stats.js +0 -2
  453. package/dist_ts/ts_interfaces/index.d.ts +0 -5
  454. package/dist_ts/ts_interfaces/index.js +0 -8
  455. package/dist_ts/ts_interfaces/plugins.d.ts +0 -2
  456. package/dist_ts/ts_interfaces/plugins.js +0 -4
  457. package/dist_ts/ts_interfaces/requests/admin.d.ts +0 -31
  458. package/dist_ts/ts_interfaces/requests/admin.js +0 -3
  459. package/dist_ts/ts_interfaces/requests/config.d.ts +0 -25
  460. package/dist_ts/ts_interfaces/requests/config.js +0 -3
  461. package/dist_ts/ts_interfaces/requests/index.d.ts +0 -4
  462. package/dist_ts/ts_interfaces/requests/index.js +0 -5
  463. package/dist_ts/ts_interfaces/requests/logs.d.ts +0 -34
  464. package/dist_ts/ts_interfaces/requests/logs.js +0 -4
  465. package/dist_ts/ts_interfaces/requests/stats.d.ts +0 -131
  466. package/dist_ts/ts_interfaces/requests/stats.js +0 -4
  467. package/readme.opsserver.md +0 -351
  468. package/test/helpers/server.loader.ts +0 -347
  469. package/test/helpers/smtp.client.ts +0 -209
  470. package/test/helpers/utils.ts +0 -311
  471. package/test/suite/smtpclient_commands/test.ccmd-01.ehlo-helo-sending.ts +0 -168
  472. package/test/suite/smtpclient_commands/test.ccmd-02.mail-from-parameters.ts +0 -277
  473. package/test/suite/smtpclient_commands/test.ccmd-03.rcpt-to-multiple.ts +0 -283
  474. package/test/suite/smtpclient_commands/test.ccmd-04.data-transmission.ts +0 -274
  475. package/test/suite/smtpclient_commands/test.ccmd-05.auth-mechanisms.ts +0 -306
  476. package/test/suite/smtpclient_commands/test.ccmd-06.command-pipelining.ts +0 -233
  477. package/test/suite/smtpclient_commands/test.ccmd-07.response-parsing.ts +0 -243
  478. package/test/suite/smtpclient_commands/test.ccmd-08.rset-command.ts +0 -333
  479. package/test/suite/smtpclient_commands/test.ccmd-09.noop-command.ts +0 -339
  480. package/test/suite/smtpclient_commands/test.ccmd-10.vrfy-expn.ts +0 -457
  481. package/test/suite/smtpclient_commands/test.ccmd-11.help-command.ts +0 -409
  482. package/test/suite/smtpclient_connection/test.ccm-01.basic-tcp-connection.ts +0 -150
  483. package/test/suite/smtpclient_connection/test.ccm-02.tls-connection.ts +0 -140
  484. package/test/suite/smtpclient_connection/test.ccm-03.starttls-upgrade.ts +0 -208
  485. package/test/suite/smtpclient_connection/test.ccm-04.connection-pooling.ts +0 -250
  486. package/test/suite/smtpclient_connection/test.ccm-05.connection-reuse.ts +0 -288
  487. package/test/suite/smtpclient_connection/test.ccm-06.connection-timeout.ts +0 -267
  488. package/test/suite/smtpclient_connection/test.ccm-07.automatic-reconnection.ts +0 -324
  489. package/test/suite/smtpclient_connection/test.ccm-08.dns-resolution.ts +0 -139
  490. package/test/suite/smtpclient_connection/test.ccm-09.ipv6-dual-stack.ts +0 -167
  491. package/test/suite/smtpclient_connection/test.ccm-10.proxy-support.ts +0 -305
  492. package/test/suite/smtpclient_connection/test.ccm-11.keepalive.ts +0 -299
  493. package/test/suite/smtpclient_edge-cases/test.cedge-01.unusual-server-responses.ts +0 -529
  494. package/test/suite/smtpclient_edge-cases/test.cedge-02.malformed-commands.ts +0 -438
  495. package/test/suite/smtpclient_edge-cases/test.cedge-03.protocol-violations.ts +0 -446
  496. package/test/suite/smtpclient_edge-cases/test.cedge-04.resource-constraints.ts +0 -530
  497. package/test/suite/smtpclient_edge-cases/test.cedge-05.encoding-issues.ts +0 -145
  498. package/test/suite/smtpclient_edge-cases/test.cedge-06.large-headers.ts +0 -180
  499. package/test/suite/smtpclient_edge-cases/test.cedge-07.concurrent-operations.ts +0 -204
  500. package/test/suite/smtpclient_email-composition/test.cep-01.basic-headers.ts +0 -245
  501. package/test/suite/smtpclient_email-composition/test.cep-02.mime-multipart.ts +0 -321
  502. package/test/suite/smtpclient_email-composition/test.cep-03.attachment-encoding.ts +0 -334
  503. package/test/suite/smtpclient_email-composition/test.cep-04.bcc-handling.ts +0 -187
  504. package/test/suite/smtpclient_email-composition/test.cep-05.reply-to-return-path.ts +0 -277
  505. package/test/suite/smtpclient_email-composition/test.cep-06.utf8-international.ts +0 -235
  506. package/test/suite/smtpclient_email-composition/test.cep-07.html-inline-images.ts +0 -489
  507. package/test/suite/smtpclient_email-composition/test.cep-08.custom-headers.ts +0 -293
  508. package/test/suite/smtpclient_email-composition/test.cep-09.priority-importance.ts +0 -314
  509. package/test/suite/smtpclient_email-composition/test.cep-10.receipts-dsn.ts +0 -411
  510. package/test/suite/smtpclient_error-handling/test.cerr-01.4xx-errors.ts +0 -232
  511. package/test/suite/smtpclient_error-handling/test.cerr-02.5xx-errors.ts +0 -309
  512. package/test/suite/smtpclient_error-handling/test.cerr-03.network-failures.ts +0 -299
  513. package/test/suite/smtpclient_error-handling/test.cerr-04.greylisting-handling.ts +0 -255
  514. package/test/suite/smtpclient_error-handling/test.cerr-05.quota-exceeded.ts +0 -273
  515. package/test/suite/smtpclient_error-handling/test.cerr-06.invalid-recipients.ts +0 -320
  516. package/test/suite/smtpclient_error-handling/test.cerr-07.message-size-limits.ts +0 -320
  517. package/test/suite/smtpclient_error-handling/test.cerr-08.rate-limiting.ts +0 -261
  518. package/test/suite/smtpclient_error-handling/test.cerr-09.connection-pool-errors.ts +0 -299
  519. package/test/suite/smtpclient_error-handling/test.cerr-10.partial-failure.ts +0 -373
  520. package/test/suite/smtpclient_performance/test.cperf-01.bulk-sending.ts +0 -332
  521. package/test/suite/smtpclient_performance/test.cperf-02.message-throughput.ts +0 -304
  522. package/test/suite/smtpclient_performance/test.cperf-03.memory-usage.ts +0 -332
  523. package/test/suite/smtpclient_performance/test.cperf-04.cpu-utilization.ts +0 -373
  524. package/test/suite/smtpclient_performance/test.cperf-05.network-efficiency.ts +0 -181
  525. package/test/suite/smtpclient_performance/test.cperf-06.caching-strategies.ts +0 -190
  526. package/test/suite/smtpclient_performance/test.cperf-07.queue-management.ts +0 -171
  527. package/test/suite/smtpclient_performance/test.cperf-08.dns-caching.ts +0 -50
  528. package/test/suite/smtpclient_reliability/test.crel-01.reconnection-logic.ts +0 -305
  529. package/test/suite/smtpclient_reliability/test.crel-02.network-interruption.ts +0 -207
  530. package/test/suite/smtpclient_reliability/test.crel-03.queue-persistence.ts +0 -469
  531. package/test/suite/smtpclient_reliability/test.crel-04.crash-recovery.ts +0 -520
  532. package/test/suite/smtpclient_reliability/test.crel-05.memory-leaks.ts +0 -503
  533. package/test/suite/smtpclient_reliability/test.crel-06.concurrency-safety.ts +0 -558
  534. package/test/suite/smtpclient_reliability/test.crel-07.resource-cleanup.ts +0 -52
  535. package/test/suite/smtpclient_rfc-compliance/test.crfc-01.rfc5321-client.ts +0 -283
  536. package/test/suite/smtpclient_rfc-compliance/test.crfc-02.esmtp-compliance.ts +0 -77
  537. package/test/suite/smtpclient_rfc-compliance/test.crfc-03.command-syntax.ts +0 -67
  538. package/test/suite/smtpclient_rfc-compliance/test.crfc-04.response-codes.ts +0 -54
  539. package/test/suite/smtpclient_rfc-compliance/test.crfc-05.state-machine.ts +0 -703
  540. package/test/suite/smtpclient_rfc-compliance/test.crfc-06.protocol-negotiation.ts +0 -688
  541. package/test/suite/smtpclient_rfc-compliance/test.crfc-07.interoperability.ts +0 -728
  542. package/test/suite/smtpclient_rfc-compliance/test.crfc-08.smtp-extensions.ts +0 -656
  543. package/test/suite/smtpclient_security/test.csec-01.tls-verification.ts +0 -88
  544. package/test/suite/smtpclient_security/test.csec-02.oauth2-authentication.ts +0 -132
  545. package/test/suite/smtpclient_security/test.csec-03.dkim-signing.ts +0 -138
  546. package/test/suite/smtpclient_security/test.csec-04.spf-compliance.ts +0 -163
  547. package/test/suite/smtpclient_security/test.csec-05.dmarc-policy.ts +0 -200
  548. package/test/suite/smtpclient_security/test.csec-06.certificate-validation.ts +0 -145
  549. package/test/suite/smtpclient_security/test.csec-07.cipher-suites.ts +0 -153
  550. package/test/suite/smtpclient_security/test.csec-08.authentication-fallback.ts +0 -154
  551. package/test/suite/smtpclient_security/test.csec-09.relay-restrictions.ts +0 -166
  552. package/test/suite/smtpclient_security/test.csec-10.anti-spam-measures.ts +0 -196
  553. package/test/suite/smtpserver_commands/test.cmd-01.ehlo-command.ts +0 -193
  554. package/test/suite/smtpserver_commands/test.cmd-02.mail-from.ts +0 -330
  555. package/test/suite/smtpserver_commands/test.cmd-03.rcpt-to.ts +0 -296
  556. package/test/suite/smtpserver_commands/test.cmd-04.data-command.ts +0 -395
  557. package/test/suite/smtpserver_commands/test.cmd-05.noop-command.ts +0 -320
  558. package/test/suite/smtpserver_commands/test.cmd-06.rset-command.ts +0 -399
  559. package/test/suite/smtpserver_commands/test.cmd-07.vrfy-command.ts +0 -391
  560. package/test/suite/smtpserver_commands/test.cmd-08.expn-command.ts +0 -450
  561. package/test/suite/smtpserver_commands/test.cmd-09.size-extension.ts +0 -465
  562. package/test/suite/smtpserver_commands/test.cmd-10.help-command.ts +0 -454
  563. package/test/suite/smtpserver_commands/test.cmd-11.command-pipelining.ts +0 -334
  564. package/test/suite/smtpserver_commands/test.cmd-12.helo-command.ts +0 -420
  565. package/test/suite/smtpserver_commands/test.cmd-13.quit-command.ts +0 -384
  566. package/test/suite/smtpserver_connection/test.cm-01.tls-connection.ts +0 -61
  567. package/test/suite/smtpserver_connection/test.cm-02.multiple-connections.ts +0 -112
  568. package/test/suite/smtpserver_connection/test.cm-03.connection-timeout.ts +0 -134
  569. package/test/suite/smtpserver_connection/test.cm-04.connection-limits.ts +0 -374
  570. package/test/suite/smtpserver_connection/test.cm-05.connection-rejection.ts +0 -296
  571. package/test/suite/smtpserver_connection/test.cm-06.starttls-upgrade.ts +0 -468
  572. package/test/suite/smtpserver_connection/test.cm-07.abrupt-disconnection.ts +0 -321
  573. package/test/suite/smtpserver_connection/test.cm-08.tls-versions.ts +0 -361
  574. package/test/suite/smtpserver_connection/test.cm-09.tls-ciphers.ts +0 -556
  575. package/test/suite/smtpserver_connection/test.cm-10.plain-connection.ts +0 -293
  576. package/test/suite/smtpserver_connection/test.cm-11.keepalive.ts +0 -382
  577. package/test/suite/smtpserver_edge-cases/test.edge-01.very-large-email.ts +0 -239
  578. package/test/suite/smtpserver_edge-cases/test.edge-02.very-small-email.ts +0 -389
  579. package/test/suite/smtpserver_edge-cases/test.edge-03.invalid-character-handling.ts +0 -479
  580. package/test/suite/smtpserver_edge-cases/test.edge-04.empty-commands.ts +0 -430
  581. package/test/suite/smtpserver_edge-cases/test.edge-05.extremely-long-lines.ts +0 -425
  582. package/test/suite/smtpserver_edge-cases/test.edge-06.extremely-long-headers.ts +0 -404
  583. package/test/suite/smtpserver_edge-cases/test.edge-07.unusual-mime-types.ts +0 -333
  584. package/test/suite/smtpserver_edge-cases/test.edge-08.nested-mime-structures.ts +0 -379
  585. package/test/suite/smtpserver_email-processing/test.ep-01.basic-email-sending.ts +0 -338
  586. package/test/suite/smtpserver_email-processing/test.ep-02.invalid-email-addresses.ts +0 -315
  587. package/test/suite/smtpserver_email-processing/test.ep-03.multiple-recipients.ts +0 -493
  588. package/test/suite/smtpserver_email-processing/test.ep-04.large-email.ts +0 -528
  589. package/test/suite/smtpserver_email-processing/test.ep-05.mime-handling.ts +0 -515
  590. package/test/suite/smtpserver_email-processing/test.ep-06.attachment-handling.ts +0 -629
  591. package/test/suite/smtpserver_email-processing/test.ep-07.special-character-handling.ts +0 -462
  592. package/test/suite/smtpserver_email-processing/test.ep-08.email-routing.ts +0 -527
  593. package/test/suite/smtpserver_email-processing/test.ep-09.delivery-status-notifications.ts +0 -486
  594. package/test/suite/smtpserver_error-handling/test.err-01.syntax-errors.ts +0 -475
  595. package/test/suite/smtpserver_error-handling/test.err-02.invalid-sequence.ts +0 -450
  596. package/test/suite/smtpserver_error-handling/test.err-03.temporary-failures.ts +0 -453
  597. package/test/suite/smtpserver_error-handling/test.err-04.permanent-failures.ts +0 -325
  598. package/test/suite/smtpserver_error-handling/test.err-05.resource-exhaustion.ts +0 -302
  599. package/test/suite/smtpserver_error-handling/test.err-06.malformed-mime.ts +0 -374
  600. package/test/suite/smtpserver_error-handling/test.err-07.exception-handling.ts +0 -333
  601. package/test/suite/smtpserver_error-handling/test.err-08.error-logging.ts +0 -324
  602. package/test/suite/smtpserver_performance/test.perf-01.throughput.ts +0 -183
  603. package/test/suite/smtpserver_performance/test.perf-02.concurrency.ts +0 -388
  604. package/test/suite/smtpserver_performance/test.perf-03.cpu-utilization.ts +0 -245
  605. package/test/suite/smtpserver_performance/test.perf-04.memory-usage.ts +0 -238
  606. package/test/suite/smtpserver_performance/test.perf-05.connection-processing-time.ts +0 -363
  607. package/test/suite/smtpserver_performance/test.perf-06.message-processing-time.ts +0 -252
  608. package/test/suite/smtpserver_performance/test.perf-07.resource-cleanup.ts +0 -317
  609. package/test/suite/smtpserver_reliability/test.rel-01.long-running-operation.ts +0 -344
  610. package/test/suite/smtpserver_reliability/test.rel-02.restart-recovery.ts +0 -328
  611. package/test/suite/smtpserver_reliability/test.rel-03.resource-leak-detection.ts +0 -394
  612. package/test/suite/smtpserver_reliability/test.rel-04.error-recovery.ts +0 -401
  613. package/test/suite/smtpserver_reliability/test.rel-05.dns-resolution-failure.ts +0 -335
  614. package/test/suite/smtpserver_reliability/test.rel-06.network-interruption.ts +0 -410
  615. package/test/suite/smtpserver_rfc-compliance/test.rfc-01.rfc5321-compliance.ts +0 -382
  616. package/test/suite/smtpserver_rfc-compliance/test.rfc-02.rfc5322-compliance.ts +0 -428
  617. package/test/suite/smtpserver_rfc-compliance/test.rfc-03.rfc7208-spf-compliance.ts +0 -330
  618. package/test/suite/smtpserver_rfc-compliance/test.rfc-04.rfc6376-dkim-compliance.ts +0 -450
  619. package/test/suite/smtpserver_rfc-compliance/test.rfc-05.rfc7489-dmarc-compliance.ts +0 -408
  620. package/test/suite/smtpserver_rfc-compliance/test.rfc-06.rfc8314-tls-compliance.ts +0 -366
  621. package/test/suite/smtpserver_rfc-compliance/test.rfc-07.rfc3461-dsn-compliance.ts +0 -399
  622. package/test/suite/smtpserver_security/test.sec-01.authentication.ts +0 -218
  623. package/test/suite/smtpserver_security/test.sec-02.authorization.ts +0 -286
  624. package/test/suite/smtpserver_security/test.sec-03.dkim-processing.ts +0 -414
  625. package/test/suite/smtpserver_security/test.sec-04.spf-checking.ts +0 -280
  626. package/test/suite/smtpserver_security/test.sec-05.dmarc-policy.ts +0 -374
  627. package/test/suite/smtpserver_security/test.sec-06.ip-reputation.ts +0 -303
  628. package/test/suite/smtpserver_security/test.sec-07.content-scanning.ts +0 -409
  629. package/test/suite/smtpserver_security/test.sec-08.rate-limiting.ts +0 -324
  630. package/test/suite/smtpserver_security/test.sec-09.tls-certificate-validation.ts +0 -312
  631. package/test/suite/smtpserver_security/test.sec-10.header-injection-prevention.ts +0 -332
  632. package/test/suite/smtpserver_security/test.sec-11.bounce-management.ts +0 -363
  633. package/test/test.base.ts +0 -65
  634. package/test/test.bouncemanager.ts +0 -196
  635. package/test/test.deliverability.ts +0 -55
  636. package/test/test.dns-manager-creation.ts +0 -141
  637. package/test/test.dns-mode-switching.ts +0 -257
  638. package/test/test.dns-validation.ts +0 -283
  639. package/test/test.email-socket-handler.ts +0 -228
  640. package/test/test.email.integration.ts +0 -377
  641. package/test/test.email.router.ts +0 -283
  642. package/test/test.emailauth.ts +0 -195
  643. package/test/test.integration.storage.ts +0 -313
  644. package/test/test.integration.ts +0 -75
  645. package/test/test.ipwarmupmanager.ts +0 -323
  646. package/test/test.minimal.ts +0 -66
  647. package/test/test.rate-limiting-integration.ts +0 -236
  648. package/test/test.ratelimiter.ts +0 -141
  649. package/test/test.reputationmonitor.ts +0 -262
  650. package/test/test.smartmail.ts +0 -248
  651. package/test/test.smtp.client.compatibility.ts +0 -154
  652. package/test/test.smtp.client.ts +0 -191
  653. package/test/test.smtp.server.ts +0 -180
  654. package/test/test.socket-handler-integration.ts +0 -240
  655. package/test/test.socket-handler-unit.ts +0 -198
  656. package/ts/deliverability/classes.ipwarmupmanager.ts +0 -896
  657. package/ts/deliverability/classes.senderreputationmonitor.ts +0 -1244
  658. package/ts/deliverability/index.ts +0 -13
  659. package/ts/errors/email.errors.ts +0 -383
  660. package/ts/errors/mta.errors.ts +0 -681
  661. package/ts/mail/core/classes.bouncemanager.ts +0 -965
  662. package/ts/mail/core/classes.email.ts +0 -941
  663. package/ts/mail/core/classes.emailvalidator.ts +0 -239
  664. package/ts/mail/core/classes.templatemanager.ts +0 -320
  665. package/ts/mail/core/index.ts +0 -5
  666. package/ts/mail/delivery/classes.delivery.queue.ts +0 -645
  667. package/ts/mail/delivery/classes.delivery.system.ts +0 -1089
  668. package/ts/mail/delivery/classes.emailsendjob.ts +0 -447
  669. package/ts/mail/delivery/classes.emailsendjob.ts.backup +0 -691
  670. package/ts/mail/delivery/classes.emailsignjob.ts +0 -67
  671. package/ts/mail/delivery/classes.mta.config.ts +0 -73
  672. package/ts/mail/delivery/classes.ratelimiter.ts +0 -281
  673. package/ts/mail/delivery/classes.smtp.client.legacy.ts +0 -1422
  674. package/ts/mail/delivery/classes.unified.rate.limiter.ts +0 -1053
  675. package/ts/mail/delivery/index.ts +0 -24
  676. package/ts/mail/delivery/interfaces.ts +0 -291
  677. package/ts/mail/delivery/smtpclient/auth-handler.ts +0 -232
  678. package/ts/mail/delivery/smtpclient/command-handler.ts +0 -343
  679. package/ts/mail/delivery/smtpclient/connection-manager.ts +0 -289
  680. package/ts/mail/delivery/smtpclient/constants.ts +0 -145
  681. package/ts/mail/delivery/smtpclient/create-client.ts +0 -94
  682. package/ts/mail/delivery/smtpclient/error-handler.ts +0 -141
  683. package/ts/mail/delivery/smtpclient/index.ts +0 -24
  684. package/ts/mail/delivery/smtpclient/interfaces.ts +0 -242
  685. package/ts/mail/delivery/smtpclient/smtp-client.ts +0 -357
  686. package/ts/mail/delivery/smtpclient/tls-handler.ts +0 -254
  687. package/ts/mail/delivery/smtpclient/utils/helpers.ts +0 -224
  688. package/ts/mail/delivery/smtpclient/utils/logging.ts +0 -212
  689. package/ts/mail/delivery/smtpclient/utils/validation.ts +0 -170
  690. package/ts/mail/delivery/smtpserver/certificate-utils.ts +0 -398
  691. package/ts/mail/delivery/smtpserver/command-handler.ts +0 -1340
  692. package/ts/mail/delivery/smtpserver/connection-manager.ts +0 -1045
  693. package/ts/mail/delivery/smtpserver/constants.ts +0 -181
  694. package/ts/mail/delivery/smtpserver/create-server.ts +0 -31
  695. package/ts/mail/delivery/smtpserver/data-handler.ts +0 -1283
  696. package/ts/mail/delivery/smtpserver/index.ts +0 -32
  697. package/ts/mail/delivery/smtpserver/interfaces.ts +0 -655
  698. package/ts/mail/delivery/smtpserver/secure-server.ts +0 -97
  699. package/ts/mail/delivery/smtpserver/security-handler.ts +0 -345
  700. package/ts/mail/delivery/smtpserver/session-manager.ts +0 -557
  701. package/ts/mail/delivery/smtpserver/smtp-server.ts +0 -804
  702. package/ts/mail/delivery/smtpserver/starttls-handler.ts +0 -262
  703. package/ts/mail/delivery/smtpserver/tls-handler.ts +0 -346
  704. package/ts/mail/delivery/smtpserver/utils/adaptive-logging.ts +0 -514
  705. package/ts/mail/delivery/smtpserver/utils/helpers.ts +0 -246
  706. package/ts/mail/delivery/smtpserver/utils/logging.ts +0 -246
  707. package/ts/mail/delivery/smtpserver/utils/validation.ts +0 -436
  708. package/ts/mail/index.ts +0 -19
  709. package/ts/mail/routing/classes.dns.manager.ts +0 -563
  710. package/ts/mail/routing/classes.dnsmanager.ts +0 -559
  711. package/ts/mail/routing/classes.domain.registry.ts +0 -139
  712. package/ts/mail/routing/classes.email.config.ts +0 -82
  713. package/ts/mail/routing/classes.email.router.ts +0 -575
  714. package/ts/mail/routing/classes.unified.email.server.ts +0 -1873
  715. package/ts/mail/routing/index.ts +0 -6
  716. package/ts/mail/routing/interfaces.ts +0 -202
  717. package/ts/mail/security/classes.dkimcreator.ts +0 -431
  718. package/ts/mail/security/classes.dkimverifier.ts +0 -382
  719. package/ts/mail/security/classes.dmarcverifier.ts +0 -478
  720. package/ts/mail/security/classes.spfverifier.ts +0 -606
  721. package/ts/mail/security/index.ts +0 -5
  722. package/ts_web/elements/ops-view-stats.ts +0 -299
@@ -1,961 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- import * as paths from '../paths.js';
3
- import { logger } from '../logger.js';
4
- /**
5
- * Default configuration
6
- */
7
- const DEFAULT_CONFIG = {
8
- enabled: true,
9
- domains: [],
10
- updateFrequency: 24 * 60 * 60 * 1000, // Daily
11
- dataSources: {
12
- spamLists: [
13
- 'zen.spamhaus.org',
14
- 'bl.spamcop.net',
15
- 'dnsbl.sorbs.net',
16
- 'b.barracudacentral.org'
17
- ],
18
- deliverabilityMonitor: null
19
- },
20
- alertThresholds: {
21
- minReputationScore: 70,
22
- maxComplaintRate: 0.1, // 0.1%
23
- maxBounceRate: 5, // 5%
24
- minOpenRate: 15 // 15%
25
- }
26
- };
27
- /**
28
- * Class for monitoring and tracking sender reputation for domains
29
- */
30
- export class SenderReputationMonitor {
31
- /**
32
- * Constructor for SenderReputationMonitor
33
- * @param config Configuration options
34
- * @param storageManager Optional StorageManager instance
35
- */
36
- constructor(config = {}, storageManager) {
37
- this.reputationData = new Map();
38
- this.updateTimer = null;
39
- this.isInitialized = false;
40
- // Merge with default config
41
- this.config = {
42
- ...DEFAULT_CONFIG,
43
- ...config,
44
- dataSources: {
45
- ...DEFAULT_CONFIG.dataSources,
46
- ...config.dataSources
47
- },
48
- alertThresholds: {
49
- ...DEFAULT_CONFIG.alertThresholds,
50
- ...config.alertThresholds
51
- }
52
- };
53
- this.storageManager = storageManager;
54
- // If no storage manager provided, log warning
55
- if (!storageManager) {
56
- logger.log('warn', '⚠️ WARNING: SenderReputationMonitor initialized without StorageManager.\n' +
57
- ' Reputation data will only be stored to filesystem.\n' +
58
- ' Consider passing a StorageManager instance for better storage flexibility.');
59
- }
60
- // Initialize (async, but we don't await here to avoid blocking constructor)
61
- this.initialize().catch(error => {
62
- logger.log('error', `Failed to initialize SenderReputationMonitor: ${error.message}`, {
63
- stack: error.stack
64
- });
65
- });
66
- }
67
- /**
68
- * Get the singleton instance
69
- * @param config Configuration options
70
- * @param storageManager Optional StorageManager instance
71
- * @returns Singleton instance
72
- */
73
- static getInstance(config = {}, storageManager) {
74
- if (!SenderReputationMonitor.instance) {
75
- SenderReputationMonitor.instance = new SenderReputationMonitor(config, storageManager);
76
- }
77
- return SenderReputationMonitor.instance;
78
- }
79
- /**
80
- * Initialize the reputation monitor
81
- */
82
- async initialize() {
83
- if (this.isInitialized)
84
- return;
85
- try {
86
- // Only load data if not running in a test environment
87
- const isTestEnvironment = process.env.NODE_ENV === 'test' || !!process.env.JEST_WORKER_ID;
88
- if (!isTestEnvironment) {
89
- // Load existing reputation data
90
- await this.loadReputationData();
91
- }
92
- // Initialize data for any new domains
93
- for (const domain of this.config.domains) {
94
- if (!this.reputationData.has(domain)) {
95
- this.initializeDomainData(domain);
96
- }
97
- }
98
- // Schedule updates if enabled and not in test environment
99
- if (this.config.enabled && !isTestEnvironment) {
100
- this.scheduleUpdates();
101
- }
102
- this.isInitialized = true;
103
- logger.log('info', `Sender Reputation Monitor initialized for ${this.config.domains.length} domains`);
104
- }
105
- catch (error) {
106
- logger.log('error', `Failed to initialize Sender Reputation Monitor: ${error.message}`, {
107
- stack: error.stack
108
- });
109
- }
110
- }
111
- /**
112
- * Initialize reputation data for a new domain
113
- * @param domain Domain to initialize
114
- */
115
- initializeDomainData(domain) {
116
- // Create new domain reputation metrics with default values
117
- const newMetrics = {
118
- domain,
119
- lastUpdated: new Date(),
120
- volume: {
121
- sent: 0,
122
- delivered: 0,
123
- hardBounces: 0,
124
- softBounces: 0,
125
- dailySendVolume: {}
126
- },
127
- engagement: {
128
- opens: 0,
129
- clicks: 0,
130
- openRate: 0,
131
- clickRate: 0,
132
- clickToOpenRate: 0
133
- },
134
- complaints: {
135
- total: 0,
136
- rate: 0,
137
- topDomains: []
138
- },
139
- authentication: {
140
- spfPassRate: 100, // Assume perfect initially
141
- dkimPassRate: 100,
142
- dmarcPassRate: 100,
143
- failures: []
144
- },
145
- blocklist: {
146
- listed: false,
147
- activeListings: [],
148
- recentDelistings: []
149
- },
150
- inboxPlacement: {
151
- overall: 95, // Start with optimistic estimate
152
- providers: {
153
- gmail: 95,
154
- outlook: 95,
155
- yahoo: 95,
156
- aol: 95,
157
- other: 95
158
- }
159
- },
160
- historical: {
161
- reputationScores: {},
162
- trends: {
163
- openRate: 0,
164
- complaintRate: 0,
165
- bounceRate: 0,
166
- spamListings: 0
167
- }
168
- }
169
- };
170
- // Generate some initial historical data points
171
- const today = new Date();
172
- for (let i = 0; i < 30; i++) {
173
- const date = new Date(today);
174
- date.setDate(date.getDate() - i);
175
- const dateKey = date.toISOString().split('T')[0];
176
- newMetrics.historical.reputationScores[dateKey] = 95; // Default good score
177
- newMetrics.volume.dailySendVolume[dateKey] = 0;
178
- }
179
- // Save the new metrics
180
- this.reputationData.set(domain, newMetrics);
181
- logger.log('info', `Initialized reputation data for domain ${domain}`);
182
- }
183
- /**
184
- * Schedule regular reputation data updates
185
- */
186
- scheduleUpdates() {
187
- if (this.updateTimer) {
188
- clearTimeout(this.updateTimer);
189
- }
190
- this.updateTimer = setTimeout(async () => {
191
- await this.updateAllDomainMetrics();
192
- this.scheduleUpdates(); // Reschedule for next update
193
- }, this.config.updateFrequency);
194
- logger.log('info', `Scheduled reputation updates every ${this.config.updateFrequency / (60 * 60 * 1000)} hours`);
195
- }
196
- /**
197
- * Update metrics for all monitored domains
198
- */
199
- async updateAllDomainMetrics() {
200
- if (!this.config.enabled)
201
- return;
202
- logger.log('info', 'Starting reputation metrics update for all domains');
203
- for (const domain of this.config.domains) {
204
- try {
205
- await this.updateDomainMetrics(domain);
206
- logger.log('info', `Updated reputation metrics for ${domain}`);
207
- }
208
- catch (error) {
209
- logger.log('error', `Error updating metrics for ${domain}: ${error.message}`, {
210
- stack: error.stack
211
- });
212
- }
213
- }
214
- // Save all updated data
215
- await this.saveReputationData();
216
- logger.log('info', 'Completed reputation metrics update for all domains');
217
- }
218
- /**
219
- * Update reputation metrics for a specific domain
220
- * @param domain Domain to update
221
- */
222
- async updateDomainMetrics(domain) {
223
- const metrics = this.reputationData.get(domain);
224
- if (!metrics) {
225
- logger.log('warn', `No reputation data found for domain ${domain}`);
226
- return;
227
- }
228
- try {
229
- // Update last updated timestamp
230
- metrics.lastUpdated = new Date();
231
- // Check blocklist status
232
- await this.checkBlocklistStatus(domain, metrics);
233
- // Update historical data
234
- this.updateHistoricalData(metrics);
235
- // Calculate current reputation score
236
- const reputationScore = this.calculateReputationScore(metrics);
237
- // Save current reputation score to historical data
238
- const today = new Date().toISOString().split('T')[0];
239
- metrics.historical.reputationScores[today] = reputationScore;
240
- // Calculate trends
241
- this.calculateTrends(metrics);
242
- // Check alert thresholds
243
- this.checkAlertThresholds(metrics);
244
- }
245
- catch (error) {
246
- logger.log('error', `Error in updateDomainMetrics for ${domain}: ${error.message}`, {
247
- stack: error.stack
248
- });
249
- }
250
- }
251
- /**
252
- * Check domain blocklist status
253
- * @param domain Domain to check
254
- * @param metrics Metrics to update
255
- */
256
- async checkBlocklistStatus(domain, metrics) {
257
- // Skip DNS lookups in test environment
258
- const isTestEnvironment = process.env.NODE_ENV === 'test' || !!process.env.JEST_WORKER_ID;
259
- if (isTestEnvironment || !this.config.dataSources.spamLists?.length) {
260
- return;
261
- }
262
- const previouslyListed = metrics.blocklist.listed;
263
- const previousListings = new Set(metrics.blocklist.activeListings.map(l => l.list));
264
- // Store current listings to detect changes
265
- const currentListings = [];
266
- // Check each blocklist
267
- for (const list of this.config.dataSources.spamLists) {
268
- try {
269
- const isListed = await this.checkDomainOnBlocklist(domain, list);
270
- if (isListed) {
271
- // If already known to be listed on this one, keep the original listing date
272
- const existingListing = metrics.blocklist.activeListings.find(l => l.list === list);
273
- if (existingListing) {
274
- currentListings.push(existingListing);
275
- }
276
- else {
277
- // New listing
278
- currentListings.push({
279
- list,
280
- listedSince: new Date()
281
- });
282
- }
283
- }
284
- }
285
- catch (error) {
286
- logger.log('warn', `Error checking ${domain} on blocklist ${list}: ${error.message}`);
287
- }
288
- }
289
- // Update active listings
290
- metrics.blocklist.activeListings = currentListings;
291
- metrics.blocklist.listed = currentListings.length > 0;
292
- // Check for delistings
293
- if (previouslyListed) {
294
- const currentListsSet = new Set(currentListings.map(l => l.list));
295
- // Convert Set to Array for compatibility with older JS versions
296
- Array.from(previousListings).forEach(list => {
297
- if (!currentListsSet.has(list)) {
298
- // This list no longer contains the domain - it was delisted
299
- const previousListing = metrics.blocklist.activeListings.find(l => l.list === list);
300
- if (previousListing) {
301
- metrics.blocklist.recentDelistings.push({
302
- list,
303
- listedFrom: previousListing.listedSince,
304
- listedTo: new Date()
305
- });
306
- }
307
- }
308
- });
309
- // Keep only recent delistings (last 90 days)
310
- const ninetyDaysAgo = new Date();
311
- ninetyDaysAgo.setDate(ninetyDaysAgo.getDate() - 90);
312
- metrics.blocklist.recentDelistings = metrics.blocklist.recentDelistings
313
- .filter(d => d.listedTo > ninetyDaysAgo);
314
- }
315
- }
316
- /**
317
- * Check if a domain is on a specific blocklist
318
- * @param domain Domain to check
319
- * @param list Blocklist to check
320
- * @returns Whether the domain is listed
321
- */
322
- async checkDomainOnBlocklist(domain, list) {
323
- try {
324
- // Look up the domain in the blocklist (simplified)
325
- if (list === 'zen.spamhaus.org') {
326
- // For Spamhaus and similar lists, we check the domain MX IPs
327
- const mxRecords = await plugins.dns.promises.resolveMx(domain);
328
- if (mxRecords && mxRecords.length > 0) {
329
- // Check the primary MX record
330
- const primaryMx = mxRecords.sort((a, b) => a.priority - b.priority)[0].exchange;
331
- // Resolve IP addresses for the MX
332
- const ips = await plugins.dns.promises.resolve(primaryMx);
333
- // Check the first IP
334
- if (ips.length > 0) {
335
- const ip = ips[0];
336
- const reversedIp = ip.split('.').reverse().join('.');
337
- const lookupDomain = `${reversedIp}.${list}`;
338
- try {
339
- await plugins.dns.promises.resolve(lookupDomain);
340
- return true; // Listed
341
- }
342
- catch (err) {
343
- if (err.code === 'ENOTFOUND') {
344
- return false; // Not listed
345
- }
346
- throw err; // Other error
347
- }
348
- }
349
- }
350
- return false;
351
- }
352
- else {
353
- // For domain-based blocklists
354
- const lookupDomain = `${domain}.${list}`;
355
- try {
356
- await plugins.dns.promises.resolve(lookupDomain);
357
- return true; // Listed
358
- }
359
- catch (err) {
360
- if (err.code === 'ENOTFOUND') {
361
- return false; // Not listed
362
- }
363
- throw err; // Other error
364
- }
365
- }
366
- }
367
- catch (error) {
368
- logger.log('warn', `Error checking blocklist status for ${domain} on ${list}: ${error.message}`);
369
- return false; // Assume not listed on error
370
- }
371
- }
372
- /**
373
- * Update historical data in metrics
374
- * @param metrics Metrics to update
375
- */
376
- updateHistoricalData(metrics) {
377
- // Keep only the last 30 days of data
378
- const dates = Object.keys(metrics.historical.reputationScores)
379
- .sort((a, b) => b.localeCompare(a)); // Sort descending
380
- if (dates.length > 30) {
381
- const daysToKeep = dates.slice(0, 30);
382
- const newScores = {};
383
- for (const day of daysToKeep) {
384
- newScores[day] = metrics.historical.reputationScores[day];
385
- }
386
- metrics.historical.reputationScores = newScores;
387
- }
388
- // Same for daily send volume
389
- const volumeDates = Object.keys(metrics.volume.dailySendVolume)
390
- .sort((a, b) => b.localeCompare(a));
391
- if (volumeDates.length > 30) {
392
- const daysToKeep = volumeDates.slice(0, 30);
393
- const newVolume = {};
394
- for (const day of daysToKeep) {
395
- newVolume[day] = metrics.volume.dailySendVolume[day];
396
- }
397
- metrics.volume.dailySendVolume = newVolume;
398
- }
399
- }
400
- /**
401
- * Calculate reputation score from metrics
402
- * @param metrics Domain reputation metrics
403
- * @returns Reputation score (0-100)
404
- */
405
- calculateReputationScore(metrics) {
406
- // Calculate component scores
407
- const components = {
408
- engagement: this.calculateEngagementScore(metrics),
409
- complaints: this.calculateComplaintScore(metrics),
410
- authentication: this.calculateAuthenticationScore(metrics),
411
- volumeStability: this.calculateVolumeStabilityScore(metrics),
412
- infrastructure: this.calculateInfrastructureScore(metrics),
413
- blocklist: this.calculateBlocklistScore(metrics)
414
- };
415
- // Apply weights to components
416
- const weightedScore = components.engagement * 0.25 +
417
- components.complaints * 0.25 +
418
- components.authentication * 0.2 +
419
- components.volumeStability * 0.1 +
420
- components.infrastructure * 0.1 +
421
- components.blocklist * 0.1;
422
- // Round to 2 decimal places
423
- return Math.round(weightedScore * 100) / 100;
424
- }
425
- /**
426
- * Calculate engagement component score
427
- * @param metrics Domain metrics
428
- * @returns Engagement score (0-100)
429
- */
430
- calculateEngagementScore(metrics) {
431
- const openRate = metrics.engagement.openRate;
432
- const clickRate = metrics.engagement.clickRate;
433
- // Benchmark open and click rates
434
- // <5% open rate = poor (score: 0-30)
435
- // 5-15% = average (score: 30-70)
436
- // >15% = good (score: 70-100)
437
- let openScore = 0;
438
- if (openRate < 5) {
439
- openScore = openRate * 6; // 0-30 scale
440
- }
441
- else if (openRate < 15) {
442
- openScore = 30 + (openRate - 5) * 4; // 30-70 scale
443
- }
444
- else {
445
- openScore = 70 + Math.min(30, (openRate - 15) * 2); // 70-100 scale
446
- }
447
- // Similarly for click rate
448
- let clickScore = 0;
449
- if (clickRate < 1) {
450
- clickScore = clickRate * 30; // 0-30 scale
451
- }
452
- else if (clickRate < 5) {
453
- clickScore = 30 + (clickRate - 1) * 10; // 30-70 scale
454
- }
455
- else {
456
- clickScore = 70 + Math.min(30, (clickRate - 5) * 6); // 70-100 scale
457
- }
458
- // Combine with 60% weight to open rate, 40% to click rate
459
- return (openScore * 0.6 + clickScore * 0.4);
460
- }
461
- /**
462
- * Calculate complaint component score
463
- * @param metrics Domain metrics
464
- * @returns Complaint score (0-100)
465
- */
466
- calculateComplaintScore(metrics) {
467
- const complaintRate = metrics.complaints.rate;
468
- // Industry standard: complaint rate should be under 0.1%
469
- // 0% = perfect (score: 100)
470
- // 0.1% = threshold (score: 70)
471
- // 0.5% = problematic (score: 30)
472
- // 1%+ = critical (score: 0)
473
- if (complaintRate === 0)
474
- return 100;
475
- if (complaintRate >= 1)
476
- return 0;
477
- if (complaintRate < 0.1) {
478
- // 0-0.1% maps to 100-70
479
- return 100 - (complaintRate / 0.1) * 30;
480
- }
481
- else if (complaintRate < 0.5) {
482
- // 0.1-0.5% maps to 70-30
483
- return 70 - ((complaintRate - 0.1) / 0.4) * 40;
484
- }
485
- else {
486
- // 0.5-1% maps to 30-0
487
- return 30 - ((complaintRate - 0.5) / 0.5) * 30;
488
- }
489
- }
490
- /**
491
- * Calculate authentication component score
492
- * @param metrics Domain metrics
493
- * @returns Authentication score (0-100)
494
- */
495
- calculateAuthenticationScore(metrics) {
496
- const spfRate = metrics.authentication.spfPassRate;
497
- const dkimRate = metrics.authentication.dkimPassRate;
498
- const dmarcRate = metrics.authentication.dmarcPassRate;
499
- // Weight SPF, DKIM, and DMARC
500
- return (spfRate * 0.3 + dkimRate * 0.3 + dmarcRate * 0.4);
501
- }
502
- /**
503
- * Calculate volume stability component score
504
- * @param metrics Domain metrics
505
- * @returns Volume stability score (0-100)
506
- */
507
- calculateVolumeStabilityScore(metrics) {
508
- const volumes = Object.values(metrics.volume.dailySendVolume);
509
- if (volumes.length < 2)
510
- return 100; // Not enough data
511
- // Calculate coefficient of variation (stdev / mean)
512
- const mean = volumes.reduce((sum, v) => sum + v, 0) / volumes.length;
513
- if (mean === 0)
514
- return 100; // No sending activity
515
- const variance = volumes.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / volumes.length;
516
- const stdev = Math.sqrt(variance);
517
- const cv = stdev / mean;
518
- // Convert to score: lower CV means more stability
519
- // CV < 0.1 is very stable (score: 90-100)
520
- // CV < 0.5 is normal (score: 60-90)
521
- // CV < 1.0 is somewhat unstable (score: 30-60)
522
- // CV >= 1.0 is unstable (score: 0-30)
523
- if (cv < 0.1) {
524
- return 90 + (1 - cv / 0.1) * 10;
525
- }
526
- else if (cv < 0.5) {
527
- return 60 + (1 - (cv - 0.1) / 0.4) * 30;
528
- }
529
- else if (cv < 1.0) {
530
- return 30 + (1 - (cv - 0.5) / 0.5) * 30;
531
- }
532
- else {
533
- return Math.max(0, 30 - (cv - 1.0) * 10);
534
- }
535
- }
536
- /**
537
- * Calculate infrastructure component score
538
- * @param metrics Domain metrics
539
- * @returns Infrastructure score (0-100)
540
- */
541
- calculateInfrastructureScore(metrics) {
542
- // This is a placeholder; in reality, this would be based on:
543
- // - IP reputation
544
- // - Reverse DNS configuration
545
- // - IP warming status
546
- // - Historical IP behavior
547
- // For now, assume good infrastructure
548
- return 90;
549
- }
550
- /**
551
- * Calculate blocklist component score
552
- * @param metrics Domain metrics
553
- * @returns Blocklist score (0-100)
554
- */
555
- calculateBlocklistScore(metrics) {
556
- // If currently listed on any blocklist, score is heavily impacted
557
- if (metrics.blocklist.listed) {
558
- // Number of active listings determines severity
559
- const listingCount = metrics.blocklist.activeListings.length;
560
- if (listingCount >= 3)
561
- return 0; // Critical: listed on 3+ lists
562
- if (listingCount === 2)
563
- return 20; // Severe: listed on 2 lists
564
- return 40; // Serious: listed on 1 list
565
- }
566
- // If recently delisted, some penalty still applies
567
- if (metrics.blocklist.recentDelistings.length > 0) {
568
- // Check how recent the delistings are
569
- const now = new Date();
570
- const mostRecent = metrics.blocklist.recentDelistings
571
- .reduce((latest, delisting) => delisting.listedTo > latest ? delisting.listedTo : latest, new Date(0));
572
- const daysSinceDelisting = Math.floor((now.getTime() - mostRecent.getTime()) / (24 * 60 * 60 * 1000));
573
- // Score improves as time passes since delisting
574
- if (daysSinceDelisting < 7)
575
- return 60; // Delisted within last week
576
- if (daysSinceDelisting < 30)
577
- return 80; // Delisted within last month
578
- return 90; // Delisted over a month ago
579
- }
580
- // Never listed
581
- return 100;
582
- }
583
- /**
584
- * Calculate trend metrics
585
- * @param metrics Domain metrics to update
586
- */
587
- calculateTrends(metrics) {
588
- // Get dates in descending order
589
- const dates = Object.keys(metrics.historical.reputationScores)
590
- .sort((a, b) => b.localeCompare(a));
591
- if (dates.length < 7) {
592
- // Not enough data for trends
593
- metrics.historical.trends = {
594
- openRate: 0,
595
- complaintRate: 0,
596
- bounceRate: 0,
597
- spamListings: 0
598
- };
599
- return;
600
- }
601
- // Calculate trends over past 7 days compared to previous 7 days
602
- const current7Days = dates.slice(0, 7);
603
- const previous7Days = dates.slice(7, 14);
604
- if (previous7Days.length < 7) {
605
- // Not enough historical data
606
- return;
607
- }
608
- // Calculate averages for the periods
609
- const currentReputation = current7Days.reduce((sum, date) => sum + metrics.historical.reputationScores[date], 0) / current7Days.length;
610
- const previousReputation = previous7Days.reduce((sum, date) => sum + metrics.historical.reputationScores[date], 0) / previous7Days.length;
611
- // Calculate percent change
612
- const reputationChange = ((currentReputation - previousReputation) / previousReputation) * 100;
613
- // For now, use reputation change for all trends (in a real implementation
614
- // we would calculate each metric's trend separately)
615
- metrics.historical.trends = {
616
- openRate: reputationChange,
617
- complaintRate: -reputationChange, // Inverse for complaint rate (negative is good)
618
- bounceRate: -reputationChange, // Inverse for bounce rate
619
- spamListings: -reputationChange // Inverse for spam listings
620
- };
621
- }
622
- /**
623
- * Check if metrics exceed alert thresholds
624
- * @param metrics Domain metrics to check
625
- */
626
- checkAlertThresholds(metrics) {
627
- const thresholds = this.config.alertThresholds;
628
- const today = new Date().toISOString().split('T')[0];
629
- const todayScore = metrics.historical.reputationScores[today] || 0;
630
- // Check reputation score
631
- if (todayScore < thresholds.minReputationScore) {
632
- this.sendAlert(metrics.domain, 'reputation_score', {
633
- score: todayScore,
634
- threshold: thresholds.minReputationScore
635
- });
636
- }
637
- // Check complaint rate
638
- if (metrics.complaints.rate > thresholds.maxComplaintRate) {
639
- this.sendAlert(metrics.domain, 'complaint_rate', {
640
- rate: metrics.complaints.rate,
641
- threshold: thresholds.maxComplaintRate
642
- });
643
- }
644
- // Check bounce rate
645
- const bounceRate = (metrics.volume.hardBounces + metrics.volume.softBounces) /
646
- Math.max(1, metrics.volume.sent) * 100;
647
- if (bounceRate > thresholds.maxBounceRate) {
648
- this.sendAlert(metrics.domain, 'bounce_rate', {
649
- rate: bounceRate,
650
- threshold: thresholds.maxBounceRate
651
- });
652
- }
653
- // Check open rate
654
- if (metrics.engagement.openRate < thresholds.minOpenRate) {
655
- this.sendAlert(metrics.domain, 'open_rate', {
656
- rate: metrics.engagement.openRate,
657
- threshold: thresholds.minOpenRate
658
- });
659
- }
660
- // Check blocklist status
661
- if (metrics.blocklist.listed) {
662
- this.sendAlert(metrics.domain, 'blocklist', {
663
- lists: metrics.blocklist.activeListings.map(l => l.list)
664
- });
665
- }
666
- }
667
- /**
668
- * Send an alert for a reputation issue
669
- * @param domain Domain with the issue
670
- * @param alertType Type of alert
671
- * @param data Alert data
672
- */
673
- sendAlert(domain, alertType, data) {
674
- logger.log('warn', `Reputation alert for ${domain}: ${alertType}`, data);
675
- // In a real implementation, this would send alerts via email,
676
- // notification systems, webhooks, etc.
677
- }
678
- /**
679
- * Record a send event for domain reputation tracking
680
- * @param domain The domain sending the email
681
- * @param event Event details
682
- */
683
- recordSendEvent(domain, event) {
684
- // Ensure we have metrics for this domain
685
- if (!this.reputationData.has(domain)) {
686
- this.initializeDomainData(domain);
687
- }
688
- const metrics = this.reputationData.get(domain);
689
- const count = event.count || 1;
690
- const today = new Date().toISOString().split('T')[0];
691
- // Update metrics based on event type
692
- switch (event.type) {
693
- case 'sent':
694
- metrics.volume.sent += count;
695
- // Update daily send volume
696
- metrics.volume.dailySendVolume[today] =
697
- (metrics.volume.dailySendVolume[today] || 0) + count;
698
- break;
699
- case 'delivered':
700
- metrics.volume.delivered += count;
701
- break;
702
- case 'bounce':
703
- if (event.hardBounce) {
704
- metrics.volume.hardBounces += count;
705
- }
706
- else {
707
- metrics.volume.softBounces += count;
708
- }
709
- break;
710
- case 'complaint':
711
- metrics.complaints.total += count;
712
- // Track by receiving domain
713
- if (event.receivingDomain) {
714
- const domainIndex = metrics.complaints.topDomains.findIndex(d => d.domain === event.receivingDomain);
715
- if (domainIndex >= 0) {
716
- metrics.complaints.topDomains[domainIndex].count += count;
717
- metrics.complaints.topDomains[domainIndex].rate =
718
- metrics.complaints.topDomains[domainIndex].count / Math.max(1, metrics.volume.sent);
719
- }
720
- else {
721
- metrics.complaints.topDomains.push({
722
- domain: event.receivingDomain,
723
- count,
724
- rate: count / Math.max(1, metrics.volume.sent)
725
- });
726
- }
727
- // Sort by count
728
- metrics.complaints.topDomains.sort((a, b) => b.count - a.count);
729
- // Keep only top 10
730
- if (metrics.complaints.topDomains.length > 10) {
731
- metrics.complaints.topDomains = metrics.complaints.topDomains.slice(0, 10);
732
- }
733
- }
734
- // Update overall complaint rate
735
- metrics.complaints.rate =
736
- metrics.complaints.total / Math.max(1, metrics.volume.sent);
737
- break;
738
- case 'open':
739
- metrics.engagement.opens += count;
740
- metrics.engagement.openRate =
741
- metrics.engagement.opens / Math.max(1, metrics.volume.delivered);
742
- break;
743
- case 'click':
744
- metrics.engagement.clicks += count;
745
- metrics.engagement.clickRate =
746
- metrics.engagement.clicks / Math.max(1, metrics.volume.delivered);
747
- metrics.engagement.clickToOpenRate =
748
- metrics.engagement.clicks / Math.max(1, metrics.engagement.opens);
749
- break;
750
- }
751
- // Update last updated timestamp
752
- metrics.lastUpdated = new Date();
753
- // Save data periodically (not after every event to avoid excessive I/O)
754
- // Skip in test environment
755
- const isTestEnvironment = process.env.NODE_ENV === 'test' || !!process.env.JEST_WORKER_ID;
756
- if (!isTestEnvironment && Math.random() < 0.01) { // ~1% chance to save on each event
757
- this.saveReputationData().catch(error => {
758
- logger.log('error', `Failed to save reputation data: ${error.message}`, {
759
- stack: error.stack
760
- });
761
- });
762
- }
763
- }
764
- /**
765
- * Get reputation data for a domain
766
- * @param domain Domain to get data for
767
- * @returns Reputation data
768
- */
769
- getReputationData(domain) {
770
- return this.reputationData.get(domain) || null;
771
- }
772
- /**
773
- * Get summary reputation data for all domains
774
- * @returns Summary data for all domains
775
- */
776
- getReputationSummary() {
777
- return Array.from(this.reputationData.entries())
778
- .map(([domain, metrics]) => {
779
- const today = new Date().toISOString().split('T')[0];
780
- const score = metrics.historical.reputationScores[today] || 0;
781
- // Determine status based on score
782
- let status;
783
- if (score >= 90)
784
- status = 'excellent';
785
- else if (score >= 75)
786
- status = 'good';
787
- else if (score >= 60)
788
- status = 'fair';
789
- else if (score >= 40)
790
- status = 'poor';
791
- else
792
- status = 'critical';
793
- return {
794
- domain,
795
- score,
796
- status,
797
- listed: metrics.blocklist.listed,
798
- trend: metrics.historical.trends.openRate // Use open rate trend as overall trend
799
- };
800
- })
801
- .sort((a, b) => b.score - a.score); // Sort by score descending
802
- }
803
- /**
804
- * Add a domain to monitor
805
- * @param domain Domain to monitor
806
- */
807
- addDomain(domain) {
808
- if (this.config.domains.includes(domain)) {
809
- logger.log('info', `Domain ${domain} is already being monitored`);
810
- return;
811
- }
812
- this.config.domains.push(domain);
813
- this.initializeDomainData(domain);
814
- this.saveReputationData().catch(error => {
815
- logger.log('error', `Failed to save reputation data after adding domain: ${error.message}`, {
816
- stack: error.stack
817
- });
818
- });
819
- logger.log('info', `Added ${domain} to reputation monitoring`);
820
- }
821
- /**
822
- * Remove a domain from monitoring
823
- * @param domain Domain to remove
824
- */
825
- removeDomain(domain) {
826
- const index = this.config.domains.indexOf(domain);
827
- if (index === -1) {
828
- logger.log('info', `Domain ${domain} is not being monitored`);
829
- return;
830
- }
831
- this.config.domains.splice(index, 1);
832
- this.reputationData.delete(domain);
833
- this.saveReputationData().catch(error => {
834
- logger.log('error', `Failed to save reputation data after removing domain: ${error.message}`, {
835
- stack: error.stack
836
- });
837
- });
838
- logger.log('info', `Removed ${domain} from reputation monitoring`);
839
- }
840
- /**
841
- * Load reputation data from storage
842
- */
843
- async loadReputationData() {
844
- // Skip loading in test environment to prevent file system race conditions
845
- const isTestEnvironment = process.env.NODE_ENV === 'test' || !!process.env.JEST_WORKER_ID;
846
- if (isTestEnvironment) {
847
- return;
848
- }
849
- try {
850
- // Try to load from storage manager first
851
- if (this.storageManager) {
852
- try {
853
- const data = await this.storageManager.get('/email/reputation/domain-reputation.json');
854
- if (data) {
855
- const reputationEntries = JSON.parse(data);
856
- for (const entry of reputationEntries) {
857
- // Restore Date objects
858
- entry.lastUpdated = new Date(entry.lastUpdated);
859
- for (const listing of entry.blocklist.activeListings) {
860
- listing.listedSince = new Date(listing.listedSince);
861
- }
862
- for (const delisting of entry.blocklist.recentDelistings) {
863
- delisting.listedFrom = new Date(delisting.listedFrom);
864
- delisting.listedTo = new Date(delisting.listedTo);
865
- }
866
- this.reputationData.set(entry.domain, entry);
867
- }
868
- logger.log('info', `Loaded reputation data for ${this.reputationData.size} domains from StorageManager`);
869
- return;
870
- }
871
- }
872
- catch (error) {
873
- // Fall through to filesystem migration check
874
- }
875
- // Check if data exists in filesystem and migrate it to storage manager
876
- const reputationDir = plugins.path.join(paths.dataDir, 'reputation');
877
- const dataFile = plugins.path.join(reputationDir, 'domain_reputation.json');
878
- if (plugins.fs.existsSync(dataFile)) {
879
- const data = plugins.fs.readFileSync(dataFile, 'utf8');
880
- const reputationEntries = JSON.parse(data);
881
- for (const entry of reputationEntries) {
882
- // Restore Date objects
883
- entry.lastUpdated = new Date(entry.lastUpdated);
884
- for (const listing of entry.blocklist.activeListings) {
885
- listing.listedSince = new Date(listing.listedSince);
886
- }
887
- for (const delisting of entry.blocklist.recentDelistings) {
888
- delisting.listedFrom = new Date(delisting.listedFrom);
889
- delisting.listedTo = new Date(delisting.listedTo);
890
- }
891
- this.reputationData.set(entry.domain, entry);
892
- }
893
- // Migrate to storage manager
894
- logger.log('info', `Migrating reputation data for ${this.reputationData.size} domains from filesystem to StorageManager`);
895
- await this.storageManager.set('/email/reputation/domain-reputation.json', JSON.stringify(Array.from(this.reputationData.values()), null, 2));
896
- logger.log('info', `Loaded and migrated reputation data for ${this.reputationData.size} domains`);
897
- }
898
- }
899
- else {
900
- // No storage manager, use filesystem directly
901
- const reputationDir = plugins.path.join(paths.dataDir, 'reputation');
902
- plugins.smartfile.fs.ensureDirSync(reputationDir);
903
- const dataFile = plugins.path.join(reputationDir, 'domain_reputation.json');
904
- if (plugins.fs.existsSync(dataFile)) {
905
- const data = plugins.fs.readFileSync(dataFile, 'utf8');
906
- const reputationEntries = JSON.parse(data);
907
- for (const entry of reputationEntries) {
908
- // Restore Date objects
909
- entry.lastUpdated = new Date(entry.lastUpdated);
910
- for (const listing of entry.blocklist.activeListings) {
911
- listing.listedSince = new Date(listing.listedSince);
912
- }
913
- for (const delisting of entry.blocklist.recentDelistings) {
914
- delisting.listedFrom = new Date(delisting.listedFrom);
915
- delisting.listedTo = new Date(delisting.listedTo);
916
- }
917
- this.reputationData.set(entry.domain, entry);
918
- }
919
- logger.log('info', `Loaded reputation data for ${this.reputationData.size} domains from filesystem`);
920
- }
921
- }
922
- }
923
- catch (error) {
924
- logger.log('error', `Failed to load reputation data: ${error.message}`, {
925
- stack: error.stack
926
- });
927
- }
928
- }
929
- /**
930
- * Save reputation data to storage
931
- */
932
- async saveReputationData() {
933
- // Skip saving in test environment to prevent file system race conditions
934
- const isTestEnvironment = process.env.NODE_ENV === 'test' || !!process.env.JEST_WORKER_ID;
935
- if (isTestEnvironment) {
936
- return;
937
- }
938
- try {
939
- const reputationEntries = Array.from(this.reputationData.values());
940
- // Save to storage manager if available
941
- if (this.storageManager) {
942
- await this.storageManager.set('/email/reputation/domain-reputation.json', JSON.stringify(reputationEntries, null, 2));
943
- logger.log('debug', `Saved reputation data for ${reputationEntries.length} domains to StorageManager`);
944
- }
945
- else {
946
- // No storage manager, use filesystem directly
947
- const reputationDir = plugins.path.join(paths.dataDir, 'reputation');
948
- plugins.smartfile.fs.ensureDirSync(reputationDir);
949
- const dataFile = plugins.path.join(reputationDir, 'domain_reputation.json');
950
- plugins.smartfile.memory.toFsSync(JSON.stringify(reputationEntries, null, 2), dataFile);
951
- logger.log('debug', `Saved reputation data for ${reputationEntries.length} domains to filesystem`);
952
- }
953
- }
954
- catch (error) {
955
- logger.log('error', `Failed to save reputation data: ${error.message}`, {
956
- stack: error.stack
957
- });
958
- }
959
- }
960
- }
961
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZW5kZXJyZXB1dGF0aW9ubW9uaXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2RlbGl2ZXJhYmlsaXR5L2NsYXNzZXMuc2VuZGVycmVwdXRhdGlvbm1vbml0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxLQUFLLEtBQUssTUFBTSxhQUFhLENBQUM7QUFDckMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQTBJdEM7O0dBRUc7QUFDSCxNQUFNLGNBQWMsR0FBdUM7SUFDekQsT0FBTyxFQUFFLElBQUk7SUFDYixPQUFPLEVBQUUsRUFBRTtJQUNYLGVBQWUsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQUUsUUFBUTtJQUM5QyxXQUFXLEVBQUU7UUFDWCxTQUFTLEVBQUU7WUFDVCxrQkFBa0I7WUFDbEIsZ0JBQWdCO1lBQ2hCLGlCQUFpQjtZQUNqQix3QkFBd0I7U0FDekI7UUFDRCxxQkFBcUIsRUFBRSxJQUFJO0tBQzVCO0lBQ0QsZUFBZSxFQUFFO1FBQ2Ysa0JBQWtCLEVBQUUsRUFBRTtRQUN0QixnQkFBZ0IsRUFBRSxHQUFHLEVBQUUsT0FBTztRQUM5QixhQUFhLEVBQUUsQ0FBQyxFQUFFLEtBQUs7UUFDdkIsV0FBVyxFQUFFLEVBQUUsQ0FBQyxNQUFNO0tBQ3ZCO0NBQ0YsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxPQUFPLHVCQUF1QjtJQVFsQzs7OztPQUlHO0lBQ0gsWUFBWSxTQUFtQyxFQUFFLEVBQUUsY0FBb0I7UUFWL0QsbUJBQWMsR0FBMEMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNsRSxnQkFBVyxHQUFtQixJQUFJLENBQUM7UUFDbkMsa0JBQWEsR0FBWSxLQUFLLENBQUM7UUFTckMsNEJBQTRCO1FBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDWixHQUFH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