@social-mail/social-mail-web-server 1.4.921 → 1.4.923
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/spawnPromise.js +1 -1
- package/dist/common/spawnPromise.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/entities/Mailbox.d.ts +2 -0
- package/dist/server/model/entities/Mailbox.d.ts.map +1 -1
- package/dist/server/model/entities/Mailbox.js.map +1 -1
- package/dist/server/model/entities/MailboxContact.d.ts +3 -0
- package/dist/server/model/entities/MailboxContact.d.ts.map +1 -1
- package/dist/server/model/entities/MailboxContact.js +14 -1
- package/dist/server/model/entities/MailboxContact.js.map +1 -1
- package/dist/server/model/entities/MailboxFolder.d.ts +10 -0
- package/dist/server/model/entities/MailboxFolder.d.ts.map +1 -0
- package/dist/server/model/entities/MailboxFolder.js +47 -0
- package/dist/server/model/entities/MailboxFolder.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/MailboxContactEvents.d.ts.map +1 -1
- package/dist/server/model/events/MailboxContactEvents.js +51 -0
- package/dist/server/model/events/MailboxContactEvents.js.map +1 -1
- package/dist/server/seed/tags/seed-tags.d.ts.map +1 -1
- package/dist/server/seed/tags/seed-tags.js +12 -0
- package/dist/server/seed/tags/seed-tags.js.map +1 -1
- package/dist/server/services/captcha/CaptchaService.d.ts.map +1 -1
- package/dist/server/services/captcha/CaptchaService.js +4 -2
- package/dist/server/services/captcha/CaptchaService.js.map +1 -1
- package/dist/server/services/tags/TagService.d.ts +3 -0
- package/dist/server/services/tags/TagService.d.ts.map +1 -1
- package/dist/server/services/tags/TagService.js +20 -0
- package/dist/server/services/tags/TagService.js.map +1 -1
- package/dist/server/smtp/services/EmailReferenceService.d.ts.map +1 -1
- package/dist/server/smtp/services/EmailReferenceService.js +39 -0
- package/dist/server/smtp/services/EmailReferenceService.js.map +1 -1
- package/dist/server/smtp/services/EmailSerializerService.d.ts +1 -0
- package/dist/server/smtp/services/EmailSerializerService.d.ts.map +1 -1
- package/dist/server/smtp/services/EmailSerializerService.js +2 -2
- package/dist/server/smtp/services/EmailSerializerService.js.map +1 -1
- package/dist/server/workflows/repair/mailbox-folders/RepairMailboxFoldersWorkflow.d.ts +11 -0
- package/dist/server/workflows/repair/mailbox-folders/RepairMailboxFoldersWorkflow.d.ts.map +1 -0
- package/dist/server/workflows/repair/mailbox-folders/RepairMailboxFoldersWorkflow.js +82 -0
- package/dist/server/workflows/repair/mailbox-folders/RepairMailboxFoldersWorkflow.js.map +1 -0
- package/dist/server/workflows/sync/SyncMailboxWorkflow.d.ts.map +1 -1
- package/dist/server/workflows/sync/SyncMailboxWorkflow.js +1 -0
- package/dist/server/workflows/sync/SyncMailboxWorkflow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/common/spawnPromise.ts +1 -1
- package/src/server/model/SocialMailContext.ts +3 -0
- package/src/server/model/entities/Mailbox.ts +2 -0
- package/src/server/model/entities/MailboxContact.ts +11 -1
- package/src/server/model/entities/MailboxFolder.ts +37 -0
- package/src/server/model/entities/Tag.ts +2 -0
- package/src/server/model/events/MailboxContactEvents.ts +60 -0
- package/src/server/seed/tags/seed-tags.ts +18 -1
- package/src/server/services/captcha/CaptchaService.ts +4 -2
- package/src/server/services/tags/TagService.ts +23 -0
- package/src/server/smtp/services/EmailReferenceService.ts +44 -0
- package/src/server/smtp/services/EmailSerializerService.ts +7 -3
- package/src/server/workflows/repair/mailbox-folders/RepairMailboxFoldersWorkflow.ts +77 -0
- package/src/server/workflows/sync/SyncMailboxWorkflow.ts +1 -0
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@ export const spawnPromise = (path, args?: string[], options?: SpawnOptionsWithou
|
|
|
24
24
|
cd.on("error", (error) => {
|
|
25
25
|
const errorText = color.red(error.stack ?? error.toString());
|
|
26
26
|
all.push(error.stack ?? error.toString());
|
|
27
|
-
if (logData) {
|
|
27
|
+
if (logData || logError) {
|
|
28
28
|
console.error(errorText);
|
|
29
29
|
}
|
|
30
30
|
reject(error);
|
|
@@ -43,6 +43,7 @@ import AccessToken from "./entities/AccessToken.js";
|
|
|
43
43
|
import ServerActivity from "./entities/ServerActivity.js";
|
|
44
44
|
import IncomingSmsSource from "./entities/IncomingSmsSource.js";
|
|
45
45
|
import VerificationToken, { VerificationTokenAddress } from "./entities/VerificationToken.js";
|
|
46
|
+
import MailboxFolder from "./entities/MailboxFolder.js";
|
|
46
47
|
|
|
47
48
|
@RegisterScoped
|
|
48
49
|
export default class SocialMailContext extends EntityContext {
|
|
@@ -107,6 +108,8 @@ export default class SocialMailContext extends EntityContext {
|
|
|
107
108
|
|
|
108
109
|
public mailboxContacts = this.model.register(MailboxContact);
|
|
109
110
|
|
|
111
|
+
public mailboxFolders = this.model.register(MailboxFolder);
|
|
112
|
+
|
|
110
113
|
public mailboxContactEmails = this.model.register(MailboxContactEmail);
|
|
111
114
|
|
|
112
115
|
public mailboxContactTags = this.model.register(MailboxContactTag);
|
|
@@ -19,6 +19,7 @@ import { IgnoreJsonProperty, JsonProperty, ReadOnlyJsonProperty } from "@entity-
|
|
|
19
19
|
import type ChannelConfig from "./ChannelConfig.js";
|
|
20
20
|
import type { WebSiteChannel } from "./WebSiteFolder.js";
|
|
21
21
|
import Domain from "./Domain.js";
|
|
22
|
+
import type MailboxFolder from "./MailboxFolder.js";
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* MailBox ID is number because foreign key on Email will
|
|
@@ -206,6 +207,7 @@ export default class Mailbox {
|
|
|
206
207
|
public subscriberActivities: SubscriberActivity[];
|
|
207
208
|
|
|
208
209
|
public websiteChannels: WebSiteChannel[];
|
|
210
|
+
folders: MailboxFolder[];
|
|
209
211
|
|
|
210
212
|
|
|
211
213
|
}
|
|
@@ -25,9 +25,10 @@ export type subscriberStatusType = typeof subscriberStatus[number];
|
|
|
25
25
|
|
|
26
26
|
@Table("MailboxContacts")
|
|
27
27
|
@Index({
|
|
28
|
-
name: "
|
|
28
|
+
name: "IX_MailBox_Thread_Tagged_DateUpdated",
|
|
29
29
|
columns: [
|
|
30
30
|
{ name: (x) => x.mailboxID, descending: false },
|
|
31
|
+
{ name: (x) => x.folderTagID, descending: false },
|
|
31
32
|
{ name: (x) => x.dateUpdated, descending: true }
|
|
32
33
|
]
|
|
33
34
|
})
|
|
@@ -59,6 +60,9 @@ export default class MailboxContact {
|
|
|
59
60
|
})
|
|
60
61
|
public emailAddressID: number;
|
|
61
62
|
|
|
63
|
+
@Column({ dataType: "BigInt", nullable: true })
|
|
64
|
+
public folderTagID: number;
|
|
65
|
+
|
|
62
66
|
@Column({ dataType: "BigInt", nullable: true})
|
|
63
67
|
@RelateTo(Email, {
|
|
64
68
|
property: (mt) => mt.lastEmail,
|
|
@@ -118,6 +122,12 @@ export default class MailboxContact {
|
|
|
118
122
|
@Column({ dataType: "Boolean", default: () => false})
|
|
119
123
|
public blocked: boolean;
|
|
120
124
|
|
|
125
|
+
@Column({ dataType: "Boolean", default: () => false})
|
|
126
|
+
public newRequest: boolean;
|
|
127
|
+
|
|
128
|
+
@Column({ dataType: "Boolean", default: () => false})
|
|
129
|
+
public spam: boolean;
|
|
130
|
+
|
|
121
131
|
@Column({ dataType: "Boolean", default: () => false})
|
|
122
132
|
public mute: boolean;
|
|
123
133
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Column from "@entity-access/entity-access/dist/decorators/Column.js";
|
|
2
|
+
import { RelateTo } from "@entity-access/entity-access/dist/decorators/Relate.js";
|
|
3
|
+
import Table from "@entity-access/entity-access/dist/decorators/Table.js";
|
|
4
|
+
import Mailbox from "./Mailbox.js";
|
|
5
|
+
import Tag from "./Tag.js";
|
|
6
|
+
|
|
7
|
+
@Table("MailboxFolders")
|
|
8
|
+
export default class MailboxFolder {
|
|
9
|
+
|
|
10
|
+
@Column({ dataType: "BigInt", key: true })
|
|
11
|
+
@RelateTo(Mailbox, {
|
|
12
|
+
property: (x) => x.mailbox,
|
|
13
|
+
inverseProperty: (x) => x.folders,
|
|
14
|
+
foreignKeyConstraint: {
|
|
15
|
+
cascade: "delete"
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
mailboxID: number;
|
|
19
|
+
|
|
20
|
+
@Column({ dataType: "BigInt", key: true })
|
|
21
|
+
@RelateTo(Tag, {
|
|
22
|
+
property: (x) => x.tag,
|
|
23
|
+
inverseProperty: (x) => x.mailboxFolders,
|
|
24
|
+
foreignKeyConstraint: {
|
|
25
|
+
cascade: "restrict"
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
tagID: number;
|
|
29
|
+
|
|
30
|
+
@Column({ dataType: "Int", default: () => 0})
|
|
31
|
+
count: number;
|
|
32
|
+
|
|
33
|
+
mailbox: Mailbox;
|
|
34
|
+
|
|
35
|
+
tag: Tag;
|
|
36
|
+
|
|
37
|
+
}
|
|
@@ -9,6 +9,7 @@ import { IgnoreJsonProperty, ReadOnlyJsonProperty } from "@entity-access/server-
|
|
|
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
|
+
import type MailboxFolder from "./MailboxFolder.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* The reason tags table exists in form of string,bigint pair is, we need
|
|
@@ -81,4 +82,5 @@ export default class Tag {
|
|
|
81
82
|
public storeItemTags: StoreItemTag[];
|
|
82
83
|
storeTags: StoreTag[];
|
|
83
84
|
storeItemFolderTags: StoreItemFolderTag[];
|
|
85
|
+
mailboxFolders: MailboxFolder[];
|
|
84
86
|
}
|
|
@@ -8,6 +8,8 @@ import { ForeignKeyFilter } from "@entity-access/entity-access/dist/model/events
|
|
|
8
8
|
import SocialMailContext from "../SocialMailContext.js";
|
|
9
9
|
import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
10
10
|
import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
|
|
11
|
+
import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
|
|
12
|
+
import TagService from "../../services/tags/TagService.js";
|
|
11
13
|
|
|
12
14
|
export default class MailboxContactEvents extends AuthenticatedEvents<MailboxContact> {
|
|
13
15
|
|
|
@@ -120,6 +122,64 @@ export default class MailboxContactEvents extends AuthenticatedEvents<MailboxCon
|
|
|
120
122
|
|
|
121
123
|
}
|
|
122
124
|
|
|
125
|
+
let tagUpdated = false;
|
|
126
|
+
|
|
127
|
+
if (entry.isModified("folderTagID")) {
|
|
128
|
+
tagUpdated = true;
|
|
129
|
+
const oldID = entry.getChange("folderTagID").oldValue;
|
|
130
|
+
await db.mailboxFolders.where({ mailboxID, oldID }, (p) => (x) => x.mailboxID === p.mailboxID && x.tagID === p.oldID)
|
|
131
|
+
.update(void 0, (p) => (x) => ({
|
|
132
|
+
count: Sql.math.max(0, x.count-1)
|
|
133
|
+
}));
|
|
134
|
+
await db.mailboxFolders.where({ mailboxID, tagID: entity.folderTagID },
|
|
135
|
+
(p) => (x) => x.mailboxID === p.mailboxID && x.tagID === p.tagID)
|
|
136
|
+
.update(void 0, (p) => (x) => ({
|
|
137
|
+
count: x.count + 1
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
const ts = ServiceProvider.resolve(this, TagService);
|
|
141
|
+
const spam = await ts.getSystemTagID("Spam");
|
|
142
|
+
const newRequest = await ts.getSystemTagID("New");
|
|
143
|
+
const isBlocked = await ts.getSystemTagID("Blocked");
|
|
144
|
+
|
|
145
|
+
entity.spam = spam === entity.folderTagID;
|
|
146
|
+
entity.newRequest = newRequest === entity.folderTagID;
|
|
147
|
+
entity.blocked = isBlocked === entity.folderTagID;
|
|
148
|
+
entry.detect();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if ( !tagUpdated && (entry.isModified("spam") || entry.isModified("newRequest") || entry.isModified("blocked"))) {
|
|
152
|
+
// update tag folder...
|
|
153
|
+
// only if older folder is one of the system folder...
|
|
154
|
+
|
|
155
|
+
const ts = ServiceProvider.resolve(this, TagService);
|
|
156
|
+
const systemIDs = await ts.getSystemTagIDs(["Contacts", "New", "Spam", "Blocked"]);
|
|
157
|
+
if (systemIDs.includes(entity.folderTagID)) {
|
|
158
|
+
const oldID = entity.folderTagID;
|
|
159
|
+
const tagID = await ts.getSystemTagID(entity.spam
|
|
160
|
+
? "Spam"
|
|
161
|
+
: entity.newRequest
|
|
162
|
+
? "New"
|
|
163
|
+
: entity.blocked
|
|
164
|
+
? "Blocked"
|
|
165
|
+
: "Contacts");
|
|
166
|
+
entity.folderTagID = tagID;
|
|
167
|
+
if (tagID !== oldID) {
|
|
168
|
+
await db.mailboxFolders
|
|
169
|
+
.where({ mailboxID, oldID }, (p) =>
|
|
170
|
+
(x) => x.mailboxID === p.mailboxID && x.tagID === p.oldID)
|
|
171
|
+
.update(void 0, (p) => (x) => ({
|
|
172
|
+
count: Sql.math.max(0, x.count-1)
|
|
173
|
+
}));
|
|
174
|
+
await db.mailboxFolders
|
|
175
|
+
.where({ mailboxID, tagID }, (p) =>
|
|
176
|
+
(x) => x.mailboxID === p.mailboxID && x.tagID === p.tagID)
|
|
177
|
+
.update(void 0, (p) => (x) => ({
|
|
178
|
+
count: x.count + 1
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
123
183
|
|
|
124
184
|
if (entry.isModified("autoClose") || entry.isModified("blocked")) {
|
|
125
185
|
if (autoClose || blocked) {
|
|
@@ -9,7 +9,7 @@ interface IFileTag {
|
|
|
9
9
|
|
|
10
10
|
interface ITagParent {
|
|
11
11
|
name: string;
|
|
12
|
-
children
|
|
12
|
+
children?: ITagLike[];
|
|
13
13
|
contentTypes?: string[];
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -154,6 +154,23 @@ export default async function seedTags(context: SocialMailContext) {
|
|
|
154
154
|
]
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
+
await addTag(context, {
|
|
158
|
+
name: "Contacts",
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
await addTag(context, {
|
|
162
|
+
name: "New",
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
await addTag(context, {
|
|
166
|
+
name: "Spam",
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
await addTag(context, {
|
|
170
|
+
name: "Blocked",
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
|
|
157
174
|
await context.saveChanges();
|
|
158
175
|
|
|
159
176
|
await updatePath(context);
|
|
@@ -94,7 +94,8 @@ export default class CaptchaService {
|
|
|
94
94
|
"-map", "[v]",
|
|
95
95
|
"-y", tf.path
|
|
96
96
|
], {
|
|
97
|
-
logData: false
|
|
97
|
+
logData: false,
|
|
98
|
+
logCommand: false
|
|
98
99
|
});
|
|
99
100
|
|
|
100
101
|
await spawnPromise("/ffmpeg/ffmpeg", [
|
|
@@ -102,7 +103,8 @@ export default class CaptchaService {
|
|
|
102
103
|
"-filter:v", "scale=300:-1",
|
|
103
104
|
"-y", saveAs
|
|
104
105
|
],{
|
|
105
|
-
logData: false
|
|
106
|
+
logData: false,
|
|
107
|
+
logCommand: false
|
|
106
108
|
});
|
|
107
109
|
}
|
|
108
110
|
|
|
@@ -2,10 +2,33 @@
|
|
|
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
|
+
import TimedCache from "@entity-access/entity-access/dist/common/cache/TimedCache.js";
|
|
6
|
+
import Tag from "../../model/entities/Tag.js";
|
|
5
7
|
|
|
6
8
|
@RegisterSingleton
|
|
7
9
|
export default class TagService {
|
|
8
10
|
|
|
11
|
+
map = new Map<string, number>();
|
|
12
|
+
|
|
13
|
+
async getSystemTagIDs(names: string[]) {
|
|
14
|
+
const ids = [];
|
|
15
|
+
for (const name of names) {
|
|
16
|
+
ids.push(await this.getSystemTagID(name));
|
|
17
|
+
}
|
|
18
|
+
return ids;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async getSystemTagID(name: string) {
|
|
22
|
+
name = name.trim().toLocaleLowerCase();
|
|
23
|
+
let tagID = this.map.get(name);
|
|
24
|
+
if (!tagID) {
|
|
25
|
+
const tags = await this.getTagID(name);
|
|
26
|
+
tagID = tags.pop();
|
|
27
|
+
this.map.set(name, tagID);
|
|
28
|
+
}
|
|
29
|
+
return tagID;
|
|
30
|
+
}
|
|
31
|
+
|
|
9
32
|
async getTagID(name: string): Promise<number[]> {
|
|
10
33
|
if (!name) {
|
|
11
34
|
return [];
|
|
@@ -390,20 +390,50 @@ export default class EmailReferenceService {
|
|
|
390
390
|
const unread = email.senderID === mailboxID || silent ? 0 : 1;
|
|
391
391
|
const total = 1;
|
|
392
392
|
|
|
393
|
+
let newRequest = email.received && email.senderID !== mailboxID;
|
|
394
|
+
|
|
395
|
+
let blocked = false;
|
|
396
|
+
let spam = false;
|
|
397
|
+
|
|
398
|
+
let addFolder = true;
|
|
399
|
+
|
|
400
|
+
const name = spam
|
|
401
|
+
? "Spam"
|
|
402
|
+
: blocked
|
|
403
|
+
? "Blocked"
|
|
404
|
+
: newRequest
|
|
405
|
+
? "New"
|
|
406
|
+
: "Contacts";
|
|
407
|
+
|
|
408
|
+
let tagID = await this.tagService.getSystemTagID(name);
|
|
409
|
+
|
|
393
410
|
await db.mailboxContacts.statements.upsert({
|
|
394
411
|
emailAddressID,
|
|
395
412
|
mailboxID,
|
|
413
|
+
folderTagID: tagID,
|
|
396
414
|
openThreads: newOpenThread === 1 ? 1 : 0,
|
|
397
415
|
totalThreads: newThread === 1 ? 1 : 0,
|
|
398
416
|
lastEmailID: emailID,
|
|
417
|
+
newRequest,
|
|
399
418
|
dateUpdated,
|
|
419
|
+
blocked,
|
|
420
|
+
spam,
|
|
400
421
|
unread,
|
|
401
422
|
total
|
|
402
423
|
},
|
|
403
424
|
(item) => {
|
|
425
|
+
addFolder = false;
|
|
404
426
|
item.unread = item.unread ? item.unread + ( unread ? 1 : 0 ) : 0;
|
|
405
427
|
item.total = item.total ? item.total + 1 : 1;
|
|
406
428
|
item.dateUpdated = dateUpdated;
|
|
429
|
+
newRequest = item.newRequest;
|
|
430
|
+
blocked = item.blocked;
|
|
431
|
+
spam = item.spam;
|
|
432
|
+
if(!item.folderTagID) {
|
|
433
|
+
item.folderTagID = tagID;
|
|
434
|
+
} else {
|
|
435
|
+
tagID = item.folderTagID;
|
|
436
|
+
}
|
|
407
437
|
if (item.autoClose || item.blocked) {
|
|
408
438
|
newOpenThread = 0;
|
|
409
439
|
newThread = 0;
|
|
@@ -417,6 +447,20 @@ export default class EmailReferenceService {
|
|
|
417
447
|
}
|
|
418
448
|
);
|
|
419
449
|
|
|
450
|
+
if (addFolder) {
|
|
451
|
+
await db.mailboxFolders.statements.upsert({
|
|
452
|
+
mailboxID,
|
|
453
|
+
tagID,
|
|
454
|
+
count: 1
|
|
455
|
+
}, (x) => {
|
|
456
|
+
x.count++;
|
|
457
|
+
return x;
|
|
458
|
+
}, {
|
|
459
|
+
mailboxID,
|
|
460
|
+
tagID
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
420
464
|
|
|
421
465
|
await db.mailboxes.where({ mailboxID }, (p) => (x) => x.mailboxID === p.mailboxID)
|
|
422
466
|
.update({ newThread, newOpenThread, unread: unread ? 1 : 0 }, (p) => (x) => ({
|
|
@@ -105,7 +105,11 @@ const stripDuplicates = (addresses: IEmailRecipientInfo[]) => {
|
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
export interface IEmailInfo {
|
|
108
|
-
externalEmailID: string,
|
|
108
|
+
externalEmailID: string,
|
|
109
|
+
labels: string[],
|
|
110
|
+
mailbox: Mailbox,
|
|
111
|
+
silent?: boolean,
|
|
112
|
+
receivedViaSMTP?: boolean,
|
|
109
113
|
messageId: string
|
|
110
114
|
};
|
|
111
115
|
|
|
@@ -147,7 +151,7 @@ export default class EmailSerializerService {
|
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
async saveRFC822File(file: LocalFile, emailInfo: IEmailInfo) {
|
|
150
|
-
const { externalEmailID, labels, mailbox, silent, messageId} = emailInfo;
|
|
154
|
+
const { externalEmailID, labels, mailbox, silent, messageId, receivedViaSMTP} = emailInfo;
|
|
151
155
|
const { tempFileService, db } = this;
|
|
152
156
|
// check if email already saved in same mailbox...
|
|
153
157
|
const { mailboxID } = mailbox;
|
|
@@ -167,7 +171,7 @@ export default class EmailSerializerService {
|
|
|
167
171
|
try {
|
|
168
172
|
// scan for viruses....
|
|
169
173
|
await AVService.scan(file);
|
|
170
|
-
await this.save(file, { mailboxes, externalEmailID, silent, labels });
|
|
174
|
+
await this.save(file, { mailboxes, externalEmailID, silent, labels, received: receivedViaSMTP });
|
|
171
175
|
} catch (error) {
|
|
172
176
|
if (error instanceof FileInfectedError) {
|
|
173
177
|
|
|
@@ -0,0 +1,77 @@
|
|
|
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 Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
5
|
+
import Mailbox from "../../../model/entities/Mailbox.js";
|
|
6
|
+
import TagService from "../../../services/tags/TagService.js";
|
|
7
|
+
|
|
8
|
+
export default class RepairMailboxFoldersWorkflow 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
|
+
const contacts = await ts.getSystemTagID("Contacts");
|
|
27
|
+
const isNew = await ts.getSystemTagID("New");
|
|
28
|
+
const isBlocked = await ts.getSystemTagID("Blocked");
|
|
29
|
+
const isSpam = await ts.getSystemTagID("Spam");
|
|
30
|
+
|
|
31
|
+
for(let i = 0;i< 100;i++) {
|
|
32
|
+
const mailboxes = await db.mailboxes.where({ start }, (p) => (x) => x.mailboxID > p.start)
|
|
33
|
+
.orderBy(void 0, (p) => (x) => x.mailboxID)
|
|
34
|
+
.limit(10)
|
|
35
|
+
.include((x) => [x.folders])
|
|
36
|
+
.toArray();
|
|
37
|
+
|
|
38
|
+
if (!mailboxes.length) {
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const iterator of mailboxes) {
|
|
43
|
+
start = iterator.mailboxID;
|
|
44
|
+
// fix tag...
|
|
45
|
+
const counts = await db.mailboxContacts.where(iterator, (p) => (x) => x.mailboxID === p.mailboxID)
|
|
46
|
+
.sum(void 0, (p) => (x) => ( {
|
|
47
|
+
blocked: x.blocked === true ? 1 : 0,
|
|
48
|
+
newRequest: x.newRequest === true ? 1 : 0,
|
|
49
|
+
spam: x.spam === true ? 1 : 0,
|
|
50
|
+
total: 1
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
await this.saveFolder(db, iterator, contacts, counts.total);
|
|
54
|
+
await this.saveFolder(db, iterator, isNew, counts.total);
|
|
55
|
+
await this.saveFolder(db, iterator, isBlocked, counts.total);
|
|
56
|
+
await this.saveFolder(db, iterator, isSpam , counts.total);
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
db.changeSet.clear();
|
|
60
|
+
}
|
|
61
|
+
return start;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async saveFolder(db: SocialMailContext, { mailboxID }: Mailbox, tagID: number, count: number) {
|
|
65
|
+
await db.mailboxFolders.statements.upsert({
|
|
66
|
+
mailboxID,
|
|
67
|
+
tagID,
|
|
68
|
+
count
|
|
69
|
+
}, (x) => {
|
|
70
|
+
x.count = count;
|
|
71
|
+
return x;
|
|
72
|
+
}, {
|
|
73
|
+
mailboxID,
|
|
74
|
+
tagID
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|