@rapidmx/restapi 0.1.0
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/LICENSE +382 -0
- package/README.md +50 -0
- package/dist/lib/blob/BlobStore.js +6 -0
- package/dist/lib/blob/BlobStore.js.map +1 -0
- package/dist/lib/blob/LocalFsBlobStore.js +101 -0
- package/dist/lib/blob/LocalFsBlobStore.js.map +1 -0
- package/dist/lib/blob/index.js +7 -0
- package/dist/lib/blob/index.js.map +1 -0
- package/dist/lib/index.js +12 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/jobs/AttachmentExtractionJob.js +124 -0
- package/dist/lib/jobs/AttachmentExtractionJob.js.map +1 -0
- package/dist/lib/jobs/CalendarReminderJob.js +132 -0
- package/dist/lib/jobs/CalendarReminderJob.js.map +1 -0
- package/dist/lib/jobs/EasDeviceStateCleanupJob.js +101 -0
- package/dist/lib/jobs/EasDeviceStateCleanupJob.js.map +1 -0
- package/dist/lib/jobs/ExternalShareExpirationJob.js +117 -0
- package/dist/lib/jobs/ExternalShareExpirationJob.js.map +1 -0
- package/dist/lib/jobs/MailboxQuotaRecalcJob.js +163 -0
- package/dist/lib/jobs/MailboxQuotaRecalcJob.js.map +1 -0
- package/dist/lib/jobs/MeetingSchedulingJob.js +106 -0
- package/dist/lib/jobs/MeetingSchedulingJob.js.map +1 -0
- package/dist/lib/jobs/QuarantineRetentionJob.js +97 -0
- package/dist/lib/jobs/QuarantineRetentionJob.js.map +1 -0
- package/dist/lib/jobs/ScanQueueJob.js +223 -0
- package/dist/lib/jobs/ScanQueueJob.js.map +1 -0
- package/dist/lib/jobs/SearchIndexJob.js +146 -0
- package/dist/lib/jobs/SearchIndexJob.js.map +1 -0
- package/dist/lib/jobs/index.js +10 -0
- package/dist/lib/jobs/index.js.map +1 -0
- package/dist/lib/jobs/mongo/AttachmentExtractionJobMongo.js +14 -0
- package/dist/lib/jobs/mongo/AttachmentExtractionJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/CalendarReminderJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/CalendarReminderJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/ExternalShareExpirationJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/ExternalShareExpirationJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/MailboxQuotaRecalcJobMongo.js +15 -0
- package/dist/lib/jobs/mongo/MailboxQuotaRecalcJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/MeetingSchedulingJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/MeetingSchedulingJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/QuarantineRetentionJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/QuarantineRetentionJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/ScanQueueJobMongo.js +18 -0
- package/dist/lib/jobs/mongo/ScanQueueJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/SearchIndexJobMongo.js +14 -0
- package/dist/lib/jobs/mongo/SearchIndexJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/index.js +10 -0
- package/dist/lib/jobs/mongo/index.js.map +1 -0
- package/dist/lib/jobs/mongo.js +2 -0
- package/dist/lib/jobs/mongo.js.map +1 -0
- package/dist/lib/jobs/sql/AttachmentExtractionJobSQL.js +14 -0
- package/dist/lib/jobs/sql/AttachmentExtractionJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/CalendarReminderJobSQL.js +13 -0
- package/dist/lib/jobs/sql/CalendarReminderJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js +13 -0
- package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/ExternalShareExpirationJobSQL.js +13 -0
- package/dist/lib/jobs/sql/ExternalShareExpirationJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/MailboxQuotaRecalcJobSQL.js +15 -0
- package/dist/lib/jobs/sql/MailboxQuotaRecalcJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/MeetingSchedulingJobSQL.js +13 -0
- package/dist/lib/jobs/sql/MeetingSchedulingJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/QuarantineRetentionJobSQL.js +13 -0
- package/dist/lib/jobs/sql/QuarantineRetentionJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/ScanQueueJobSQL.js +18 -0
- package/dist/lib/jobs/sql/ScanQueueJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/SearchIndexJobSQL.js +14 -0
- package/dist/lib/jobs/sql/SearchIndexJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/index.js +10 -0
- package/dist/lib/jobs/sql/index.js.map +1 -0
- package/dist/lib/jobs/sql.js +2 -0
- package/dist/lib/jobs/sql.js.map +1 -0
- package/dist/lib/models/index.js +2 -0
- package/dist/lib/models/index.js.map +1 -0
- package/dist/lib/models/mongo/AttachmentMongo.js +129 -0
- package/dist/lib/models/mongo/AttachmentMongo.js.map +1 -0
- package/dist/lib/models/mongo/CalendarEventMongo.js +172 -0
- package/dist/lib/models/mongo/CalendarEventMongo.js.map +1 -0
- package/dist/lib/models/mongo/CalendarShareLinkMongo.js +85 -0
- package/dist/lib/models/mongo/CalendarShareLinkMongo.js.map +1 -0
- package/dist/lib/models/mongo/ContactListMongo.js +60 -0
- package/dist/lib/models/mongo/ContactListMongo.js.map +1 -0
- package/dist/lib/models/mongo/ContactMongo.js +148 -0
- package/dist/lib/models/mongo/ContactMongo.js.map +1 -0
- package/dist/lib/models/mongo/DeviceSyncStateMongo.js +97 -0
- package/dist/lib/models/mongo/DeviceSyncStateMongo.js.map +1 -0
- package/dist/lib/models/mongo/FolderMongo.js +102 -0
- package/dist/lib/models/mongo/FolderMongo.js.map +1 -0
- package/dist/lib/models/mongo/IngestQueueEntryMongo.js +93 -0
- package/dist/lib/models/mongo/IngestQueueEntryMongo.js.map +1 -0
- package/dist/lib/models/mongo/MailboxMongo.js +105 -0
- package/dist/lib/models/mongo/MailboxMongo.js.map +1 -0
- package/dist/lib/models/mongo/MessageMongo.js +180 -0
- package/dist/lib/models/mongo/MessageMongo.js.map +1 -0
- package/dist/lib/models/mongo/NoteMongo.js +83 -0
- package/dist/lib/models/mongo/NoteMongo.js.map +1 -0
- package/dist/lib/models/mongo/QuarantineEntryMongo.js +99 -0
- package/dist/lib/models/mongo/QuarantineEntryMongo.js.map +1 -0
- package/dist/lib/models/mongo/ScanResultMongo.js +112 -0
- package/dist/lib/models/mongo/ScanResultMongo.js.map +1 -0
- package/dist/lib/models/mongo/SearchIndexStateMongo.js +83 -0
- package/dist/lib/models/mongo/SearchIndexStateMongo.js.map +1 -0
- package/dist/lib/models/mongo/TaskMongo.js +105 -0
- package/dist/lib/models/mongo/TaskMongo.js.map +1 -0
- package/dist/lib/models/mongo/index.js +16 -0
- package/dist/lib/models/mongo/index.js.map +1 -0
- package/dist/lib/models/mongo.js +2 -0
- package/dist/lib/models/mongo.js.map +1 -0
- package/dist/lib/models/sql/AttachmentSQL.js +129 -0
- package/dist/lib/models/sql/AttachmentSQL.js.map +1 -0
- package/dist/lib/models/sql/CalendarEventSQL.js +176 -0
- package/dist/lib/models/sql/CalendarEventSQL.js.map +1 -0
- package/dist/lib/models/sql/CalendarShareLinkSQL.js +85 -0
- package/dist/lib/models/sql/CalendarShareLinkSQL.js.map +1 -0
- package/dist/lib/models/sql/ContactListSQL.js +60 -0
- package/dist/lib/models/sql/ContactListSQL.js.map +1 -0
- package/dist/lib/models/sql/ContactSQL.js +148 -0
- package/dist/lib/models/sql/ContactSQL.js.map +1 -0
- package/dist/lib/models/sql/DeviceSyncStateSQL.js +97 -0
- package/dist/lib/models/sql/DeviceSyncStateSQL.js.map +1 -0
- package/dist/lib/models/sql/FolderSQL.js +106 -0
- package/dist/lib/models/sql/FolderSQL.js.map +1 -0
- package/dist/lib/models/sql/IngestQueueEntrySQL.js +97 -0
- package/dist/lib/models/sql/IngestQueueEntrySQL.js.map +1 -0
- package/dist/lib/models/sql/MailboxSQL.js +105 -0
- package/dist/lib/models/sql/MailboxSQL.js.map +1 -0
- package/dist/lib/models/sql/MessageSQL.js +184 -0
- package/dist/lib/models/sql/MessageSQL.js.map +1 -0
- package/dist/lib/models/sql/NoteSQL.js +83 -0
- package/dist/lib/models/sql/NoteSQL.js.map +1 -0
- package/dist/lib/models/sql/QuarantineEntrySQL.js +103 -0
- package/dist/lib/models/sql/QuarantineEntrySQL.js.map +1 -0
- package/dist/lib/models/sql/ScanResultSQL.js +116 -0
- package/dist/lib/models/sql/ScanResultSQL.js.map +1 -0
- package/dist/lib/models/sql/SearchIndexStateSQL.js +83 -0
- package/dist/lib/models/sql/SearchIndexStateSQL.js.map +1 -0
- package/dist/lib/models/sql/TaskSQL.js +109 -0
- package/dist/lib/models/sql/TaskSQL.js.map +1 -0
- package/dist/lib/models/sql/index.js +16 -0
- package/dist/lib/models/sql/index.js.map +1 -0
- package/dist/lib/models/sql.js +2 -0
- package/dist/lib/models/sql.js.map +1 -0
- package/dist/lib/models/types.js +108 -0
- package/dist/lib/models/types.js.map +1 -0
- package/dist/lib/mongo.js +8 -0
- package/dist/lib/mongo.js.map +1 -0
- package/dist/lib/push/MailPushRoute.js +42 -0
- package/dist/lib/push/MailPushRoute.js.map +1 -0
- package/dist/lib/push/index.js +6 -0
- package/dist/lib/push/index.js.map +1 -0
- package/dist/lib/routes/BaseAttachmentRoute.js +142 -0
- package/dist/lib/routes/BaseAttachmentRoute.js.map +1 -0
- package/dist/lib/routes/BaseCalendarShareLinkRoute.js +123 -0
- package/dist/lib/routes/BaseCalendarShareLinkRoute.js.map +1 -0
- package/dist/lib/routes/BaseFolderRoute.js +192 -0
- package/dist/lib/routes/BaseFolderRoute.js.map +1 -0
- package/dist/lib/routes/BaseMailIngestRoute.js +179 -0
- package/dist/lib/routes/BaseMailIngestRoute.js.map +1 -0
- package/dist/lib/routes/BaseMailboxRoute.js +187 -0
- package/dist/lib/routes/BaseMailboxRoute.js.map +1 -0
- package/dist/lib/routes/BaseMessageRoute.js +142 -0
- package/dist/lib/routes/BaseMessageRoute.js.map +1 -0
- package/dist/lib/routes/BaseScopedChildRoute.js +348 -0
- package/dist/lib/routes/BaseScopedChildRoute.js.map +1 -0
- package/dist/lib/routes/BaseSearchRoute.js +91 -0
- package/dist/lib/routes/BaseSearchRoute.js.map +1 -0
- package/dist/lib/routes/index.js +13 -0
- package/dist/lib/routes/index.js.map +1 -0
- package/dist/lib/routes/mongo/AttachmentRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/AttachmentRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/CalendarEventRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/CalendarEventRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/CalendarShareLinkRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/CalendarShareLinkRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/ContactListRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/ContactListRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/ContactRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/ContactRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/FolderRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/FolderRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/IngestQueueRouteMongo.js +33 -0
- package/dist/lib/routes/mongo/IngestQueueRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/MailIngestRouteMongo.js +14 -0
- package/dist/lib/routes/mongo/MailIngestRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/MailboxRouteMongo.js +39 -0
- package/dist/lib/routes/mongo/MailboxRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/MessageRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/MessageRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/NoteRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/NoteRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/QuarantineRouteMongo.js +35 -0
- package/dist/lib/routes/mongo/QuarantineRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/SearchRouteMongo.js +13 -0
- package/dist/lib/routes/mongo/SearchRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/TaskRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/TaskRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/index.js +15 -0
- package/dist/lib/routes/mongo/index.js.map +1 -0
- package/dist/lib/routes/mongo.js +2 -0
- package/dist/lib/routes/mongo.js.map +1 -0
- package/dist/lib/routes/sql/AttachmentRouteSQL.js +26 -0
- package/dist/lib/routes/sql/AttachmentRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/CalendarEventRouteSQL.js +27 -0
- package/dist/lib/routes/sql/CalendarEventRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/CalendarShareLinkRouteSQL.js +26 -0
- package/dist/lib/routes/sql/CalendarShareLinkRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/ContactListRouteSQL.js +26 -0
- package/dist/lib/routes/sql/ContactListRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/ContactRouteSQL.js +27 -0
- package/dist/lib/routes/sql/ContactRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/FolderRouteSQL.js +26 -0
- package/dist/lib/routes/sql/FolderRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/IngestQueueRouteSQL.js +29 -0
- package/dist/lib/routes/sql/IngestQueueRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/MailIngestRouteSQL.js +35 -0
- package/dist/lib/routes/sql/MailIngestRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/MailboxRouteSQL.js +64 -0
- package/dist/lib/routes/sql/MailboxRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/MessageRouteSQL.js +27 -0
- package/dist/lib/routes/sql/MessageRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/NoteRouteSQL.js +26 -0
- package/dist/lib/routes/sql/NoteRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/QuarantineRouteSQL.js +29 -0
- package/dist/lib/routes/sql/QuarantineRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/SearchRouteSQL.js +13 -0
- package/dist/lib/routes/sql/SearchRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/TaskRouteSQL.js +27 -0
- package/dist/lib/routes/sql/TaskRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/index.js +15 -0
- package/dist/lib/routes/sql/index.js.map +1 -0
- package/dist/lib/routes/sql.js +2 -0
- package/dist/lib/routes/sql.js.map +1 -0
- package/dist/lib/scan/AvScanProvider.js +2 -0
- package/dist/lib/scan/AvScanProvider.js.map +1 -0
- package/dist/lib/scan/ClamAvScanProvider.js +112 -0
- package/dist/lib/scan/ClamAvScanProvider.js.map +1 -0
- package/dist/lib/scan/RspamdSpamScanProvider.js +100 -0
- package/dist/lib/scan/RspamdSpamScanProvider.js.map +1 -0
- package/dist/lib/scan/ScanPipeline.js +118 -0
- package/dist/lib/scan/ScanPipeline.js.map +1 -0
- package/dist/lib/scan/SpamScanProvider.js +2 -0
- package/dist/lib/scan/SpamScanProvider.js.map +1 -0
- package/dist/lib/scan/index.js +10 -0
- package/dist/lib/scan/index.js.map +1 -0
- package/dist/lib/search/MongoTextSearchProvider.js +116 -0
- package/dist/lib/search/MongoTextSearchProvider.js.map +1 -0
- package/dist/lib/search/OpenSearchProvider.js +156 -0
- package/dist/lib/search/OpenSearchProvider.js.map +1 -0
- package/dist/lib/search/PostgresFullTextSearchProvider.js +139 -0
- package/dist/lib/search/PostgresFullTextSearchProvider.js.map +1 -0
- package/dist/lib/search/SearchProvider.js +6 -0
- package/dist/lib/search/SearchProvider.js.map +1 -0
- package/dist/lib/search/extraction/DocxTextExtractor.js +27 -0
- package/dist/lib/search/extraction/DocxTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/ExtractorRegistry.js +82 -0
- package/dist/lib/search/extraction/ExtractorRegistry.js.map +1 -0
- package/dist/lib/search/extraction/HtmlTextExtractor.js +20 -0
- package/dist/lib/search/extraction/HtmlTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/PdfTextExtractor.js +22 -0
- package/dist/lib/search/extraction/PdfTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/PlainTextExtractor.js +14 -0
- package/dist/lib/search/extraction/PlainTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/TextExtractor.js +6 -0
- package/dist/lib/search/extraction/TextExtractor.js.map +1 -0
- package/dist/lib/search/index.js +15 -0
- package/dist/lib/search/index.js.map +1 -0
- package/dist/lib/sql.js +8 -0
- package/dist/lib/sql.js.map +1 -0
- package/dist/lib/transport/MTAIngestAdapter.js +30 -0
- package/dist/lib/transport/MTAIngestAdapter.js.map +1 -0
- package/dist/lib/transport/MailTransport.js +6 -0
- package/dist/lib/transport/MailTransport.js.map +1 -0
- package/dist/lib/transport/PostfixSendmailTransport.js +61 -0
- package/dist/lib/transport/PostfixSendmailTransport.js.map +1 -0
- package/dist/lib/transport/index.js +8 -0
- package/dist/lib/transport/index.js.map +1 -0
- package/dist/lib/util/FolderUtils.js +50 -0
- package/dist/lib/util/FolderUtils.js.map +1 -0
- package/dist/lib/util/MailSendUtils.js +36 -0
- package/dist/lib/util/MailSendUtils.js.map +1 -0
- package/dist/lib/util/MailboxScopeUtils.js +23 -0
- package/dist/lib/util/MailboxScopeUtils.js.map +1 -0
- package/dist/lib/util/OptionalDeps.js +23 -0
- package/dist/lib/util/OptionalDeps.js.map +1 -0
- package/dist/lib/util/RecoverableRepoUtils.js +42 -0
- package/dist/lib/util/RecoverableRepoUtils.js.map +1 -0
- package/dist/lib/util/index.js +17 -0
- package/dist/lib/util/index.js.map +1 -0
- package/dist/types/blob/BlobStore.d.ts +54 -0
- package/dist/types/blob/LocalFsBlobStore.d.ts +23 -0
- package/dist/types/blob/index.d.ts +2 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/jobs/AttachmentExtractionJob.d.ts +34 -0
- package/dist/types/jobs/CalendarReminderJob.d.ts +37 -0
- package/dist/types/jobs/EasDeviceStateCleanupJob.d.ts +26 -0
- package/dist/types/jobs/ExternalShareExpirationJob.d.ts +34 -0
- package/dist/types/jobs/MailboxQuotaRecalcJob.d.ts +44 -0
- package/dist/types/jobs/MeetingSchedulingJob.d.ts +32 -0
- package/dist/types/jobs/QuarantineRetentionJob.d.ts +27 -0
- package/dist/types/jobs/ScanQueueJob.d.ts +41 -0
- package/dist/types/jobs/SearchIndexJob.d.ts +37 -0
- package/dist/types/jobs/index.d.ts +9 -0
- package/dist/types/jobs/mongo/AttachmentExtractionJobMongo.d.ts +6 -0
- package/dist/types/jobs/mongo/CalendarReminderJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/EasDeviceStateCleanupJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/ExternalShareExpirationJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/MailboxQuotaRecalcJobMongo.d.ts +7 -0
- package/dist/types/jobs/mongo/MeetingSchedulingJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/QuarantineRetentionJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/ScanQueueJobMongo.d.ts +10 -0
- package/dist/types/jobs/mongo/SearchIndexJobMongo.d.ts +6 -0
- package/dist/types/jobs/mongo/index.d.ts +9 -0
- package/dist/types/jobs/mongo.d.ts +1 -0
- package/dist/types/jobs/sql/AttachmentExtractionJobSQL.d.ts +6 -0
- package/dist/types/jobs/sql/CalendarReminderJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/EasDeviceStateCleanupJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/ExternalShareExpirationJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/MailboxQuotaRecalcJobSQL.d.ts +7 -0
- package/dist/types/jobs/sql/MeetingSchedulingJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/QuarantineRetentionJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/ScanQueueJobSQL.d.ts +10 -0
- package/dist/types/jobs/sql/SearchIndexJobSQL.d.ts +6 -0
- package/dist/types/jobs/sql/index.d.ts +9 -0
- package/dist/types/jobs/sql.d.ts +1 -0
- package/dist/types/models/index.d.ts +1 -0
- package/dist/types/models/mongo/AttachmentMongo.d.ts +22 -0
- package/dist/types/models/mongo/CalendarEventMongo.d.ts +28 -0
- package/dist/types/models/mongo/CalendarShareLinkMongo.d.ts +16 -0
- package/dist/types/models/mongo/ContactListMongo.d.ts +13 -0
- package/dist/types/models/mongo/ContactMongo.d.ts +25 -0
- package/dist/types/models/mongo/DeviceSyncStateMongo.d.ts +18 -0
- package/dist/types/models/mongo/FolderMongo.d.ts +18 -0
- package/dist/types/models/mongo/IngestQueueEntryMongo.d.ts +17 -0
- package/dist/types/models/mongo/MailboxMongo.d.ts +18 -0
- package/dist/types/models/mongo/MessageMongo.d.ts +29 -0
- package/dist/types/models/mongo/NoteMongo.d.ts +16 -0
- package/dist/types/models/mongo/QuarantineEntryMongo.d.ts +18 -0
- package/dist/types/models/mongo/ScanResultMongo.d.ts +23 -0
- package/dist/types/models/mongo/SearchIndexStateMongo.d.ts +16 -0
- package/dist/types/models/mongo/TaskMongo.d.ts +19 -0
- package/dist/types/models/mongo/index.d.ts +15 -0
- package/dist/types/models/mongo.d.ts +1 -0
- package/dist/types/models/sql/AttachmentSQL.d.ts +22 -0
- package/dist/types/models/sql/CalendarEventSQL.d.ts +28 -0
- package/dist/types/models/sql/CalendarShareLinkSQL.d.ts +16 -0
- package/dist/types/models/sql/ContactListSQL.d.ts +13 -0
- package/dist/types/models/sql/ContactSQL.d.ts +25 -0
- package/dist/types/models/sql/DeviceSyncStateSQL.d.ts +18 -0
- package/dist/types/models/sql/FolderSQL.d.ts +18 -0
- package/dist/types/models/sql/IngestQueueEntrySQL.d.ts +17 -0
- package/dist/types/models/sql/MailboxSQL.d.ts +18 -0
- package/dist/types/models/sql/MessageSQL.d.ts +29 -0
- package/dist/types/models/sql/NoteSQL.d.ts +16 -0
- package/dist/types/models/sql/QuarantineEntrySQL.d.ts +18 -0
- package/dist/types/models/sql/ScanResultSQL.d.ts +23 -0
- package/dist/types/models/sql/SearchIndexStateSQL.d.ts +16 -0
- package/dist/types/models/sql/TaskSQL.d.ts +19 -0
- package/dist/types/models/sql/index.d.ts +15 -0
- package/dist/types/models/sql.d.ts +1 -0
- package/dist/types/models/types.d.ts +541 -0
- package/dist/types/mongo.d.ts +3 -0
- package/dist/types/push/MailPushRoute.d.ts +37 -0
- package/dist/types/push/index.d.ts +1 -0
- package/dist/types/routes/BaseAttachmentRoute.d.ts +24 -0
- package/dist/types/routes/BaseCalendarShareLinkRoute.d.ts +35 -0
- package/dist/types/routes/BaseFolderRoute.d.ts +58 -0
- package/dist/types/routes/BaseMailIngestRoute.d.ts +47 -0
- package/dist/types/routes/BaseMailboxRoute.d.ts +60 -0
- package/dist/types/routes/BaseMessageRoute.d.ts +27 -0
- package/dist/types/routes/BaseScopedChildRoute.d.ts +61 -0
- package/dist/types/routes/BaseSearchRoute.d.ts +23 -0
- package/dist/types/routes/index.d.ts +8 -0
- package/dist/types/routes/mongo/AttachmentRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/CalendarEventRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/CalendarShareLinkRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/ContactListRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/ContactRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/FolderRouteMongo.d.ts +5 -0
- package/dist/types/routes/mongo/IngestQueueRouteMongo.d.ts +13 -0
- package/dist/types/routes/mongo/MailIngestRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/MailboxRouteMongo.d.ts +8 -0
- package/dist/types/routes/mongo/MessageRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/NoteRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/QuarantineRouteMongo.d.ts +15 -0
- package/dist/types/routes/mongo/SearchRouteMongo.d.ts +5 -0
- package/dist/types/routes/mongo/TaskRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/index.d.ts +14 -0
- package/dist/types/routes/mongo.d.ts +1 -0
- package/dist/types/routes/sql/AttachmentRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/CalendarEventRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/CalendarShareLinkRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/ContactListRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/ContactRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/FolderRouteSQL.d.ts +5 -0
- package/dist/types/routes/sql/IngestQueueRouteSQL.d.ts +9 -0
- package/dist/types/routes/sql/MailIngestRouteSQL.d.ts +23 -0
- package/dist/types/routes/sql/MailboxRouteSQL.d.ts +22 -0
- package/dist/types/routes/sql/MessageRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/NoteRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/QuarantineRouteSQL.d.ts +9 -0
- package/dist/types/routes/sql/SearchRouteSQL.d.ts +5 -0
- package/dist/types/routes/sql/TaskRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/index.d.ts +14 -0
- package/dist/types/routes/sql.d.ts +1 -0
- package/dist/types/scan/AvScanProvider.d.ts +22 -0
- package/dist/types/scan/ClamAvScanProvider.d.ts +17 -0
- package/dist/types/scan/RspamdSpamScanProvider.d.ts +16 -0
- package/dist/types/scan/ScanPipeline.d.ts +53 -0
- package/dist/types/scan/SpamScanProvider.d.ts +29 -0
- package/dist/types/scan/index.d.ts +5 -0
- package/dist/types/search/MongoTextSearchProvider.d.ts +22 -0
- package/dist/types/search/OpenSearchProvider.d.ts +24 -0
- package/dist/types/search/PostgresFullTextSearchProvider.d.ts +21 -0
- package/dist/types/search/SearchProvider.d.ts +62 -0
- package/dist/types/search/extraction/DocxTextExtractor.d.ts +14 -0
- package/dist/types/search/extraction/ExtractorRegistry.d.ts +19 -0
- package/dist/types/search/extraction/HtmlTextExtractor.d.ts +11 -0
- package/dist/types/search/extraction/PdfTextExtractor.d.ts +10 -0
- package/dist/types/search/extraction/PlainTextExtractor.d.ts +10 -0
- package/dist/types/search/extraction/TextExtractor.d.ts +17 -0
- package/dist/types/search/index.d.ts +10 -0
- package/dist/types/sql.d.ts +3 -0
- package/dist/types/transport/MTAIngestAdapter.d.ts +25 -0
- package/dist/types/transport/MailTransport.d.ts +29 -0
- package/dist/types/transport/PostfixSendmailTransport.d.ts +15 -0
- package/dist/types/transport/index.d.ts +3 -0
- package/dist/types/util/FolderUtils.d.ts +15 -0
- package/dist/types/util/MailSendUtils.d.ts +19 -0
- package/dist/types/util/MailboxScopeUtils.d.ts +19 -0
- package/dist/types/util/OptionalDeps.d.ts +9 -0
- package/dist/types/util/RecoverableRepoUtils.d.ts +24 -0
- package/dist/types/util/index.d.ts +12 -0
- package/package.json +122 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { ObjectDecorators } from "@rapidrest/core";
|
|
11
|
+
import { ConnectionManager } from "@rapidrest/service-core";
|
|
12
|
+
const { Config, Init, Inject, Logger } = ObjectDecorators;
|
|
13
|
+
const TABLE_NAME = "mail_search_index";
|
|
14
|
+
/**
|
|
15
|
+
* `SearchProvider` backed by Postgres's native full-text search (`tsvector`/`to_tsquery` with a GIN index) —
|
|
16
|
+
* the embedded default for a SQL-backed deployment that hasn't opted into a dedicated search engine. Documents
|
|
17
|
+
* are stored in a dedicated table separate from the entities they're derived from, keyed by
|
|
18
|
+
* `(entity_type, entity_uid)`.
|
|
19
|
+
*
|
|
20
|
+
* @author Jean-Philippe Steinmetz
|
|
21
|
+
*/
|
|
22
|
+
export class PostgresFullTextSearchProvider {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.name = "postgres";
|
|
25
|
+
this.datasourceName = "sql";
|
|
26
|
+
}
|
|
27
|
+
async init() {
|
|
28
|
+
const conn = this.connectionManager?.connections.get(this.datasourceName);
|
|
29
|
+
if (!conn || typeof conn.query !== "function") {
|
|
30
|
+
throw new Error(`PostgresFullTextSearchProvider: no SQL connection found for datasource '${this.datasourceName}'.`);
|
|
31
|
+
}
|
|
32
|
+
this.dataSource = conn;
|
|
33
|
+
await this.dataSource.query(`
|
|
34
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
|
|
35
|
+
entity_type varchar(32) NOT NULL,
|
|
36
|
+
entity_uid varchar(64) NOT NULL,
|
|
37
|
+
mailbox_uid varchar(64) NOT NULL,
|
|
38
|
+
subject text,
|
|
39
|
+
body text,
|
|
40
|
+
attachment_text text,
|
|
41
|
+
participants text,
|
|
42
|
+
date_for_sort timestamptz,
|
|
43
|
+
search_vector tsvector,
|
|
44
|
+
PRIMARY KEY (entity_type, entity_uid)
|
|
45
|
+
)
|
|
46
|
+
`);
|
|
47
|
+
await this.dataSource.query(`CREATE INDEX IF NOT EXISTS mail_search_index_vector ON ${TABLE_NAME} USING GIN (search_vector)`);
|
|
48
|
+
await this.dataSource.query(`CREATE INDEX IF NOT EXISTS mail_search_index_mailbox ON ${TABLE_NAME} (mailbox_uid, entity_type)`);
|
|
49
|
+
}
|
|
50
|
+
async index(doc) {
|
|
51
|
+
await this.bulkIndex([doc]);
|
|
52
|
+
}
|
|
53
|
+
async bulkIndex(docs) {
|
|
54
|
+
if (!this.dataSource || docs.length === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const doc of docs) {
|
|
58
|
+
const attachmentText = (doc.attachmentText ?? []).join("\n");
|
|
59
|
+
const participants = (doc.participants ?? []).join(" ");
|
|
60
|
+
await this.dataSource.query(`INSERT INTO ${TABLE_NAME}
|
|
61
|
+
(entity_type, entity_uid, mailbox_uid, subject, body, attachment_text, participants, date_for_sort, search_vector)
|
|
62
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8,
|
|
63
|
+
setweight(to_tsvector('english', coalesce($4, '')), 'A') ||
|
|
64
|
+
setweight(to_tsvector('english', coalesce($5, '')), 'B') ||
|
|
65
|
+
setweight(to_tsvector('english', coalesce($6, '')), 'C') ||
|
|
66
|
+
setweight(to_tsvector('english', coalesce($7, '')), 'D'))
|
|
67
|
+
ON CONFLICT (entity_type, entity_uid) DO UPDATE SET
|
|
68
|
+
mailbox_uid = EXCLUDED.mailbox_uid,
|
|
69
|
+
subject = EXCLUDED.subject,
|
|
70
|
+
body = EXCLUDED.body,
|
|
71
|
+
attachment_text = EXCLUDED.attachment_text,
|
|
72
|
+
participants = EXCLUDED.participants,
|
|
73
|
+
date_for_sort = EXCLUDED.date_for_sort,
|
|
74
|
+
search_vector = EXCLUDED.search_vector`, [
|
|
75
|
+
doc.entityType,
|
|
76
|
+
doc.entityUid,
|
|
77
|
+
doc.mailboxUid,
|
|
78
|
+
doc.subject ?? null,
|
|
79
|
+
doc.body ?? null,
|
|
80
|
+
attachmentText || null,
|
|
81
|
+
participants || null,
|
|
82
|
+
doc.dateForSort ?? null,
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async remove(entityType, entityUid) {
|
|
87
|
+
await this.dataSource?.query(`DELETE FROM ${TABLE_NAME} WHERE entity_type = $1 AND entity_uid = $2`, [
|
|
88
|
+
entityType,
|
|
89
|
+
entityUid,
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
async search(query) {
|
|
93
|
+
if (!this.dataSource) {
|
|
94
|
+
return { results: [] };
|
|
95
|
+
}
|
|
96
|
+
const limit = Math.min(query.limit ?? 25, 200);
|
|
97
|
+
const offset = query.cursor ? Math.max(0, parseInt(query.cursor, 10) || 0) : 0;
|
|
98
|
+
const typeFilter = query.entityTypes && query.entityTypes.length > 0 ? `AND entity_type = ANY($3::text[])` : "";
|
|
99
|
+
const params = [query.mailboxUid, query.text];
|
|
100
|
+
if (typeFilter) {
|
|
101
|
+
params.push(query.entityTypes);
|
|
102
|
+
}
|
|
103
|
+
params.push(limit + 1, offset);
|
|
104
|
+
const rows = await this.dataSource.query(`SELECT entity_type, entity_uid, ts_rank(search_vector, plainto_tsquery('english', $2)) AS rank
|
|
105
|
+
FROM ${TABLE_NAME}
|
|
106
|
+
WHERE mailbox_uid = $1 AND search_vector @@ plainto_tsquery('english', $2) ${typeFilter}
|
|
107
|
+
ORDER BY rank DESC
|
|
108
|
+
LIMIT $${typeFilter ? 4 : 3} OFFSET $${typeFilter ? 5 : 4}`, params);
|
|
109
|
+
const hasMore = rows.length > limit;
|
|
110
|
+
const page = hasMore ? rows.slice(0, limit) : rows;
|
|
111
|
+
return {
|
|
112
|
+
results: page.map((row) => ({
|
|
113
|
+
entityType: row.entity_type,
|
|
114
|
+
entityUid: row.entity_uid,
|
|
115
|
+
score: Number(row.rank),
|
|
116
|
+
})),
|
|
117
|
+
nextCursor: hasMore ? String(offset + limit) : undefined,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
__decorate([
|
|
122
|
+
Inject(ConnectionManager),
|
|
123
|
+
__metadata("design:type", ConnectionManager)
|
|
124
|
+
], PostgresFullTextSearchProvider.prototype, "connectionManager", void 0);
|
|
125
|
+
__decorate([
|
|
126
|
+
Config("mail:search:postgres:datasource", "sql"),
|
|
127
|
+
__metadata("design:type", String)
|
|
128
|
+
], PostgresFullTextSearchProvider.prototype, "datasourceName", void 0);
|
|
129
|
+
__decorate([
|
|
130
|
+
Logger,
|
|
131
|
+
__metadata("design:type", Object)
|
|
132
|
+
], PostgresFullTextSearchProvider.prototype, "logger", void 0);
|
|
133
|
+
__decorate([
|
|
134
|
+
Init,
|
|
135
|
+
__metadata("design:type", Function),
|
|
136
|
+
__metadata("design:paramtypes", []),
|
|
137
|
+
__metadata("design:returntype", Promise)
|
|
138
|
+
], PostgresFullTextSearchProvider.prototype, "init", null);
|
|
139
|
+
//# sourceMappingURL=PostgresFullTextSearchProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresFullTextSearchProvider.js","sourceRoot":"","sources":["../../../src/search/PostgresFullTextSearchProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=SearchProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchProvider.js","sourceRoot":"","sources":["../../../src/search/SearchProvider.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { importOptional } from "../../util/OptionalDeps.js";
|
|
6
|
+
/**
|
|
7
|
+
* Extracts text from Word (`.docx`) attachment content via the optional peer dependency `mammoth`.
|
|
8
|
+
*
|
|
9
|
+
* Excel/PowerPoint (`.xlsx`/`.pptx`) are deliberately out of scope for the initial pragmatic subset — their
|
|
10
|
+
* text is largely tabular/slide-fragmented and extracts poorly with a generic converter. Revisit with a
|
|
11
|
+
* dedicated extractor if search relevance over spreadsheet/slide attachments becomes a real requirement.
|
|
12
|
+
*
|
|
13
|
+
* @author Jean-Philippe Steinmetz
|
|
14
|
+
*/
|
|
15
|
+
export class DocxTextExtractor {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.mimeTypes = [
|
|
18
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
async extract(content) {
|
|
22
|
+
const mammoth = await importOptional("mammoth");
|
|
23
|
+
const result = await mammoth.extractRawText({ buffer: content });
|
|
24
|
+
return result.value ?? "";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=DocxTextExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocxTextExtractor.js","sourceRoot":"","sources":["../../../../src/search/extraction/DocxTextExtractor.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D;;;;;;;;GAQG;AACH,MAAM,OAAO,iBAAiB;IAA9B;QACoB,cAAS,GAAa;YAClC,yEAAyE;SAC5E,CAAC;IAON,CAAC;IALU,KAAK,CAAC,OAAO,CAAC,OAAe;QAChC,MAAM,OAAO,GAAQ,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IAC9B,CAAC;CACJ"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
12
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
13
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
14
|
+
import { ObjectDecorators } from "@rapidrest/core";
|
|
15
|
+
import { DocxTextExtractor } from "./DocxTextExtractor.js";
|
|
16
|
+
import { HtmlTextExtractor } from "./HtmlTextExtractor.js";
|
|
17
|
+
import { PdfTextExtractor } from "./PdfTextExtractor.js";
|
|
18
|
+
import { PlainTextExtractor } from "./PlainTextExtractor.js";
|
|
19
|
+
const { Config, Logger } = ObjectDecorators;
|
|
20
|
+
/**
|
|
21
|
+
* Dispatches attachment content to the `TextExtractor` registered for its MIME type, applying a size cap and
|
|
22
|
+
* timeout so a single huge or pathological attachment cannot stall `AttachmentExtractionJob` indefinitely.
|
|
23
|
+
*
|
|
24
|
+
* @author Jean-Philippe Steinmetz
|
|
25
|
+
*/
|
|
26
|
+
export class ExtractorRegistry {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.maxBytes = 25 * 1024 * 1024;
|
|
29
|
+
this.timeoutMs = 30000;
|
|
30
|
+
this.extractors = [
|
|
31
|
+
new PlainTextExtractor(),
|
|
32
|
+
new HtmlTextExtractor(),
|
|
33
|
+
new PdfTextExtractor(),
|
|
34
|
+
new DocxTextExtractor(),
|
|
35
|
+
];
|
|
36
|
+
this.byMimeType = new Map(this.extractors.flatMap((extractor) => extractor.mimeTypes.map((mimeType) => [mimeType, extractor])));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Extracts text from `content` if a `TextExtractor` is registered for `mimeType` and `content` is within
|
|
40
|
+
* the configured size cap, otherwise returns `undefined` without error (an unsupported/oversized
|
|
41
|
+
* attachment simply isn't indexed by content — its filename is still searchable via the entity itself).
|
|
42
|
+
*/
|
|
43
|
+
async extract(mimeType, content) {
|
|
44
|
+
const extractor = this.byMimeType.get(mimeType);
|
|
45
|
+
if (!extractor) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
if (content.length > this.maxBytes) {
|
|
49
|
+
this.logger?.debug(`Skipping text extraction for ${mimeType}: content exceeds ${this.maxBytes} bytes.`);
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
let timeoutHandle;
|
|
53
|
+
try {
|
|
54
|
+
return await Promise.race([
|
|
55
|
+
extractor.extract(content),
|
|
56
|
+
new Promise((_resolve, reject) => {
|
|
57
|
+
timeoutHandle = setTimeout(() => reject(new Error(`Text extraction for ${mimeType} timed out after ${this.timeoutMs}ms.`)), this.timeoutMs);
|
|
58
|
+
}),
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
this.logger?.warn(`Text extraction failed for ${mimeType}: ${err.message}`);
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
clearTimeout(timeoutHandle);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
__decorate([
|
|
71
|
+
Config("mail:search:extraction:max_bytes", 25 * 1024 * 1024),
|
|
72
|
+
__metadata("design:type", Number)
|
|
73
|
+
], ExtractorRegistry.prototype, "maxBytes", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
Config("mail:search:extraction:timeout_ms", 30000),
|
|
76
|
+
__metadata("design:type", Number)
|
|
77
|
+
], ExtractorRegistry.prototype, "timeoutMs", void 0);
|
|
78
|
+
__decorate([
|
|
79
|
+
Logger,
|
|
80
|
+
__metadata("design:type", Object)
|
|
81
|
+
], ExtractorRegistry.prototype, "logger", void 0);
|
|
82
|
+
//# sourceMappingURL=ExtractorRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExtractorRegistry.js","sourceRoot":"","sources":["../../../../src/search/extraction/ExtractorRegistry.ts"],"names":[],"mappings":";;;;;;;;;AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IAA9B;QAEY,aAAQ,GAAW,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;QAGpC,cAAS,GAAW,KAAM,CAAC;QAK3B,eAAU,GAAoB;YAClC,IAAI,kBAAkB,EAAE;YACxB,IAAI,iBAAiB,EAAE;YACvB,IAAI,gBAAgB,EAAE;YACtB,IAAI,iBAAiB,EAAE;SAC1B,CAAC;QAEM,eAAU,GAA+B,IAAI,GAAG,CACpD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CACvG,CAAC;IAoCN,CAAC;IAlCG;;;;OAIG;IACI,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,OAAe;QAClD,MAAM,SAAS,GAA8B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3E,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,gCAAgC,QAAQ,qBAAqB,IAAI,CAAC,QAAQ,SAAS,CAAC,CAAC;YACxG,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,IAAI,aAAyC,CAAC;QAC9C,IAAI,CAAC;YACD,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;gBACtB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;gBAC1B,IAAI,OAAO,CAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;oBACrC,aAAa,GAAG,UAAU,CACtB,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,QAAQ,oBAAoB,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC,EAC/F,IAAI,CAAC,SAAS,CACjB,CAAC;gBACN,CAAC,CAAC;aACL,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,8BAA8B,QAAQ,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5E,OAAO,SAAS,CAAC;QACrB,CAAC;gBAAS,CAAC;YACP,YAAY,CAAC,aAAa,CAAC,CAAC;QAChC,CAAC;IACL,CAAC;CACJ;AArDW;IADP,MAAM,CAAC,kCAAkC,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;;mDACjB;AAGpC;IADP,MAAM,CAAC,mCAAmC,EAAE,KAAM,CAAC;;oDACjB;AAG3B;IADP,MAAM;;iDACa"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { convert } from "html-to-text";
|
|
6
|
+
/**
|
|
7
|
+
* Strips markup from HTML attachment/body content, keeping only its rendered text — used both for attachment
|
|
8
|
+
* text extraction and to derive `Message.bodyPreview` from an HTML body.
|
|
9
|
+
*
|
|
10
|
+
* @author Jean-Philippe Steinmetz
|
|
11
|
+
*/
|
|
12
|
+
export class HtmlTextExtractor {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.mimeTypes = ["text/html"];
|
|
15
|
+
}
|
|
16
|
+
async extract(content) {
|
|
17
|
+
return convert(content.toString("utf-8"), { wordwrap: false });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=HtmlTextExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HtmlTextExtractor.js","sourceRoot":"","sources":["../../../../src/search/extraction/HtmlTextExtractor.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IAA9B;QACoB,cAAS,GAAa,CAAC,WAAW,CAAC,CAAC;IAKxD,CAAC;IAHU,KAAK,CAAC,OAAO,CAAC,OAAe;QAChC,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC;CACJ"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { importOptional } from "../../util/OptionalDeps.js";
|
|
6
|
+
/**
|
|
7
|
+
* Extracts text from PDF attachment content via the optional peer dependency `pdf-parse`.
|
|
8
|
+
*
|
|
9
|
+
* @author Jean-Philippe Steinmetz
|
|
10
|
+
*/
|
|
11
|
+
export class PdfTextExtractor {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.mimeTypes = ["application/pdf"];
|
|
14
|
+
}
|
|
15
|
+
async extract(content) {
|
|
16
|
+
const pdfParse = await importOptional("pdf-parse");
|
|
17
|
+
const parse = pdfParse.default ?? pdfParse;
|
|
18
|
+
const result = await parse(content);
|
|
19
|
+
return result.text ?? "";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=PdfTextExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PdfTextExtractor.js","sourceRoot":"","sources":["../../../../src/search/extraction/PdfTextExtractor.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAA7B;QACoB,cAAS,GAAa,CAAC,iBAAiB,CAAC,CAAC;IAQ9D,CAAC;IANU,KAAK,CAAC,OAAO,CAAC,OAAe;QAChC,MAAM,QAAQ,GAAQ,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACpC,OAAO,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7B,CAAC;CACJ"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passes plain-text attachment content through unchanged (decoded as UTF-8).
|
|
3
|
+
*
|
|
4
|
+
* @author Jean-Philippe Steinmetz
|
|
5
|
+
*/
|
|
6
|
+
export class PlainTextExtractor {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.mimeTypes = ["text/plain", "text/csv", "text/markdown"];
|
|
9
|
+
}
|
|
10
|
+
async extract(content) {
|
|
11
|
+
return content.toString("utf-8");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=PlainTextExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlainTextExtractor.js","sourceRoot":"","sources":["../../../../src/search/extraction/PlainTextExtractor.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IAA/B;QACoB,cAAS,GAAa,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;IAKtF,CAAC;IAHU,KAAK,CAAC,OAAO,CAAC,OAAe;QAChC,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;CACJ"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=TextExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextExtractor.js","sourceRoot":"","sources":["../../../../src/search/extraction/TextExtractor.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export * from "./SearchProvider.js";
|
|
6
|
+
export * from "./MongoTextSearchProvider.js";
|
|
7
|
+
export * from "./PostgresFullTextSearchProvider.js";
|
|
8
|
+
export * from "./OpenSearchProvider.js";
|
|
9
|
+
export * from "./extraction/TextExtractor.js";
|
|
10
|
+
export * from "./extraction/PlainTextExtractor.js";
|
|
11
|
+
export * from "./extraction/HtmlTextExtractor.js";
|
|
12
|
+
export * from "./extraction/PdfTextExtractor.js";
|
|
13
|
+
export * from "./extraction/DocxTextExtractor.js";
|
|
14
|
+
export * from "./extraction/ExtractorRegistry.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/search/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC"}
|
package/dist/lib/sql.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export * from "./models/sql.js";
|
|
6
|
+
export * from "./routes/sql.js";
|
|
7
|
+
export * from "./jobs/sql.js";
|
|
8
|
+
//# sourceMappingURL=sql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* Documents the HTTP contract an MTA (Postfix, Haraka, ...) integrates against to hand accepted internet mail
|
|
7
|
+
* to this library. This is not a pluggable interface implemented in code — it is the fixed shape that
|
|
8
|
+
* `BaseMailIngestRoute` (see `routes/mongo/MailIngestRouteMongo.ts` / `routes/sql/MailIngestRouteSQL.ts`)
|
|
9
|
+
* exposes, documented here as the integration target for whichever MTA a deployment chooses.
|
|
10
|
+
*
|
|
11
|
+
* Both endpoints are internal-only: bound to loopback/an internal network in the server's HTTP configuration,
|
|
12
|
+
* and additionally gated by a shared bearer secret (`mail:transport:ingest:secret`) checked against the
|
|
13
|
+
* `Authorization` header — never exposed to the public internet.
|
|
14
|
+
*
|
|
15
|
+
* ### `GET /internal/mta/resolve?rcpt=<address>`
|
|
16
|
+
* Called by the MTA's recipient-validation hook (e.g. Postfix `recipient_lookup` via a `tcp_table`/socketmap,
|
|
17
|
+
* or an LMTP handshake) before accepting a message for `rcpt`, so a message for a nonexistent mailbox is
|
|
18
|
+
* rejected at the SMTP conversation stage rather than accepted and later bounced (avoiding backscatter).
|
|
19
|
+
* Responds `200` if a `Mailbox` exists for `rcpt` (as a primary or alias address), `404` otherwise.
|
|
20
|
+
*
|
|
21
|
+
* ### `POST /internal/mta/deliver`
|
|
22
|
+
* Called by the MTA's content-filter/pipe once it has accepted a message. The request body is the raw,
|
|
23
|
+
* unparsed RFC 5322 message; envelope-from/envelope-to are carried as `X-Envelope-From`/`X-Envelope-To`
|
|
24
|
+
* headers. The handler does only the minimum synchronous work — persist the raw bytes to the `BlobStore` and
|
|
25
|
+
* create an `IngestQueueEntry` — then returns `202` immediately, deferring parsing/scanning/delivery to
|
|
26
|
+
* `ScanQueueJob`. This bounds SMTP-transaction latency and lets the MTA's own queue (not this library's) own
|
|
27
|
+
* retry/backpressure semantics.
|
|
28
|
+
*/
|
|
29
|
+
export const MTA_INGEST_CONTRACT_DOC = "See MTAIngestAdapter.ts for the GET /internal/mta/resolve and POST /internal/mta/deliver contract.";
|
|
30
|
+
//# sourceMappingURL=MTAIngestAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MTAIngestAdapter.js","sourceRoot":"","sources":["../../../src/transport/MTAIngestAdapter.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAChC,oGAAoG,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=MailTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MailTransport.js","sourceRoot":"","sources":["../../../src/transport/MailTransport.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
12
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
13
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
14
|
+
import * as nodemailer from "nodemailer";
|
|
15
|
+
import { ObjectDecorators } from "@rapidrest/core";
|
|
16
|
+
const { Config, Logger } = ObjectDecorators;
|
|
17
|
+
/**
|
|
18
|
+
* `MailTransport` adapter that hands a fully composed message to the local Postfix (or any other locally
|
|
19
|
+
* installed MTA) via the `sendmail(1)` command-line interface — the simplest integration that works with
|
|
20
|
+
* essentially any Unix MTA, and lets Postfix (with an OpenDKIM milter) apply DKIM signing on the way out
|
|
21
|
+
* exactly as it would for mail submitted by any other local process.
|
|
22
|
+
*
|
|
23
|
+
* @author Jean-Philippe Steinmetz
|
|
24
|
+
*/
|
|
25
|
+
export class PostfixSendmailTransport {
|
|
26
|
+
constructor() {
|
|
27
|
+
this.name = "postfix-sendmail";
|
|
28
|
+
this.sendmailPath = "/usr/sbin/sendmail";
|
|
29
|
+
}
|
|
30
|
+
async send(message) {
|
|
31
|
+
const transport = nodemailer.createTransport({
|
|
32
|
+
sendmail: true,
|
|
33
|
+
path: this.sendmailPath,
|
|
34
|
+
newline: "unix",
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
const info = await transport.sendMail({
|
|
38
|
+
envelope: { from: message.envelopeFrom, to: message.envelopeTo },
|
|
39
|
+
raw: message.raw,
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
accepted: (info.accepted ?? message.envelopeTo).map(String),
|
|
43
|
+
rejected: (info.rejected ?? []).map(String),
|
|
44
|
+
messageId: info.messageId,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
this.logger?.error(`Failed to relay outbound message via sendmail: ${err.message}`);
|
|
49
|
+
return { accepted: [], rejected: message.envelopeTo };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
__decorate([
|
|
54
|
+
Config("mail:transport:sendmail:path", "/usr/sbin/sendmail"),
|
|
55
|
+
__metadata("design:type", String)
|
|
56
|
+
], PostfixSendmailTransport.prototype, "sendmailPath", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
Logger,
|
|
59
|
+
__metadata("design:type", Object)
|
|
60
|
+
], PostfixSendmailTransport.prototype, "logger", void 0);
|
|
61
|
+
//# sourceMappingURL=PostfixSendmailTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostfixSendmailTransport.js","sourceRoot":"","sources":["../../../src/transport/PostfixSendmailTransport.ts"],"names":[],"mappings":";;;;;;;;;AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC;AAE5C;;;;;;;GAOG;AACH,MAAM,OAAO,wBAAwB;IAArC;QACoB,SAAI,GAAW,kBAAkB,CAAC;QAG1C,iBAAY,GAAW,oBAAoB,CAAC;IA2BxD,CAAC;IAtBU,KAAK,CAAC,IAAI,CAAC,OAAwB;QACtC,MAAM,SAAS,GAAG,UAAU,CAAC,eAAe,CAAC;YACzC,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI,CAAC,YAAY;YACvB,OAAO,EAAE,MAAM;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;gBAClC,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,EAAE,OAAO,CAAC,UAAU,EAAE;gBAChE,GAAG,EAAE,OAAO,CAAC,GAAG;aACnB,CAAC,CAAC;YACH,OAAO;gBACH,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC3D,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;aAC5B,CAAC;QACN,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,kDAAkD,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACpF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;QAC1D,CAAC;IACL,CAAC;CACJ;AA3BW;IADP,MAAM,CAAC,8BAA8B,EAAE,oBAAoB,CAAC;;8DACT;AAG5C;IADP,MAAM;;wDACa"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export * from "./MailTransport.js";
|
|
6
|
+
export * from "./PostfixSendmailTransport.js";
|
|
7
|
+
export * from "./MTAIngestAdapter.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { FolderType } from "../models/types.js";
|
|
2
|
+
const DEFAULT_FOLDER_NAMES = {
|
|
3
|
+
[FolderType.INBOX]: "Inbox",
|
|
4
|
+
[FolderType.SENT_ITEMS]: "Sent Items",
|
|
5
|
+
[FolderType.DRAFTS]: "Drafts",
|
|
6
|
+
[FolderType.DELETED_ITEMS]: "Deleted Items",
|
|
7
|
+
[FolderType.OUTBOX]: "Outbox",
|
|
8
|
+
[FolderType.JUNK]: "Junk Email",
|
|
9
|
+
[FolderType.CALENDAR]: "Calendar",
|
|
10
|
+
[FolderType.CONTACTS]: "Contacts",
|
|
11
|
+
[FolderType.TASKS]: "Tasks",
|
|
12
|
+
[FolderType.NOTES]: "Notes",
|
|
13
|
+
[FolderType.USER]: "New Folder",
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Finds the given mailbox's well-known folder of `type` (e.g. its Inbox, Junk, Sent Items), creating it — with
|
|
17
|
+
* the platform's conventional display name — if it does not already exist. Every well-known folder is
|
|
18
|
+
* provisioned lazily this way rather than all at once when a `Mailbox` is created, so a mailbox that never
|
|
19
|
+
* receives a piece of spam, for example, never has an empty Junk folder to show for it.
|
|
20
|
+
*
|
|
21
|
+
* @param folderRepo A `RepoUtils` bound to the caller's concrete `Folder` entity class (Mongo or SQL).
|
|
22
|
+
* @param folderClass The concrete `Folder` entity class `folderRepo` is bound to, used to construct a new row.
|
|
23
|
+
* @param mailboxUid The mailbox to find or create the folder within.
|
|
24
|
+
* @param type The well-known folder type to find or create. Must not be `FolderType.USER`.
|
|
25
|
+
*/
|
|
26
|
+
export async function findOrCreateWellKnownFolder(folderRepo, folderClass, mailboxUid, type, user) {
|
|
27
|
+
const existing = await folderRepo.find({ mailboxUid, type }, { ignoreACL: true, limit: 1 });
|
|
28
|
+
if (existing.length > 0) {
|
|
29
|
+
return existing[0];
|
|
30
|
+
}
|
|
31
|
+
const instance = new folderClass({
|
|
32
|
+
mailboxUid,
|
|
33
|
+
name: DEFAULT_FOLDER_NAMES[type],
|
|
34
|
+
type,
|
|
35
|
+
unreadCount: 0,
|
|
36
|
+
totalCount: 0,
|
|
37
|
+
syncKeyVersion: 0,
|
|
38
|
+
});
|
|
39
|
+
// `parentUid` must be set explicitly to the owning mailbox's ACL uid — without it, `RepoUtils.create()`'s
|
|
40
|
+
// default (parenting to the `Folder` *class* ACL, which is deny-all) would leave this folder unreachable
|
|
41
|
+
// by anyone, including the mailbox's own owner, once a real per-record ACL exists for `Folder` (see the
|
|
42
|
+
// architecture note on `Message.mailboxUid`). Matches `BaseFolderRoute.create()`'s same seeding for
|
|
43
|
+
// client-initiated folder creation.
|
|
44
|
+
return await folderRepo.create(instance, {
|
|
45
|
+
user,
|
|
46
|
+
ignoreACL: true,
|
|
47
|
+
acl: { uid: instance.uid, parentUid: mailboxUid, records: [] },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=FolderUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FolderUtils.js","sourceRoot":"","sources":["../../../src/util/FolderUtils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAU,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,oBAAoB,GAA+B;IACrD,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO;IAC3B,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,YAAY;IACrC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC7B,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,eAAe;IAC3C,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ;IAC7B,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,YAAY;IAC/B,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,UAAU;IACjC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,UAAU;IACjC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO;IAC3B,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO;IAC3B,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,YAAY;CAClC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC7C,UAAwB,EACxB,WAAgB,EAChB,UAAkB,EAClB,IAA0C,EAC1C,IAAc;IAEd,MAAM,QAAQ,GAAQ,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACjG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,QAAQ,GAAM,IAAI,WAAW,CAAC;QAChC,UAAU;QACV,IAAI,EAAE,oBAAoB,CAAC,IAAI,CAAC;QAChC,IAAI;QACJ,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,CAAC;QACb,cAAc,EAAE,CAAC;KACpB,CAAC,CAAC;IAEH,0GAA0G;IAC1G,yGAAyG;IACzG,wGAAwG;IACxG,oGAAoG;IACpG,oCAAoC;IACpC,OAAO,MAAM,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,IAAI;QACJ,SAAS,EAAE,IAAI;QACf,GAAG,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,EAAE;KACjE,CAAC,CAAC;AACP,CAAC"}
|