@serve.zone/dcrouter 2.12.4

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