@social-mail/social-mail-web-server 1.5.415 → 1.5.416
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/dist/common/Mailto.d.ts +17 -0
- package/dist/common/Mailto.d.ts.map +1 -0
- package/dist/common/Mailto.js +27 -0
- package/dist/common/Mailto.js.map +1 -0
- package/dist/common/cacheFor.d.ts +10 -1
- package/dist/common/cacheFor.d.ts.map +1 -1
- package/dist/common/cacheFor.js +18 -2
- package/dist/common/cacheFor.js.map +1 -1
- package/dist/server/model/SocialMailContext.d.ts +2 -0
- package/dist/server/model/SocialMailContext.d.ts.map +1 -1
- package/dist/server/model/SocialMailContext.js +2 -0
- package/dist/server/model/SocialMailContext.js.map +1 -1
- package/dist/server/model/SocialMailContextEvents.d.ts.map +1 -1
- package/dist/server/model/SocialMailContextEvents.js +3 -0
- package/dist/server/model/SocialMailContextEvents.js.map +1 -1
- package/dist/server/model/entities/Email.d.ts +2 -0
- package/dist/server/model/entities/Email.d.ts.map +1 -1
- package/dist/server/model/entities/Email.js.map +1 -1
- package/dist/server/model/entities/EmailAddress.d.ts +2 -0
- package/dist/server/model/entities/EmailAddress.d.ts.map +1 -1
- package/dist/server/model/entities/EmailAddress.js.map +1 -1
- package/dist/server/model/entities/EmailRecipient.d.ts +1 -1
- package/dist/server/model/entities/EmailRecipient.d.ts.map +1 -1
- package/dist/server/model/entities/EmailRecipient.js +2 -2
- package/dist/server/model/entities/EmailRecipient.js.map +1 -1
- package/dist/server/model/entities/Mailbox.d.ts +1 -0
- package/dist/server/model/entities/Mailbox.d.ts.map +1 -1
- package/dist/server/model/entities/Mailbox.js +4 -0
- package/dist/server/model/entities/Mailbox.js.map +1 -1
- package/dist/server/model/entities/ThreadParticipant.d.ts +22 -0
- package/dist/server/model/entities/ThreadParticipant.d.ts.map +1 -0
- package/dist/server/model/entities/ThreadParticipant.js +53 -0
- package/dist/server/model/entities/ThreadParticipant.js.map +1 -0
- package/dist/server/model/events/EmailEvents.d.ts.map +1 -1
- package/dist/server/model/events/EmailEvents.js +17 -7
- package/dist/server/model/events/EmailEvents.js.map +1 -1
- package/dist/server/model/events/MailboxEvents.d.ts.map +1 -1
- package/dist/server/model/events/MailboxEvents.js +2 -0
- package/dist/server/model/events/MailboxEvents.js.map +1 -1
- package/dist/server/model/events/ThreadParticipantEvents.d.ts +8 -0
- package/dist/server/model/events/ThreadParticipantEvents.d.ts.map +1 -0
- package/dist/server/model/events/ThreadParticipantEvents.js +19 -0
- package/dist/server/model/events/ThreadParticipantEvents.js.map +1 -0
- package/dist/server/seed/ui/seed-ui.js +1 -1
- package/dist/server/services/EmailAddressService.d.ts +4 -2
- package/dist/server/services/EmailAddressService.d.ts.map +1 -1
- package/dist/server/services/EmailAddressService.js +4 -4
- package/dist/server/services/EmailAddressService.js.map +1 -1
- package/dist/server/services/StoreFileService.d.ts +3 -1
- package/dist/server/services/StoreFileService.d.ts.map +1 -1
- package/dist/server/services/StoreFileService.js.map +1 -1
- package/dist/server/services/TemplateExpander.js +1 -1
- package/dist/server/services/TemplateExpander.js.map +1 -1
- package/dist/server/services/accounts/sales/SalesInvoiceService.d.ts +3 -1
- package/dist/server/services/accounts/sales/SalesInvoiceService.d.ts.map +1 -1
- package/dist/server/services/accounts/sales/SalesInvoiceService.js.map +1 -1
- package/dist/server/services/channels/ChannelModerationService.d.ts +8 -0
- package/dist/server/services/channels/ChannelModerationService.d.ts.map +1 -0
- package/dist/server/{smtp/services/EmailThreadService.js → services/channels/ChannelModerationService.js} +19 -7
- package/dist/server/services/channels/ChannelModerationService.js.map +1 -0
- package/dist/server/services/dom/HtmlSanitizer.d.ts.map +1 -1
- package/dist/server/services/dom/HtmlSanitizer.js +7 -1
- package/dist/server/services/dom/HtmlSanitizer.js.map +1 -1
- package/dist/server/services/domain-keys/DomainKeyService.d.ts +3 -1
- package/dist/server/services/domain-keys/DomainKeyService.d.ts.map +1 -1
- package/dist/server/services/domain-keys/DomainKeyService.js.map +1 -1
- package/dist/server/services/files/FileAccessService.d.ts +3 -1
- package/dist/server/services/files/FileAccessService.d.ts.map +1 -1
- package/dist/server/services/files/FileAccessService.js +0 -2
- package/dist/server/services/files/FileAccessService.js.map +1 -1
- package/dist/server/services/files/SnapshotService.d.ts +3 -1
- package/dist/server/services/files/SnapshotService.d.ts.map +1 -1
- package/dist/server/services/files/SnapshotService.js.map +1 -1
- package/dist/server/services/files/WebSiteService.d.ts +3 -1
- package/dist/server/services/files/WebSiteService.d.ts.map +1 -1
- package/dist/server/services/files/WebSiteService.js.map +1 -1
- package/dist/server/services/store/StoreConfigService.d.ts +3 -1
- package/dist/server/services/store/StoreConfigService.d.ts.map +1 -1
- package/dist/server/services/store/StoreConfigService.js.map +1 -1
- package/dist/server/services/threads/EmailThreadService.d.ts +7 -0
- package/dist/server/services/threads/EmailThreadService.d.ts.map +1 -0
- package/dist/server/services/threads/EmailThreadService.js +45 -0
- package/dist/server/services/threads/EmailThreadService.js.map +1 -0
- package/dist/server/smtp/dns/DnsService.d.ts +3 -1
- package/dist/server/smtp/dns/DnsService.d.ts.map +1 -1
- package/dist/server/smtp/dns/DnsService.js.map +1 -1
- package/dist/server/smtp/services/AccessTokenService.d.ts +4 -2
- package/dist/server/smtp/services/AccessTokenService.d.ts.map +1 -1
- package/dist/server/smtp/services/AccessTokenService.js +23 -28
- package/dist/server/smtp/services/AccessTokenService.js.map +1 -1
- package/dist/server/smtp/services/CachedEmailService.d.ts.map +1 -1
- package/dist/server/smtp/services/CachedEmailService.js +6 -1
- package/dist/server/smtp/services/CachedEmailService.js.map +1 -1
- package/dist/server/smtp/services/EmailPostReceiveService.d.ts +8 -0
- package/dist/server/smtp/services/EmailPostReceiveService.d.ts.map +1 -1
- package/dist/server/smtp/services/EmailPostReceiveService.js +48 -6
- package/dist/server/smtp/services/EmailPostReceiveService.js.map +1 -1
- package/dist/server/smtp/services/EngagementService.d.ts.map +1 -1
- package/dist/server/smtp/services/EngagementService.js +5 -0
- package/dist/server/smtp/services/EngagementService.js.map +1 -1
- package/dist/server/smtp/services/WebSiteChannelService.d.ts +3 -3
- package/dist/server/smtp/services/WebSiteChannelService.d.ts.map +1 -1
- package/dist/server/smtp/services/WebSiteChannelService.js +27 -26
- package/dist/server/smtp/services/WebSiteChannelService.js.map +1 -1
- package/dist/server/storage/TempFileService.d.ts.map +1 -1
- package/dist/server/storage/TempFileService.js +7 -2
- package/dist/server/storage/TempFileService.js.map +1 -1
- package/dist/server/templates/channel/SubscriberRequested.d.ts.map +1 -1
- package/dist/server/templates/channel/SubscriberRequested.js +5 -1
- package/dist/server/templates/channel/SubscriberRequested.js.map +1 -1
- package/dist/server/workflows/pending/PendingPostReceiveWorkflow.d.ts.map +1 -1
- package/dist/server/workflows/pending/PendingPostReceiveWorkflow.js +3 -14
- package/dist/server/workflows/pending/PendingPostReceiveWorkflow.js.map +1 -1
- package/dist/server/workflows/smtp/DispatchEmailToMX.d.ts +3 -1
- package/dist/server/workflows/smtp/DispatchEmailToMX.d.ts.map +1 -1
- package/dist/server/workflows/smtp/DispatchEmailToMX.js +30 -4
- package/dist/server/workflows/smtp/DispatchEmailToMX.js.map +1 -1
- package/dist/server/workflows/smtp/MailDispatcherService.d.ts.map +1 -1
- package/dist/server/workflows/smtp/MailDispatcherService.js +5 -1
- package/dist/server/workflows/smtp/MailDispatcherService.js.map +1 -1
- package/dist/server/workflows/smtp/PrepareEmailToSend.d.ts +3 -1
- package/dist/server/workflows/smtp/PrepareEmailToSend.d.ts.map +1 -1
- package/dist/server/workflows/smtp/PrepareEmailToSend.js +15 -4
- package/dist/server/workflows/smtp/PrepareEmailToSend.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/wwwroot/routes/@[channel]/[slug]/index.js +4 -4
- package/dist/wwwroot/routes/@[channel]/[slug]/index.js.map +1 -1
- package/dist/wwwroot/routes/api/site/snapshot/index.d.ts.map +1 -1
- package/dist/wwwroot/routes/api/site/snapshot/index.js.map +1 -1
- package/package.json +3 -3
- package/src/common/Mailto.ts +39 -0
- package/src/common/cacheFor.ts +26 -4
- package/src/server/model/SocialMailContext.ts +3 -0
- package/src/server/model/SocialMailContextEvents.ts +4 -0
- package/src/server/model/entities/Email.ts +2 -0
- package/src/server/model/entities/EmailAddress.ts +2 -0
- package/src/server/model/entities/EmailRecipient.ts +2 -2
- package/src/server/model/entities/Mailbox.ts +3 -0
- package/src/server/model/entities/ThreadParticipant.ts +45 -0
- package/src/server/model/events/EmailEvents.ts +19 -7
- package/src/server/model/events/MailboxEvents.ts +2 -0
- package/src/server/model/events/ThreadParticipantEvents.ts +27 -0
- package/src/server/seed/ui/seed-ui.ts +1 -1
- package/src/server/services/EmailAddressService.ts +8 -5
- package/src/server/services/StoreFileService.ts +6 -2
- package/src/server/services/TemplateExpander.ts +1 -1
- package/src/server/services/accounts/sales/SalesInvoiceService.ts +5 -2
- package/src/server/services/channels/ChannelModerationService.ts +27 -0
- package/src/server/services/dom/HtmlSanitizer.ts +7 -1
- package/src/server/services/domain-keys/DomainKeyService.ts +4 -2
- package/src/server/services/files/FileAccessService.ts +4 -5
- package/src/server/services/files/SnapshotService.ts +5 -2
- package/src/server/services/files/WebSiteService.ts +5 -2
- package/src/server/services/store/StoreConfigService.ts +5 -2
- package/src/server/services/tags/TagService.ts +1 -1
- package/src/server/services/threads/EmailThreadService.ts +39 -0
- package/src/server/smtp/dns/DnsService.ts +4 -3
- package/src/server/smtp/services/AccessTokenService.ts +20 -22
- package/src/server/smtp/services/CachedEmailService.ts +5 -1
- package/src/server/smtp/services/EmailPostReceiveService.ts +54 -9
- package/src/server/smtp/services/EngagementService.ts +6 -0
- package/src/server/smtp/services/WebSiteChannelService.ts +17 -17
- package/src/server/storage/TempFileService.ts +7 -2
- package/src/server/templates/channel/SubscriberRequested.tsx +5 -1
- package/src/server/workflows/pending/PendingPostReceiveWorkflow.ts +3 -16
- package/src/server/workflows/smtp/DispatchEmailToMX.ts +33 -3
- package/src/server/workflows/smtp/MailDispatcherService.ts +6 -1
- package/src/server/workflows/smtp/PrepareEmailToSend.ts +16 -3
- package/src/wwwroot/routes/@[channel]/[slug]/index.tsx +4 -4
- package/src/wwwroot/routes/api/site/snapshot/index.ts +1 -0
- package/dist/server/smtp/services/EmailThreadService.d.ts +0 -7
- package/dist/server/smtp/services/EmailThreadService.d.ts.map +0 -1
- package/dist/server/smtp/services/EmailThreadService.js.map +0 -1
- package/src/server/smtp/services/EmailThreadService.ts +0 -15
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Inject, { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
-
import { cacheFor } from "../../../common/cacheFor.js";
|
|
2
|
+
import {ICacheContainer, ObjectCache, cacheFor } from "../../../common/cacheFor.js";
|
|
3
3
|
import { globalServices } from "../../../globalServices.js";
|
|
4
4
|
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
5
5
|
import EncryptionService from "../encryption/EncryptionService.js";
|
|
@@ -7,8 +7,11 @@ import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
|
7
7
|
import { chainToCamel } from "../../../common/chainToCamel.js";
|
|
8
8
|
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
@RegisterSingleton
|
|
11
|
-
export default class StoreConfigService {
|
|
12
|
+
export default class StoreConfigService implements ICacheContainer<StoreConfigService> {
|
|
13
|
+
|
|
14
|
+
cache: ObjectCache<StoreConfigService>;
|
|
12
15
|
|
|
13
16
|
@Inject
|
|
14
17
|
encryptionService: EncryptionService;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
3
|
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
4
4
|
import { ConsoleLogger } from "@entity-access/entity-access/dist/common/Logger.js";
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
import Tag from "../../model/entities/Tag.js";
|
|
7
7
|
|
|
8
8
|
@RegisterSingleton
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import Inject, { RegisterScoped } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
3
|
+
|
|
4
|
+
@RegisterScoped
|
|
5
|
+
export default class EmailThreadService {
|
|
6
|
+
|
|
7
|
+
@Inject
|
|
8
|
+
db: SocialMailContext;
|
|
9
|
+
|
|
10
|
+
async unsubscribe(senderID, emailID) {
|
|
11
|
+
|
|
12
|
+
const { db } = this;
|
|
13
|
+
|
|
14
|
+
const threadID = (await db.emails.where({ emailID }, (p) => (x) => x.emailID === p.emailID)
|
|
15
|
+
.map(void 0, (p) => (x) => ({ threadID: x.threadID})).first())?.threadID ?? emailID;
|
|
16
|
+
await db.threadParticipants.statements.update({
|
|
17
|
+
unsubscribed: true
|
|
18
|
+
}, {
|
|
19
|
+
emailAddressID: senderID,
|
|
20
|
+
emailID: threadID
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async saveParticipant(senderID, emailID) {
|
|
26
|
+
const { db } = this;
|
|
27
|
+
|
|
28
|
+
const threadID = (await db.emails.where({ emailID }, (p) => (x) => x.emailID === p.emailID)
|
|
29
|
+
.map(void 0, (p) => (x) => ({ threadID: x.threadID})).first())?.threadID ?? emailID;
|
|
30
|
+
await db.threadParticipants.statements.selectOrInsert({
|
|
31
|
+
emailAddressID: senderID,
|
|
32
|
+
emailID: threadID
|
|
33
|
+
}, {
|
|
34
|
+
emailAddressID: senderID,
|
|
35
|
+
emailID: threadID
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
2
|
import dns2 from "dns2";
|
|
3
3
|
import { SPFRecords } from "./SPFRecords.js";
|
|
4
|
-
|
|
5
|
-
import { cacheFor } from "../../../common/cacheFor.js";
|
|
4
|
+
|
|
5
|
+
import {ICacheContainer, ObjectCache, cacheFor } from "../../../common/cacheFor.js";
|
|
6
6
|
|
|
7
7
|
export interface IDKIMRecord {
|
|
8
8
|
keyType: string;
|
|
@@ -11,8 +11,9 @@ export interface IDKIMRecord {
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@RegisterSingleton
|
|
14
|
-
export default class DnsService {
|
|
14
|
+
export default class DnsService implements ICacheContainer<DnsService> {
|
|
15
15
|
|
|
16
|
+
cache: ObjectCache<DnsService>;
|
|
16
17
|
|
|
17
18
|
@cacheFor()
|
|
18
19
|
public async getDomainKey(selector: string, domain: string, nameServers?: string[]): Promise<IDKIMRecord> {
|
|
@@ -1,33 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
3
|
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
4
4
|
import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
5
5
|
import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
|
|
6
|
-
|
|
7
|
-
const timedCache = new TimedCache();
|
|
6
|
+
import { ICacheContainer, ObjectCache } from "../../../common/cacheFor.js";
|
|
8
7
|
|
|
9
8
|
@RegisterSingleton
|
|
10
|
-
export default class AccessTokenService {
|
|
9
|
+
export default class AccessTokenService implements ICacheContainer<AccessTokenService> {
|
|
10
|
+
|
|
11
|
+
cache: ObjectCache<AccessTokenService>;
|
|
11
12
|
|
|
12
13
|
async login(tokenID, secret) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
await db.changeSet.getEntry(token).loadNavigationAsync((x) => x.user);
|
|
29
|
-
return token.user;
|
|
30
|
-
});
|
|
14
|
+
using scope = ServiceProvider.createScope(this);
|
|
15
|
+
const db = scope.resolve(SocialMailContext);
|
|
16
|
+
const tokens = await db.accessTokens
|
|
17
|
+
.where({ tokenID, secret } , (p) => (x) =>
|
|
18
|
+
x.tokenID === p.tokenID as any
|
|
19
|
+
&& x.secret === p.secret)
|
|
20
|
+
.updateSelect(void 0, (p) => (x) => ({
|
|
21
|
+
lastUsed: Sql.date.now()
|
|
22
|
+
}));
|
|
23
|
+
const token = tokens[0];
|
|
24
|
+
if (!token) {
|
|
25
|
+
throw new EntityAccessError(`Invalid access token`);
|
|
26
|
+
}
|
|
27
|
+
await db.changeSet.getEntry(token).loadNavigationAsync((x) => x.user);
|
|
28
|
+
return token.user;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
}
|
|
@@ -38,7 +38,11 @@ export default class CachedEmailService {
|
|
|
38
38
|
|
|
39
39
|
let logFile: EmailLog;
|
|
40
40
|
|
|
41
|
-
if (
|
|
41
|
+
if (signedFileLogID) {
|
|
42
|
+
logFile = await this.db.emailLogs
|
|
43
|
+
.where({ signedFileLogID }, (p) => (x) => x.logID === p.signedFileLogID)
|
|
44
|
+
.first();
|
|
45
|
+
} else {
|
|
42
46
|
|
|
43
47
|
if (emailAddressID) {
|
|
44
48
|
|
|
@@ -13,6 +13,8 @@ import SendWebPushNotification from "../../workflows/web-push/SendWebPushNotific
|
|
|
13
13
|
import TempFileService from "../../storage/TempFileService.js";
|
|
14
14
|
import CachedEmailService from "./CachedEmailService.js";
|
|
15
15
|
import QueueInvokeWebHookWorkflow from "../../workflows/web-hooks/QueueInvokeWebHookWorkflow.js";
|
|
16
|
+
import EmailThreadService from "../../services/threads/EmailThreadService.js";
|
|
17
|
+
import ChannelModerationService from "../../services/channels/ChannelModerationService.js";
|
|
16
18
|
|
|
17
19
|
@RegisterScoped
|
|
18
20
|
export default class EmailPostReceiveService {
|
|
@@ -35,6 +37,29 @@ export default class EmailPostReceiveService {
|
|
|
35
37
|
@Inject
|
|
36
38
|
context?: WorkflowContext;
|
|
37
39
|
|
|
40
|
+
@Inject
|
|
41
|
+
ets?: EmailThreadService;
|
|
42
|
+
|
|
43
|
+
@Inject
|
|
44
|
+
cms?: ChannelModerationService;
|
|
45
|
+
|
|
46
|
+
async executeAll({ senderID, emailID }) {
|
|
47
|
+
const { db } = this;
|
|
48
|
+
const mcs = await db.mailboxContactEmails.where({ emailID, senderID}, (p) => (x) => x.emailID === p.emailID
|
|
49
|
+
&& x.mailboxID !== p.senderID )
|
|
50
|
+
.select(void 0, (p) => ({ mailboxID }) => ({ mailboxID }))
|
|
51
|
+
.toArray();
|
|
52
|
+
|
|
53
|
+
for (const { mailboxID } of mcs) {
|
|
54
|
+
await this.execute({
|
|
55
|
+
senderID,
|
|
56
|
+
emailID,
|
|
57
|
+
recipientID: mailboxID
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
await db.emails.statements.update({ statePostReceiveInvoked: true}, { emailID });
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
async execute(input: { senderID, emailID, recipientID }) {
|
|
39
64
|
await this.dispatchChannel(input);
|
|
40
65
|
await this.queueWebHooks(input);
|
|
@@ -93,7 +118,8 @@ export default class EmailPostReceiveService {
|
|
|
93
118
|
return;
|
|
94
119
|
}
|
|
95
120
|
|
|
96
|
-
|
|
121
|
+
let channel = await eas.getHostedMailbox(recipientID);
|
|
122
|
+
channel = channel?.isChannel ? channel : void 0;
|
|
97
123
|
|
|
98
124
|
if (ne.engagement) {
|
|
99
125
|
|
|
@@ -104,17 +130,20 @@ export default class EmailPostReceiveService {
|
|
|
104
130
|
|
|
105
131
|
switch(ne.engagement) {
|
|
106
132
|
case "✅":
|
|
107
|
-
if (
|
|
133
|
+
if (channel) {
|
|
108
134
|
return await channelService.approveSubscriber(emailID);
|
|
109
135
|
}
|
|
110
136
|
return;
|
|
111
137
|
case "🔔":
|
|
112
|
-
case "🔕":
|
|
113
|
-
case "❌":
|
|
114
138
|
case "📈":
|
|
115
139
|
return;
|
|
140
|
+
case "🔕":
|
|
141
|
+
case "❌":
|
|
142
|
+
// unsubscribe particular thread...
|
|
143
|
+
await this.ets.unsubscribe(senderID, emailID);
|
|
144
|
+
return;
|
|
116
145
|
case "➕":
|
|
117
|
-
if (
|
|
146
|
+
if (channel) {
|
|
118
147
|
await BroadcastEmail.broadcast(this.context, {
|
|
119
148
|
mailboxID: recipientID,
|
|
120
149
|
emailID,
|
|
@@ -125,13 +154,21 @@ export default class EmailPostReceiveService {
|
|
|
125
154
|
return;
|
|
126
155
|
case "💬":
|
|
127
156
|
// following will make comment appear publicly
|
|
128
|
-
|
|
129
|
-
|
|
157
|
+
if (channel && !channel.isPrivateChannel && channel.requiresCommentModeration) {
|
|
158
|
+
await db.emails.where(input, (p) => (x) => x.emailID === p.emailID
|
|
130
159
|
&& x.parent.status === "published"
|
|
131
160
|
)
|
|
132
|
-
.update(void 0, (p) => (x) => ({ status: "
|
|
161
|
+
.update(void 0, (p) => (x) => ({ status: "pending-approval" }));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
await db.emails.where(input, (p) => (x) => x.emailID === p.emailID
|
|
165
|
+
&& x.parent.status === "published"
|
|
166
|
+
)
|
|
167
|
+
.update(void 0, (p) => (x) => ({ status: "published" }));
|
|
168
|
+
await this.ets.saveParticipant(senderID, emailID);
|
|
133
169
|
return;
|
|
134
170
|
default:
|
|
171
|
+
await this.ets.saveParticipant(senderID, emailID);
|
|
135
172
|
return;
|
|
136
173
|
}
|
|
137
174
|
}
|
|
@@ -141,7 +178,7 @@ export default class EmailPostReceiveService {
|
|
|
141
178
|
&& x.emailAddressID === p.senderID)
|
|
142
179
|
.first();
|
|
143
180
|
|
|
144
|
-
if(!
|
|
181
|
+
if(!channel) {
|
|
145
182
|
|
|
146
183
|
// send push notification here...
|
|
147
184
|
if (mc?.blocked) {
|
|
@@ -160,6 +197,12 @@ export default class EmailPostReceiveService {
|
|
|
160
197
|
return;
|
|
161
198
|
}
|
|
162
199
|
|
|
200
|
+
if (!channel.isPrivateChannel && channel.requiresPostModeration) {
|
|
201
|
+
if(await this.cms.addToQueue(channel, emailID, mc)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
163
206
|
// can send...
|
|
164
207
|
if (!mc || !(mc.canContribute || mc.isOwner)) {
|
|
165
208
|
return;
|
|
@@ -205,6 +248,8 @@ export default class EmailPostReceiveService {
|
|
|
205
248
|
}
|
|
206
249
|
}
|
|
207
250
|
|
|
251
|
+
await this.ets.saveParticipant(senderID, emailID);
|
|
252
|
+
|
|
208
253
|
await BroadcastEmail.broadcast(this.context, {
|
|
209
254
|
mailboxID: recipientID,
|
|
210
255
|
emailID,
|
|
@@ -137,6 +137,12 @@ export default class EngagementService {
|
|
|
137
137
|
engagement: p.engagement
|
|
138
138
|
}));
|
|
139
139
|
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const en = await this.extractEngagementFromBody(email);
|
|
144
|
+
if (en) {
|
|
145
|
+
await this.db.emails.statements.update({ engagement: en}, { emailID: email.emailID});
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import Inject, { RegisterScoped, RegisterSingleton, RegisterTransient, ServiceCollection, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
3
|
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
4
4
|
import GlobalEvents from "../../../common/GlobalEvents.js";
|
|
5
|
+
import { cacheFor, ICacheContainer, ObjectCache } from "../../../common/cacheFor.js";
|
|
6
|
+
|
|
7
|
+
export default class WebSiteChannelService implements ICacheContainer<WebSiteChannelService> {
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
cache: ObjectCache<WebSiteChannelService>;
|
|
7
10
|
|
|
8
11
|
@Inject
|
|
9
12
|
globalEvents: GlobalEvents;
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
using scope = ServiceProvider.createScope(this);
|
|
16
|
-
const db = scope.resolve(SocialMailContext);
|
|
14
|
+
@cacheFor()
|
|
15
|
+
async getMailboxes(host: string) {
|
|
16
|
+
using scope = ServiceProvider.createScope(this);
|
|
17
|
+
const db = scope.resolve(SocialMailContext);
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
host = host?.toLocaleLowerCase() ?? "localhost";
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const mailboxes = await db.mailboxes.where({ host}, (p) => (x) =>
|
|
22
|
+
x.websiteChannels
|
|
23
|
+
.some((w) => w.website.hosts
|
|
24
|
+
.some((h)=> h.host === p.host)))
|
|
25
|
+
.toArray();
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
});
|
|
27
|
+
return mailboxes.map((x) => x.mailboxID);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
clear() {
|
|
@@ -32,7 +32,7 @@ export default class WebSiteChannelService {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
protected postInit() {
|
|
35
|
-
this.globalEvents.on("web-site-channel-host-clear" as any, () => this.cache
|
|
35
|
+
this.globalEvents.on("web-site-channel-host-clear" as any, () => this.cache?.clear("getMailboxes") );
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
}
|
|
@@ -19,6 +19,7 @@ import GZip from "./compression/gz.js";
|
|
|
19
19
|
import DiskCacheService from "../services/cache/DiskCacheService.js";
|
|
20
20
|
import ensureDir from "../../common/FileApi.js";
|
|
21
21
|
import { globalEnv } from "../../common/globalEnv.js";
|
|
22
|
+
import { platform } from "os";
|
|
22
23
|
|
|
23
24
|
const tmpdir = globalEnv.tmpDir;
|
|
24
25
|
const tmpPath = path.join(tmpdir, "t");
|
|
@@ -184,8 +185,12 @@ export default class TempFileService {
|
|
|
184
185
|
// and remove folder's write permission so file cannot be deleted
|
|
185
186
|
|
|
186
187
|
const tf = await this.createTempFile(fileInfo.ext, fileName, contentType);
|
|
187
|
-
if (
|
|
188
|
-
|
|
188
|
+
if (platform() !== "win32") {
|
|
189
|
+
// this fails in docker alpine
|
|
190
|
+
// don't know why...
|
|
191
|
+
if (existsSync(tf.path)) {
|
|
192
|
+
await fsp.unlink(tf.path);
|
|
193
|
+
}
|
|
189
194
|
}
|
|
190
195
|
// await fsp.symlink(typeof src === "string" ? src : src.path, tf.path);
|
|
191
196
|
// This operation would be fast
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import XNode from "@entity-access/server-pages/dist/html/XNode.js";
|
|
2
|
+
import { Mailto } from "../../../common/Mailto.js";
|
|
2
3
|
|
|
3
4
|
export default function SubscriberRequested({
|
|
4
5
|
channelEmail,
|
|
@@ -6,6 +7,9 @@ export default function SubscriberRequested({
|
|
|
6
7
|
emailAddress,
|
|
7
8
|
html
|
|
8
9
|
}) {
|
|
10
|
+
const link = Mailto.templateLink({
|
|
11
|
+
emoji: "✅",
|
|
12
|
+
});
|
|
9
13
|
return <div>
|
|
10
14
|
Subscriber: {name} < {emailAddress} > wants to join your network.
|
|
11
15
|
<br/>
|
|
@@ -18,7 +22,7 @@ export default function SubscriberRequested({
|
|
|
18
22
|
<br/>
|
|
19
23
|
<a
|
|
20
24
|
style="border: none; text-decoration: none;"
|
|
21
|
-
|
|
25
|
+
href={link}
|
|
22
26
|
title="Approve">
|
|
23
27
|
<button style="margin: 1px;padding:2px;padding-left: 5px;padding-right: 5px; border: solid 1px lightgray; border-radius: 9999px; display: inline-flex; align-items: center;">
|
|
24
28
|
✅ Approve
|
|
@@ -46,29 +46,16 @@ export default class PendingPostReceiveWorkflow extends Workflow {
|
|
|
46
46
|
return 0;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
for (const
|
|
49
|
+
for (const item of items) {
|
|
50
50
|
try {
|
|
51
|
-
|
|
52
51
|
// channels can never send an email
|
|
53
|
-
|
|
54
|
-
const mcs = await db.mailboxContactEmails.where({ emailID, senderID}, (p) => (x) => x.emailID === p.emailID
|
|
55
|
-
&& x.mailboxID !== p.senderID )
|
|
56
|
-
.select(void 0, (p) => ({ mailboxID }) => ({ mailboxID }))
|
|
57
|
-
.toArray();
|
|
58
|
-
for(const { mailboxID } of mcs) {
|
|
59
|
-
await prs.execute({
|
|
60
|
-
senderID,
|
|
61
|
-
emailID,
|
|
62
|
-
recipientID: mailboxID
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
await db.emails.statements.update({ statePostReceiveInvoked: true}, { emailID });
|
|
52
|
+
await prs.executeAll(item);
|
|
66
53
|
} catch (error) {
|
|
67
54
|
console.warn(error);
|
|
68
55
|
// we will ignore and continue?
|
|
69
56
|
}
|
|
70
57
|
db.changeSet.clear();
|
|
71
|
-
start = emailID;
|
|
58
|
+
start = item.emailID;
|
|
72
59
|
}
|
|
73
60
|
|
|
74
61
|
return start;
|
|
@@ -17,6 +17,8 @@ import ESmtpClient from "../../../protocols/smtp/ESmtpClient.js";
|
|
|
17
17
|
import DnsService from "../../smtp/dns/DnsService.js";
|
|
18
18
|
import EncryptionService from "../../services/encryption/EncryptionService.js";
|
|
19
19
|
import EmailReferenceService from "../../smtp/services/EmailReferenceService.js";
|
|
20
|
+
import EmailPostReceiveService from "../../smtp/services/EmailPostReceiveService.js";
|
|
21
|
+
import EngagementService from "../../smtp/services/EngagementService.js";
|
|
20
22
|
|
|
21
23
|
export const smtpPool = new NamedObjectPool<SMTPClient>((host) => ({
|
|
22
24
|
asyncFactory: () => new SMTPClient({ host }).connect(),
|
|
@@ -167,7 +169,9 @@ export default class DispatchEmailToMX extends Workflow<IMessageEnvelope> {
|
|
|
167
169
|
@Inject els?: EmailLogService,
|
|
168
170
|
@Inject eas?: EmailAddressService,
|
|
169
171
|
@Inject db?: SocialMailContext,
|
|
170
|
-
@Inject ers?: EmailReferenceService
|
|
172
|
+
@Inject ers?: EmailReferenceService,
|
|
173
|
+
@Inject eps?: EmailPostReceiveService,
|
|
174
|
+
@Inject ees?: EngagementService
|
|
171
175
|
) {
|
|
172
176
|
|
|
173
177
|
// if it is local...
|
|
@@ -177,9 +181,34 @@ export default class DispatchEmailToMX extends Workflow<IMessageEnvelope> {
|
|
|
177
181
|
const mailboxID = await eas.getHostedMailboxID(this.input.to[0]);
|
|
178
182
|
|
|
179
183
|
if (!external && mailboxID) {
|
|
180
|
-
// const dateReceived = DateTime.now;
|
|
181
184
|
|
|
182
|
-
|
|
185
|
+
const dateReceived = DateTime.now;
|
|
186
|
+
try {
|
|
187
|
+
|
|
188
|
+
// internal broad casting is not working
|
|
189
|
+
// we either need to create an email or add the recipient
|
|
190
|
+
|
|
191
|
+
await db.mailboxEmails.statements.selectOrInsert({
|
|
192
|
+
mailboxID,
|
|
193
|
+
emailID
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await db.mailboxContactEmails.statements.selectOrInsert({
|
|
197
|
+
mailboxID,
|
|
198
|
+
emailID,
|
|
199
|
+
emailAddressID,
|
|
200
|
+
signedFileLogID,
|
|
201
|
+
dateReceived
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
// await ers.updateReferences({ emailID, dateUpdated: dateReceived, silent: false, timeRead: null });
|
|
206
|
+
if (senderID !== emailAddressID) {
|
|
207
|
+
await eps.execute({ senderID, emailID, recipientID: emailAddressID });
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
|
|
211
|
+
}
|
|
183
212
|
|
|
184
213
|
// await PostReceiveWorkflow.queue(this.context, {
|
|
185
214
|
// senderID: this.input.senderID,
|
|
@@ -188,6 +217,7 @@ export default class DispatchEmailToMX extends Workflow<IMessageEnvelope> {
|
|
|
188
217
|
// sent: false
|
|
189
218
|
// });
|
|
190
219
|
|
|
220
|
+
|
|
191
221
|
return {
|
|
192
222
|
statusCode: SmtpStatusCodes.Ok,
|
|
193
223
|
status: "Ok",
|
|
@@ -78,7 +78,11 @@ export default class MailDispatcherService {
|
|
|
78
78
|
.include((x) => x.emailAddress)
|
|
79
79
|
.first();
|
|
80
80
|
|
|
81
|
-
to ??= email.recipients.
|
|
81
|
+
to ??= email.recipients.filter((r) => r.type === "to")
|
|
82
|
+
.map((r) => r.replyTo ?? r.emailAddress.emailAddress);
|
|
83
|
+
|
|
84
|
+
const cc = email.recipients.filter((r) => r.type === "cc")
|
|
85
|
+
.map((r) => r.emailAddress.emailAddress);
|
|
82
86
|
|
|
83
87
|
if (!email.senderName) {
|
|
84
88
|
email.senderName = email.senderEmail.mailbox.emailAddress.name;
|
|
@@ -140,6 +144,7 @@ export default class MailDispatcherService {
|
|
|
140
144
|
const mail = new MailComposer({
|
|
141
145
|
from: { name: email.senderName, address: mb.emailAddress.emailAddress },
|
|
142
146
|
to,
|
|
147
|
+
cc,
|
|
143
148
|
html,
|
|
144
149
|
text: email.textBody,
|
|
145
150
|
subject: email.subject,
|
|
@@ -4,6 +4,9 @@ import Workflow, { UniqueActivity } from "@entity-access/entity-access/dist/work
|
|
|
4
4
|
// import BroadcastEmailToMX from "../channel/BroadcastEmailToMX.js";
|
|
5
5
|
import DispatchEmailToMX from "./DispatchEmailToMX.js";
|
|
6
6
|
import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
7
|
+
import PendingReferencesWorkflow from "../pending/PendingReferencesWorkflow.js";
|
|
8
|
+
import EmailReferenceService from "../../smtp/services/EmailReferenceService.js";
|
|
9
|
+
import EmailPostReceiveService from "../../smtp/services/EmailPostReceiveService.js";
|
|
7
10
|
|
|
8
11
|
const pad = (n, max) => {
|
|
9
12
|
if (n < 0) {
|
|
@@ -102,12 +105,22 @@ export default class PrepareEmailToSend extends Workflow<number, string> {
|
|
|
102
105
|
|
|
103
106
|
@UniqueActivity
|
|
104
107
|
async updateStatus(
|
|
105
|
-
@Inject db?: SocialMailContext
|
|
108
|
+
@Inject db?: SocialMailContext,
|
|
109
|
+
@Inject ers?: EmailReferenceService,
|
|
110
|
+
@Inject eps?: EmailPostReceiveService
|
|
106
111
|
) {
|
|
107
|
-
await db.emails.where({ id: this.input}, (p) => (x) => x.emailID === p.id && x.status !== "published")
|
|
108
|
-
.
|
|
112
|
+
const [sent] = await db.emails.where({ id: this.input}, (p) => (x) => x.emailID === p.id && x.status !== "published")
|
|
113
|
+
.updateSelect(void 0, (p) => (x) => ({
|
|
109
114
|
status: "sent",
|
|
110
115
|
dateUpdated: Sql.date.now()
|
|
111
116
|
}));
|
|
117
|
+
|
|
118
|
+
const emailID = this.input;
|
|
119
|
+
|
|
120
|
+
await ers.updateReferences({ emailID, silent: true });
|
|
121
|
+
await db.emails.statements.update({ stateReferencesUpdated: true}, { emailID });
|
|
122
|
+
|
|
123
|
+
// load recipients...
|
|
124
|
+
await eps.executeAll(sent);
|
|
112
125
|
}
|
|
113
126
|
}
|
|
@@ -84,14 +84,14 @@ export default class extends Page {
|
|
|
84
84
|
|
|
85
85
|
if (meta?.length) {
|
|
86
86
|
body = body.replace(/\<head[^\>]*\>/, (s, v) => {
|
|
87
|
-
return s + meta.map((x) => x.render()).join("\r\n");
|
|
87
|
+
return s + meta.map((x) => x.render()).join("\r\n") + "\r\n";
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
|
-
body = body.replace(/\<head[^\>]*\>/, (s, v) => {
|
|
91
|
-
return s + `<script>var socialMail = ${socialMail};</script>`;
|
|
92
|
-
});
|
|
93
90
|
}
|
|
94
91
|
|
|
92
|
+
body = body.replace(/\<head[^\>]*\>/, (s, v) => {
|
|
93
|
+
return s + `\r\n<script>var socialMail = ${socialMail};</script>\r\n`;
|
|
94
|
+
});
|
|
95
95
|
// const body = await this.channelPageService.modifyPage({
|
|
96
96
|
// host,
|
|
97
97
|
// url: this.request.URL.toString(),
|
|
@@ -12,6 +12,7 @@ import CacheService from "../../../../../server/services/cache/CacheService.js";
|
|
|
12
12
|
import { globalEnv } from "../../../../../common/globalEnv.js";
|
|
13
13
|
import TimedCache from "@entity-access/entity-access/dist/common/cache/TimedCache.js";
|
|
14
14
|
|
|
15
|
+
|
|
15
16
|
const cache = new TimedCache();
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
2
|
-
import { Email } from "../../model/entities/Email.js";
|
|
3
|
-
export declare class EmailThreadService {
|
|
4
|
-
db: SocialMailContext;
|
|
5
|
-
fixThreads(email: Email): Promise<void>;
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=EmailThreadService.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EmailThreadService.d.ts","sourceRoot":"","sources":["../../../../src/server/smtp/services/EmailThreadService.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAEtD,qBACa,kBAAkB;IAG3B,EAAE,EAAE,iBAAiB,CAAC;IAEhB,UAAU,CAAC,KAAK,EAAE,KAAK;CAIhC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EmailThreadService.js","sourceRoot":"","sources":["../../../../src/server/smtp/services/EmailThreadService.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AAI1D,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAK3B,KAAK,CAAC,UAAU,CAAC,KAAY;IAE7B,CAAC;CAEJ,CAAA;AANG;IADC,MAAM;8BACH,iBAAiB;8CAAC;AAHb,kBAAkB;IAD9B,cAAc;GACF,kBAAkB,CAS9B"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import Inject, { RegisterScoped } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
-
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
3
|
-
import { Email } from "../../model/entities/Email.js";
|
|
4
|
-
|
|
5
|
-
@RegisterScoped
|
|
6
|
-
export class EmailThreadService {
|
|
7
|
-
|
|
8
|
-
@Inject
|
|
9
|
-
db: SocialMailContext;
|
|
10
|
-
|
|
11
|
-
async fixThreads(email: Email) {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
}
|