@geekmidas/emailkit 0.0.5 → 0.0.7

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,5 +1,5 @@
1
+ import { render } from "@react-email/components";
1
2
  import nodemailer from "nodemailer";
2
- import { renderToStaticMarkup } from "react-dom/server";
3
3
 
4
4
  //#region src/client.ts
5
5
  var SMTPClient = class {
@@ -14,6 +14,7 @@ var SMTPClient = class {
14
14
  ...this.config.defaults,
15
15
  ...options
16
16
  };
17
+ if (!mailOptions.from) throw new Error("The \"from\" field is required in email options or defaults");
17
18
  if (!mailOptions.text && !mailOptions.html) throw new Error("Either text or html content must be provided");
18
19
  const info = await this.transporter.sendMail(mailOptions);
19
20
  return {
@@ -24,10 +25,10 @@ var SMTPClient = class {
24
25
  };
25
26
  }
26
27
  async sendTemplate(template, options) {
27
- const templateFn = this.config.templates[template];
28
- if (!templateFn) throw new Error(`Template "${String(template)}" not found`);
29
- const element = templateFn(options.props);
30
- const html = renderToStaticMarkup(element);
28
+ const Component = this.config.templates[template];
29
+ if (!Component) throw new Error(`Template "${String(template)}" not found`);
30
+ const element = Component(options.props);
31
+ const html = await render(element);
31
32
  return this.send({
32
33
  ...options,
33
34
  html
@@ -53,4 +54,5 @@ function createEmailClient(config) {
53
54
  }
54
55
 
55
56
  //#endregion
56
- export { SMTPClient, createEmailClient };
57
+ export { SMTPClient, createEmailClient };
58
+ //# sourceMappingURL=client-BkN5BGeJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-BkN5BGeJ.mjs","names":["config: EmailClientConfig<T>","options: SendOptions","template: K","options: Omit<SendOptions, 'template'> & {\n props: TemplatePropsFor<T, K>;\n }"],"sources":["../src/client.ts"],"sourcesContent":["import { render } from '@react-email/components';\nimport nodemailer, { type Transporter } from 'nodemailer';\nimport type {\n EmailClient,\n EmailClientConfig,\n SendOptions,\n SendResult,\n TemplateNames,\n TemplatePropsFor,\n TemplateRecord,\n} from './types';\n\nexport class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {\n private transporter: Transporter;\n private config: EmailClientConfig<T>;\n\n constructor(config: EmailClientConfig<T>) {\n this.config = config;\n this.transporter = nodemailer.createTransport(config.smtp as any);\n }\n\n async send(options: SendOptions): Promise<SendResult> {\n const mailOptions = {\n ...this.config.defaults,\n ...options,\n };\n\n if (!mailOptions.from) {\n throw new Error(\n 'The \"from\" field is required in email options or defaults',\n );\n }\n\n if (!mailOptions.text && !mailOptions.html) {\n throw new Error('Either text or html content must be provided');\n }\n\n const info = await this.transporter.sendMail(mailOptions);\n\n return {\n messageId: info.messageId,\n accepted: info.accepted || [],\n rejected: info.rejected || [],\n response: info.response,\n };\n }\n\n async sendTemplate<K extends TemplateNames<T>>(\n template: K,\n options: Omit<SendOptions, 'template'> & {\n props: TemplatePropsFor<T, K>;\n },\n ): Promise<SendResult> {\n const Component = this.config.templates[template];\n if (!Component) {\n throw new Error(`Template \"${String(template)}\" not found`);\n }\n\n const element = Component(options.props);\n const html = await render(element);\n\n return this.send({\n ...options,\n html,\n });\n }\n\n async verify(): Promise<boolean> {\n try {\n await this.transporter.verify();\n return true;\n } catch {\n return false;\n }\n }\n\n async close(): Promise<void> {\n this.transporter.close();\n }\n\n getTemplateNames(): TemplateNames<T>[] {\n return Object.keys(this.config.templates) as TemplateNames<T>[];\n }\n}\n\nexport function createEmailClient<T extends TemplateRecord>(\n config: EmailClientConfig<T>,\n): SMTPClient<T> {\n return new SMTPClient(config);\n}\n"],"mappings":";;;;AAYA,IAAa,aAAb,MAA4E;CAC1E,AAAQ;CACR,AAAQ;CAER,YAAYA,QAA8B;AACxC,OAAK,SAAS;AACd,OAAK,cAAc,WAAW,gBAAgB,OAAO,KAAY;CAClE;CAED,MAAM,KAAKC,SAA2C;EACpD,MAAM,cAAc;GAClB,GAAG,KAAK,OAAO;GACf,GAAG;EACJ;AAED,OAAK,YAAY,KACf,OAAM,IAAI,MACR;AAIJ,OAAK,YAAY,SAAS,YAAY,KACpC,OAAM,IAAI,MAAM;EAGlB,MAAM,OAAO,MAAM,KAAK,YAAY,SAAS,YAAY;AAEzD,SAAO;GACL,WAAW,KAAK;GAChB,UAAU,KAAK,YAAY,CAAE;GAC7B,UAAU,KAAK,YAAY,CAAE;GAC7B,UAAU,KAAK;EAChB;CACF;CAED,MAAM,aACJC,UACAC,SAGqB;EACrB,MAAM,YAAY,KAAK,OAAO,UAAU;AACxC,OAAK,UACH,OAAM,IAAI,OAAO,YAAY,OAAO,SAAS,CAAC;EAGhD,MAAM,UAAU,UAAU,QAAQ,MAAM;EACxC,MAAM,OAAO,MAAM,OAAO,QAAQ;AAElC,SAAO,KAAK,KAAK;GACf,GAAG;GACH;EACD,EAAC;CACH;CAED,MAAM,SAA2B;AAC/B,MAAI;AACF,SAAM,KAAK,YAAY,QAAQ;AAC/B,UAAO;EACR,QAAO;AACN,UAAO;EACR;CACF;CAED,MAAM,QAAuB;AAC3B,OAAK,YAAY,OAAO;CACzB;CAED,mBAAuC;AACrC,SAAO,OAAO,KAAK,KAAK,OAAO,UAAU;CAC1C;AACF;AAED,SAAgB,kBACdH,QACe;AACf,QAAO,IAAI,WAAW;AACvB"}
@@ -1,4 +1,4 @@
1
- import { EmailClient, EmailClientConfig, EmailOptions, SendOptions, SendResult, TemplateNames, TemplatePropsFor, TemplateRecord } from "./types-DSf2ldGX.mjs";
1
+ import { EmailClient, EmailClientConfig, SendOptions, SendResult, TemplateNames, TemplatePropsFor, TemplateRecord } from "./types-DJ4UGqFX.mjs";
2
2
 
3
3
  //#region src/client.d.ts
4
4
  declare class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
@@ -6,7 +6,7 @@ declare class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
6
6
  private config;
7
7
  constructor(config: EmailClientConfig<T>);
8
8
  send(options: SendOptions): Promise<SendResult>;
9
- sendTemplate<K extends TemplateNames<T>>(template: K, options: Omit<EmailOptions, 'template'> & {
9
+ sendTemplate<K extends TemplateNames<T>>(template: K, options: Omit<SendOptions, 'template'> & {
10
10
  props: TemplatePropsFor<T, K>;
11
11
  }): Promise<SendResult>;
12
12
  verify(): Promise<boolean>;
@@ -15,4 +15,5 @@ declare class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
15
15
  }
16
16
  declare function createEmailClient<T extends TemplateRecord>(config: EmailClientConfig<T>): SMTPClient<T>;
17
17
  //#endregion
18
- export { SMTPClient, createEmailClient };
18
+ export { SMTPClient, createEmailClient };
19
+ //# sourceMappingURL=client-C6OqJtD1.d.mts.map
@@ -1,4 +1,4 @@
1
- import { EmailClient, EmailClientConfig, EmailOptions, SendOptions, SendResult, TemplateNames, TemplatePropsFor, TemplateRecord } from "./types-BQX9cJo1.cjs";
1
+ import { EmailClient, EmailClientConfig, SendOptions, SendResult, TemplateNames, TemplatePropsFor, TemplateRecord } from "./types-BTcAZ0B-.cjs";
2
2
 
3
3
  //#region src/client.d.ts
4
4
  declare class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
@@ -6,7 +6,7 @@ declare class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
6
6
  private config;
7
7
  constructor(config: EmailClientConfig<T>);
8
8
  send(options: SendOptions): Promise<SendResult>;
9
- sendTemplate<K extends TemplateNames<T>>(template: K, options: Omit<EmailOptions, 'template'> & {
9
+ sendTemplate<K extends TemplateNames<T>>(template: K, options: Omit<SendOptions, 'template'> & {
10
10
  props: TemplatePropsFor<T, K>;
11
11
  }): Promise<SendResult>;
12
12
  verify(): Promise<boolean>;
@@ -15,4 +15,5 @@ declare class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
15
15
  }
16
16
  declare function createEmailClient<T extends TemplateRecord>(config: EmailClientConfig<T>): SMTPClient<T>;
17
17
  //#endregion
18
- export { SMTPClient, createEmailClient };
18
+ export { SMTPClient, createEmailClient };
19
+ //# sourceMappingURL=client-CgQM19MQ.d.cts.map
@@ -21,8 +21,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  }) : target, mod));
22
22
 
23
23
  //#endregion
24
+ const __react_email_components = __toESM(require("@react-email/components"));
24
25
  const nodemailer = __toESM(require("nodemailer"));
25
- const react_dom_server = __toESM(require("react-dom/server"));
26
26
 
27
27
  //#region src/client.ts
28
28
  var SMTPClient = class {
@@ -37,6 +37,7 @@ var SMTPClient = class {
37
37
  ...this.config.defaults,
38
38
  ...options
39
39
  };
40
+ if (!mailOptions.from) throw new Error("The \"from\" field is required in email options or defaults");
40
41
  if (!mailOptions.text && !mailOptions.html) throw new Error("Either text or html content must be provided");
41
42
  const info = await this.transporter.sendMail(mailOptions);
42
43
  return {
@@ -47,10 +48,10 @@ var SMTPClient = class {
47
48
  };
48
49
  }
49
50
  async sendTemplate(template, options) {
50
- const templateFn = this.config.templates[template];
51
- if (!templateFn) throw new Error(`Template "${String(template)}" not found`);
52
- const element = templateFn(options.props);
53
- const html = (0, react_dom_server.renderToStaticMarkup)(element);
51
+ const Component = this.config.templates[template];
52
+ if (!Component) throw new Error(`Template "${String(template)}" not found`);
53
+ const element = Component(options.props);
54
+ const html = await (0, __react_email_components.render)(element);
54
55
  return this.send({
55
56
  ...options,
56
57
  html
@@ -82,15 +83,10 @@ Object.defineProperty(exports, 'SMTPClient', {
82
83
  return SMTPClient;
83
84
  }
84
85
  });
85
- Object.defineProperty(exports, '__toESM', {
86
- enumerable: true,
87
- get: function () {
88
- return __toESM;
89
- }
90
- });
91
86
  Object.defineProperty(exports, 'createEmailClient', {
92
87
  enumerable: true,
93
88
  get: function () {
94
89
  return createEmailClient;
95
90
  }
96
- });
91
+ });
92
+ //# sourceMappingURL=client-sZNHPYYg.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-sZNHPYYg.cjs","names":["config: EmailClientConfig<T>","options: SendOptions","template: K","options: Omit<SendOptions, 'template'> & {\n props: TemplatePropsFor<T, K>;\n }"],"sources":["../src/client.ts"],"sourcesContent":["import { render } from '@react-email/components';\nimport nodemailer, { type Transporter } from 'nodemailer';\nimport type {\n EmailClient,\n EmailClientConfig,\n SendOptions,\n SendResult,\n TemplateNames,\n TemplatePropsFor,\n TemplateRecord,\n} from './types';\n\nexport class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {\n private transporter: Transporter;\n private config: EmailClientConfig<T>;\n\n constructor(config: EmailClientConfig<T>) {\n this.config = config;\n this.transporter = nodemailer.createTransport(config.smtp as any);\n }\n\n async send(options: SendOptions): Promise<SendResult> {\n const mailOptions = {\n ...this.config.defaults,\n ...options,\n };\n\n if (!mailOptions.from) {\n throw new Error(\n 'The \"from\" field is required in email options or defaults',\n );\n }\n\n if (!mailOptions.text && !mailOptions.html) {\n throw new Error('Either text or html content must be provided');\n }\n\n const info = await this.transporter.sendMail(mailOptions);\n\n return {\n messageId: info.messageId,\n accepted: info.accepted || [],\n rejected: info.rejected || [],\n response: info.response,\n };\n }\n\n async sendTemplate<K extends TemplateNames<T>>(\n template: K,\n options: Omit<SendOptions, 'template'> & {\n props: TemplatePropsFor<T, K>;\n },\n ): Promise<SendResult> {\n const Component = this.config.templates[template];\n if (!Component) {\n throw new Error(`Template \"${String(template)}\" not found`);\n }\n\n const element = Component(options.props);\n const html = await render(element);\n\n return this.send({\n ...options,\n html,\n });\n }\n\n async verify(): Promise<boolean> {\n try {\n await this.transporter.verify();\n return true;\n } catch {\n return false;\n }\n }\n\n async close(): Promise<void> {\n this.transporter.close();\n }\n\n getTemplateNames(): TemplateNames<T>[] {\n return Object.keys(this.config.templates) as TemplateNames<T>[];\n }\n}\n\nexport function createEmailClient<T extends TemplateRecord>(\n config: EmailClientConfig<T>,\n): SMTPClient<T> {\n return new SMTPClient(config);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,IAAa,aAAb,MAA4E;CAC1E,AAAQ;CACR,AAAQ;CAER,YAAYA,QAA8B;AACxC,OAAK,SAAS;AACd,OAAK,cAAc,mBAAW,gBAAgB,OAAO,KAAY;CAClE;CAED,MAAM,KAAKC,SAA2C;EACpD,MAAM,cAAc;GAClB,GAAG,KAAK,OAAO;GACf,GAAG;EACJ;AAED,OAAK,YAAY,KACf,OAAM,IAAI,MACR;AAIJ,OAAK,YAAY,SAAS,YAAY,KACpC,OAAM,IAAI,MAAM;EAGlB,MAAM,OAAO,MAAM,KAAK,YAAY,SAAS,YAAY;AAEzD,SAAO;GACL,WAAW,KAAK;GAChB,UAAU,KAAK,YAAY,CAAE;GAC7B,UAAU,KAAK,YAAY,CAAE;GAC7B,UAAU,KAAK;EAChB;CACF;CAED,MAAM,aACJC,UACAC,SAGqB;EACrB,MAAM,YAAY,KAAK,OAAO,UAAU;AACxC,OAAK,UACH,OAAM,IAAI,OAAO,YAAY,OAAO,SAAS,CAAC;EAGhD,MAAM,UAAU,UAAU,QAAQ,MAAM;EACxC,MAAM,OAAO,MAAM,qCAAO,QAAQ;AAElC,SAAO,KAAK,KAAK;GACf,GAAG;GACH;EACD,EAAC;CACH;CAED,MAAM,SAA2B;AAC/B,MAAI;AACF,SAAM,KAAK,YAAY,QAAQ;AAC/B,UAAO;EACR,QAAO;AACN,UAAO;EACR;CACF;CAED,MAAM,QAAuB;AAC3B,OAAK,YAAY,OAAO;CACzB;CAED,mBAAuC;AACrC,SAAO,OAAO,KAAK,KAAK,OAAO,UAAU;CAC1C;AACF;AAED,SAAgB,kBACdH,QACe;AACf,QAAO,IAAI,WAAW;AACvB"}
package/dist/client.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_client = require('./client-Dc4Thg_P.cjs');
1
+ const require_client = require('./client-sZNHPYYg.cjs');
2
2
 
3
3
  exports.SMTPClient = require_client.SMTPClient;
4
4
  exports.createEmailClient = require_client.createEmailClient;
package/dist/client.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- import "./types-BQX9cJo1.cjs";
2
- import { SMTPClient, createEmailClient } from "./client-Dm7WOF9y.cjs";
1
+ import "./types-BTcAZ0B-.cjs";
2
+ import { SMTPClient, createEmailClient } from "./client-CgQM19MQ.cjs";
3
3
  export { SMTPClient, createEmailClient };
package/dist/client.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import "./types-DSf2ldGX.mjs";
2
- import { SMTPClient, createEmailClient } from "./client-CEgPwECo.mjs";
1
+ import "./types-DJ4UGqFX.mjs";
2
+ import { SMTPClient, createEmailClient } from "./client-C6OqJtD1.mjs";
3
3
  export { SMTPClient, createEmailClient };
package/dist/client.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { SMTPClient, createEmailClient } from "./client-B7LjRjRM.mjs";
1
+ import { SMTPClient, createEmailClient } from "./client-BkN5BGeJ.mjs";
2
2
 
3
3
  export { SMTPClient, createEmailClient };
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_client = require('./client-Dc4Thg_P.cjs');
1
+ const require_client = require('./client-sZNHPYYg.cjs');
2
2
 
3
3
  exports.SMTPClient = require_client.SMTPClient;
4
4
  exports.createEmailClient = require_client.createEmailClient;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendResult } from "./types-BQX9cJo1.cjs";
2
- import { SMTPClient, createEmailClient } from "./client-Dm7WOF9y.cjs";
1
+ import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendResult } from "./types-BTcAZ0B-.cjs";
2
+ import { SMTPClient, createEmailClient } from "./client-CgQM19MQ.cjs";
3
3
  export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPClient, SMTPConfig, SendResult, createEmailClient };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendResult } from "./types-DSf2ldGX.mjs";
2
- import { SMTPClient, createEmailClient } from "./client-CEgPwECo.mjs";
1
+ import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendResult } from "./types-DJ4UGqFX.mjs";
2
+ import { SMTPClient, createEmailClient } from "./client-C6OqJtD1.mjs";
3
3
  export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPClient, SMTPConfig, SendResult, createEmailClient };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { SMTPClient, createEmailClient } from "./client-B7LjRjRM.mjs";
1
+ import { SMTPClient, createEmailClient } from "./client-BkN5BGeJ.mjs";
2
2
 
3
3
  export { SMTPClient, createEmailClient };
@@ -60,6 +60,11 @@ type TemplatePropsFor<T extends TemplateRecord, K extends TemplateNames<T>> = Te
60
60
  interface EmailClientConfig<T extends TemplateRecord = TemplateRecord> {
61
61
  smtp: SMTPConfig;
62
62
  templates: T;
63
+ dkim?: {
64
+ domainName: string;
65
+ keySelector: string;
66
+ privateKey: string;
67
+ };
63
68
  defaults: {
64
69
  from?: string | Address;
65
70
  replyTo?: string | Address;
@@ -67,12 +72,12 @@ interface EmailClientConfig<T extends TemplateRecord = TemplateRecord> {
67
72
  }
68
73
  interface EmailClient<T extends TemplateRecord = TemplateRecord> {
69
74
  send(options: SendOptions): Promise<SendResult>;
70
- sendTemplate<K extends TemplateNames<T>>(template: K, options: Omit<EmailOptions, 'from'> & {
71
- from?: string | Address;
75
+ sendTemplate<K extends TemplateNames<T>>(template: K, options: SendOptions & {
72
76
  props: TemplatePropsFor<T, K>;
73
77
  }): Promise<SendResult>;
74
78
  verify(): Promise<boolean>;
75
79
  close(): Promise<void>;
76
80
  }
77
81
  //#endregion
78
- export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord };
82
+ export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord };
83
+ //# sourceMappingURL=types-BTcAZ0B-.d.cts.map
@@ -1,5 +1,5 @@
1
- import { ReactElement } from "react";
2
1
  import { Address } from "nodemailer/lib/mailer";
2
+ import { ReactElement } from "react";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  interface EmailOptions {
@@ -60,6 +60,11 @@ type TemplatePropsFor<T extends TemplateRecord, K extends TemplateNames<T>> = Te
60
60
  interface EmailClientConfig<T extends TemplateRecord = TemplateRecord> {
61
61
  smtp: SMTPConfig;
62
62
  templates: T;
63
+ dkim?: {
64
+ domainName: string;
65
+ keySelector: string;
66
+ privateKey: string;
67
+ };
63
68
  defaults: {
64
69
  from?: string | Address;
65
70
  replyTo?: string | Address;
@@ -67,12 +72,12 @@ interface EmailClientConfig<T extends TemplateRecord = TemplateRecord> {
67
72
  }
68
73
  interface EmailClient<T extends TemplateRecord = TemplateRecord> {
69
74
  send(options: SendOptions): Promise<SendResult>;
70
- sendTemplate<K extends TemplateNames<T>>(template: K, options: Omit<EmailOptions, 'from'> & {
71
- from?: string | Address;
75
+ sendTemplate<K extends TemplateNames<T>>(template: K, options: SendOptions & {
72
76
  props: TemplatePropsFor<T, K>;
73
77
  }): Promise<SendResult>;
74
78
  verify(): Promise<boolean>;
75
79
  close(): Promise<void>;
76
80
  }
77
81
  //#endregion
78
- export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord };
82
+ export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord };
83
+ //# sourceMappingURL=types-DJ4UGqFX.d.mts.map
package/dist/types.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord } from "./types-BQX9cJo1.cjs";
1
+ import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord } from "./types-BTcAZ0B-.cjs";
2
2
  export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord };
package/dist/types.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord } from "./types-DSf2ldGX.mjs";
1
+ import { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord } from "./types-DJ4UGqFX.mjs";
2
2
  export { Attachment, EmailClient, EmailClientConfig, EmailOptions, EmailTemplate, PlainEmailOptions, SMTPConfig, SendOptions, SendResult, TemplateNames, TemplateProps, TemplatePropsFor, TemplateRecord };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/emailkit",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Type-safe email client with SMTP support and React templates",
5
5
  "private": false,
6
6
  "type": "module",
@@ -19,7 +19,6 @@
19
19
  "nodemailer": "^6.9.7"
20
20
  },
21
21
  "devDependencies": {
22
- "@types/node": "^22.0.0",
23
22
  "@types/nodemailer": "^6.4.14",
24
23
  "@types/react": "^18.2.0",
25
24
  "@types/react-dom": "^18.2.0",
@@ -29,7 +28,8 @@
29
28
  },
30
29
  "peerDependencies": {
31
30
  "react": ">=18.0.0",
32
- "react-dom": ">=18.0.0"
31
+ "react-dom": ">=18.0.0",
32
+ "@react-email/components": "~1.0.1"
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=22.0.0"
package/src/client.ts CHANGED
@@ -1,9 +1,8 @@
1
+ import { render } from '@react-email/components';
1
2
  import nodemailer, { type Transporter } from 'nodemailer';
2
- import { renderToStaticMarkup } from 'react-dom/server';
3
3
  import type {
4
4
  EmailClient,
5
5
  EmailClientConfig,
6
- EmailOptions,
7
6
  SendOptions,
8
7
  SendResult,
9
8
  TemplateNames,
@@ -26,6 +25,12 @@ export class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
26
25
  ...options,
27
26
  };
28
27
 
28
+ if (!mailOptions.from) {
29
+ throw new Error(
30
+ 'The "from" field is required in email options or defaults',
31
+ );
32
+ }
33
+
29
34
  if (!mailOptions.text && !mailOptions.html) {
30
35
  throw new Error('Either text or html content must be provided');
31
36
  }
@@ -42,17 +47,17 @@ export class SMTPClient<T extends TemplateRecord> implements EmailClient<T> {
42
47
 
43
48
  async sendTemplate<K extends TemplateNames<T>>(
44
49
  template: K,
45
- options: Omit<EmailOptions, 'template'> & {
50
+ options: Omit<SendOptions, 'template'> & {
46
51
  props: TemplatePropsFor<T, K>;
47
52
  },
48
53
  ): Promise<SendResult> {
49
- const templateFn = this.config.templates[template];
50
- if (!templateFn) {
54
+ const Component = this.config.templates[template];
55
+ if (!Component) {
51
56
  throw new Error(`Template "${String(template)}" not found`);
52
57
  }
53
58
 
54
- const element = templateFn(options.props);
55
- const html = renderToStaticMarkup(element);
59
+ const element = Component(options.props);
60
+ const html = await render(element);
56
61
 
57
62
  return this.send({
58
63
  ...options,
package/src/types.ts CHANGED
@@ -77,6 +77,11 @@ export type TemplatePropsFor<
77
77
  export interface EmailClientConfig<T extends TemplateRecord = TemplateRecord> {
78
78
  smtp: SMTPConfig;
79
79
  templates: T;
80
+ dkim?: {
81
+ domainName: string;
82
+ keySelector: string;
83
+ privateKey: string;
84
+ };
80
85
  defaults: {
81
86
  from?: string | Address;
82
87
  replyTo?: string | Address;
@@ -87,8 +92,7 @@ export interface EmailClient<T extends TemplateRecord = TemplateRecord> {
87
92
  send(options: SendOptions): Promise<SendResult>;
88
93
  sendTemplate<K extends TemplateNames<T>>(
89
94
  template: K,
90
- options: Omit<EmailOptions, 'from'> & {
91
- from?: string | Address;
95
+ options: SendOptions & {
92
96
  props: TemplatePropsFor<T, K>;
93
97
  },
94
98
  ): Promise<SendResult>;
@@ -1,150 +0,0 @@
1
- const require_client = require('../client-Dc4Thg_P.cjs');
2
- require("react");
3
- const vitest = require_client.__toESM(require("vitest"));
4
- const react_jsx_runtime = require_client.__toESM(require("react/jsx-runtime"));
5
-
6
- //#region src/__tests__/client.spec.tsx
7
- vitest.vi.mock("nodemailer", () => ({ default: { createTransport: vitest.vi.fn(() => ({
8
- sendMail: vitest.vi.fn().mockResolvedValue({
9
- messageId: "test-message-id",
10
- accepted: ["test@example.com"],
11
- rejected: [],
12
- response: "250 OK"
13
- }),
14
- verify: vitest.vi.fn().mockResolvedValue(true),
15
- close: vitest.vi.fn()
16
- })) } }));
17
- const TestTemplate = ({ name }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
18
- "Hello ",
19
- name,
20
- "!"
21
- ] });
22
- const AnotherTemplate = ({ title, message }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: message })] });
23
- (0, vitest.describe)("SMTPClient", () => {
24
- let client;
25
- const templates = {
26
- test: TestTemplate,
27
- another: AnotherTemplate
28
- };
29
- const config = {
30
- smtp: {
31
- host: "smtp.example.com",
32
- port: 587,
33
- auth: {
34
- user: "test@example.com",
35
- pass: "password"
36
- }
37
- },
38
- templates,
39
- defaults: { from: "noreply@example.com" }
40
- };
41
- (0, vitest.beforeEach)(() => {
42
- client = require_client.createEmailClient(config);
43
- });
44
- (0, vitest.describe)("send", () => {
45
- (0, vitest.it)("should send plain text email", async () => {
46
- const result = await client.send({
47
- from: "sender@example.com",
48
- to: "recipient@example.com",
49
- subject: "Test Email",
50
- text: "This is a test email"
51
- });
52
- (0, vitest.expect)(result).toEqual({
53
- messageId: "test-message-id",
54
- accepted: ["test@example.com"],
55
- rejected: [],
56
- response: "250 OK"
57
- });
58
- });
59
- (0, vitest.it)("should send HTML email", async () => {
60
- const result = await client.send({
61
- from: "sender@example.com",
62
- to: "recipient@example.com",
63
- subject: "Test Email",
64
- html: "<p>This is a test email</p>"
65
- });
66
- (0, vitest.expect)(result.messageId).toBe("test-message-id");
67
- });
68
- (0, vitest.it)("should use default from address", async () => {
69
- const result = await client.send({
70
- to: "recipient@example.com",
71
- subject: "Test Email",
72
- text: "This is a test email",
73
- from: {
74
- name: "Test Sender",
75
- address: "sender@example.com"
76
- }
77
- });
78
- (0, vitest.expect)(result.messageId).toBe("test-message-id");
79
- });
80
- (0, vitest.it)("should throw error if no content provided", async () => {
81
- await (0, vitest.expect)(client.send({
82
- from: "sender@example.com",
83
- to: "recipient@example.com",
84
- subject: "Test Email"
85
- })).rejects.toThrow("Either text or html content must be provided");
86
- });
87
- (0, vitest.it)("should support multiple recipients", async () => {
88
- const result = await client.send({
89
- from: "sender@example.com",
90
- to: ["recipient1@example.com", "recipient2@example.com"],
91
- subject: "Test Email",
92
- text: "This is a test email"
93
- });
94
- (0, vitest.expect)(result.messageId).toBe("test-message-id");
95
- });
96
- (0, vitest.it)("should support CC and BCC", async () => {
97
- const result = await client.send({
98
- from: "sender@example.com",
99
- to: "recipient@example.com",
100
- cc: "cc@example.com",
101
- bcc: ["bcc1@example.com", "bcc2@example.com"],
102
- subject: "Test Email",
103
- text: "This is a test email"
104
- });
105
- (0, vitest.expect)(result.messageId).toBe("test-message-id");
106
- });
107
- });
108
- (0, vitest.describe)("sendTemplate", () => {
109
- (0, vitest.it)("should send email with React template", async () => {
110
- const result = await client.sendTemplate("test", {
111
- from: "sender@example.com",
112
- to: "recipient@example.com",
113
- subject: "Test Template Email",
114
- props: { name: "John" }
115
- });
116
- (0, vitest.expect)(result.messageId).toBe("test-message-id");
117
- });
118
- (0, vitest.it)("should send email with another template", async () => {
119
- const result = await client.sendTemplate("another", {
120
- from: "sender@example.com",
121
- to: "recipient@example.com",
122
- subject: "Another Template Email",
123
- props: {
124
- title: "Hello",
125
- message: "World"
126
- }
127
- });
128
- (0, vitest.expect)(result.messageId).toBe("test-message-id");
129
- });
130
- });
131
- (0, vitest.describe)("verify", () => {
132
- (0, vitest.it)("should verify SMTP connection", async () => {
133
- const result = await client.verify();
134
- (0, vitest.expect)(result).toBe(true);
135
- });
136
- });
137
- (0, vitest.describe)("close", () => {
138
- (0, vitest.it)("should close SMTP connection", async () => {
139
- await (0, vitest.expect)(client.close()).resolves.not.toThrow();
140
- });
141
- });
142
- (0, vitest.describe)("template names", () => {
143
- (0, vitest.it)("should return available template names", () => {
144
- const templateNames = client.getTemplateNames();
145
- (0, vitest.expect)(templateNames).toEqual(["test", "another"]);
146
- });
147
- });
148
- });
149
-
150
- //#endregion
@@ -1 +0,0 @@
1
- export { };
@@ -1 +0,0 @@
1
- export { };
@@ -1,150 +0,0 @@
1
- import { createEmailClient } from "../client-B7LjRjRM.mjs";
2
- import "react";
3
- import { beforeEach, describe, expect, it, vi } from "vitest";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
-
6
- //#region src/__tests__/client.spec.tsx
7
- vi.mock("nodemailer", () => ({ default: { createTransport: vi.fn(() => ({
8
- sendMail: vi.fn().mockResolvedValue({
9
- messageId: "test-message-id",
10
- accepted: ["test@example.com"],
11
- rejected: [],
12
- response: "250 OK"
13
- }),
14
- verify: vi.fn().mockResolvedValue(true),
15
- close: vi.fn()
16
- })) } }));
17
- const TestTemplate = ({ name }) => /* @__PURE__ */ jsxs("div", { children: [
18
- "Hello ",
19
- name,
20
- "!"
21
- ] });
22
- const AnotherTemplate = ({ title, message }) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h1", { children: title }), /* @__PURE__ */ jsx("p", { children: message })] });
23
- describe("SMTPClient", () => {
24
- let client;
25
- const templates = {
26
- test: TestTemplate,
27
- another: AnotherTemplate
28
- };
29
- const config = {
30
- smtp: {
31
- host: "smtp.example.com",
32
- port: 587,
33
- auth: {
34
- user: "test@example.com",
35
- pass: "password"
36
- }
37
- },
38
- templates,
39
- defaults: { from: "noreply@example.com" }
40
- };
41
- beforeEach(() => {
42
- client = createEmailClient(config);
43
- });
44
- describe("send", () => {
45
- it("should send plain text email", async () => {
46
- const result = await client.send({
47
- from: "sender@example.com",
48
- to: "recipient@example.com",
49
- subject: "Test Email",
50
- text: "This is a test email"
51
- });
52
- expect(result).toEqual({
53
- messageId: "test-message-id",
54
- accepted: ["test@example.com"],
55
- rejected: [],
56
- response: "250 OK"
57
- });
58
- });
59
- it("should send HTML email", async () => {
60
- const result = await client.send({
61
- from: "sender@example.com",
62
- to: "recipient@example.com",
63
- subject: "Test Email",
64
- html: "<p>This is a test email</p>"
65
- });
66
- expect(result.messageId).toBe("test-message-id");
67
- });
68
- it("should use default from address", async () => {
69
- const result = await client.send({
70
- to: "recipient@example.com",
71
- subject: "Test Email",
72
- text: "This is a test email",
73
- from: {
74
- name: "Test Sender",
75
- address: "sender@example.com"
76
- }
77
- });
78
- expect(result.messageId).toBe("test-message-id");
79
- });
80
- it("should throw error if no content provided", async () => {
81
- await expect(client.send({
82
- from: "sender@example.com",
83
- to: "recipient@example.com",
84
- subject: "Test Email"
85
- })).rejects.toThrow("Either text or html content must be provided");
86
- });
87
- it("should support multiple recipients", async () => {
88
- const result = await client.send({
89
- from: "sender@example.com",
90
- to: ["recipient1@example.com", "recipient2@example.com"],
91
- subject: "Test Email",
92
- text: "This is a test email"
93
- });
94
- expect(result.messageId).toBe("test-message-id");
95
- });
96
- it("should support CC and BCC", async () => {
97
- const result = await client.send({
98
- from: "sender@example.com",
99
- to: "recipient@example.com",
100
- cc: "cc@example.com",
101
- bcc: ["bcc1@example.com", "bcc2@example.com"],
102
- subject: "Test Email",
103
- text: "This is a test email"
104
- });
105
- expect(result.messageId).toBe("test-message-id");
106
- });
107
- });
108
- describe("sendTemplate", () => {
109
- it("should send email with React template", async () => {
110
- const result = await client.sendTemplate("test", {
111
- from: "sender@example.com",
112
- to: "recipient@example.com",
113
- subject: "Test Template Email",
114
- props: { name: "John" }
115
- });
116
- expect(result.messageId).toBe("test-message-id");
117
- });
118
- it("should send email with another template", async () => {
119
- const result = await client.sendTemplate("another", {
120
- from: "sender@example.com",
121
- to: "recipient@example.com",
122
- subject: "Another Template Email",
123
- props: {
124
- title: "Hello",
125
- message: "World"
126
- }
127
- });
128
- expect(result.messageId).toBe("test-message-id");
129
- });
130
- });
131
- describe("verify", () => {
132
- it("should verify SMTP connection", async () => {
133
- const result = await client.verify();
134
- expect(result).toBe(true);
135
- });
136
- });
137
- describe("close", () => {
138
- it("should close SMTP connection", async () => {
139
- await expect(client.close()).resolves.not.toThrow();
140
- });
141
- });
142
- describe("template names", () => {
143
- it("should return available template names", () => {
144
- const templateNames = client.getTemplateNames();
145
- expect(templateNames).toEqual(["test", "another"]);
146
- });
147
- });
148
- });
149
-
150
- //#endregion