@social-mail/social-mail-web-server 1.4.705 → 1.4.707

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/wwwroot/routes/index.tsx"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,mCAAmC,CAAC;AAEzD,OAAO,cAAc,MAAM,+CAA+C,CAAC;AAG3E,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAG5D,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,MAAM,EAAE,QAAQ,CAAC;IAGjB,cAAc,EAAE,cAAc,CAAC;IAE/B,GAAG,EAAE,GAAG,CAAC;IAEH,GAAG;CA8EZ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/wwwroot/routes/index.tsx"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,mCAAmC,CAAC;AAEzD,OAAO,cAAc,MAAM,+CAA+C,CAAC;AAG3E,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAG5D,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,MAAM,EAAE,QAAQ,CAAC;IAGjB,cAAc,EAAE,cAAc,CAAC;IAE/B,GAAG,EAAE,GAAG,CAAC;IAEH,GAAG;CAkGZ"}
@@ -25,21 +25,39 @@ export default class default_1 extends Page {
25
25
  if (webSite) {
26
26
  // this is a static web site...
27
27
  // if path is empty... load /index.html....
28
+ let notFound = false;
28
29
  let path = this.childPath;
29
30
  if (!file) {
30
31
  path = ["index.html"];
31
32
  }
32
- const appFile = await this.websiteService.getSnapshotFile(webSite, path);
33
+ let appFile = await this.websiteService.getSnapshotFile(webSite, path);
33
34
  if (!appFile) {
34
35
  if (file === "favicon.ico") {
35
36
  this.cacheControl = "public, max-age=8600";
36
37
  return new FileResult(ImagesFolder.file("favicon.ico"));
37
38
  }
38
- return this.notFound();
39
+ if (file === "robots.txt") {
40
+ return this.notFound();
41
+ }
42
+ appFile = await this.websiteService.getSnapshotFile(webSite, ["index.html"]);
43
+ if (appFile === null) {
44
+ return this.notFound();
45
+ }
46
+ notFound = true;
39
47
  }
40
48
  delete appFile.fileContent;
41
49
  const tfs = ServiceProvider.resolve(this, TempFileService);
42
50
  const localFile = await tfs.downloadAppFile(appFile);
51
+ if (notFound) {
52
+ const body = await localFile.readAsText();
53
+ console.error(`404: ${this.request?.URL?.toString()}`);
54
+ return this.content({
55
+ body,
56
+ contentType: "text/html",
57
+ suppressLog: true,
58
+ status: 404
59
+ });
60
+ }
43
61
  return new TempFileResult(localFile, {
44
62
  contentDisposition: forceDownload
45
63
  ? "attachment"
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/wwwroot/routes/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/wwwroot/routes/index.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-web-server",
3
- "version": "1.4.705",
3
+ "version": "1.4.707",
4
4
  "description": "## Phase 1",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -34,6 +34,12 @@ export type emailStatusType = typeof emailStatuses[number];
34
34
  columns: [ { name: (x) => x.externalEmailID, descending: false }],
35
35
  filter: (x) => x.externalEmailID !== null
36
36
  })
37
+ @Index({
38
+ name: "IX_Emails_SentMessageID",
39
+ columns: [ { name: (x) => x.sentMessageID, descending: false }],
40
+ filter: (x) => x.sentMessageID !== null,
41
+ unique: true
42
+ })
37
43
  @Index({
38
44
  name: "IX_Emails_HasHtmlBody",
39
45
  columns: [ { name: (x) => x.emailID, descending: true }],
@@ -124,6 +130,9 @@ export class Email {
124
130
  })
125
131
  public mimeFileID: number;
126
132
 
133
+ @Column({ dataType: "Char", length: 200, nullable: true})
134
+ public sentMessageID: string;
135
+
127
136
  @Column({ dataType: "BigInt", nullable: true })
128
137
  @RelateTo({
129
138
  type: () => EmailLog,
@@ -223,18 +223,16 @@ export default class EmailEvents extends AuthenticatedEvents<Email> {
223
223
 
224
224
  private async updateScheduleAndReferences(entity: Email) {
225
225
 
226
- let saveChangesCalled = false;
227
-
228
226
  const { emailID, silent, dateReceived, htmlBody, tempID } = entity;
229
227
 
230
- if (tempID) {
231
- const html = htmlBody.replaceAll(tempID, Base36.encode(emailID));
228
+ let updateEmail = false;
232
229
 
233
- if (html !== htmlBody) {
234
- entity.htmlBody = html;
235
- this.db.queuePostSaveTask(() => this.db.saveChangesWithoutEvents());
236
- saveChangesCalled = true;
237
- }
230
+ let html = htmlBody;
231
+
232
+ if (tempID) {
233
+ html = htmlBody.replaceAll(tempID, Base36.encode(emailID));
234
+ updateEmail ||= html !== htmlBody;
235
+ entity.htmlBody = html;
238
236
  }
239
237
 
240
238
 
@@ -253,19 +251,29 @@ export default class EmailEvents extends AuthenticatedEvents<Email> {
253
251
  });
254
252
  }
255
253
 
254
+ let sentMessageID = entity.sentMessageID ?? null;
255
+
256
256
  if (entity.status === "scheduled") {
257
257
  entity.userID = this.sessionUser?.userID ?? void 0;
258
258
  const dateSent = DateTime.from(entity.dateSent);
259
259
  // insert a job in queue...
260
260
  const id = `send-email-${emailID}-${dateSent.msSinceEpoch.toString(36)}`;
261
261
  entity.workflowID = id;
262
+ sentMessageID = entity.headerMessageID;
263
+ updateEmail = true;
262
264
  await this.workflowContext.queue(PrepareEmailToSend, emailID, {
263
265
  eta: dateSent,
264
266
  id
265
267
  });
266
- if (!saveChangesCalled) {
267
- this.db.queuePostSaveTask(() => this.db.saveChangesWithoutEvents());
268
- }
268
+ }
269
+
270
+ if (updateEmail) {
271
+ await this.db.emails.where(entity, (p) => (x) => x.emailID === p.emailID)
272
+ .update(entity, (p) => (x) => ({
273
+ htmlBody: p.htmlBody,
274
+ workflowID: p.workflowID,
275
+ sentMessageID: p.sentMessageID
276
+ }));
269
277
  }
270
278
  }
271
279
 
@@ -104,6 +104,10 @@ const stripDuplicates = (addresses: IEmailRecipientInfo[]) => {
104
104
  return r;
105
105
  };
106
106
 
107
+ export interface IEmailInfo {
108
+ externalEmailID: string, labels: string[], mailbox: Mailbox, silent?: boolean,
109
+ messageId: string
110
+ };
107
111
 
108
112
  @RegisterScoped
109
113
  export default class EmailSerializerService {
@@ -135,20 +139,23 @@ export default class EmailSerializerService {
135
139
  @Inject
136
140
  private workflowContext: WorkflowContext;
137
141
 
138
- async saveRFC822(text: string, externalEmailID: string, labels: string[], mailbox: Mailbox, silent?: boolean) {
142
+ async saveRFC822(text: string, emailInfo: IEmailInfo) {
139
143
  const { tempFileService } = this;
140
144
  const file = await tempFileService.createTempFile(".eml", void 0, "message/rfc822");
141
145
  await writeFile(file.path, text, "utf8");
142
- await this.saveRFC822File(file, externalEmailID, labels, mailbox, silent);
146
+ await this.saveRFC822File(file, emailInfo);
143
147
  }
144
148
 
145
- async saveRFC822File(file: LocalFile, externalEmailID: string, labels: string[], mailbox: Mailbox, silent?: boolean) {
149
+ async saveRFC822File(file: LocalFile, emailInfo: IEmailInfo) {
150
+ const { externalEmailID, labels, mailbox, silent, messageId} = emailInfo;
146
151
  const { tempFileService, db } = this;
147
152
  // check if email already saved in same mailbox...
148
153
  const { mailboxID } = mailbox;
149
154
  if (externalEmailID) {
150
- const existing = await db.mailboxEmails.where({ mailboxID, externalEmailID}, (p) => (x) => x.mailboxID === p.mailboxID
155
+ const existing = await db.mailboxEmails.where({ mailboxID, externalEmailID, messageId }, (p) => (x) =>
156
+ (x.mailboxID === p.mailboxID
151
157
  && x.email.externalEmailID === p.externalEmailID)
158
+ || x.email.sentMessageID === p.messageId)
152
159
  .some();
153
160
 
154
161
  if (existing) {
@@ -197,7 +204,7 @@ export default class EmailSerializerService {
197
204
  const mime = mail.compile();
198
205
 
199
206
  const emailFile = await tempFileService.createFrom("harmful-email.zip", mime.createReadStream(), "message/rfc822");
200
- await this.saveRFC822File(emailFile, externalEmailID, labels, mailbox, silent);
207
+ await this.saveRFC822File(emailFile, emailInfo);
201
208
  return;
202
209
  }
203
210
  throw error;
@@ -219,7 +219,7 @@ export default class SyncMailboxWorkflow extends Workflow<any, any> {
219
219
 
220
220
  i++;
221
221
 
222
- const { emailID, uid, labels } = iterator;
222
+ const { emailID, uid, labels, messageId } = iterator;
223
223
  const cUID = BigInt(uid);
224
224
  if (cUID > currentLastUID && cUID < end) {
225
225
  currentLastUID = cUID;
@@ -255,7 +255,13 @@ export default class SyncMailboxWorkflow extends Workflow<any, any> {
255
255
  const result = await client.uidFetchRFC822(uid);
256
256
  syncState.progress = (BigInt(syncState.progress) + 1n).toString();
257
257
  // console.log(`Saving ${uid}`);
258
- await serializer.saveRFC822(result.rfc822, emailID, labels, target.mailbox, true);
258
+ await serializer.saveRFC822(result.rfc822, {
259
+ externalEmailID: emailID,
260
+ messageId,
261
+ labels,
262
+ mailbox: target.mailbox,
263
+ silent: true
264
+ });
259
265
  // console.log(`Saved ${uid}`);
260
266
  }
261
267
 
@@ -29,21 +29,41 @@ export default class extends Page {
29
29
  if (webSite) {
30
30
  // this is a static web site...
31
31
  // if path is empty... load /index.html....
32
+
33
+ let notFound = false;
34
+
32
35
  let path = this.childPath;
33
36
  if (!file) {
34
37
  path = ["index.html"];
35
38
  }
36
- const appFile = await this.websiteService.getSnapshotFile(webSite, path);
39
+ let appFile = await this.websiteService.getSnapshotFile(webSite, path);
37
40
  if (!appFile) {
38
41
  if (file === "favicon.ico") {
39
42
  this.cacheControl = "public, max-age=8600";
40
43
  return new FileResult(ImagesFolder.file("favicon.ico"));
41
44
  }
42
- return this.notFound();
45
+ if (file === "robots.txt") {
46
+ return this.notFound();
47
+ }
48
+ appFile = await this.websiteService.getSnapshotFile(webSite, ["index.html"]);
49
+ if (appFile === null) {
50
+ return this.notFound();
51
+ }
52
+ notFound = true;
43
53
  }
44
54
  delete appFile.fileContent;
45
55
  const tfs = ServiceProvider.resolve(this, TempFileService);
46
56
  const localFile = await tfs.downloadAppFile(appFile);
57
+ if (notFound) {
58
+ const body = await localFile.readAsText();
59
+ console.error(`404: ${this.request?.URL?.toString()}`);
60
+ return this.content({
61
+ body,
62
+ contentType: "text/html",
63
+ suppressLog: true,
64
+ status: 404
65
+ });
66
+ }
47
67
  return new TempFileResult(
48
68
  localFile,
49
69
  {