@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.
- package/.dockerignore +1 -0
- package/.gitea/workflows/docker_nottags.yaml +71 -0
- package/.gitea/workflows/docker_tags.yaml +106 -0
- package/.vscode/launch.json +11 -0
- package/.vscode/settings.json +26 -0
- package/Dockerfile +46 -0
- package/changelog.md +247 -0
- package/cli.child.js +4 -0
- package/cli.child.ts +4 -0
- package/cli.js +4 -0
- package/cli.ts.js +5 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.dcrouter.d.ts +238 -0
- package/dist_ts/classes.dcrouter.js +1008 -0
- package/dist_ts/config/index.d.ts +1 -0
- package/dist_ts/config/index.js +3 -0
- package/dist_ts/config/validator.d.ts +104 -0
- package/dist_ts/config/validator.js +152 -0
- package/dist_ts/deliverability/classes.ipwarmupmanager.d.ts +253 -0
- package/dist_ts/deliverability/classes.ipwarmupmanager.js +639 -0
- package/dist_ts/deliverability/classes.senderreputationmonitor.d.ts +300 -0
- package/dist_ts/deliverability/classes.senderreputationmonitor.js +961 -0
- package/dist_ts/deliverability/index.d.ts +2 -0
- package/dist_ts/deliverability/index.js +3 -0
- package/dist_ts/errors/base.errors.d.ts +224 -0
- package/dist_ts/errors/base.errors.js +310 -0
- package/dist_ts/errors/email.errors.d.ts +175 -0
- package/dist_ts/errors/email.errors.js +265 -0
- package/dist_ts/errors/error-handler.d.ts +98 -0
- package/dist_ts/errors/error-handler.js +282 -0
- package/dist_ts/errors/error.codes.d.ts +115 -0
- package/dist_ts/errors/error.codes.js +136 -0
- package/dist_ts/errors/index.d.ts +56 -0
- package/dist_ts/errors/index.js +138 -0
- package/dist_ts/errors/mta.errors.d.ts +259 -0
- package/dist_ts/errors/mta.errors.js +472 -0
- package/dist_ts/errors/reputation.errors.d.ts +183 -0
- package/dist_ts/errors/reputation.errors.js +292 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +6 -0
- package/dist_ts/logger.d.ts +17 -0
- package/dist_ts/logger.js +77 -0
- package/dist_ts/mail/core/classes.bouncemanager.d.ts +200 -0
- package/dist_ts/mail/core/classes.bouncemanager.js +778 -0
- package/dist_ts/mail/core/classes.email.d.ts +291 -0
- package/dist_ts/mail/core/classes.email.js +780 -0
- package/dist_ts/mail/core/classes.emailvalidator.d.ts +61 -0
- package/dist_ts/mail/core/classes.emailvalidator.js +182 -0
- package/dist_ts/mail/core/classes.templatemanager.d.ts +95 -0
- package/dist_ts/mail/core/classes.templatemanager.js +239 -0
- package/dist_ts/mail/core/index.d.ts +4 -0
- package/dist_ts/mail/core/index.js +6 -0
- package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +163 -0
- package/dist_ts/mail/delivery/classes.delivery.queue.js +485 -0
- package/dist_ts/mail/delivery/classes.delivery.system.d.ts +186 -0
- package/dist_ts/mail/delivery/classes.delivery.system.js +846 -0
- package/dist_ts/mail/delivery/classes.emailsendjob.d.ts +84 -0
- package/dist_ts/mail/delivery/classes.emailsendjob.js +362 -0
- package/dist_ts/mail/delivery/classes.emailsignjob.d.ts +18 -0
- package/dist_ts/mail/delivery/classes.emailsignjob.js +44 -0
- package/dist_ts/mail/delivery/classes.mta.config.d.ts +22 -0
- package/dist_ts/mail/delivery/classes.mta.config.js +51 -0
- package/dist_ts/mail/delivery/classes.ratelimiter.d.ts +98 -0
- package/dist_ts/mail/delivery/classes.ratelimiter.js +205 -0
- package/dist_ts/mail/delivery/classes.smtp.client.legacy.d.ts +275 -0
- package/dist_ts/mail/delivery/classes.smtp.client.legacy.js +973 -0
- package/dist_ts/mail/delivery/classes.unified.rate.limiter.d.ts +200 -0
- package/dist_ts/mail/delivery/classes.unified.rate.limiter.js +817 -0
- package/dist_ts/mail/delivery/index.d.ts +12 -0
- package/dist_ts/mail/delivery/index.js +18 -0
- package/dist_ts/mail/delivery/interfaces.d.ts +243 -0
- package/dist_ts/mail/delivery/interfaces.js +17 -0
- package/dist_ts/mail/delivery/smtpclient/auth-handler.d.ts +43 -0
- package/dist_ts/mail/delivery/smtpclient/auth-handler.js +188 -0
- package/dist_ts/mail/delivery/smtpclient/command-handler.d.ts +67 -0
- package/dist_ts/mail/delivery/smtpclient/command-handler.js +276 -0
- package/dist_ts/mail/delivery/smtpclient/connection-manager.d.ts +48 -0
- package/dist_ts/mail/delivery/smtpclient/connection-manager.js +238 -0
- package/dist_ts/mail/delivery/smtpclient/constants.d.ts +129 -0
- package/dist_ts/mail/delivery/smtpclient/constants.js +135 -0
- package/dist_ts/mail/delivery/smtpclient/create-client.d.ts +22 -0
- package/dist_ts/mail/delivery/smtpclient/create-client.js +86 -0
- package/dist_ts/mail/delivery/smtpclient/error-handler.d.ts +28 -0
- package/dist_ts/mail/delivery/smtpclient/error-handler.js +110 -0
- package/dist_ts/mail/delivery/smtpclient/index.d.ts +16 -0
- package/dist_ts/mail/delivery/smtpclient/index.js +21 -0
- package/dist_ts/mail/delivery/smtpclient/interfaces.d.ts +183 -0
- package/dist_ts/mail/delivery/smtpclient/interfaces.js +19 -0
- package/dist_ts/mail/delivery/smtpclient/smtp-client.d.ts +58 -0
- package/dist_ts/mail/delivery/smtpclient/smtp-client.js +279 -0
- package/dist_ts/mail/delivery/smtpclient/tls-handler.d.ts +33 -0
- package/dist_ts/mail/delivery/smtpclient/tls-handler.js +202 -0
- package/dist_ts/mail/delivery/smtpclient/utils/helpers.d.ts +77 -0
- package/dist_ts/mail/delivery/smtpclient/utils/helpers.js +196 -0
- package/dist_ts/mail/delivery/smtpclient/utils/logging.d.ts +46 -0
- package/dist_ts/mail/delivery/smtpclient/utils/logging.js +153 -0
- package/dist_ts/mail/delivery/smtpclient/utils/validation.d.ts +38 -0
- package/dist_ts/mail/delivery/smtpclient/utils/validation.js +139 -0
- package/dist_ts/mail/delivery/smtpserver/certificate-utils.d.ts +45 -0
- package/dist_ts/mail/delivery/smtpserver/certificate-utils.js +345 -0
- package/dist_ts/mail/delivery/smtpserver/command-handler.d.ts +156 -0
- package/dist_ts/mail/delivery/smtpserver/command-handler.js +1159 -0
- package/dist_ts/mail/delivery/smtpserver/connection-manager.d.ts +159 -0
- package/dist_ts/mail/delivery/smtpserver/connection-manager.js +894 -0
- package/dist_ts/mail/delivery/smtpserver/constants.d.ts +130 -0
- package/dist_ts/mail/delivery/smtpserver/constants.js +162 -0
- package/dist_ts/mail/delivery/smtpserver/create-server.d.ts +14 -0
- package/dist_ts/mail/delivery/smtpserver/create-server.js +28 -0
- package/dist_ts/mail/delivery/smtpserver/data-handler.d.ts +123 -0
- package/dist_ts/mail/delivery/smtpserver/data-handler.js +1148 -0
- package/dist_ts/mail/delivery/smtpserver/index.d.ts +20 -0
- package/dist_ts/mail/delivery/smtpserver/index.js +27 -0
- package/dist_ts/mail/delivery/smtpserver/interfaces.d.ts +530 -0
- package/dist_ts/mail/delivery/smtpserver/interfaces.js +10 -0
- package/dist_ts/mail/delivery/smtpserver/secure-server.d.ts +15 -0
- package/dist_ts/mail/delivery/smtpserver/secure-server.js +79 -0
- package/dist_ts/mail/delivery/smtpserver/security-handler.d.ts +86 -0
- package/dist_ts/mail/delivery/smtpserver/security-handler.js +234 -0
- package/dist_ts/mail/delivery/smtpserver/session-manager.d.ts +140 -0
- package/dist_ts/mail/delivery/smtpserver/session-manager.js +469 -0
- package/dist_ts/mail/delivery/smtpserver/smtp-server.d.ts +137 -0
- package/dist_ts/mail/delivery/smtpserver/smtp-server.js +666 -0
- package/dist_ts/mail/delivery/smtpserver/starttls-handler.d.ts +21 -0
- package/dist_ts/mail/delivery/smtpserver/starttls-handler.js +207 -0
- package/dist_ts/mail/delivery/smtpserver/tls-handler.d.ts +66 -0
- package/dist_ts/mail/delivery/smtpserver/tls-handler.js +261 -0
- package/dist_ts/mail/delivery/smtpserver/utils/adaptive-logging.d.ts +117 -0
- package/dist_ts/mail/delivery/smtpserver/utils/adaptive-logging.js +411 -0
- package/dist_ts/mail/delivery/smtpserver/utils/helpers.d.ts +78 -0
- package/dist_ts/mail/delivery/smtpserver/utils/helpers.js +208 -0
- package/dist_ts/mail/delivery/smtpserver/utils/logging.d.ts +106 -0
- package/dist_ts/mail/delivery/smtpserver/utils/logging.js +181 -0
- package/dist_ts/mail/delivery/smtpserver/utils/validation.d.ts +69 -0
- package/dist_ts/mail/delivery/smtpserver/utils/validation.js +360 -0
- package/dist_ts/mail/index.d.ts +8 -0
- package/dist_ts/mail/index.js +13 -0
- package/dist_ts/mail/routing/classes.dns.manager.d.ts +65 -0
- package/dist_ts/mail/routing/classes.dns.manager.js +413 -0
- package/dist_ts/mail/routing/classes.dnsmanager.d.ts +165 -0
- package/dist_ts/mail/routing/classes.dnsmanager.js +430 -0
- package/dist_ts/mail/routing/classes.domain.registry.d.ts +54 -0
- package/dist_ts/mail/routing/classes.domain.registry.js +118 -0
- package/dist_ts/mail/routing/classes.email.config.d.ts +64 -0
- package/dist_ts/mail/routing/classes.email.config.js +2 -0
- package/dist_ts/mail/routing/classes.email.router.d.ts +171 -0
- package/dist_ts/mail/routing/classes.email.router.js +491 -0
- package/dist_ts/mail/routing/classes.unified.email.server.d.ts +426 -0
- package/dist_ts/mail/routing/classes.unified.email.server.js +1454 -0
- package/dist_ts/mail/routing/index.d.ts +5 -0
- package/dist_ts/mail/routing/index.js +7 -0
- package/dist_ts/mail/routing/interfaces.d.ts +187 -0
- package/dist_ts/mail/routing/interfaces.js +2 -0
- package/dist_ts/mail/security/classes.dkimcreator.d.ts +68 -0
- package/dist_ts/mail/security/classes.dkimcreator.js +346 -0
- package/dist_ts/mail/security/classes.dkimverifier.d.ts +46 -0
- package/dist_ts/mail/security/classes.dkimverifier.js +317 -0
- package/dist_ts/mail/security/classes.dmarcverifier.d.ts +123 -0
- package/dist_ts/mail/security/classes.dmarcverifier.js +365 -0
- package/dist_ts/mail/security/classes.spfverifier.d.ts +103 -0
- package/dist_ts/mail/security/classes.spfverifier.js +492 -0
- package/dist_ts/mail/security/index.d.ts +4 -0
- package/dist_ts/mail/security/index.js +6 -0
- package/dist_ts/opsserver/classes.opsserver.d.ts +14 -0
- package/dist_ts/opsserver/classes.opsserver.js +37 -0
- package/dist_ts/opsserver/index.d.ts +1 -0
- package/dist_ts/opsserver/index.js +2 -0
- package/dist_ts/paths.d.ts +14 -0
- package/dist_ts/paths.js +39 -0
- package/dist_ts/plugins.d.ts +43 -0
- package/dist_ts/plugins.js +50 -0
- package/dist_ts/security/classes.contentscanner.d.ts +160 -0
- package/dist_ts/security/classes.contentscanner.js +634 -0
- package/dist_ts/security/classes.ipreputationchecker.d.ts +150 -0
- package/dist_ts/security/classes.ipreputationchecker.js +508 -0
- package/dist_ts/security/classes.securitylogger.d.ts +140 -0
- package/dist_ts/security/classes.securitylogger.js +232 -0
- package/dist_ts/security/index.d.ts +3 -0
- package/dist_ts/security/index.js +4 -0
- package/dist_ts/sms/classes.smsservice.d.ts +15 -0
- package/dist_ts/sms/classes.smsservice.js +72 -0
- package/dist_ts/sms/config/sms.config.d.ts +93 -0
- package/dist_ts/sms/config/sms.config.js +2 -0
- package/dist_ts/sms/config/sms.schema.d.ts +5 -0
- package/dist_ts/sms/config/sms.schema.js +121 -0
- package/dist_ts/sms/index.d.ts +1 -0
- package/dist_ts/sms/index.js +2 -0
- package/dist_ts/storage/classes.storagemanager.d.ts +82 -0
- package/dist_ts/storage/classes.storagemanager.js +341 -0
- package/dist_ts/storage/index.d.ts +1 -0
- package/dist_ts/storage/index.js +3 -0
- package/dist_ts/ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/ts/00_commitinfo_data.js +9 -0
- package/dist_ts/ts/classes.dcrouter.d.ts +238 -0
- package/dist_ts/ts/classes.dcrouter.js +1008 -0
- package/dist_ts/ts/config/index.d.ts +1 -0
- package/dist_ts/ts/config/index.js +3 -0
- package/dist_ts/ts/config/validator.d.ts +104 -0
- package/dist_ts/ts/config/validator.js +152 -0
- package/dist_ts/ts/deliverability/classes.ipwarmupmanager.d.ts +253 -0
- package/dist_ts/ts/deliverability/classes.ipwarmupmanager.js +639 -0
- package/dist_ts/ts/deliverability/classes.senderreputationmonitor.d.ts +300 -0
- package/dist_ts/ts/deliverability/classes.senderreputationmonitor.js +961 -0
- package/dist_ts/ts/deliverability/index.d.ts +2 -0
- package/dist_ts/ts/deliverability/index.js +3 -0
- package/dist_ts/ts/errors/base.errors.d.ts +224 -0
- package/dist_ts/ts/errors/base.errors.js +310 -0
- package/dist_ts/ts/errors/email.errors.d.ts +175 -0
- package/dist_ts/ts/errors/email.errors.js +265 -0
- package/dist_ts/ts/errors/error-handler.d.ts +98 -0
- package/dist_ts/ts/errors/error-handler.js +282 -0
- package/dist_ts/ts/errors/error.codes.d.ts +115 -0
- package/dist_ts/ts/errors/error.codes.js +136 -0
- package/dist_ts/ts/errors/index.d.ts +56 -0
- package/dist_ts/ts/errors/index.js +138 -0
- package/dist_ts/ts/errors/mta.errors.d.ts +259 -0
- package/dist_ts/ts/errors/mta.errors.js +472 -0
- package/dist_ts/ts/errors/reputation.errors.d.ts +183 -0
- package/dist_ts/ts/errors/reputation.errors.js +292 -0
- package/dist_ts/ts/index.d.ts +4 -0
- package/dist_ts/ts/index.js +6 -0
- package/dist_ts/ts/logger.d.ts +17 -0
- package/dist_ts/ts/logger.js +77 -0
- package/dist_ts/ts/mail/core/classes.bouncemanager.d.ts +200 -0
- package/dist_ts/ts/mail/core/classes.bouncemanager.js +778 -0
- package/dist_ts/ts/mail/core/classes.email.d.ts +291 -0
- package/dist_ts/ts/mail/core/classes.email.js +780 -0
- package/dist_ts/ts/mail/core/classes.emailvalidator.d.ts +61 -0
- package/dist_ts/ts/mail/core/classes.emailvalidator.js +182 -0
- package/dist_ts/ts/mail/core/classes.templatemanager.d.ts +95 -0
- package/dist_ts/ts/mail/core/classes.templatemanager.js +239 -0
- package/dist_ts/ts/mail/core/index.d.ts +4 -0
- package/dist_ts/ts/mail/core/index.js +6 -0
- package/dist_ts/ts/mail/delivery/classes.delivery.queue.d.ts +163 -0
- package/dist_ts/ts/mail/delivery/classes.delivery.queue.js +485 -0
- package/dist_ts/ts/mail/delivery/classes.delivery.system.d.ts +186 -0
- package/dist_ts/ts/mail/delivery/classes.delivery.system.js +846 -0
- package/dist_ts/ts/mail/delivery/classes.emailsendjob.d.ts +84 -0
- package/dist_ts/ts/mail/delivery/classes.emailsendjob.js +362 -0
- package/dist_ts/ts/mail/delivery/classes.emailsignjob.d.ts +18 -0
- package/dist_ts/ts/mail/delivery/classes.emailsignjob.js +44 -0
- package/dist_ts/ts/mail/delivery/classes.mta.config.d.ts +22 -0
- package/dist_ts/ts/mail/delivery/classes.mta.config.js +51 -0
- package/dist_ts/ts/mail/delivery/classes.ratelimiter.d.ts +98 -0
- package/dist_ts/ts/mail/delivery/classes.ratelimiter.js +205 -0
- package/dist_ts/ts/mail/delivery/classes.smtp.client.legacy.d.ts +275 -0
- package/dist_ts/ts/mail/delivery/classes.smtp.client.legacy.js +973 -0
- package/dist_ts/ts/mail/delivery/classes.unified.rate.limiter.d.ts +200 -0
- package/dist_ts/ts/mail/delivery/classes.unified.rate.limiter.js +817 -0
- package/dist_ts/ts/mail/delivery/index.d.ts +12 -0
- package/dist_ts/ts/mail/delivery/index.js +18 -0
- package/dist_ts/ts/mail/delivery/interfaces.d.ts +243 -0
- package/dist_ts/ts/mail/delivery/interfaces.js +17 -0
- package/dist_ts/ts/mail/delivery/smtpclient/auth-handler.d.ts +43 -0
- package/dist_ts/ts/mail/delivery/smtpclient/auth-handler.js +188 -0
- package/dist_ts/ts/mail/delivery/smtpclient/command-handler.d.ts +67 -0
- package/dist_ts/ts/mail/delivery/smtpclient/command-handler.js +276 -0
- package/dist_ts/ts/mail/delivery/smtpclient/connection-manager.d.ts +48 -0
- package/dist_ts/ts/mail/delivery/smtpclient/connection-manager.js +238 -0
- package/dist_ts/ts/mail/delivery/smtpclient/constants.d.ts +129 -0
- package/dist_ts/ts/mail/delivery/smtpclient/constants.js +135 -0
- package/dist_ts/ts/mail/delivery/smtpclient/create-client.d.ts +22 -0
- package/dist_ts/ts/mail/delivery/smtpclient/create-client.js +86 -0
- package/dist_ts/ts/mail/delivery/smtpclient/error-handler.d.ts +28 -0
- package/dist_ts/ts/mail/delivery/smtpclient/error-handler.js +110 -0
- package/dist_ts/ts/mail/delivery/smtpclient/index.d.ts +16 -0
- package/dist_ts/ts/mail/delivery/smtpclient/index.js +21 -0
- package/dist_ts/ts/mail/delivery/smtpclient/interfaces.d.ts +183 -0
- package/dist_ts/ts/mail/delivery/smtpclient/interfaces.js +19 -0
- package/dist_ts/ts/mail/delivery/smtpclient/smtp-client.d.ts +58 -0
- package/dist_ts/ts/mail/delivery/smtpclient/smtp-client.js +279 -0
- package/dist_ts/ts/mail/delivery/smtpclient/tls-handler.d.ts +33 -0
- package/dist_ts/ts/mail/delivery/smtpclient/tls-handler.js +202 -0
- package/dist_ts/ts/mail/delivery/smtpclient/utils/helpers.d.ts +77 -0
- package/dist_ts/ts/mail/delivery/smtpclient/utils/helpers.js +196 -0
- package/dist_ts/ts/mail/delivery/smtpclient/utils/logging.d.ts +46 -0
- package/dist_ts/ts/mail/delivery/smtpclient/utils/logging.js +153 -0
- package/dist_ts/ts/mail/delivery/smtpclient/utils/validation.d.ts +38 -0
- package/dist_ts/ts/mail/delivery/smtpclient/utils/validation.js +139 -0
- package/dist_ts/ts/mail/delivery/smtpserver/certificate-utils.d.ts +45 -0
- package/dist_ts/ts/mail/delivery/smtpserver/certificate-utils.js +345 -0
- package/dist_ts/ts/mail/delivery/smtpserver/command-handler.d.ts +156 -0
- package/dist_ts/ts/mail/delivery/smtpserver/command-handler.js +1159 -0
- package/dist_ts/ts/mail/delivery/smtpserver/connection-manager.d.ts +159 -0
- package/dist_ts/ts/mail/delivery/smtpserver/connection-manager.js +894 -0
- package/dist_ts/ts/mail/delivery/smtpserver/constants.d.ts +130 -0
- package/dist_ts/ts/mail/delivery/smtpserver/constants.js +162 -0
- package/dist_ts/ts/mail/delivery/smtpserver/create-server.d.ts +14 -0
- package/dist_ts/ts/mail/delivery/smtpserver/create-server.js +28 -0
- package/dist_ts/ts/mail/delivery/smtpserver/data-handler.d.ts +123 -0
- package/dist_ts/ts/mail/delivery/smtpserver/data-handler.js +1148 -0
- package/dist_ts/ts/mail/delivery/smtpserver/index.d.ts +20 -0
- package/dist_ts/ts/mail/delivery/smtpserver/index.js +27 -0
- package/dist_ts/ts/mail/delivery/smtpserver/interfaces.d.ts +530 -0
- package/dist_ts/ts/mail/delivery/smtpserver/interfaces.js +10 -0
- package/dist_ts/ts/mail/delivery/smtpserver/secure-server.d.ts +15 -0
- package/dist_ts/ts/mail/delivery/smtpserver/secure-server.js +79 -0
- package/dist_ts/ts/mail/delivery/smtpserver/security-handler.d.ts +86 -0
- package/dist_ts/ts/mail/delivery/smtpserver/security-handler.js +234 -0
- package/dist_ts/ts/mail/delivery/smtpserver/session-manager.d.ts +140 -0
- package/dist_ts/ts/mail/delivery/smtpserver/session-manager.js +469 -0
- package/dist_ts/ts/mail/delivery/smtpserver/smtp-server.d.ts +137 -0
- package/dist_ts/ts/mail/delivery/smtpserver/smtp-server.js +666 -0
- package/dist_ts/ts/mail/delivery/smtpserver/starttls-handler.d.ts +21 -0
- package/dist_ts/ts/mail/delivery/smtpserver/starttls-handler.js +207 -0
- package/dist_ts/ts/mail/delivery/smtpserver/tls-handler.d.ts +66 -0
- package/dist_ts/ts/mail/delivery/smtpserver/tls-handler.js +261 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/adaptive-logging.d.ts +117 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/adaptive-logging.js +411 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/helpers.d.ts +78 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/helpers.js +208 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/logging.d.ts +106 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/logging.js +181 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/validation.d.ts +69 -0
- package/dist_ts/ts/mail/delivery/smtpserver/utils/validation.js +360 -0
- package/dist_ts/ts/mail/index.d.ts +8 -0
- package/dist_ts/ts/mail/index.js +13 -0
- package/dist_ts/ts/mail/routing/classes.dns.manager.d.ts +65 -0
- package/dist_ts/ts/mail/routing/classes.dns.manager.js +413 -0
- package/dist_ts/ts/mail/routing/classes.dnsmanager.d.ts +165 -0
- package/dist_ts/ts/mail/routing/classes.dnsmanager.js +430 -0
- package/dist_ts/ts/mail/routing/classes.domain.registry.d.ts +54 -0
- package/dist_ts/ts/mail/routing/classes.domain.registry.js +118 -0
- package/dist_ts/ts/mail/routing/classes.email.config.d.ts +64 -0
- package/dist_ts/ts/mail/routing/classes.email.config.js +2 -0
- package/dist_ts/ts/mail/routing/classes.email.router.d.ts +171 -0
- package/dist_ts/ts/mail/routing/classes.email.router.js +491 -0
- package/dist_ts/ts/mail/routing/classes.unified.email.server.d.ts +426 -0
- package/dist_ts/ts/mail/routing/classes.unified.email.server.js +1454 -0
- package/dist_ts/ts/mail/routing/index.d.ts +5 -0
- package/dist_ts/ts/mail/routing/index.js +7 -0
- package/dist_ts/ts/mail/routing/interfaces.d.ts +187 -0
- package/dist_ts/ts/mail/routing/interfaces.js +2 -0
- package/dist_ts/ts/mail/security/classes.dkimcreator.d.ts +68 -0
- package/dist_ts/ts/mail/security/classes.dkimcreator.js +346 -0
- package/dist_ts/ts/mail/security/classes.dkimverifier.d.ts +46 -0
- package/dist_ts/ts/mail/security/classes.dkimverifier.js +317 -0
- package/dist_ts/ts/mail/security/classes.dmarcverifier.d.ts +123 -0
- package/dist_ts/ts/mail/security/classes.dmarcverifier.js +365 -0
- package/dist_ts/ts/mail/security/classes.spfverifier.d.ts +103 -0
- package/dist_ts/ts/mail/security/classes.spfverifier.js +492 -0
- package/dist_ts/ts/mail/security/index.d.ts +4 -0
- package/dist_ts/ts/mail/security/index.js +6 -0
- package/dist_ts/ts/opsserver/classes.opsserver.d.ts +20 -0
- package/dist_ts/ts/opsserver/classes.opsserver.js +44 -0
- package/dist_ts/ts/opsserver/handlers/admin.handler.d.ts +31 -0
- package/dist_ts/ts/opsserver/handlers/admin.handler.js +177 -0
- package/dist_ts/ts/opsserver/handlers/config.handler.d.ts +10 -0
- package/dist_ts/ts/opsserver/handlers/config.handler.js +100 -0
- package/dist_ts/ts/opsserver/handlers/index.d.ts +5 -0
- package/dist_ts/ts/opsserver/handlers/index.js +6 -0
- package/dist_ts/ts/opsserver/handlers/logs.handler.d.ts +10 -0
- package/dist_ts/ts/opsserver/handlers/logs.handler.js +121 -0
- package/dist_ts/ts/opsserver/handlers/security.handler.d.ts +11 -0
- package/dist_ts/ts/opsserver/handlers/security.handler.js +118 -0
- package/dist_ts/ts/opsserver/handlers/stats.handler.d.ts +13 -0
- package/dist_ts/ts/opsserver/handlers/stats.handler.js +233 -0
- package/dist_ts/ts/opsserver/helpers/guards.d.ts +25 -0
- package/dist_ts/ts/opsserver/helpers/guards.js +41 -0
- package/dist_ts/ts/opsserver/index.d.ts +1 -0
- package/dist_ts/ts/opsserver/index.js +2 -0
- package/dist_ts/ts/paths.d.ts +14 -0
- package/dist_ts/ts/paths.js +39 -0
- package/dist_ts/ts/plugins.d.ts +46 -0
- package/dist_ts/ts/plugins.js +53 -0
- package/dist_ts/ts/security/classes.contentscanner.d.ts +160 -0
- package/dist_ts/ts/security/classes.contentscanner.js +634 -0
- package/dist_ts/ts/security/classes.ipreputationchecker.d.ts +150 -0
- package/dist_ts/ts/security/classes.ipreputationchecker.js +508 -0
- package/dist_ts/ts/security/classes.securitylogger.d.ts +140 -0
- package/dist_ts/ts/security/classes.securitylogger.js +232 -0
- package/dist_ts/ts/security/index.d.ts +3 -0
- package/dist_ts/ts/security/index.js +4 -0
- package/dist_ts/ts/sms/classes.smsservice.d.ts +15 -0
- package/dist_ts/ts/sms/classes.smsservice.js +72 -0
- package/dist_ts/ts/sms/config/sms.config.d.ts +93 -0
- package/dist_ts/ts/sms/config/sms.config.js +2 -0
- package/dist_ts/ts/sms/config/sms.schema.d.ts +5 -0
- package/dist_ts/ts/sms/config/sms.schema.js +121 -0
- package/dist_ts/ts/sms/index.d.ts +1 -0
- package/dist_ts/ts/sms/index.js +2 -0
- package/dist_ts/ts/storage/classes.storagemanager.d.ts +82 -0
- package/dist_ts/ts/storage/classes.storagemanager.js +341 -0
- package/dist_ts/ts/storage/index.d.ts +1 -0
- package/dist_ts/ts/storage/index.js +3 -0
- package/dist_ts/ts_interfaces/data/auth.d.ts +8 -0
- package/dist_ts/ts_interfaces/data/auth.js +2 -0
- package/dist_ts/ts_interfaces/data/index.d.ts +2 -0
- package/dist_ts/ts_interfaces/data/index.js +3 -0
- package/dist_ts/ts_interfaces/data/stats.d.ts +93 -0
- package/dist_ts/ts_interfaces/data/stats.js +2 -0
- package/dist_ts/ts_interfaces/index.d.ts +5 -0
- package/dist_ts/ts_interfaces/index.js +8 -0
- package/dist_ts/ts_interfaces/plugins.d.ts +2 -0
- package/dist_ts/ts_interfaces/plugins.js +4 -0
- package/dist_ts/ts_interfaces/requests/admin.d.ts +31 -0
- package/dist_ts/ts_interfaces/requests/admin.js +3 -0
- package/dist_ts/ts_interfaces/requests/config.d.ts +25 -0
- package/dist_ts/ts_interfaces/requests/config.js +3 -0
- package/dist_ts/ts_interfaces/requests/index.d.ts +4 -0
- package/dist_ts/ts_interfaces/requests/index.js +5 -0
- package/dist_ts/ts_interfaces/requests/logs.d.ts +34 -0
- package/dist_ts/ts_interfaces/requests/logs.js +4 -0
- package/dist_ts/ts_interfaces/requests/stats.d.ts +131 -0
- package/dist_ts/ts_interfaces/requests/stats.js +4 -0
- package/html/index.html +121 -0
- package/npmextra.json +45 -0
- package/package.json +83 -0
- package/readme.hints.md +906 -0
- package/readme.md +1253 -0
- package/readme.opsserver.md +351 -0
- package/test/helpers/server.loader.ts +347 -0
- package/test/helpers/smtp.client.ts +209 -0
- package/test/helpers/utils.ts +311 -0
- package/test/readme.md +443 -0
- package/test/suite/smtpclient_commands/test.ccmd-01.ehlo-helo-sending.ts +168 -0
- package/test/suite/smtpclient_commands/test.ccmd-02.mail-from-parameters.ts +277 -0
- package/test/suite/smtpclient_commands/test.ccmd-03.rcpt-to-multiple.ts +283 -0
- package/test/suite/smtpclient_commands/test.ccmd-04.data-transmission.ts +274 -0
- package/test/suite/smtpclient_commands/test.ccmd-05.auth-mechanisms.ts +306 -0
- package/test/suite/smtpclient_commands/test.ccmd-06.command-pipelining.ts +233 -0
- package/test/suite/smtpclient_commands/test.ccmd-07.response-parsing.ts +243 -0
- package/test/suite/smtpclient_commands/test.ccmd-08.rset-command.ts +333 -0
- package/test/suite/smtpclient_commands/test.ccmd-09.noop-command.ts +339 -0
- package/test/suite/smtpclient_commands/test.ccmd-10.vrfy-expn.ts +457 -0
- package/test/suite/smtpclient_commands/test.ccmd-11.help-command.ts +409 -0
- package/test/suite/smtpclient_connection/test.ccm-01.basic-tcp-connection.ts +150 -0
- package/test/suite/smtpclient_connection/test.ccm-02.tls-connection.ts +140 -0
- package/test/suite/smtpclient_connection/test.ccm-03.starttls-upgrade.ts +208 -0
- package/test/suite/smtpclient_connection/test.ccm-04.connection-pooling.ts +250 -0
- package/test/suite/smtpclient_connection/test.ccm-05.connection-reuse.ts +288 -0
- package/test/suite/smtpclient_connection/test.ccm-06.connection-timeout.ts +267 -0
- package/test/suite/smtpclient_connection/test.ccm-07.automatic-reconnection.ts +324 -0
- package/test/suite/smtpclient_connection/test.ccm-08.dns-resolution.ts +139 -0
- package/test/suite/smtpclient_connection/test.ccm-09.ipv6-dual-stack.ts +167 -0
- package/test/suite/smtpclient_connection/test.ccm-10.proxy-support.ts +305 -0
- package/test/suite/smtpclient_connection/test.ccm-11.keepalive.ts +299 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-01.unusual-server-responses.ts +529 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-02.malformed-commands.ts +438 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-03.protocol-violations.ts +446 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-04.resource-constraints.ts +530 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-05.encoding-issues.ts +145 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-06.large-headers.ts +180 -0
- package/test/suite/smtpclient_edge-cases/test.cedge-07.concurrent-operations.ts +204 -0
- package/test/suite/smtpclient_email-composition/test.cep-01.basic-headers.ts +245 -0
- package/test/suite/smtpclient_email-composition/test.cep-02.mime-multipart.ts +321 -0
- package/test/suite/smtpclient_email-composition/test.cep-03.attachment-encoding.ts +334 -0
- package/test/suite/smtpclient_email-composition/test.cep-04.bcc-handling.ts +187 -0
- package/test/suite/smtpclient_email-composition/test.cep-05.reply-to-return-path.ts +277 -0
- package/test/suite/smtpclient_email-composition/test.cep-06.utf8-international.ts +235 -0
- package/test/suite/smtpclient_email-composition/test.cep-07.html-inline-images.ts +489 -0
- package/test/suite/smtpclient_email-composition/test.cep-08.custom-headers.ts +293 -0
- package/test/suite/smtpclient_email-composition/test.cep-09.priority-importance.ts +314 -0
- package/test/suite/smtpclient_email-composition/test.cep-10.receipts-dsn.ts +411 -0
- package/test/suite/smtpclient_error-handling/test.cerr-01.4xx-errors.ts +232 -0
- package/test/suite/smtpclient_error-handling/test.cerr-02.5xx-errors.ts +309 -0
- package/test/suite/smtpclient_error-handling/test.cerr-03.network-failures.ts +299 -0
- package/test/suite/smtpclient_error-handling/test.cerr-04.greylisting-handling.ts +255 -0
- package/test/suite/smtpclient_error-handling/test.cerr-05.quota-exceeded.ts +273 -0
- package/test/suite/smtpclient_error-handling/test.cerr-06.invalid-recipients.ts +320 -0
- package/test/suite/smtpclient_error-handling/test.cerr-07.message-size-limits.ts +320 -0
- package/test/suite/smtpclient_error-handling/test.cerr-08.rate-limiting.ts +261 -0
- package/test/suite/smtpclient_error-handling/test.cerr-09.connection-pool-errors.ts +299 -0
- package/test/suite/smtpclient_error-handling/test.cerr-10.partial-failure.ts +373 -0
- package/test/suite/smtpclient_performance/test.cperf-01.bulk-sending.ts +332 -0
- package/test/suite/smtpclient_performance/test.cperf-02.message-throughput.ts +304 -0
- package/test/suite/smtpclient_performance/test.cperf-03.memory-usage.ts +332 -0
- package/test/suite/smtpclient_performance/test.cperf-04.cpu-utilization.ts +373 -0
- package/test/suite/smtpclient_performance/test.cperf-05.network-efficiency.ts +181 -0
- package/test/suite/smtpclient_performance/test.cperf-06.caching-strategies.ts +190 -0
- package/test/suite/smtpclient_performance/test.cperf-07.queue-management.ts +171 -0
- package/test/suite/smtpclient_performance/test.cperf-08.dns-caching.ts +50 -0
- package/test/suite/smtpclient_reliability/test.crel-01.reconnection-logic.ts +305 -0
- package/test/suite/smtpclient_reliability/test.crel-02.network-interruption.ts +207 -0
- package/test/suite/smtpclient_reliability/test.crel-03.queue-persistence.ts +469 -0
- package/test/suite/smtpclient_reliability/test.crel-04.crash-recovery.ts +520 -0
- package/test/suite/smtpclient_reliability/test.crel-05.memory-leaks.ts +503 -0
- package/test/suite/smtpclient_reliability/test.crel-06.concurrency-safety.ts +558 -0
- package/test/suite/smtpclient_reliability/test.crel-07.resource-cleanup.ts +52 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-01.rfc5321-client.ts +283 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-02.esmtp-compliance.ts +77 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-03.command-syntax.ts +67 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-04.response-codes.ts +54 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-05.state-machine.ts +703 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-06.protocol-negotiation.ts +688 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-07.interoperability.ts +728 -0
- package/test/suite/smtpclient_rfc-compliance/test.crfc-08.smtp-extensions.ts +656 -0
- package/test/suite/smtpclient_security/test.csec-01.tls-verification.ts +88 -0
- package/test/suite/smtpclient_security/test.csec-02.oauth2-authentication.ts +132 -0
- package/test/suite/smtpclient_security/test.csec-03.dkim-signing.ts +138 -0
- package/test/suite/smtpclient_security/test.csec-04.spf-compliance.ts +163 -0
- package/test/suite/smtpclient_security/test.csec-05.dmarc-policy.ts +200 -0
- package/test/suite/smtpclient_security/test.csec-06.certificate-validation.ts +145 -0
- package/test/suite/smtpclient_security/test.csec-07.cipher-suites.ts +153 -0
- package/test/suite/smtpclient_security/test.csec-08.authentication-fallback.ts +154 -0
- package/test/suite/smtpclient_security/test.csec-09.relay-restrictions.ts +166 -0
- package/test/suite/smtpclient_security/test.csec-10.anti-spam-measures.ts +196 -0
- package/test/suite/smtpserver_commands/test.cmd-01.ehlo-command.ts +193 -0
- package/test/suite/smtpserver_commands/test.cmd-02.mail-from.ts +330 -0
- package/test/suite/smtpserver_commands/test.cmd-03.rcpt-to.ts +296 -0
- package/test/suite/smtpserver_commands/test.cmd-04.data-command.ts +395 -0
- package/test/suite/smtpserver_commands/test.cmd-05.noop-command.ts +320 -0
- package/test/suite/smtpserver_commands/test.cmd-06.rset-command.ts +399 -0
- package/test/suite/smtpserver_commands/test.cmd-07.vrfy-command.ts +391 -0
- package/test/suite/smtpserver_commands/test.cmd-08.expn-command.ts +450 -0
- package/test/suite/smtpserver_commands/test.cmd-09.size-extension.ts +465 -0
- package/test/suite/smtpserver_commands/test.cmd-10.help-command.ts +454 -0
- package/test/suite/smtpserver_commands/test.cmd-11.command-pipelining.ts +334 -0
- package/test/suite/smtpserver_commands/test.cmd-12.helo-command.ts +420 -0
- package/test/suite/smtpserver_commands/test.cmd-13.quit-command.ts +384 -0
- package/test/suite/smtpserver_connection/test.cm-01.tls-connection.ts +61 -0
- package/test/suite/smtpserver_connection/test.cm-02.multiple-connections.ts +112 -0
- package/test/suite/smtpserver_connection/test.cm-03.connection-timeout.ts +134 -0
- package/test/suite/smtpserver_connection/test.cm-04.connection-limits.ts +374 -0
- package/test/suite/smtpserver_connection/test.cm-05.connection-rejection.ts +296 -0
- package/test/suite/smtpserver_connection/test.cm-06.starttls-upgrade.ts +468 -0
- package/test/suite/smtpserver_connection/test.cm-07.abrupt-disconnection.ts +321 -0
- package/test/suite/smtpserver_connection/test.cm-08.tls-versions.ts +361 -0
- package/test/suite/smtpserver_connection/test.cm-09.tls-ciphers.ts +556 -0
- package/test/suite/smtpserver_connection/test.cm-10.plain-connection.ts +293 -0
- package/test/suite/smtpserver_connection/test.cm-11.keepalive.ts +382 -0
- package/test/suite/smtpserver_edge-cases/test.edge-01.very-large-email.ts +239 -0
- package/test/suite/smtpserver_edge-cases/test.edge-02.very-small-email.ts +389 -0
- package/test/suite/smtpserver_edge-cases/test.edge-03.invalid-character-handling.ts +479 -0
- package/test/suite/smtpserver_edge-cases/test.edge-04.empty-commands.ts +430 -0
- package/test/suite/smtpserver_edge-cases/test.edge-05.extremely-long-lines.ts +425 -0
- package/test/suite/smtpserver_edge-cases/test.edge-06.extremely-long-headers.ts +404 -0
- package/test/suite/smtpserver_edge-cases/test.edge-07.unusual-mime-types.ts +333 -0
- package/test/suite/smtpserver_edge-cases/test.edge-08.nested-mime-structures.ts +379 -0
- package/test/suite/smtpserver_email-processing/test.ep-01.basic-email-sending.ts +338 -0
- package/test/suite/smtpserver_email-processing/test.ep-02.invalid-email-addresses.ts +315 -0
- package/test/suite/smtpserver_email-processing/test.ep-03.multiple-recipients.ts +493 -0
- package/test/suite/smtpserver_email-processing/test.ep-04.large-email.ts +528 -0
- package/test/suite/smtpserver_email-processing/test.ep-05.mime-handling.ts +515 -0
- package/test/suite/smtpserver_email-processing/test.ep-06.attachment-handling.ts +629 -0
- package/test/suite/smtpserver_email-processing/test.ep-07.special-character-handling.ts +462 -0
- package/test/suite/smtpserver_email-processing/test.ep-08.email-routing.ts +527 -0
- package/test/suite/smtpserver_email-processing/test.ep-09.delivery-status-notifications.ts +486 -0
- package/test/suite/smtpserver_error-handling/test.err-01.syntax-errors.ts +475 -0
- package/test/suite/smtpserver_error-handling/test.err-02.invalid-sequence.ts +450 -0
- package/test/suite/smtpserver_error-handling/test.err-03.temporary-failures.ts +453 -0
- package/test/suite/smtpserver_error-handling/test.err-04.permanent-failures.ts +325 -0
- package/test/suite/smtpserver_error-handling/test.err-05.resource-exhaustion.ts +302 -0
- package/test/suite/smtpserver_error-handling/test.err-06.malformed-mime.ts +374 -0
- package/test/suite/smtpserver_error-handling/test.err-07.exception-handling.ts +333 -0
- package/test/suite/smtpserver_error-handling/test.err-08.error-logging.ts +324 -0
- package/test/suite/smtpserver_performance/test.perf-01.throughput.ts +183 -0
- package/test/suite/smtpserver_performance/test.perf-02.concurrency.ts +388 -0
- package/test/suite/smtpserver_performance/test.perf-03.cpu-utilization.ts +245 -0
- package/test/suite/smtpserver_performance/test.perf-04.memory-usage.ts +238 -0
- package/test/suite/smtpserver_performance/test.perf-05.connection-processing-time.ts +363 -0
- package/test/suite/smtpserver_performance/test.perf-06.message-processing-time.ts +252 -0
- package/test/suite/smtpserver_performance/test.perf-07.resource-cleanup.ts +317 -0
- package/test/suite/smtpserver_reliability/test.rel-01.long-running-operation.ts +344 -0
- package/test/suite/smtpserver_reliability/test.rel-02.restart-recovery.ts +328 -0
- package/test/suite/smtpserver_reliability/test.rel-03.resource-leak-detection.ts +394 -0
- package/test/suite/smtpserver_reliability/test.rel-04.error-recovery.ts +401 -0
- package/test/suite/smtpserver_reliability/test.rel-05.dns-resolution-failure.ts +335 -0
- package/test/suite/smtpserver_reliability/test.rel-06.network-interruption.ts +410 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-01.rfc5321-compliance.ts +382 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-02.rfc5322-compliance.ts +428 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-03.rfc7208-spf-compliance.ts +330 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-04.rfc6376-dkim-compliance.ts +450 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-05.rfc7489-dmarc-compliance.ts +408 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-06.rfc8314-tls-compliance.ts +366 -0
- package/test/suite/smtpserver_rfc-compliance/test.rfc-07.rfc3461-dsn-compliance.ts +399 -0
- package/test/suite/smtpserver_security/test.sec-01.authentication.ts +218 -0
- package/test/suite/smtpserver_security/test.sec-02.authorization.ts +286 -0
- package/test/suite/smtpserver_security/test.sec-03.dkim-processing.ts +414 -0
- package/test/suite/smtpserver_security/test.sec-04.spf-checking.ts +280 -0
- package/test/suite/smtpserver_security/test.sec-05.dmarc-policy.ts +374 -0
- package/test/suite/smtpserver_security/test.sec-06.ip-reputation.ts +303 -0
- package/test/suite/smtpserver_security/test.sec-07.content-scanning.ts +409 -0
- package/test/suite/smtpserver_security/test.sec-08.rate-limiting.ts +324 -0
- package/test/suite/smtpserver_security/test.sec-09.tls-certificate-validation.ts +312 -0
- package/test/suite/smtpserver_security/test.sec-10.header-injection-prevention.ts +332 -0
- package/test/suite/smtpserver_security/test.sec-11.bounce-management.ts +363 -0
- package/test/test.base.ts +65 -0
- package/test/test.bouncemanager.ts +196 -0
- package/test/test.config.md +175 -0
- package/test/test.contentscanner.ts +265 -0
- package/test/test.dcrouter.email.ts +201 -0
- package/test/test.deliverability.ts +55 -0
- package/test/test.dns-manager-creation.ts +141 -0
- package/test/test.dns-mode-switching.ts +257 -0
- package/test/test.dns-server-config.ts +140 -0
- package/test/test.dns-socket-handler.ts +169 -0
- package/test/test.dns-validation.ts +283 -0
- package/test/test.email-socket-handler.ts +228 -0
- package/test/test.email.integration.ts +377 -0
- package/test/test.email.router.ts +283 -0
- package/test/test.emailauth.ts +195 -0
- package/test/test.errors.ts +408 -0
- package/test/test.integration.storage.ts +313 -0
- package/test/test.integration.ts +75 -0
- package/test/test.ipreputationchecker.ts +179 -0
- package/test/test.ipwarmupmanager.ts +323 -0
- package/test/test.jwt-auth.ts +130 -0
- package/test/test.minimal.ts +66 -0
- package/test/test.opsserver-api.ts +83 -0
- package/test/test.protected-endpoint.ts +115 -0
- package/test/test.rate-limiting-integration.ts +236 -0
- package/test/test.ratelimiter.ts +141 -0
- package/test/test.reputationmonitor.ts +262 -0
- package/test/test.smartmail.ts +248 -0
- package/test/test.smtp.client.compatibility.ts +154 -0
- package/test/test.smtp.client.ts +191 -0
- package/test/test.smtp.server.ts +180 -0
- package/test/test.socket-handler-integration.ts +240 -0
- package/test/test.socket-handler-unit.ts +198 -0
- package/test/test.storagemanager.ts +289 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.dcrouter.ts +1310 -0
- package/ts/config/index.ts +2 -0
- package/ts/config/validator.ts +266 -0
- package/ts/deliverability/classes.ipwarmupmanager.ts +896 -0
- package/ts/deliverability/classes.senderreputationmonitor.ts +1244 -0
- package/ts/deliverability/index.ts +13 -0
- package/ts/errors/base.errors.ts +525 -0
- package/ts/errors/email.errors.ts +383 -0
- package/ts/errors/error-handler.ts +412 -0
- package/ts/errors/error.codes.ts +165 -0
- package/ts/errors/index.ts +195 -0
- package/ts/errors/mta.errors.ts +681 -0
- package/ts/errors/reputation.errors.ts +422 -0
- package/ts/index.ts +7 -0
- package/ts/logger.ts +91 -0
- package/ts/mail/core/classes.bouncemanager.ts +965 -0
- package/ts/mail/core/classes.email.ts +941 -0
- package/ts/mail/core/classes.emailvalidator.ts +239 -0
- package/ts/mail/core/classes.templatemanager.ts +320 -0
- package/ts/mail/core/index.ts +5 -0
- package/ts/mail/delivery/classes.delivery.queue.ts +645 -0
- package/ts/mail/delivery/classes.delivery.system.ts +1089 -0
- package/ts/mail/delivery/classes.emailsendjob.ts +447 -0
- package/ts/mail/delivery/classes.emailsendjob.ts.backup +691 -0
- package/ts/mail/delivery/classes.emailsignjob.ts +67 -0
- package/ts/mail/delivery/classes.mta.config.ts +73 -0
- package/ts/mail/delivery/classes.ratelimiter.ts +281 -0
- package/ts/mail/delivery/classes.smtp.client.legacy.ts +1422 -0
- package/ts/mail/delivery/classes.unified.rate.limiter.ts +1053 -0
- package/ts/mail/delivery/index.ts +24 -0
- package/ts/mail/delivery/interfaces.ts +291 -0
- package/ts/mail/delivery/smtpclient/auth-handler.ts +232 -0
- package/ts/mail/delivery/smtpclient/command-handler.ts +343 -0
- package/ts/mail/delivery/smtpclient/connection-manager.ts +289 -0
- package/ts/mail/delivery/smtpclient/constants.ts +145 -0
- package/ts/mail/delivery/smtpclient/create-client.ts +94 -0
- package/ts/mail/delivery/smtpclient/error-handler.ts +141 -0
- package/ts/mail/delivery/smtpclient/index.ts +24 -0
- package/ts/mail/delivery/smtpclient/interfaces.ts +242 -0
- package/ts/mail/delivery/smtpclient/smtp-client.ts +357 -0
- package/ts/mail/delivery/smtpclient/tls-handler.ts +254 -0
- package/ts/mail/delivery/smtpclient/utils/helpers.ts +224 -0
- package/ts/mail/delivery/smtpclient/utils/logging.ts +212 -0
- package/ts/mail/delivery/smtpclient/utils/validation.ts +170 -0
- package/ts/mail/delivery/smtpserver/certificate-utils.ts +398 -0
- package/ts/mail/delivery/smtpserver/command-handler.ts +1340 -0
- package/ts/mail/delivery/smtpserver/connection-manager.ts +1045 -0
- package/ts/mail/delivery/smtpserver/constants.ts +181 -0
- package/ts/mail/delivery/smtpserver/create-server.ts +31 -0
- package/ts/mail/delivery/smtpserver/data-handler.ts +1283 -0
- package/ts/mail/delivery/smtpserver/index.ts +32 -0
- package/ts/mail/delivery/smtpserver/interfaces.ts +655 -0
- package/ts/mail/delivery/smtpserver/secure-server.ts +97 -0
- package/ts/mail/delivery/smtpserver/security-handler.ts +345 -0
- package/ts/mail/delivery/smtpserver/session-manager.ts +557 -0
- package/ts/mail/delivery/smtpserver/smtp-server.ts +804 -0
- package/ts/mail/delivery/smtpserver/starttls-handler.ts +262 -0
- package/ts/mail/delivery/smtpserver/tls-handler.ts +346 -0
- package/ts/mail/delivery/smtpserver/utils/adaptive-logging.ts +514 -0
- package/ts/mail/delivery/smtpserver/utils/helpers.ts +246 -0
- package/ts/mail/delivery/smtpserver/utils/logging.ts +246 -0
- package/ts/mail/delivery/smtpserver/utils/validation.ts +436 -0
- package/ts/mail/index.ts +19 -0
- package/ts/mail/routing/classes.dns.manager.ts +563 -0
- package/ts/mail/routing/classes.dnsmanager.ts +559 -0
- package/ts/mail/routing/classes.domain.registry.ts +139 -0
- package/ts/mail/routing/classes.email.config.ts +82 -0
- package/ts/mail/routing/classes.email.router.ts +575 -0
- package/ts/mail/routing/classes.unified.email.server.ts +1873 -0
- package/ts/mail/routing/index.ts +6 -0
- package/ts/mail/routing/interfaces.ts +202 -0
- package/ts/mail/security/classes.dkimcreator.ts +431 -0
- package/ts/mail/security/classes.dkimverifier.ts +382 -0
- package/ts/mail/security/classes.dmarcverifier.ts +478 -0
- package/ts/mail/security/classes.spfverifier.ts +606 -0
- package/ts/mail/security/index.ts +5 -0
- package/ts/opsserver/classes.opsserver.ts +65 -0
- package/ts/opsserver/handlers/admin.handler.ts +240 -0
- package/ts/opsserver/handlers/config.handler.ts +150 -0
- package/ts/opsserver/handlers/index.ts +5 -0
- package/ts/opsserver/handlers/logs.handler.ts +195 -0
- package/ts/opsserver/handlers/security.handler.ts +208 -0
- package/ts/opsserver/handlers/stats.handler.ts +344 -0
- package/ts/opsserver/helpers/guards.ts +56 -0
- package/ts/opsserver/index.ts +1 -0
- package/ts/paths.ts +48 -0
- package/ts/plugins.ts +94 -0
- package/ts/security/classes.contentscanner.ts +739 -0
- package/ts/security/classes.ipreputationchecker.ts +592 -0
- package/ts/security/classes.securitylogger.ts +299 -0
- package/ts/security/index.ts +21 -0
- package/ts/sms/classes.smsservice.ts +98 -0
- package/ts/sms/config/sms.config.ts +109 -0
- package/ts/sms/config/sms.schema.ts +122 -0
- package/ts/sms/index.ts +1 -0
- package/ts/storage/classes.storagemanager.ts +400 -0
- package/ts/storage/index.ts +2 -0
- package/ts/tspublish.json +3 -0
- package/ts_interfaces/data/auth.ts +8 -0
- package/ts_interfaces/data/index.ts +2 -0
- package/ts_interfaces/data/stats.ts +101 -0
- package/ts_interfaces/index.ts +9 -0
- package/ts_interfaces/plugins.ts +6 -0
- package/ts_interfaces/requests/admin.ts +46 -0
- package/ts_interfaces/requests/config.ts +35 -0
- package/ts_interfaces/requests/index.ts +4 -0
- package/ts_interfaces/requests/logs.ts +44 -0
- package/ts_interfaces/requests/stats.ts +162 -0
- package/ts_interfaces/tspublish.json +3 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/appstate.ts +361 -0
- package/ts_web/elements/index.ts +7 -0
- package/ts_web/elements/ops-dashboard.ts +165 -0
- package/ts_web/elements/ops-view-config.ts +268 -0
- package/ts_web/elements/ops-view-logs.ts +207 -0
- package/ts_web/elements/ops-view-overview.ts +222 -0
- package/ts_web/elements/ops-view-security.ts +471 -0
- package/ts_web/elements/ops-view-stats.ts +299 -0
- package/ts_web/elements/shared/css.ts +10 -0
- package/ts_web/elements/shared/index.ts +2 -0
- package/ts_web/elements/shared/ops-sectionheading.ts +42 -0
- package/ts_web/index.ts +9 -0
- package/ts_web/plugins.ts +11 -0
- package/ts_web/tspublish.json +3 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,965 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as paths from '../../paths.js';
|
|
3
|
+
import { logger } from '../../logger.js';
|
|
4
|
+
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';
|
|
5
|
+
import { LRUCache } from 'lru-cache';
|
|
6
|
+
import type { Email } from './classes.email.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Bounce types for categorizing the reasons for bounces
|
|
10
|
+
*/
|
|
11
|
+
export enum BounceType {
|
|
12
|
+
// Hard bounces (permanent failures)
|
|
13
|
+
INVALID_RECIPIENT = 'invalid_recipient',
|
|
14
|
+
DOMAIN_NOT_FOUND = 'domain_not_found',
|
|
15
|
+
MAILBOX_FULL = 'mailbox_full',
|
|
16
|
+
MAILBOX_INACTIVE = 'mailbox_inactive',
|
|
17
|
+
BLOCKED = 'blocked',
|
|
18
|
+
SPAM_RELATED = 'spam_related',
|
|
19
|
+
POLICY_RELATED = 'policy_related',
|
|
20
|
+
|
|
21
|
+
// Soft bounces (temporary failures)
|
|
22
|
+
SERVER_UNAVAILABLE = 'server_unavailable',
|
|
23
|
+
TEMPORARY_FAILURE = 'temporary_failure',
|
|
24
|
+
QUOTA_EXCEEDED = 'quota_exceeded',
|
|
25
|
+
NETWORK_ERROR = 'network_error',
|
|
26
|
+
TIMEOUT = 'timeout',
|
|
27
|
+
|
|
28
|
+
// Special cases
|
|
29
|
+
AUTO_RESPONSE = 'auto_response',
|
|
30
|
+
CHALLENGE_RESPONSE = 'challenge_response',
|
|
31
|
+
UNKNOWN = 'unknown'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Hard vs soft bounce classification
|
|
36
|
+
*/
|
|
37
|
+
export enum BounceCategory {
|
|
38
|
+
HARD = 'hard',
|
|
39
|
+
SOFT = 'soft',
|
|
40
|
+
AUTO_RESPONSE = 'auto_response',
|
|
41
|
+
UNKNOWN = 'unknown'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Bounce data structure
|
|
46
|
+
*/
|
|
47
|
+
export interface BounceRecord {
|
|
48
|
+
id: string;
|
|
49
|
+
originalEmailId?: string;
|
|
50
|
+
recipient: string;
|
|
51
|
+
sender: string;
|
|
52
|
+
domain: string;
|
|
53
|
+
subject?: string;
|
|
54
|
+
bounceType: BounceType;
|
|
55
|
+
bounceCategory: BounceCategory;
|
|
56
|
+
timestamp: number;
|
|
57
|
+
smtpResponse?: string;
|
|
58
|
+
diagnosticCode?: string;
|
|
59
|
+
statusCode?: string;
|
|
60
|
+
headers?: Record<string, string>;
|
|
61
|
+
processed: boolean;
|
|
62
|
+
retryCount?: number;
|
|
63
|
+
nextRetryTime?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Email bounce patterns to identify bounce types in SMTP responses and bounce messages
|
|
68
|
+
*/
|
|
69
|
+
const BOUNCE_PATTERNS = {
|
|
70
|
+
// Hard bounce patterns
|
|
71
|
+
[BounceType.INVALID_RECIPIENT]: [
|
|
72
|
+
/no such user/i,
|
|
73
|
+
/user unknown/i,
|
|
74
|
+
/does not exist/i,
|
|
75
|
+
/invalid recipient/i,
|
|
76
|
+
/unknown recipient/i,
|
|
77
|
+
/no mailbox/i,
|
|
78
|
+
/user not found/i,
|
|
79
|
+
/recipient address rejected/i,
|
|
80
|
+
/550 5\.1\.1/i
|
|
81
|
+
],
|
|
82
|
+
[BounceType.DOMAIN_NOT_FOUND]: [
|
|
83
|
+
/domain not found/i,
|
|
84
|
+
/unknown domain/i,
|
|
85
|
+
/no such domain/i,
|
|
86
|
+
/host not found/i,
|
|
87
|
+
/domain invalid/i,
|
|
88
|
+
/550 5\.1\.2/i
|
|
89
|
+
],
|
|
90
|
+
[BounceType.MAILBOX_FULL]: [
|
|
91
|
+
/mailbox full/i,
|
|
92
|
+
/over quota/i,
|
|
93
|
+
/quota exceeded/i,
|
|
94
|
+
/552 5\.2\.2/i
|
|
95
|
+
],
|
|
96
|
+
[BounceType.MAILBOX_INACTIVE]: [
|
|
97
|
+
/mailbox disabled/i,
|
|
98
|
+
/mailbox inactive/i,
|
|
99
|
+
/account disabled/i,
|
|
100
|
+
/mailbox not active/i,
|
|
101
|
+
/account suspended/i
|
|
102
|
+
],
|
|
103
|
+
[BounceType.BLOCKED]: [
|
|
104
|
+
/blocked/i,
|
|
105
|
+
/rejected/i,
|
|
106
|
+
/denied/i,
|
|
107
|
+
/blacklisted/i,
|
|
108
|
+
/prohibited/i,
|
|
109
|
+
/refused/i,
|
|
110
|
+
/550 5\.7\./i
|
|
111
|
+
],
|
|
112
|
+
[BounceType.SPAM_RELATED]: [
|
|
113
|
+
/spam/i,
|
|
114
|
+
/bulk mail/i,
|
|
115
|
+
/content rejected/i,
|
|
116
|
+
/message rejected/i,
|
|
117
|
+
/550 5\.7\.1/i
|
|
118
|
+
],
|
|
119
|
+
|
|
120
|
+
// Soft bounce patterns
|
|
121
|
+
[BounceType.SERVER_UNAVAILABLE]: [
|
|
122
|
+
/server unavailable/i,
|
|
123
|
+
/service unavailable/i,
|
|
124
|
+
/try again later/i,
|
|
125
|
+
/try later/i,
|
|
126
|
+
/451 4\.3\./i,
|
|
127
|
+
/421 4\.3\./i
|
|
128
|
+
],
|
|
129
|
+
[BounceType.TEMPORARY_FAILURE]: [
|
|
130
|
+
/temporary failure/i,
|
|
131
|
+
/temporary error/i,
|
|
132
|
+
/temporary problem/i,
|
|
133
|
+
/try again/i,
|
|
134
|
+
/451 4\./i
|
|
135
|
+
],
|
|
136
|
+
[BounceType.QUOTA_EXCEEDED]: [
|
|
137
|
+
/quota temporarily exceeded/i,
|
|
138
|
+
/mailbox temporarily full/i,
|
|
139
|
+
/452 4\.2\.2/i
|
|
140
|
+
],
|
|
141
|
+
[BounceType.NETWORK_ERROR]: [
|
|
142
|
+
/network error/i,
|
|
143
|
+
/connection error/i,
|
|
144
|
+
/connection timed out/i,
|
|
145
|
+
/routing error/i,
|
|
146
|
+
/421 4\.4\./i
|
|
147
|
+
],
|
|
148
|
+
[BounceType.TIMEOUT]: [
|
|
149
|
+
/timed out/i,
|
|
150
|
+
/timeout/i,
|
|
151
|
+
/450 4\.4\.2/i
|
|
152
|
+
],
|
|
153
|
+
|
|
154
|
+
// Auto-responses
|
|
155
|
+
[BounceType.AUTO_RESPONSE]: [
|
|
156
|
+
/auto[- ]reply/i,
|
|
157
|
+
/auto[- ]response/i,
|
|
158
|
+
/vacation/i,
|
|
159
|
+
/out of office/i,
|
|
160
|
+
/away from office/i,
|
|
161
|
+
/on vacation/i,
|
|
162
|
+
/automatic reply/i
|
|
163
|
+
],
|
|
164
|
+
[BounceType.CHALLENGE_RESPONSE]: [
|
|
165
|
+
/challenge[- ]response/i,
|
|
166
|
+
/verify your email/i,
|
|
167
|
+
/confirm your email/i,
|
|
168
|
+
/email verification/i
|
|
169
|
+
]
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Retry strategy configuration for soft bounces
|
|
174
|
+
*/
|
|
175
|
+
interface RetryStrategy {
|
|
176
|
+
maxRetries: number;
|
|
177
|
+
initialDelay: number; // milliseconds
|
|
178
|
+
maxDelay: number; // milliseconds
|
|
179
|
+
backoffFactor: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Manager for handling email bounces
|
|
184
|
+
*/
|
|
185
|
+
export class BounceManager {
|
|
186
|
+
// Retry strategy with exponential backoff
|
|
187
|
+
private retryStrategy: RetryStrategy = {
|
|
188
|
+
maxRetries: 5,
|
|
189
|
+
initialDelay: 15 * 60 * 1000, // 15 minutes
|
|
190
|
+
maxDelay: 24 * 60 * 60 * 1000, // 24 hours
|
|
191
|
+
backoffFactor: 2
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Store of bounced emails
|
|
195
|
+
private bounceStore: BounceRecord[] = [];
|
|
196
|
+
|
|
197
|
+
// Cache of recently bounced email addresses to avoid sending to known bad addresses
|
|
198
|
+
private bounceCache: LRUCache<string, {
|
|
199
|
+
lastBounce: number;
|
|
200
|
+
count: number;
|
|
201
|
+
type: BounceType;
|
|
202
|
+
category: BounceCategory;
|
|
203
|
+
}>;
|
|
204
|
+
|
|
205
|
+
// Suppression list for addresses that should not receive emails
|
|
206
|
+
private suppressionList: Map<string, {
|
|
207
|
+
reason: string;
|
|
208
|
+
timestamp: number;
|
|
209
|
+
expiresAt?: number; // undefined means permanent
|
|
210
|
+
}> = new Map();
|
|
211
|
+
|
|
212
|
+
private storageManager?: any; // StorageManager instance
|
|
213
|
+
|
|
214
|
+
constructor(options?: {
|
|
215
|
+
retryStrategy?: Partial<RetryStrategy>;
|
|
216
|
+
maxCacheSize?: number;
|
|
217
|
+
cacheTTL?: number;
|
|
218
|
+
storageManager?: any;
|
|
219
|
+
}) {
|
|
220
|
+
// Set retry strategy with defaults
|
|
221
|
+
if (options?.retryStrategy) {
|
|
222
|
+
this.retryStrategy = {
|
|
223
|
+
...this.retryStrategy,
|
|
224
|
+
...options.retryStrategy
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Initialize bounce cache with LRU (least recently used) caching
|
|
229
|
+
this.bounceCache = new LRUCache<string, any>({
|
|
230
|
+
max: options?.maxCacheSize || 10000,
|
|
231
|
+
ttl: options?.cacheTTL || 30 * 24 * 60 * 60 * 1000, // 30 days default
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Store storage manager reference
|
|
235
|
+
this.storageManager = options?.storageManager;
|
|
236
|
+
|
|
237
|
+
// Load suppression list from storage
|
|
238
|
+
// Note: This is async but we can't await in constructor
|
|
239
|
+
// The suppression list will be loaded asynchronously
|
|
240
|
+
this.loadSuppressionList().catch(error => {
|
|
241
|
+
logger.log('error', `Failed to load suppression list on startup: ${error.message}`);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Process a bounce notification
|
|
247
|
+
* @param bounceData Bounce data to process
|
|
248
|
+
* @returns Processed bounce record
|
|
249
|
+
*/
|
|
250
|
+
public async processBounce(bounceData: Partial<BounceRecord>): Promise<BounceRecord> {
|
|
251
|
+
try {
|
|
252
|
+
// Add required fields if missing
|
|
253
|
+
const bounce: BounceRecord = {
|
|
254
|
+
id: bounceData.id || plugins.uuid.v4(),
|
|
255
|
+
recipient: bounceData.recipient,
|
|
256
|
+
sender: bounceData.sender,
|
|
257
|
+
domain: bounceData.domain || bounceData.recipient.split('@')[1],
|
|
258
|
+
subject: bounceData.subject,
|
|
259
|
+
bounceType: bounceData.bounceType || BounceType.UNKNOWN,
|
|
260
|
+
bounceCategory: bounceData.bounceCategory || BounceCategory.UNKNOWN,
|
|
261
|
+
timestamp: bounceData.timestamp || Date.now(),
|
|
262
|
+
smtpResponse: bounceData.smtpResponse,
|
|
263
|
+
diagnosticCode: bounceData.diagnosticCode,
|
|
264
|
+
statusCode: bounceData.statusCode,
|
|
265
|
+
headers: bounceData.headers,
|
|
266
|
+
processed: false,
|
|
267
|
+
originalEmailId: bounceData.originalEmailId,
|
|
268
|
+
retryCount: bounceData.retryCount || 0,
|
|
269
|
+
nextRetryTime: bounceData.nextRetryTime
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// Determine bounce type and category if not provided
|
|
273
|
+
if (!bounceData.bounceType || bounceData.bounceType === BounceType.UNKNOWN) {
|
|
274
|
+
const bounceInfo = this.detectBounceType(
|
|
275
|
+
bounce.smtpResponse || '',
|
|
276
|
+
bounce.diagnosticCode || '',
|
|
277
|
+
bounce.statusCode || ''
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
bounce.bounceType = bounceInfo.type;
|
|
281
|
+
bounce.bounceCategory = bounceInfo.category;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Process the bounce based on category
|
|
285
|
+
switch (bounce.bounceCategory) {
|
|
286
|
+
case BounceCategory.HARD:
|
|
287
|
+
// Handle hard bounce - add to suppression list
|
|
288
|
+
await this.handleHardBounce(bounce);
|
|
289
|
+
break;
|
|
290
|
+
|
|
291
|
+
case BounceCategory.SOFT:
|
|
292
|
+
// Handle soft bounce - schedule retry if eligible
|
|
293
|
+
await this.handleSoftBounce(bounce);
|
|
294
|
+
break;
|
|
295
|
+
|
|
296
|
+
case BounceCategory.AUTO_RESPONSE:
|
|
297
|
+
// Handle auto-response - typically no action needed
|
|
298
|
+
logger.log('info', `Auto-response detected for ${bounce.recipient}`);
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
default:
|
|
302
|
+
// Unknown bounce type - log for investigation
|
|
303
|
+
logger.log('warn', `Unknown bounce type for ${bounce.recipient}`, {
|
|
304
|
+
bounceType: bounce.bounceType,
|
|
305
|
+
smtpResponse: bounce.smtpResponse
|
|
306
|
+
});
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Store the bounce record
|
|
311
|
+
bounce.processed = true;
|
|
312
|
+
this.bounceStore.push(bounce);
|
|
313
|
+
|
|
314
|
+
// Update the bounce cache
|
|
315
|
+
this.updateBounceCache(bounce);
|
|
316
|
+
|
|
317
|
+
// Log the bounce
|
|
318
|
+
logger.log(
|
|
319
|
+
bounce.bounceCategory === BounceCategory.HARD ? 'warn' : 'info',
|
|
320
|
+
`Email bounce processed: ${bounce.bounceCategory} bounce for ${bounce.recipient}`,
|
|
321
|
+
{
|
|
322
|
+
bounceType: bounce.bounceType,
|
|
323
|
+
domain: bounce.domain,
|
|
324
|
+
category: bounce.bounceCategory
|
|
325
|
+
}
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
// Enhanced security logging
|
|
329
|
+
SecurityLogger.getInstance().logEvent({
|
|
330
|
+
level: bounce.bounceCategory === BounceCategory.HARD
|
|
331
|
+
? SecurityLogLevel.WARN
|
|
332
|
+
: SecurityLogLevel.INFO,
|
|
333
|
+
type: SecurityEventType.EMAIL_VALIDATION,
|
|
334
|
+
message: `Email bounce detected: ${bounce.bounceCategory} bounce for recipient`,
|
|
335
|
+
domain: bounce.domain,
|
|
336
|
+
details: {
|
|
337
|
+
recipient: bounce.recipient,
|
|
338
|
+
bounceType: bounce.bounceType,
|
|
339
|
+
smtpResponse: bounce.smtpResponse,
|
|
340
|
+
diagnosticCode: bounce.diagnosticCode,
|
|
341
|
+
statusCode: bounce.statusCode
|
|
342
|
+
},
|
|
343
|
+
success: false
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
return bounce;
|
|
347
|
+
} catch (error) {
|
|
348
|
+
logger.log('error', `Error processing bounce: ${error.message}`, {
|
|
349
|
+
error: error.message,
|
|
350
|
+
bounceData
|
|
351
|
+
});
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Process an SMTP failure as a bounce
|
|
358
|
+
* @param recipient Recipient email
|
|
359
|
+
* @param smtpResponse SMTP error response
|
|
360
|
+
* @param options Additional options
|
|
361
|
+
* @returns Processed bounce record
|
|
362
|
+
*/
|
|
363
|
+
public async processSmtpFailure(
|
|
364
|
+
recipient: string,
|
|
365
|
+
smtpResponse: string,
|
|
366
|
+
options: {
|
|
367
|
+
sender?: string;
|
|
368
|
+
originalEmailId?: string;
|
|
369
|
+
statusCode?: string;
|
|
370
|
+
headers?: Record<string, string>;
|
|
371
|
+
} = {}
|
|
372
|
+
): Promise<BounceRecord> {
|
|
373
|
+
// Create bounce data from SMTP failure
|
|
374
|
+
const bounceData: Partial<BounceRecord> = {
|
|
375
|
+
recipient,
|
|
376
|
+
sender: options.sender || '',
|
|
377
|
+
domain: recipient.split('@')[1],
|
|
378
|
+
smtpResponse,
|
|
379
|
+
statusCode: options.statusCode,
|
|
380
|
+
headers: options.headers,
|
|
381
|
+
originalEmailId: options.originalEmailId,
|
|
382
|
+
timestamp: Date.now()
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// Process as a regular bounce
|
|
386
|
+
return this.processBounce(bounceData);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Process a bounce notification email
|
|
391
|
+
* @param bounceEmail The email containing bounce information
|
|
392
|
+
* @returns Processed bounce record or null if not a bounce
|
|
393
|
+
*/
|
|
394
|
+
public async processBounceEmail(bounceEmail: Email): Promise<BounceRecord | null> {
|
|
395
|
+
try {
|
|
396
|
+
// Check if this is a bounce notification
|
|
397
|
+
const subject = bounceEmail.getSubject();
|
|
398
|
+
const body = bounceEmail.getBody();
|
|
399
|
+
|
|
400
|
+
// Check for common bounce notification subject patterns
|
|
401
|
+
const isBounceSubject = /mail delivery|delivery (failed|status|notification)|failure notice|returned mail|undeliverable|delivery problem/i.test(subject);
|
|
402
|
+
|
|
403
|
+
if (!isBounceSubject) {
|
|
404
|
+
// Not a bounce notification based on subject
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Extract original recipient from the body or headers
|
|
409
|
+
let recipient = '';
|
|
410
|
+
let originalMessageId = '';
|
|
411
|
+
|
|
412
|
+
// Extract recipient from common bounce formats
|
|
413
|
+
const recipientMatch = body.match(/(?:failed recipient|to[:=]\s*|recipient:|delivery failed:)\s*<?([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>?/i);
|
|
414
|
+
if (recipientMatch && recipientMatch[1]) {
|
|
415
|
+
recipient = recipientMatch[1];
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Extract diagnostic code
|
|
419
|
+
let diagnosticCode = '';
|
|
420
|
+
const diagnosticMatch = body.match(/diagnostic(?:-|\\s+)code:\s*(.+)(?:\n|$)/i);
|
|
421
|
+
if (diagnosticMatch && diagnosticMatch[1]) {
|
|
422
|
+
diagnosticCode = diagnosticMatch[1].trim();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Extract SMTP status code
|
|
426
|
+
let statusCode = '';
|
|
427
|
+
const statusMatch = body.match(/status(?:-|\\s+)code:\s*([0-9.]+)/i);
|
|
428
|
+
if (statusMatch && statusMatch[1]) {
|
|
429
|
+
statusCode = statusMatch[1].trim();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// If recipient not found in standard patterns, try DSN (Delivery Status Notification) format
|
|
433
|
+
if (!recipient) {
|
|
434
|
+
// Look for DSN format with Original-Recipient or Final-Recipient fields
|
|
435
|
+
const originalRecipientMatch = body.match(/original-recipient:.*?([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i);
|
|
436
|
+
const finalRecipientMatch = body.match(/final-recipient:.*?([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i);
|
|
437
|
+
|
|
438
|
+
if (originalRecipientMatch && originalRecipientMatch[1]) {
|
|
439
|
+
recipient = originalRecipientMatch[1];
|
|
440
|
+
} else if (finalRecipientMatch && finalRecipientMatch[1]) {
|
|
441
|
+
recipient = finalRecipientMatch[1];
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// If still no recipient, can't process as bounce
|
|
446
|
+
if (!recipient) {
|
|
447
|
+
logger.log('warn', 'Could not extract recipient from bounce notification', {
|
|
448
|
+
subject,
|
|
449
|
+
sender: bounceEmail.from
|
|
450
|
+
});
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Extract original message ID if available
|
|
455
|
+
const messageIdMatch = body.match(/original[ -]message[ -]id:[ \t]*<?([^>]+)>?/i);
|
|
456
|
+
if (messageIdMatch && messageIdMatch[1]) {
|
|
457
|
+
originalMessageId = messageIdMatch[1].trim();
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Create bounce data
|
|
461
|
+
const bounceData: Partial<BounceRecord> = {
|
|
462
|
+
recipient,
|
|
463
|
+
sender: bounceEmail.from,
|
|
464
|
+
domain: recipient.split('@')[1],
|
|
465
|
+
subject: bounceEmail.getSubject(),
|
|
466
|
+
diagnosticCode,
|
|
467
|
+
statusCode,
|
|
468
|
+
timestamp: Date.now(),
|
|
469
|
+
headers: {}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// Process as a regular bounce
|
|
473
|
+
return this.processBounce(bounceData);
|
|
474
|
+
} catch (error) {
|
|
475
|
+
logger.log('error', `Error processing bounce email: ${error.message}`);
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Handle a hard bounce by adding to suppression list
|
|
482
|
+
* @param bounce The bounce record
|
|
483
|
+
*/
|
|
484
|
+
private async handleHardBounce(bounce: BounceRecord): Promise<void> {
|
|
485
|
+
// Add to suppression list permanently (no expiry)
|
|
486
|
+
this.addToSuppressionList(bounce.recipient, `Hard bounce: ${bounce.bounceType}`, undefined);
|
|
487
|
+
|
|
488
|
+
// Increment bounce count in cache
|
|
489
|
+
this.updateBounceCache(bounce);
|
|
490
|
+
|
|
491
|
+
// Save to permanent storage
|
|
492
|
+
await this.saveBounceRecord(bounce);
|
|
493
|
+
|
|
494
|
+
// Log hard bounce for monitoring
|
|
495
|
+
logger.log('warn', `Hard bounce for ${bounce.recipient}: ${bounce.bounceType}`, {
|
|
496
|
+
domain: bounce.domain,
|
|
497
|
+
smtpResponse: bounce.smtpResponse,
|
|
498
|
+
diagnosticCode: bounce.diagnosticCode
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Handle a soft bounce by scheduling a retry if eligible
|
|
504
|
+
* @param bounce The bounce record
|
|
505
|
+
*/
|
|
506
|
+
private async handleSoftBounce(bounce: BounceRecord): Promise<void> {
|
|
507
|
+
// Check if we've exceeded max retries
|
|
508
|
+
if (bounce.retryCount >= this.retryStrategy.maxRetries) {
|
|
509
|
+
logger.log('warn', `Max retries exceeded for ${bounce.recipient}, treating as hard bounce`);
|
|
510
|
+
|
|
511
|
+
// Convert to hard bounce after max retries
|
|
512
|
+
bounce.bounceCategory = BounceCategory.HARD;
|
|
513
|
+
await this.handleHardBounce(bounce);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Calculate next retry time with exponential backoff
|
|
518
|
+
const delay = Math.min(
|
|
519
|
+
this.retryStrategy.initialDelay * Math.pow(this.retryStrategy.backoffFactor, bounce.retryCount),
|
|
520
|
+
this.retryStrategy.maxDelay
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
bounce.retryCount++;
|
|
524
|
+
bounce.nextRetryTime = Date.now() + delay;
|
|
525
|
+
|
|
526
|
+
// Add to suppression list temporarily (with expiry)
|
|
527
|
+
this.addToSuppressionList(
|
|
528
|
+
bounce.recipient,
|
|
529
|
+
`Soft bounce: ${bounce.bounceType}`,
|
|
530
|
+
bounce.nextRetryTime
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
// Log the retry schedule
|
|
534
|
+
logger.log('info', `Scheduled retry ${bounce.retryCount} for ${bounce.recipient} at ${new Date(bounce.nextRetryTime).toISOString()}`, {
|
|
535
|
+
bounceType: bounce.bounceType,
|
|
536
|
+
retryCount: bounce.retryCount,
|
|
537
|
+
nextRetry: bounce.nextRetryTime
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Add an email address to the suppression list
|
|
543
|
+
* @param email Email address to suppress
|
|
544
|
+
* @param reason Reason for suppression
|
|
545
|
+
* @param expiresAt Expiration timestamp (undefined for permanent)
|
|
546
|
+
*/
|
|
547
|
+
public addToSuppressionList(
|
|
548
|
+
email: string,
|
|
549
|
+
reason: string,
|
|
550
|
+
expiresAt?: number
|
|
551
|
+
): void {
|
|
552
|
+
this.suppressionList.set(email.toLowerCase(), {
|
|
553
|
+
reason,
|
|
554
|
+
timestamp: Date.now(),
|
|
555
|
+
expiresAt
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
// Save asynchronously without blocking
|
|
559
|
+
this.saveSuppressionList().catch(error => {
|
|
560
|
+
logger.log('error', `Failed to save suppression list after adding ${email}: ${error.message}`);
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
logger.log('info', `Added ${email} to suppression list`, {
|
|
564
|
+
reason,
|
|
565
|
+
expiresAt: expiresAt ? new Date(expiresAt).toISOString() : 'permanent'
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Remove an email address from the suppression list
|
|
571
|
+
* @param email Email address to remove
|
|
572
|
+
*/
|
|
573
|
+
public removeFromSuppressionList(email: string): void {
|
|
574
|
+
const wasRemoved = this.suppressionList.delete(email.toLowerCase());
|
|
575
|
+
|
|
576
|
+
if (wasRemoved) {
|
|
577
|
+
// Save asynchronously without blocking
|
|
578
|
+
this.saveSuppressionList().catch(error => {
|
|
579
|
+
logger.log('error', `Failed to save suppression list after removing ${email}: ${error.message}`);
|
|
580
|
+
});
|
|
581
|
+
logger.log('info', `Removed ${email} from suppression list`);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Check if an email is on the suppression list
|
|
587
|
+
* @param email Email address to check
|
|
588
|
+
* @returns Whether the email is suppressed
|
|
589
|
+
*/
|
|
590
|
+
public isEmailSuppressed(email: string): boolean {
|
|
591
|
+
const lowercaseEmail = email.toLowerCase();
|
|
592
|
+
const suppression = this.suppressionList.get(lowercaseEmail);
|
|
593
|
+
|
|
594
|
+
if (!suppression) {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Check if suppression has expired
|
|
599
|
+
if (suppression.expiresAt && Date.now() > suppression.expiresAt) {
|
|
600
|
+
this.suppressionList.delete(lowercaseEmail);
|
|
601
|
+
// Save asynchronously without blocking
|
|
602
|
+
this.saveSuppressionList().catch(error => {
|
|
603
|
+
logger.log('error', `Failed to save suppression list after expiry cleanup: ${error.message}`);
|
|
604
|
+
});
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return true;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Get suppression information for an email
|
|
613
|
+
* @param email Email address to check
|
|
614
|
+
* @returns Suppression information or null if not suppressed
|
|
615
|
+
*/
|
|
616
|
+
public getSuppressionInfo(email: string): {
|
|
617
|
+
reason: string;
|
|
618
|
+
timestamp: number;
|
|
619
|
+
expiresAt?: number;
|
|
620
|
+
} | null {
|
|
621
|
+
const lowercaseEmail = email.toLowerCase();
|
|
622
|
+
const suppression = this.suppressionList.get(lowercaseEmail);
|
|
623
|
+
|
|
624
|
+
if (!suppression) {
|
|
625
|
+
return null;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Check if suppression has expired
|
|
629
|
+
if (suppression.expiresAt && Date.now() > suppression.expiresAt) {
|
|
630
|
+
this.suppressionList.delete(lowercaseEmail);
|
|
631
|
+
// Save asynchronously without blocking
|
|
632
|
+
this.saveSuppressionList().catch(error => {
|
|
633
|
+
logger.log('error', `Failed to save suppression list after expiry cleanup: ${error.message}`);
|
|
634
|
+
});
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return suppression;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Save suppression list to disk
|
|
643
|
+
*/
|
|
644
|
+
private async saveSuppressionList(): Promise<void> {
|
|
645
|
+
try {
|
|
646
|
+
const suppressionData = JSON.stringify(Array.from(this.suppressionList.entries()));
|
|
647
|
+
|
|
648
|
+
if (this.storageManager) {
|
|
649
|
+
// Use storage manager
|
|
650
|
+
await this.storageManager.set('/email/bounces/suppression-list.json', suppressionData);
|
|
651
|
+
} else {
|
|
652
|
+
// Fall back to filesystem
|
|
653
|
+
plugins.smartfile.memory.toFsSync(
|
|
654
|
+
suppressionData,
|
|
655
|
+
plugins.path.join(paths.dataDir, 'emails', 'suppression_list.json')
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
} catch (error) {
|
|
659
|
+
logger.log('error', `Failed to save suppression list: ${error.message}`);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Load suppression list from disk
|
|
665
|
+
*/
|
|
666
|
+
private async loadSuppressionList(): Promise<void> {
|
|
667
|
+
try {
|
|
668
|
+
let entries = null;
|
|
669
|
+
let needsMigration = false;
|
|
670
|
+
|
|
671
|
+
if (this.storageManager) {
|
|
672
|
+
// Try to load from storage manager first
|
|
673
|
+
const suppressionData = await this.storageManager.get('/email/bounces/suppression-list.json');
|
|
674
|
+
|
|
675
|
+
if (suppressionData) {
|
|
676
|
+
entries = JSON.parse(suppressionData);
|
|
677
|
+
} else {
|
|
678
|
+
// Check if data exists in filesystem and migrate
|
|
679
|
+
const suppressionPath = plugins.path.join(paths.dataDir, 'emails', 'suppression_list.json');
|
|
680
|
+
|
|
681
|
+
if (plugins.fs.existsSync(suppressionPath)) {
|
|
682
|
+
const data = plugins.fs.readFileSync(suppressionPath, 'utf8');
|
|
683
|
+
entries = JSON.parse(data);
|
|
684
|
+
needsMigration = true;
|
|
685
|
+
|
|
686
|
+
logger.log('info', 'Migrating suppression list from filesystem to StorageManager');
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
} else {
|
|
690
|
+
// No storage manager, use filesystem directly
|
|
691
|
+
const suppressionPath = plugins.path.join(paths.dataDir, 'emails', 'suppression_list.json');
|
|
692
|
+
|
|
693
|
+
if (plugins.fs.existsSync(suppressionPath)) {
|
|
694
|
+
const data = plugins.fs.readFileSync(suppressionPath, 'utf8');
|
|
695
|
+
entries = JSON.parse(data);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
if (entries) {
|
|
700
|
+
this.suppressionList = new Map(entries);
|
|
701
|
+
|
|
702
|
+
// Clean expired entries
|
|
703
|
+
const now = Date.now();
|
|
704
|
+
let expiredCount = 0;
|
|
705
|
+
|
|
706
|
+
for (const [email, info] of this.suppressionList.entries()) {
|
|
707
|
+
if (info.expiresAt && now > info.expiresAt) {
|
|
708
|
+
this.suppressionList.delete(email);
|
|
709
|
+
expiredCount++;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
if (expiredCount > 0 || needsMigration) {
|
|
714
|
+
logger.log('info', `Cleaned ${expiredCount} expired entries from suppression list`);
|
|
715
|
+
await this.saveSuppressionList();
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
logger.log('info', `Loaded ${this.suppressionList.size} entries from suppression list`);
|
|
719
|
+
}
|
|
720
|
+
} catch (error) {
|
|
721
|
+
logger.log('error', `Failed to load suppression list: ${error.message}`);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Save bounce record to disk
|
|
727
|
+
* @param bounce Bounce record to save
|
|
728
|
+
*/
|
|
729
|
+
private async saveBounceRecord(bounce: BounceRecord): Promise<void> {
|
|
730
|
+
try {
|
|
731
|
+
const bounceData = JSON.stringify(bounce, null, 2);
|
|
732
|
+
|
|
733
|
+
if (this.storageManager) {
|
|
734
|
+
// Use storage manager
|
|
735
|
+
await this.storageManager.set(`/email/bounces/records/${bounce.id}.json`, bounceData);
|
|
736
|
+
} else {
|
|
737
|
+
// Fall back to filesystem
|
|
738
|
+
const bouncePath = plugins.path.join(
|
|
739
|
+
paths.dataDir,
|
|
740
|
+
'emails',
|
|
741
|
+
'bounces',
|
|
742
|
+
`${bounce.id}.json`
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
// Ensure directory exists
|
|
746
|
+
const bounceDir = plugins.path.join(paths.dataDir, 'emails', 'bounces');
|
|
747
|
+
plugins.smartfile.fs.ensureDirSync(bounceDir);
|
|
748
|
+
|
|
749
|
+
plugins.smartfile.memory.toFsSync(bounceData, bouncePath);
|
|
750
|
+
}
|
|
751
|
+
} catch (error) {
|
|
752
|
+
logger.log('error', `Failed to save bounce record: ${error.message}`);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Update bounce cache with new bounce information
|
|
758
|
+
* @param bounce Bounce record to update cache with
|
|
759
|
+
*/
|
|
760
|
+
private updateBounceCache(bounce: BounceRecord): void {
|
|
761
|
+
const email = bounce.recipient.toLowerCase();
|
|
762
|
+
const existing = this.bounceCache.get(email);
|
|
763
|
+
|
|
764
|
+
if (existing) {
|
|
765
|
+
// Update existing cache entry
|
|
766
|
+
existing.lastBounce = bounce.timestamp;
|
|
767
|
+
existing.count++;
|
|
768
|
+
existing.type = bounce.bounceType;
|
|
769
|
+
existing.category = bounce.bounceCategory;
|
|
770
|
+
} else {
|
|
771
|
+
// Create new cache entry
|
|
772
|
+
this.bounceCache.set(email, {
|
|
773
|
+
lastBounce: bounce.timestamp,
|
|
774
|
+
count: 1,
|
|
775
|
+
type: bounce.bounceType,
|
|
776
|
+
category: bounce.bounceCategory
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Check bounce history for an email address
|
|
783
|
+
* @param email Email address to check
|
|
784
|
+
* @returns Bounce information or null if no bounces
|
|
785
|
+
*/
|
|
786
|
+
public getBounceInfo(email: string): {
|
|
787
|
+
lastBounce: number;
|
|
788
|
+
count: number;
|
|
789
|
+
type: BounceType;
|
|
790
|
+
category: BounceCategory;
|
|
791
|
+
} | null {
|
|
792
|
+
return this.bounceCache.get(email.toLowerCase()) || null;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Analyze SMTP response and diagnostic codes to determine bounce type
|
|
797
|
+
* @param smtpResponse SMTP response string
|
|
798
|
+
* @param diagnosticCode Diagnostic code from bounce
|
|
799
|
+
* @param statusCode Status code from bounce
|
|
800
|
+
* @returns Detected bounce type and category
|
|
801
|
+
*/
|
|
802
|
+
private detectBounceType(
|
|
803
|
+
smtpResponse: string,
|
|
804
|
+
diagnosticCode: string,
|
|
805
|
+
statusCode: string
|
|
806
|
+
): {
|
|
807
|
+
type: BounceType;
|
|
808
|
+
category: BounceCategory;
|
|
809
|
+
} {
|
|
810
|
+
// Combine all text for comprehensive pattern matching
|
|
811
|
+
const fullText = `${smtpResponse} ${diagnosticCode} ${statusCode}`.toLowerCase();
|
|
812
|
+
|
|
813
|
+
// Check for auto-responses first
|
|
814
|
+
if (this.matchesPattern(fullText, BounceType.AUTO_RESPONSE) ||
|
|
815
|
+
this.matchesPattern(fullText, BounceType.CHALLENGE_RESPONSE)) {
|
|
816
|
+
return {
|
|
817
|
+
type: BounceType.AUTO_RESPONSE,
|
|
818
|
+
category: BounceCategory.AUTO_RESPONSE
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Check for hard bounces
|
|
823
|
+
for (const bounceType of [
|
|
824
|
+
BounceType.INVALID_RECIPIENT,
|
|
825
|
+
BounceType.DOMAIN_NOT_FOUND,
|
|
826
|
+
BounceType.MAILBOX_FULL,
|
|
827
|
+
BounceType.MAILBOX_INACTIVE,
|
|
828
|
+
BounceType.BLOCKED,
|
|
829
|
+
BounceType.SPAM_RELATED,
|
|
830
|
+
BounceType.POLICY_RELATED
|
|
831
|
+
]) {
|
|
832
|
+
if (this.matchesPattern(fullText, bounceType)) {
|
|
833
|
+
return {
|
|
834
|
+
type: bounceType,
|
|
835
|
+
category: BounceCategory.HARD
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Check for soft bounces
|
|
841
|
+
for (const bounceType of [
|
|
842
|
+
BounceType.SERVER_UNAVAILABLE,
|
|
843
|
+
BounceType.TEMPORARY_FAILURE,
|
|
844
|
+
BounceType.QUOTA_EXCEEDED,
|
|
845
|
+
BounceType.NETWORK_ERROR,
|
|
846
|
+
BounceType.TIMEOUT
|
|
847
|
+
]) {
|
|
848
|
+
if (this.matchesPattern(fullText, bounceType)) {
|
|
849
|
+
return {
|
|
850
|
+
type: bounceType,
|
|
851
|
+
category: BounceCategory.SOFT
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// Handle DSN (Delivery Status Notification) status codes
|
|
857
|
+
if (statusCode) {
|
|
858
|
+
// Format: class.subject.detail
|
|
859
|
+
const parts = statusCode.split('.');
|
|
860
|
+
if (parts.length >= 2) {
|
|
861
|
+
const statusClass = parts[0];
|
|
862
|
+
const statusSubject = parts[1];
|
|
863
|
+
|
|
864
|
+
// 5.X.X is permanent failure (hard bounce)
|
|
865
|
+
if (statusClass === '5') {
|
|
866
|
+
// Try to determine specific type based on subject
|
|
867
|
+
if (statusSubject === '1') {
|
|
868
|
+
return { type: BounceType.INVALID_RECIPIENT, category: BounceCategory.HARD };
|
|
869
|
+
} else if (statusSubject === '2') {
|
|
870
|
+
return { type: BounceType.MAILBOX_FULL, category: BounceCategory.HARD };
|
|
871
|
+
} else if (statusSubject === '7') {
|
|
872
|
+
return { type: BounceType.BLOCKED, category: BounceCategory.HARD };
|
|
873
|
+
} else {
|
|
874
|
+
return { type: BounceType.UNKNOWN, category: BounceCategory.HARD };
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// 4.X.X is temporary failure (soft bounce)
|
|
879
|
+
if (statusClass === '4') {
|
|
880
|
+
// Try to determine specific type based on subject
|
|
881
|
+
if (statusSubject === '2') {
|
|
882
|
+
return { type: BounceType.QUOTA_EXCEEDED, category: BounceCategory.SOFT };
|
|
883
|
+
} else if (statusSubject === '3') {
|
|
884
|
+
return { type: BounceType.SERVER_UNAVAILABLE, category: BounceCategory.SOFT };
|
|
885
|
+
} else if (statusSubject === '4') {
|
|
886
|
+
return { type: BounceType.NETWORK_ERROR, category: BounceCategory.SOFT };
|
|
887
|
+
} else {
|
|
888
|
+
return { type: BounceType.TEMPORARY_FAILURE, category: BounceCategory.SOFT };
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// Default to unknown
|
|
895
|
+
return {
|
|
896
|
+
type: BounceType.UNKNOWN,
|
|
897
|
+
category: BounceCategory.UNKNOWN
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* Check if text matches any pattern for a bounce type
|
|
903
|
+
* @param text Text to check against patterns
|
|
904
|
+
* @param bounceType Bounce type to get patterns for
|
|
905
|
+
* @returns Whether the text matches any pattern
|
|
906
|
+
*/
|
|
907
|
+
private matchesPattern(text: string, bounceType: BounceType): boolean {
|
|
908
|
+
const patterns = BOUNCE_PATTERNS[bounceType];
|
|
909
|
+
|
|
910
|
+
if (!patterns) {
|
|
911
|
+
return false;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
for (const pattern of patterns) {
|
|
915
|
+
if (pattern.test(text)) {
|
|
916
|
+
return true;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
return false;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Get all known hard bounced addresses
|
|
925
|
+
* @returns Array of hard bounced email addresses
|
|
926
|
+
*/
|
|
927
|
+
public getHardBouncedAddresses(): string[] {
|
|
928
|
+
const hardBounced: string[] = [];
|
|
929
|
+
|
|
930
|
+
for (const [email, info] of this.bounceCache.entries()) {
|
|
931
|
+
if (info.category === BounceCategory.HARD) {
|
|
932
|
+
hardBounced.push(email);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
return hardBounced;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Get suppression list
|
|
941
|
+
* @returns Array of suppressed email addresses
|
|
942
|
+
*/
|
|
943
|
+
public getSuppressionList(): string[] {
|
|
944
|
+
return Array.from(this.suppressionList.keys());
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Clear old bounce records (for maintenance)
|
|
949
|
+
* @param olderThan Timestamp to remove records older than
|
|
950
|
+
* @returns Number of records removed
|
|
951
|
+
*/
|
|
952
|
+
public clearOldBounceRecords(olderThan: number): number {
|
|
953
|
+
let removed = 0;
|
|
954
|
+
|
|
955
|
+
this.bounceStore = this.bounceStore.filter(bounce => {
|
|
956
|
+
if (bounce.timestamp < olderThan) {
|
|
957
|
+
removed++;
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
960
|
+
return true;
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
return removed;
|
|
964
|
+
}
|
|
965
|
+
}
|