@social-mail/social-mail-client 1.2.9 → 1.2.11

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.
Files changed (40) hide show
  1. package/dist/admin/AdminAppIndex.pack.js +320 -17
  2. package/dist/admin/AdminAppIndex.pack.js.map +1 -1
  3. package/dist/admin/AdminAppIndex.pack.min.js +6 -6
  4. package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
  5. package/dist/common/pages/mailboxes/MailboxEditorPage.d.ts +0 -1
  6. package/dist/common/pages/mailboxes/MailboxEditorPage.d.ts.map +1 -1
  7. package/dist/common/pages/mailboxes/MailboxEditorPage.js +3 -8
  8. package/dist/common/pages/mailboxes/MailboxEditorPage.js.map +1 -1
  9. package/dist/common/pages/mailboxes/MailboxListPage.d.ts +1 -0
  10. package/dist/common/pages/mailboxes/MailboxListPage.d.ts.map +1 -1
  11. package/dist/common/pages/mailboxes/MailboxListPage.js +39 -4
  12. package/dist/common/pages/mailboxes/MailboxListPage.js.map +1 -1
  13. package/dist/common/pages/mailboxes/external-mailboxes/AddExternalMailboxPage.d.ts +22 -0
  14. package/dist/common/pages/mailboxes/external-mailboxes/AddExternalMailboxPage.d.ts.map +1 -0
  15. package/dist/common/pages/mailboxes/external-mailboxes/AddExternalMailboxPage.js +148 -0
  16. package/dist/common/pages/mailboxes/external-mailboxes/AddExternalMailboxPage.js.map +1 -0
  17. package/dist/common/pages/mailboxes/services/ExternalMailboxService.d.ts +22 -0
  18. package/dist/common/pages/mailboxes/services/ExternalMailboxService.d.ts.map +1 -0
  19. package/dist/common/pages/mailboxes/services/ExternalMailboxService.js +110 -0
  20. package/dist/common/pages/mailboxes/services/ExternalMailboxService.js.map +1 -0
  21. package/dist/common/pages/mailboxes/services/MailboxService.d.ts +1 -1
  22. package/dist/common/pages/mailboxes/services/MailboxService.d.ts.map +1 -1
  23. package/dist/common/pages/mailboxes/services/MailboxService.js +6 -2
  24. package/dist/common/pages/mailboxes/services/MailboxService.js.map +1 -1
  25. package/dist/model/model.d.ts +15 -1
  26. package/dist/model/model.d.ts.map +1 -1
  27. package/dist/model/model.js +7 -2
  28. package/dist/model/model.js.map +1 -1
  29. package/dist/tsconfig.tsbuildinfo +1 -1
  30. package/dist/web/AppIndex.pack.js +320 -17
  31. package/dist/web/AppIndex.pack.js.map +1 -1
  32. package/dist/web/AppIndex.pack.min.js +5 -5
  33. package/dist/web/AppIndex.pack.min.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/common/pages/mailboxes/MailboxEditorPage.tsx +3 -6
  36. package/src/common/pages/mailboxes/MailboxListPage.tsx +31 -4
  37. package/src/common/pages/mailboxes/external-mailboxes/AddExternalMailboxPage.tsx +125 -0
  38. package/src/common/pages/mailboxes/services/ExternalMailboxService.ts +111 -0
  39. package/src/common/pages/mailboxes/services/MailboxService.ts +6 -2
  40. package/src/model/model.ts +18 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-client",
3
- "version": "1.2.9",
3
+ "version": "1.2.11",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -22,14 +22,12 @@ export default class MailboxEditorPage extends PopupWindowPage {
22
22
 
23
23
  private model: IMailbox;
24
24
 
25
- private domain: IDomain = null;
26
-
27
25
  @InjectProperty
28
26
  private mailboxService: MailboxService;
29
27
 
30
28
  async init() {
31
29
 
32
- this.title = "Add Mailbox";
30
+ this.title = "Add Hosted Mailbox";
33
31
 
34
32
  this.model = this.parameters?.model ?? Mailbox.create({
35
33
  emailAddress: EmailAddress.create({
@@ -48,8 +46,7 @@ export default class MailboxEditorPage extends PopupWindowPage {
48
46
 
49
47
  this.model.username = "";
50
48
 
51
- const domains = await this.mailboxService.domains();
52
- this.model.domain = domains[0];
49
+ const domains = await this.mailboxService.domains(true);
53
50
 
54
51
  this.model.name = SocialMailApp.user.displayName;
55
52
 
@@ -66,7 +63,7 @@ export default class MailboxEditorPage extends PopupWindowPage {
66
63
  />
67
64
  </FormField>
68
65
  <FormField label="Email Address">
69
- <span text={Bind.oneWay(() => `${this.model.username}@${this.model.domain.domain}`)}/>
66
+ <span text={Bind.oneWay(() => `${this.model.username}@${this.model.domain.domain.name}`)}/>
70
67
  </FormField>
71
68
  <FormField label="Create Channel">
72
69
  <Checkbox
@@ -5,7 +5,7 @@ import { ContentPage, isMobileView } from "@web-atoms/web-controls/dist/mobile-a
5
5
  import InfiniteRepeater from "../../controls/repeater/InfiniteRepeater";
6
6
  import MailboxService from "./services/MailboxService";
7
7
  import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
8
- import { IDomain, IHostedDomain, IMailbox } from "../../../model/model";
8
+ import { Domain, HostedDomain, IDomain, IHostedDomain, IMailbox } from "../../../model/model";
9
9
  import Action from "@web-atoms/core/dist/view-model/Action";
10
10
  import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
11
11
  import MailboxEditorPage from "./MailboxEditorPage";
@@ -16,6 +16,9 @@ import styled from "@web-atoms/core/dist/style/styled";
16
16
  import MailboxDetailPage from "./MailboxDetailPage";
17
17
  import ComboBox from "@web-atoms/web-controls/dist/basic/ComboBox";
18
18
  import { Icon } from "../../icons/Icons";
19
+ import { InlinePopupButton } from "@web-atoms/web-controls/dist/basic/InlinePopup";
20
+ import { MenuItem } from "@web-atoms/web-controls/dist/basic/PopupButton";
21
+ import AddExternalMailboxPage from "./external-mailboxes/AddExternalMailboxPage";
19
22
 
20
23
  const css = styled.css `
21
24
  &[data-page-type=master-detail] > [data-page-element=content][data-mode=desktop] {
@@ -37,13 +40,16 @@ export default class MailboxListPage extends MasterDetailPage {
37
40
 
38
41
  private version = 0;
39
42
 
40
- private domainID: number;
43
+ private domainID: number = 0;
41
44
 
42
45
  async init() {
43
46
 
44
47
  this.domains = await this.mailboxService.domains();
45
48
 
46
- this.domainID = this.domains[0].domainID;
49
+ this.domains.insert(0, Domain.create({
50
+ name: "Any",
51
+ domainID: 0,
52
+ }));
47
53
 
48
54
  this.titleRenderer = () => <div data-layout="row">
49
55
  <ComboBox
@@ -52,12 +58,21 @@ export default class MailboxListPage extends MasterDetailPage {
52
58
  items={this.domains}
53
59
  value={Bind.twoWaysImmediate(() => this.domainID)}
54
60
  />
55
- <i class="fas fa-plus" data-click-event="add-mailbox"/>
61
+ { this.domains.length > 1
62
+ && <i class="fas fa-plus" data-click-event="add-mailbox"/> }
56
63
  </div>;
57
64
 
58
65
 
59
66
  this.headerRenderer = () => <div data-layout="row">
60
67
  <input value={Bind.twoWaysImmediate(() => this.search)}/>
68
+ <InlinePopupButton
69
+ icon="fas fa-plus"
70
+ label="Add"
71
+ popup={() => <div>
72
+ <MenuItem data-click-event="add-mailbox" label="Hosted Mailbox"/>
73
+ <MenuItem data-click-event="add-external-mailbox" label="External Mailbox"/>
74
+ </div>}
75
+ />
61
76
  </div>;
62
77
 
63
78
  this.renderer = <div>
@@ -104,6 +119,13 @@ export default class MailboxListPage extends MasterDetailPage {
104
119
 
105
120
  @Action({ onEvent: "add-mailbox"})
106
121
  async addMailbox() {
122
+
123
+ const domains = await this.mailboxService.domains(true);
124
+ if (!domains.length) {
125
+ alert("There are no hosted domains available, please create domain name from the admin console.");
126
+ return;
127
+ }
128
+
107
129
  await PageNavigator.pushPageForResult(MailboxEditorPage, { domainID: this.domainID });
108
130
  this.version++;
109
131
  }
@@ -113,4 +135,9 @@ export default class MailboxListPage extends MasterDetailPage {
113
135
  this.openDetail(MailboxDetailPage, mailbox);
114
136
  }
115
137
 
138
+ @Action({ onEvent: "add-external-mailbox"})
139
+ async addExternalMailbox() {
140
+ await PageNavigator.pushPageForResult(AddExternalMailboxPage);
141
+ }
142
+
116
143
  }
@@ -0,0 +1,125 @@
1
+ import Bind from "@web-atoms/core/dist/core/Bind";
2
+ import XNode from "@web-atoms/core/dist/core/XNode";
3
+ import Action from "@web-atoms/core/dist/view-model/Action";
4
+ import Form from "@web-atoms/web-controls/dist/basic/Form";
5
+ import FormField from "@web-atoms/web-controls/dist/basic/FormField";
6
+ import PasswordBox from "@web-atoms/web-controls/dist/basic/PasswordBox";
7
+ import { PopupWindowPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
8
+ import { AddIconButton } from "../../../controls/buttons/IconButton";
9
+ import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
10
+ import EntityService from "../../../../services/EntityService";
11
+ import { HostedDomain } from "../../../../model/model";
12
+ import ExternalMailboxService from "../services/ExternalMailboxService";
13
+ import Checkbox from "@web-atoms/web-controls/dist/basic/Checkbox";
14
+
15
+ export default class AddExternalMailboxPage extends PopupWindowPage {
16
+
17
+ model = {
18
+ emailAddress: "",
19
+ displayName: "",
20
+ imapHost: "",
21
+ imapPort: 993,
22
+ imapSecure: true,
23
+ smtpHost: "",
24
+ smtpPort: 465,
25
+ smtpSecure: true,
26
+ username: "",
27
+ password: "",
28
+ smtpUsername: "",
29
+ smtpPassword: ""
30
+ };
31
+
32
+ @InjectProperty
33
+ private externalMailboxService: ExternalMailboxService;
34
+
35
+ async init() {
36
+
37
+ this.title = "Add External Mailbox";
38
+
39
+ this.renderer = <div style-max-width="400px">
40
+ <div>
41
+ Use this form only if you do not own the domain of the email address.
42
+ If you plan to migrate domain back to this server, we recommend creating
43
+ hosted mailbox and add sync account to migrate your emails.
44
+ </div>
45
+ <hr/>
46
+ <Form>
47
+ <FormField label="Display/From Name">
48
+ <input
49
+ autofocus={true}
50
+ value={Bind.twoWaysImmediate(() => this.model.displayName)}/>
51
+ </FormField>
52
+ <FormField label="Email Address">
53
+ <input
54
+ value={Bind.twoWaysImmediate(() => this.model.emailAddress)}/>
55
+ </FormField>
56
+ <FormField label="Username">
57
+ <input value={Bind.twoWaysImmediate(() => this.model.username)}/>
58
+ </FormField>
59
+ <FormField label="Password">
60
+ <PasswordBox
61
+ value={Bind.twoWaysImmediate(() => this.model.password)}/>
62
+ </FormField>
63
+ <FormField label="IMAP (Server/Host)">
64
+ <input value={Bind.twoWaysImmediate(() => this.model.imapHost)}/>
65
+ </FormField>
66
+ <FormField label="IMAP Port">
67
+ <div data-layout="row">
68
+ <input value={Bind.twoWaysImmediate(() => this.model.imapPort)}/>
69
+ <Checkbox checked={Bind.twoWaysImmediate(() => this.model.imapSecure)} text="Secure"/>
70
+ </div>
71
+ </FormField>
72
+ <FormField label="SMTP (Server/Host)">
73
+ <input value={Bind.twoWaysImmediate(() => this.model.smtpHost)}/>
74
+ </FormField>
75
+ <FormField label="SMTP Port">
76
+ <div data-layout="row">
77
+ <input value={Bind.twoWaysImmediate(() => this.model.smtpPort)}/>
78
+ <Checkbox checked={Bind.twoWaysImmediate(() => this.model.smtpSecure)} text="Secure"/>
79
+ </div>
80
+ </FormField>
81
+ <div data-layout="sticky-command-row">
82
+ <AddIconButton
83
+ data-submit-event="add-new-mailbox"
84
+ text="Add Mailbox"
85
+ />
86
+ </div>
87
+ </Form>
88
+ </div>;
89
+
90
+ }
91
+
92
+ @Action({
93
+ onEvent: "input",
94
+ defer: 1000
95
+ })
96
+ async onInput() {
97
+ if(this.model.imapHost) {
98
+ return;
99
+ }
100
+ const { emailAddress } = this.model;
101
+ if(!emailAddress) {
102
+ return;
103
+ }
104
+ if (emailAddress.indexOf("@") === -1) {
105
+ return;
106
+ }
107
+ const domain = emailAddress.split("@").pop();
108
+ if (domain.length <= 5) {
109
+ return;
110
+ }
111
+
112
+ this.model.imapHost = `imap.${domain}`;
113
+ this.model.smtpHost = `smtp.${domain}`;
114
+ this.model.username = emailAddress;
115
+ }
116
+
117
+ @Action({
118
+ onEvent: "add-new-mailbox",
119
+ close: true
120
+ })
121
+ addNewMailbox() {
122
+ return this.externalMailboxService.createMailbox(this.model);
123
+ }
124
+
125
+ }
@@ -0,0 +1,111 @@
1
+ import DITransient from "@web-atoms/core/dist/di/DITransient";
2
+ import { Inject } from "@web-atoms/core/dist/di/Inject";
3
+ import EntityService from "../../../../services/EntityService";
4
+ import { Domain, HostedDomain, Mailbox, MailboxSyncTarget } from "../../../../model/model";
5
+ import DateTime from "@web-atoms/date-time/dist/DateTime";
6
+
7
+ export interface IExternalMailbox {
8
+ emailAddress: string,
9
+ displayName: string,
10
+ imapHost: string,
11
+ imapPort: number,
12
+ imapSecure: boolean,
13
+ smtpHost: string,
14
+ smtpPort: number,
15
+ smtpSecure: boolean,
16
+ username: string,
17
+ password: string,
18
+ smtpUsername: string,
19
+ smtpPassword: string
20
+ }
21
+
22
+ @DITransient()
23
+ export default class ExternalMailboxService {
24
+
25
+ @Inject
26
+ private entityService: EntityService;
27
+
28
+ public async createDomain(emailAddress: string, retry = 3): Promise<{ domainID?: number }> {
29
+ try {
30
+ const index = emailAddress.lastIndexOf("@");
31
+ let domainName = emailAddress;
32
+ if (index !== -1) {
33
+ domainName = emailAddress.substring(index + 1);
34
+ }
35
+ domainName = domainName.toLocaleLowerCase();
36
+ const d = await this.entityService.query(HostedDomain)
37
+ .where({ domainName }, (p) => (x) => x.domain.name === p.domainName)
38
+ .firstOrDefault();
39
+ if (d) {
40
+ return d;
41
+ }
42
+ const hd = HostedDomain.create({
43
+ domainNameToCreate: domainName,
44
+ external: true
45
+ });
46
+ return await this.entityService.save(hd);
47
+ } catch (error) {
48
+ if(retry--) {
49
+ return await this.createDomain(emailAddress, retry - 1);
50
+ }
51
+ throw error;
52
+ }
53
+ }
54
+
55
+ async createMailbox(model: IExternalMailbox) {
56
+ const {
57
+ emailAddress,
58
+ displayName: name,
59
+ username,
60
+ password,
61
+ imapHost,
62
+ imapPort,
63
+ imapSecure,
64
+ smtpHost,
65
+ smtpPort,
66
+ smtpSecure,
67
+ smtpUsername,
68
+ smtpPassword,
69
+ } = model;
70
+ const hd = await this.createDomain(emailAddress);
71
+
72
+ const dateCreated = DateTime.now;
73
+
74
+ const [ emailUsername ] = emailAddress.split("@");
75
+
76
+ const mb = Mailbox.create({
77
+ domainID: hd.domainID,
78
+ username: emailUsername,
79
+ name,
80
+ dateCreated,
81
+ dateUpdated: dateCreated,
82
+ indexAttachments: true,
83
+ indexImageAttachments: true,
84
+ syncTargets: [
85
+ MailboxSyncTarget.create({
86
+ protocol: "imap",
87
+ host: imapHost,
88
+ port: imapPort,
89
+ isSecure: imapSecure,
90
+ username,
91
+ newPassword: password,
92
+ direction: "in",
93
+ active: true
94
+ }),
95
+ MailboxSyncTarget.create({
96
+ protocol: "smtp" as any,
97
+ host: smtpHost,
98
+ port: smtpPort,
99
+ isSecure: smtpSecure,
100
+ username: smtpUsername || username,
101
+ newPassword: smtpPassword || password,
102
+ direction: "in",
103
+ active: true
104
+ })
105
+ ]
106
+ });
107
+
108
+ await this.entityService.save(mb);
109
+ }
110
+
111
+ }
@@ -11,8 +11,12 @@ export default class MailboxService {
11
11
  @Inject
12
12
  private entityService: EntityService;
13
13
 
14
- public async domains() {
15
- const hosted = await this.entityService.query(HostedDomain)
14
+ public async domains(onlyHosted = false) {
15
+ let q = this.entityService.query(HostedDomain);
16
+ if (onlyHosted) {
17
+ q = q.where({}, (p) => (x) => x.external === false);
18
+ }
19
+ const hosted = await q
16
20
  .include((x) => x.domain)
17
21
  .toArray();
18
22
  return hosted.map((x) => x.domain);
@@ -214,6 +214,7 @@ export interface IHostedDomain extends IClrEntity {
214
214
  enableReceive?: boolean;
215
215
  enableSend?: boolean;
216
216
  useRelay?: boolean;
217
+ external?: boolean;
217
218
  aliasForName?: string | null;
218
219
  domainNameToCreate?: string;
219
220
  domain?: IDomain;
@@ -227,7 +228,7 @@ export interface IHostedDomain extends IClrEntity {
227
228
  templates?: ICollection<IEmailTemplate>;
228
229
  }
229
230
 
230
- export const HostedDomain: IModel<IHostedDomain> = new Model<IHostedDomain>("HostedDomain", ["domainID"], { enableReceive: false,enableSend: false,useRelay: false });
231
+ export const HostedDomain: IModel<IHostedDomain> = new Model<IHostedDomain>("HostedDomain", ["domainID"], { enableReceive: false,enableSend: false,useRelay: false,external: false });
231
232
 
232
233
  export interface IDomainUser extends IClrEntity {
233
234
  domainID?: number;
@@ -294,6 +295,7 @@ export interface IEmail extends IClrEntity {
294
295
  parentID?: number | null;
295
296
  forwardedID?: number | null;
296
297
  engagement?: string | null;
298
+ tags?: string | null;
297
299
  htmlBodyUrl?: string;
298
300
  senderEmail?: IEmailAddress;
299
301
  senderUser?: IUser;
@@ -306,7 +308,7 @@ export interface IEmail extends IClrEntity {
306
308
  engagements?: ICollection<IEmailEngagement>;
307
309
  logs?: ICollection<IAppLog>;
308
310
  recipients?: ICollection<IEmailRecipient>;
309
- tags?: ICollection<IEmailTag>;
311
+ emailTags?: ICollection<IEmailTag>;
310
312
  mailboxes?: ICollection<IMailboxEmail>;
311
313
  lastEmailThreads?: ICollection<IMailboxContact>;
312
314
  threadEmails?: ICollection<IMailboxContactEmail>;
@@ -458,6 +460,7 @@ export interface IMailboxContact extends IClrEntity {
458
460
  mailbox?: IMailbox;
459
461
  emailAddress?: IEmailAddress;
460
462
  lastEmail?: IEmail;
463
+ tags?: ICollection<IMailboxContactTag>;
461
464
  }
462
465
 
463
466
  export const MailboxContactStatusArray = [{"label":"invited","value":"invited"},{"label":"added","value":"added"},{"label":"active","value":"active"},{"label":"unsubscribed","value":"unsubscribed"},{"label":"blocked","value":"blocked"}];
@@ -477,6 +480,18 @@ export interface IMailboxContactEmail extends IClrEntity {
477
480
 
478
481
  export const MailboxContactEmail: IModel<IMailboxContactEmail> = new Model<IMailboxContactEmail>("MailboxContactEmail", ["mailboxID","emailAddressID","emailID"], { dateReceived: new DefaultFactory(() => new DateTime()) });
479
482
 
483
+ export interface IMailboxContactTag extends IClrEntity {
484
+ mailboxID?: number;
485
+ emailAddressID?: number;
486
+ tagID?: number;
487
+ count?: number;
488
+ dateUpdated?: DateTime;
489
+ tag?: ITag;
490
+ mailboxContact?: IMailboxContact;
491
+ }
492
+
493
+ export const MailboxContactTag: IModel<IMailboxContactTag> = new Model<IMailboxContactTag>("MailboxContactTag", ["mailboxID","emailAddressID","tagID"], { count: 0,dateUpdated: new DefaultFactory(() => new DateTime()) });
494
+
480
495
  export interface IMailboxSyncTarget extends IClrEntity {
481
496
  readonly syncTargetID?: number;
482
497
  mailboxID?: number;
@@ -698,6 +713,7 @@ export interface ITag extends IClrEntity {
698
713
  children?: ICollection<ITag>;
699
714
  fileTags?: ICollection<IAppFileTag>;
700
715
  emailTags?: ICollection<IEmailTag>;
716
+ mailboxContactTags?: ICollection<IMailboxContactTag>;
701
717
  }
702
718
 
703
719
  export const Tag: IModel<ITag> = new Model<ITag>("Tag", ["tagID"], { name: "",isSystemTag: false });