@social-mail/social-mail-web-server 1.5.49 → 1.5.50
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/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/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/EmailAddressName.d.ts +19 -0
- package/dist/server/model/entities/EmailAddressName.d.ts.map +1 -0
- package/dist/server/model/entities/EmailAddressName.js +47 -0
- package/dist/server/model/entities/EmailAddressName.js.map +1 -0
- package/dist/server/model/entities/Tag.d.ts +2 -0
- package/dist/server/model/entities/Tag.d.ts.map +1 -1
- package/dist/server/model/entities/Tag.js.map +1 -1
- package/dist/server/model/events/EmailAddressNameEvents.d.ts +7 -0
- package/dist/server/model/events/EmailAddressNameEvents.d.ts.map +1 -0
- package/dist/server/model/events/EmailAddressNameEvents.js +10 -0
- package/dist/server/model/events/EmailAddressNameEvents.js.map +1 -0
- package/dist/server/seed/ui/seed-ui.js +1 -1
- package/dist/server/services/EmailAddressService.d.ts.map +1 -1
- package/dist/server/services/EmailAddressService.js +10 -1
- package/dist/server/services/EmailAddressService.js.map +1 -1
- package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.d.ts +11 -0
- package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.d.ts.map +1 -0
- package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.js +44 -0
- package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.js.map +1 -0
- package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.d.ts +9 -0
- package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.d.ts.map +1 -0
- package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.js +64 -0
- package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/server/model/SocialMailContext.ts +3 -0
- package/src/server/model/SocialMailContextEvents.ts +3 -0
- package/src/server/model/entities/EmailAddress.ts +2 -0
- package/src/server/model/entities/EmailAddressName.ts +37 -0
- package/src/server/model/entities/Tag.ts +3 -1
- package/src/server/model/events/EmailAddressNameEvents.ts +14 -0
- package/src/server/seed/ui/seed-ui.ts +1 -1
- package/src/server/services/EmailAddressService.ts +13 -1
- package/src/server/workflows/email-address/UpdateEmailAddressNameWorkflow.ts +30 -0
- package/src/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.ts +57 -0
package/package.json
CHANGED
|
@@ -45,6 +45,7 @@ import IncomingSmsSource from "./entities/IncomingSmsSource.js";
|
|
|
45
45
|
import VerificationToken, { VerificationTokenAddress } from "./entities/VerificationToken.js";
|
|
46
46
|
import MailboxFolder from "./entities/MailboxFolder.js";
|
|
47
47
|
import HostedZone, { HostedZoneRecord, HostedZoneUser } from "./entities/HostedZone.js";
|
|
48
|
+
import EmailAddressName from "./entities/EmailAddressName.js";
|
|
48
49
|
|
|
49
50
|
@RegisterScoped
|
|
50
51
|
export default class SocialMailContext extends EntityContext {
|
|
@@ -205,6 +206,8 @@ export default class SocialMailContext extends EntityContext {
|
|
|
205
206
|
|
|
206
207
|
public verificationTokenAddresses = this.model.register(VerificationTokenAddress);
|
|
207
208
|
|
|
209
|
+
public emailAddressNames = this.model.register(EmailAddressName);
|
|
210
|
+
|
|
208
211
|
public tags = this.model.register(Tag);
|
|
209
212
|
|
|
210
213
|
}
|
|
@@ -97,6 +97,8 @@ import StoreTagEvents from "./events/StoreTagEvents.js";
|
|
|
97
97
|
import StoreItemFolderTagEvents from "./events/StoreItemFolderTagEvents.js";
|
|
98
98
|
import HostedZone, { HostedZoneRecord, HostedZoneUser } from "./entities/HostedZone.js";
|
|
99
99
|
import HostedZoneEvents, { HostedZoneRecordEvents, HostedZoneUserEvents } from "./events/HostedZoneEvents.js";
|
|
100
|
+
import EmailAddressName from "./entities/EmailAddressName.js";
|
|
101
|
+
import EmailAddressNameEvents from "./events/EmailAddressNameEvents.js";
|
|
100
102
|
|
|
101
103
|
@RegisterSingleton
|
|
102
104
|
export default class SocialMailContextEvents extends ContextEvents {
|
|
@@ -127,6 +129,7 @@ export default class SocialMailContextEvents extends ContextEvents {
|
|
|
127
129
|
this.register(HostedZoneUser, HostedZoneUserEvents);
|
|
128
130
|
this.register(Email, EmailEvents);
|
|
129
131
|
this.register(EmailAddress, EmailAddressEvents);
|
|
132
|
+
this.register(EmailAddressName, EmailAddressNameEvents);
|
|
130
133
|
this.register(EmailEngagement, EmailEngagementEvents);
|
|
131
134
|
this.register(EmailRecipient, EmailRecipientEvents);
|
|
132
135
|
this.register(EmailTag, EmailTagEvents);
|
|
@@ -9,6 +9,7 @@ import Domain from "./Domain.js";
|
|
|
9
9
|
import type MailboxContact from "./MailboxContact.js";
|
|
10
10
|
import type { ContactEmail } from "./Contact.js";
|
|
11
11
|
import type SubscriberActivity from "./SubscriberActivity.js";
|
|
12
|
+
import type EmailAddressName from "./EmailAddressName.js";
|
|
12
13
|
|
|
13
14
|
@Table("EmailAddresses")
|
|
14
15
|
@Index({
|
|
@@ -50,5 +51,6 @@ export default class EmailAddress {
|
|
|
50
51
|
public contactEmails: ContactEmail[];
|
|
51
52
|
|
|
52
53
|
public subscriberActivities: SubscriberActivity[];
|
|
54
|
+
names: EmailAddressName[];
|
|
53
55
|
|
|
54
56
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Column from "@entity-access/entity-access/dist/decorators/Column.js";
|
|
2
|
+
import Table from "@entity-access/entity-access/dist/decorators/Table.js";
|
|
3
|
+
import { RelateTo } from "@entity-access/entity-access/dist/decorators/Relate.js";
|
|
4
|
+
import EmailAddress from "./EmailAddress.js";
|
|
5
|
+
import Tag from "./Tag.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This table exists as an index of all historical name tokens used in the email address.
|
|
9
|
+
*
|
|
10
|
+
* Akash @ Social Mail <akash@socialmail.me>
|
|
11
|
+
* Akash Kava <akash@socialmail.me>
|
|
12
|
+
* EmailAddressNameToken will contain ids of akash, kava, social, mail tokens
|
|
13
|
+
*
|
|
14
|
+
* Why not use FTS?
|
|
15
|
+
* FTS will not keep history, this table will keep history of names.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
@Table("EmailAddressNames")
|
|
19
|
+
export default class EmailAddressName {
|
|
20
|
+
|
|
21
|
+
@Column({ dataType: "BigInt", key: true })
|
|
22
|
+
@RelateTo(Tag, {
|
|
23
|
+
property: (x) => x.tag,
|
|
24
|
+
inverseProperty: (x) => x.emailAddressNames
|
|
25
|
+
})
|
|
26
|
+
tagID: number;
|
|
27
|
+
|
|
28
|
+
@Column({ dataType: "BigInt", key: true })
|
|
29
|
+
@RelateTo(EmailAddress, {
|
|
30
|
+
property: (x) => x.emailAddress,
|
|
31
|
+
inverseProperty: (x) => x.names
|
|
32
|
+
})
|
|
33
|
+
emailAddressID: number;
|
|
34
|
+
|
|
35
|
+
tag: Tag;
|
|
36
|
+
emailAddress: EmailAddress;
|
|
37
|
+
}
|
|
@@ -5,11 +5,12 @@ import type AppFileTag from "./AppFileTag.js";
|
|
|
5
5
|
import { RelateTo } from "@entity-access/entity-access/dist/decorators/Relate.js";
|
|
6
6
|
import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
7
7
|
import type { ContactTag } from "./Contact.js";
|
|
8
|
-
import {
|
|
8
|
+
import { ReadOnlyJsonProperty } from "@entity-access/server-pages/dist/services/ModelService.js";
|
|
9
9
|
import type MailboxContactTag from "./MailboxContactTag.js";
|
|
10
10
|
import type EmailTag from "./EmailTag.js";
|
|
11
11
|
import type { StoreItemFolderTag, StoreItemTag, StoreTag } from "./Store.js";
|
|
12
12
|
import type MailboxFolder from "./MailboxFolder.js";
|
|
13
|
+
import type EmailAddressName from "./EmailAddressName.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* The reason tags table exists in form of string,bigint pair is, we need
|
|
@@ -83,4 +84,5 @@ export default class Tag {
|
|
|
83
84
|
storeTags: StoreTag[];
|
|
84
85
|
storeItemFolderTags: StoreItemFolderTag[];
|
|
85
86
|
mailboxFolders: MailboxFolder[];
|
|
87
|
+
emailAddressNames: EmailAddressName[];
|
|
86
88
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IEntityQuery } from "@entity-access/entity-access/dist/model/IFilterWithParameter.js";
|
|
2
|
+
import EmailAddressName from "../entities/EmailAddressName.js";
|
|
3
|
+
import AuthenticatedEvents from "./AuthenticatedEvents.js";
|
|
4
|
+
|
|
5
|
+
export default class EmailAddressNameEvents extends AuthenticatedEvents<EmailAddressName> {
|
|
6
|
+
|
|
7
|
+
filter(query: IEntityQuery<EmailAddressName>): IEntityQuery<EmailAddressName> {
|
|
8
|
+
if (this.verify) {
|
|
9
|
+
this.sessionUser.ensureLoggedIn();
|
|
10
|
+
}
|
|
11
|
+
return query.limit(20);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
3
|
import SocialMailContext from "../model/SocialMailContext.js";
|
|
4
4
|
import { globalServices } from "../../globalServices.js";
|
|
5
5
|
import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
|
|
6
6
|
import { cacheFor } from "../../common/cacheFor.js";
|
|
7
7
|
import Domain from "../model/entities/Domain.js";
|
|
8
|
+
import WorkflowContext from "@entity-access/entity-access/dist/workflows/WorkflowContext.js";
|
|
9
|
+
import UpdateEmailAddressNameWorkflow from "../workflows/email-address/UpdateEmailAddressNameWorkflow.js";
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
@RegisterSingleton
|
|
@@ -145,6 +147,8 @@ export default class EmailAddressService {
|
|
|
145
147
|
|
|
146
148
|
emailAddress = emailAddress.trim().toLocaleLowerCase();
|
|
147
149
|
|
|
150
|
+
name = name?.trim();
|
|
151
|
+
|
|
148
152
|
const tokens = emailAddress.split("@");
|
|
149
153
|
if (tokens.length !== 2) {
|
|
150
154
|
if (validate) {
|
|
@@ -182,9 +186,17 @@ export default class EmailAddressService {
|
|
|
182
186
|
// });
|
|
183
187
|
const ea = await db.emailAddresses.statements.selectOrInsert(changes, { emailAddress });
|
|
184
188
|
const hasMailbox = await db.mailboxes.where(ea, (p) => (x) => x.mailboxID === p.emailAddressID).some();
|
|
189
|
+
if (name && ea.name !== name) {
|
|
190
|
+
// schedule for names tag
|
|
191
|
+
const wc = ServiceProvider.resolve(this, WorkflowContext);
|
|
192
|
+
await wc.queue(UpdateEmailAddressNameWorkflow, { id: ea.emailAddressID, name });
|
|
193
|
+
}
|
|
185
194
|
if(!hasMailbox && ((name && ea.name !== name) || ea.domainID !== domainID)) {
|
|
186
195
|
ea.name = name;
|
|
187
196
|
ea.domainID = domainID;
|
|
197
|
+
|
|
198
|
+
// schedule tag updates...
|
|
199
|
+
|
|
188
200
|
await db.emailAddresses.statements.update(ea);
|
|
189
201
|
// await db.emailAddresses.saveDirect({
|
|
190
202
|
// mode: "update",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Inject from "@entity-access/entity-access/dist/di/di.js";
|
|
2
|
+
import Workflow, { UniqueActivity } from "@entity-access/entity-access/dist/workflows/Workflow.js";
|
|
3
|
+
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
4
|
+
import TagService from "../../services/tags/TagService.js";
|
|
5
|
+
|
|
6
|
+
export default class UpdateEmailAddressNameWorkflow extends Workflow<{ id: number, name: string }> {
|
|
7
|
+
|
|
8
|
+
async run() {
|
|
9
|
+
await this.update();
|
|
10
|
+
return 1;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@UniqueActivity
|
|
14
|
+
async update(
|
|
15
|
+
@Inject db?: SocialMailContext,
|
|
16
|
+
@Inject ts?: TagService
|
|
17
|
+
) {
|
|
18
|
+
const { id: emailAddressID } = this.input;
|
|
19
|
+
// split tags...
|
|
20
|
+
const tokens = this.input.name.split(/[^\p{L}]+/igmu);
|
|
21
|
+
for (const token of tokens) {
|
|
22
|
+
if (!token) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const tagID = await ts.getSystemTagID(token);
|
|
26
|
+
await db.emailAddressNames.statements.selectOrInsert({ tagID, emailAddressID },{ tagID, emailAddressID });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Workflow, { UniqueActivity } from "@entity-access/entity-access/dist/workflows/Workflow.js";
|
|
2
|
+
import SocialMailContext from "../../../model/SocialMailContext.js";
|
|
3
|
+
import Inject from "@entity-access/entity-access/dist/di/di.js";
|
|
4
|
+
import Hashtags from "../../../../common/Hashtags.js";
|
|
5
|
+
import TagService from "../../../services/tags/TagService.js";
|
|
6
|
+
import { Email } from "../../../model/entities/Email.js";
|
|
7
|
+
|
|
8
|
+
export default class RepairEmailNameTagsWorkflow extends Workflow {
|
|
9
|
+
|
|
10
|
+
static taskGroup = "batch";
|
|
11
|
+
|
|
12
|
+
async run() {
|
|
13
|
+
let start = 0;
|
|
14
|
+
do{
|
|
15
|
+
start = await this.fixEmailTags(start);
|
|
16
|
+
} while(BigInt(start));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@UniqueActivity
|
|
20
|
+
async fixEmailTags(
|
|
21
|
+
start: number,
|
|
22
|
+
@Inject db?: SocialMailContext,
|
|
23
|
+
@Inject ts?: TagService
|
|
24
|
+
) {
|
|
25
|
+
|
|
26
|
+
for(let i = 0;i< 100;i++) {
|
|
27
|
+
const emails = await db.emailAddresses.where({ start }, (p) => (x) => x.emailAddressID > p.start)
|
|
28
|
+
.orderBy(void 0, (p) => (x) => x.emailAddressID)
|
|
29
|
+
.limit(10)
|
|
30
|
+
.toArray();
|
|
31
|
+
|
|
32
|
+
if (!emails.length) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (const { emailAddressID, name } of emails) {
|
|
37
|
+
start = emailAddressID;
|
|
38
|
+
if (!name) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// fix tag...
|
|
42
|
+
const tokens = name.split(/[^\p{L}]+/igmu);
|
|
43
|
+
for (const token of tokens) {
|
|
44
|
+
if (!token) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const tagID = await ts.getSystemTagID(token);
|
|
48
|
+
await db.emailAddressNames.statements.selectOrInsert({ tagID, emailAddressID },{ tagID, emailAddressID });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
db.changeSet.clear();
|
|
52
|
+
}
|
|
53
|
+
return start;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
}
|