@drax/email-back 0.9.0

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 (34) hide show
  1. package/dist/config/EmailConfig.js +14 -0
  2. package/dist/factory/EmailServiceFactory.js +46 -0
  3. package/dist/index.js +4 -0
  4. package/dist/interfaces/IEmailLayout.js +1 -0
  5. package/dist/interfaces/ITransportConfig.js +1 -0
  6. package/dist/services/EmailLayoutService.js +106 -0
  7. package/dist/services/EmailService.js +58 -0
  8. package/package.json +42 -0
  9. package/src/config/EmailConfig.ts +14 -0
  10. package/src/factory/EmailServiceFactory.ts +56 -0
  11. package/src/index.ts +18 -0
  12. package/src/interfaces/IEmailLayout.ts +25 -0
  13. package/src/interfaces/ITransportConfig.ts +21 -0
  14. package/src/services/EmailLayoutService.ts +123 -0
  15. package/src/services/EmailService.ts +81 -0
  16. package/test/Email.test.ts +83 -0
  17. package/test/EmailLayout.test.ts +193 -0
  18. package/test/template.pug +123 -0
  19. package/tsconfig.json +16 -0
  20. package/tsconfig.tsbuildinfo +1 -0
  21. package/types/config/EmailConfig.d.ts +14 -0
  22. package/types/config/EmailConfig.d.ts.map +1 -0
  23. package/types/factory/EmailServiceFactory.d.ts +11 -0
  24. package/types/factory/EmailServiceFactory.d.ts.map +1 -0
  25. package/types/index.d.ts +8 -0
  26. package/types/index.d.ts.map +1 -0
  27. package/types/interfaces/IEmailLayout.d.ts +19 -0
  28. package/types/interfaces/IEmailLayout.d.ts.map +1 -0
  29. package/types/interfaces/ITransportConfig.d.ts +19 -0
  30. package/types/interfaces/ITransportConfig.d.ts.map +1 -0
  31. package/types/services/EmailLayoutService.d.ts +12 -0
  32. package/types/services/EmailLayoutService.d.ts.map +1 -0
  33. package/types/services/EmailService.d.ts +13 -0
  34. package/types/services/EmailService.d.ts.map +1 -0
@@ -0,0 +1,83 @@
1
+ import {describe, test} from "vitest";
2
+ import {EmailLayoutService} from '../src/services/EmailLayoutService.js'
3
+ import {fileURLToPath} from "url";
4
+ import path from "path";
5
+ import {EmailServiceFactory} from "../src/factory/EmailServiceFactory.js";
6
+
7
+
8
+ let body = `
9
+ <h2 style="font-size: 22px; color: #333333; font-weight: 600; margin: 0 0 10px 0;">Bienvenido a Nuestro Boletín</h2>
10
+ <p style="font-size: 16px; line-height: 1.6; color: #555555; margin: 0 0 15px 0;">Hola, nos complace anunciarte nuestras últimas novedades. En este correo te mantendremos actualizado sobre todos nuestros productos y servicios. Gracias por formar parte de nuestra comunidad.</p>
11
+ <p style="font-size: 16px; line-height: 1.6; color: #555555; margin: 0;">Si tienes alguna duda, no dudes en contactarnos. Estamos aquí para ayudarte.</p>
12
+ `
13
+
14
+ //I Need the absolute path of template.pug file in the same directory as this file with nodejs 20 and type module
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+ const templatePath = path.join(__dirname, 'template.pug');
18
+
19
+ describe("Email Service", function () {
20
+
21
+
22
+ test("Email Send with Preview Logo Title default style", async () => {
23
+
24
+ // modify run configuration: --env-file .env
25
+
26
+ let emailLayoutService = new EmailLayoutService({
27
+ headerCentered: false,
28
+ headerTitle: 'Example',
29
+ headerLogo: 'https://media.sondeosglobal.com/media/files/cincarnato/2023/11/sndlogo-H31daC.png',
30
+ footerCopyright: 'My Company. Todos los derechos reservados.',
31
+ footerContent: '<p>Some Text here.</p>',
32
+ })
33
+
34
+ const mail = {
35
+ from: 'from@example.com',
36
+ to: 'to@example.com',
37
+ subject: 'the subject',
38
+ html: emailLayoutService.html(body),
39
+ text: ''
40
+ }
41
+
42
+ let emailService = EmailServiceFactory.instance
43
+
44
+ const r = await emailService.sendEmail({
45
+ from: 'ci.sys.virtual@gmail.com',
46
+ to: 'cristian.cdi@gmail.com',
47
+ subject: 'the subject',
48
+ html: emailLayoutService.html(body),
49
+ })
50
+
51
+ console.log("R", r)
52
+
53
+ })
54
+
55
+ test("Email send Image", async () => {
56
+
57
+ // modify run configuration: --env-file .env
58
+
59
+ let emailLayoutService = new EmailLayoutService({
60
+ headerCentered: false,
61
+ headerImage: 'https://media.sondeosglobal.com/media/files/cincarnato/2025/1/bannerdrax-rsDnbj.png',
62
+ headerImageStyle: 'width: 800px; display: block; margin: 0 auto;',
63
+ footerCopyright: 'My Company. Todos los derechos reservados.',
64
+ footerContent: '<p>Some Text here.</p>',
65
+ footerUnsubscribe: '<a href="/">Unsuscribe</a>'
66
+ })
67
+
68
+
69
+ let emailService = EmailServiceFactory.instance
70
+
71
+ const r = await emailService.sendEmail({
72
+ from: 'ci.sys.virtual@gmail.com',
73
+ to: 'cristian.cdi@gmail.com',
74
+ subject: 'the subject',
75
+ html: emailLayoutService.html(body),
76
+ })
77
+
78
+ console.log("R", r)
79
+
80
+ })
81
+
82
+
83
+ })
@@ -0,0 +1,193 @@
1
+ import {describe, test} from "vitest";
2
+ import {EmailLayoutService} from '../src/services/EmailLayoutService.js'
3
+ import {EmailService} from '../src/services/EmailService.js'
4
+ import previewEmail from 'preview-email';
5
+ import {fileURLToPath} from "url";
6
+ import path from "path";
7
+
8
+
9
+ let body = `
10
+ <h2 style="font-size: 22px; color: #333333; font-weight: 600; margin: 0 0 10px 0;">Bienvenido a Nuestro Boletín</h2>
11
+ <p style="font-size: 16px; line-height: 1.6; color: #555555; margin: 0 0 15px 0;">Hola, nos complace anunciarte nuestras últimas novedades. En este correo te mantendremos actualizado sobre todos nuestros productos y servicios. Gracias por formar parte de nuestra comunidad.</p>
12
+ <p style="font-size: 16px; line-height: 1.6; color: #555555; margin: 0;">Si tienes alguna duda, no dudes en contactarnos. Estamos aquí para ayudarte.</p>
13
+ `
14
+
15
+ //I Need the absolute path of template.pug file in the same directory as this file with nodejs 20 and type module
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+ const templatePath = path.join(__dirname, 'template.pug');
19
+
20
+ describe("Email Layout", function () {
21
+
22
+
23
+ test("Email Layout Preview Image", async () => {
24
+
25
+ let emailLayoutService = new EmailLayoutService({
26
+ headerCentered: true,
27
+ headerImage: 'https://media.sondeosglobal.com/media/files/cincarnato/2025/1/bannerdrax-rsDnbj.png',
28
+ headerImageStyle: 'height: 170px; width: auto; display: block; margin: auto;',
29
+ footerCopyright: 'My Company. Todos los derechos reservados.',
30
+ footerUnsubscribe: '<a>Unsuscribe</a>'
31
+ })
32
+
33
+ const mail = {
34
+ from: 'from@example.com',
35
+ to: 'to@example.com',
36
+ subject: 'the subject',
37
+ html: emailLayoutService.html(body),
38
+ text: '',
39
+
40
+ }
41
+
42
+ const r = await previewEmail(mail,{ template: templatePath})
43
+
44
+ console.log("R", r)
45
+
46
+ })
47
+
48
+ test("Email Layout Preview Logo Title", async () => {
49
+
50
+ let emailLayoutService = new EmailLayoutService({
51
+ maxWidth: '900px',
52
+ headerCentered: false,
53
+ headerBgColor: 'red',
54
+ headerTitle: 'Example',
55
+ headerTitleStyle: 'color: yellow; font-size: 28px; margin: 0; font-weight: 700;',
56
+ headerLogo: 'https://media.sondeosglobal.com/media/files/cincarnato/2023/11/sndlogo-H31daC.png',
57
+ headerLogoStyle: 'height: 70px; width: auto; display: block; margin: auto;',
58
+ footerBgColor: 'cyan',
59
+ footerCopyright: 'My Company. Todos los derechos reservados.',
60
+ footerContent: '<p>Some Text here.</p>',
61
+ footerUnsubscribe: '<a href="/">Unsuscribe</a>'
62
+ })
63
+
64
+
65
+ const mail = {
66
+ from: 'from@example.com',
67
+ to: 'to@example.com',
68
+ subject: 'the subject',
69
+ html: emailLayoutService.html(body),
70
+ text: ''
71
+ }
72
+
73
+ const r = await previewEmail(mail,{ template: templatePath})
74
+
75
+ console.log("R", r)
76
+
77
+ })
78
+
79
+ test("Email Layout Preview Logo Title default style", async () => {
80
+
81
+ let emailLayoutService = new EmailLayoutService({
82
+ headerCentered: false,
83
+ headerTitle: 'Example',
84
+ headerLogo: 'https://media.sondeosglobal.com/media/files/cincarnato/2023/11/sndlogo-H31daC.png',
85
+ footerCopyright: 'My Company. Todos los derechos reservados.',
86
+ footerContent: '<p>Some Text here.</p>',
87
+ })
88
+
89
+ const mail = {
90
+ from: 'from@example.com',
91
+ to: 'to@example.com',
92
+ subject: 'the subject',
93
+ html: emailLayoutService.html(body),
94
+ text: ''
95
+ }
96
+
97
+ const r = await previewEmail(mail,{ template: templatePath})
98
+
99
+ console.log("R", r)
100
+
101
+ })
102
+
103
+ test("Email Layout Preview Logo", async () => {
104
+
105
+ let emailLayoutService = new EmailLayoutService({
106
+ maxWidth: '900px',
107
+ headerCentered: false,
108
+ headerBgColor: 'red',
109
+ headerColor: 'yellow',
110
+ headerLogo: 'https://media.sondeosglobal.com/media/files/cincarnato/2023/11/sndlogo-H31daC.png',
111
+ footerBgColor: 'cyan',
112
+ footerCopyright: 'My Company. Todos los derechos reservados.',
113
+ footerContent: '<p>Some Text here.</p>',
114
+ footerUnsubscribe: '<a href="/">Unsuscribe</a>'
115
+ })
116
+
117
+
118
+ const mail = {
119
+ from: 'from@example.com',
120
+ to: 'to@example.com',
121
+ subject: 'the subject',
122
+ html: emailLayoutService.html(body),
123
+ text: ''
124
+ }
125
+
126
+ const r = await previewEmail(mail,{ template: templatePath})
127
+
128
+ console.log("R", r)
129
+
130
+ })
131
+
132
+ test("Email Layout Preview Title", async () => {
133
+
134
+ let emailLayoutService = new EmailLayoutService({
135
+ maxWidth: '900px',
136
+ headerCentered: false,
137
+ headerBgColor: 'red',
138
+ headerColor: 'yellow',
139
+ headerTitle: 'Example',
140
+ footerBgColor: 'cyan',
141
+ footerCopyright: 'My Company. Todos los derechos reservados.',
142
+ footerContent: '<p>Some Text here.</p>',
143
+ footerUnsubscribe: '<a href="/">Unsuscribe</a>'
144
+ })
145
+
146
+
147
+ const mail = {
148
+ from: 'from@example.com',
149
+ to: 'to@example.com',
150
+ subject: 'the subject',
151
+ html: emailLayoutService.html(body),
152
+ text: ''
153
+ }
154
+
155
+ const r = await previewEmail(mail,{ template: templatePath})
156
+
157
+ console.log("R", r)
158
+
159
+ })
160
+
161
+ test("Email Layout send", async () => {
162
+
163
+ let emailLayoutService = new EmailLayoutService({
164
+ headerCentered: false,
165
+ headerImage: 'https://media.sondeosglobal.com/media/files/cincarnato/2025/1/banner-lZEeQe.png',
166
+ headerTitle: 'Example',
167
+ headerLogo: 'https://media.sondeosglobal.com/media/files/cincarnato/2023/11/sndlogo-H31daC.png',
168
+ footerCopyright: 'My Company. Todos los derechos reservados.',
169
+ footerContent: '<p>Some Text here.</p>',
170
+ footerUnsubscribe: '<a href="/">Unsuscribe</a>'
171
+ })
172
+
173
+
174
+ let emailService = new EmailService('gmail', {
175
+ auth: {
176
+ user: process.env.EMAIL_AUTH_USERNAME,
177
+ pass: process.env.EMAIL_AUTH_PASSWORD
178
+ }
179
+ })
180
+
181
+ const r = await emailService.sendEmail({
182
+ from: 'ci.sys.virtual@gmail.com',
183
+ to: 'cristian.cdi@gmail.com',
184
+ subject: 'the subject',
185
+ html: emailLayoutService.html(body),
186
+ })
187
+
188
+ console.log("R", r)
189
+
190
+ })
191
+
192
+
193
+ })
@@ -0,0 +1,123 @@
1
+ doctype html
2
+ html
3
+ head
4
+ meta(charset="utf-8")
5
+ meta(http-equiv="x-ua-compatible", content="ie=edge")
6
+ if subject
7
+ title= subject
8
+ meta(name="viewport", content="width=device-width, initial-scale=1")
9
+ style(type='text/css').
10
+ iframe {
11
+ border: 0;
12
+ height: 100%;
13
+ width: 100%;
14
+ min-height: 800px;
15
+ max-width: 100%;
16
+ display: block;
17
+ }
18
+ .preview-email-tabs {
19
+ display: flex;
20
+ flex-wrap: wrap;
21
+ max-width: 100%;
22
+ border: 1px solid black;
23
+ background: #ffffff;
24
+ }
25
+ .preview-email-tabs input[type="radio"] {
26
+ display: none;
27
+ }
28
+ .preview-email-tabs label {
29
+ padding: 1rem;
30
+ background: #ffffff;
31
+ font-weight: bold;
32
+ cursor: pointer;
33
+ }
34
+ .preview-email-tabs .preview-email-tab {
35
+ width: 100%;
36
+ background: #fff;
37
+ order: 1;
38
+ display: none;
39
+ }
40
+ .preview-email-tabs input[type='radio']:checked + label + .preview-email-tab {
41
+ display: block;
42
+ }
43
+ .preview-email-tabs input[type="radio"]:checked + label {
44
+ background: #fff;
45
+ }
46
+ body
47
+ table
48
+ if base64
49
+ tr
50
+ td(colspan=2, style='text-align:right;'): button(type='button', onclick='downloadRawEmail()') Download Original
51
+ script.
52
+ function downloadRawEmail() {
53
+ var link = document.createElement('a');
54
+ link.href = "data:message/rfc822;base64,#{base64}";
55
+ link.download = "#{messageId ? messageId.replace('<', '').replace('>', '').split('@')[0] : Date.now()}.eml";
56
+ link.click();
57
+ }
58
+ each headerLine, i in headerLines
59
+ - const index = headerLine.line.indexOf(': ')
60
+ - const value = headerLine.line.slice(index + 2)
61
+ - const header = headers.get(headerLine.key)
62
+ tr
63
+ td
64
+ strong= headerLine.line.slice(0, index)
65
+ td
66
+ if header
67
+ case headerLine.key
68
+ when 'content-type'
69
+ //- TODO: header.params[key]
70
+ = header.value || header || value
71
+ when 'content-disposition'
72
+ when 'dkim-signature'
73
+ //- TODO: header.params[key]
74
+ = value
75
+ when 'subject'
76
+ when 'references'
77
+ when 'message-id'
78
+ when 'in-reply-to'
79
+ when 'priority'
80
+ when 'x-priority'
81
+ when 'x-msmail-priority'
82
+ when 'importance'
83
+ = header.value || header || value
84
+ when 'from'
85
+ when 'to'
86
+ when 'cc'
87
+ when 'bcc'
88
+ when 'sender'
89
+ when 'reply-to'
90
+ when 'delivered-to'
91
+ when 'return-path'
92
+ if header.html
93
+ != header.html
94
+ else
95
+ = header.value || header || value
96
+ default
97
+ //- when 'date'
98
+ = header.value || header || value
99
+ else
100
+ = value
101
+ if attachments && attachments.length > 0
102
+ tr
103
+ td: strong Attachments
104
+ td
105
+ ul
106
+ each a in attachments
107
+ li
108
+ a(href=`data:${a.contentType};base64,${a.content.toString('base64')}`, download=a.filename, target='_blank')
109
+ if a.filename
110
+ code= a.filename
111
+ else
112
+ code= 'Unnamed file'
113
+ .preview-email-tabs
114
+ if html
115
+ input(type='radio', name='preview_email', checked)#tab-html
116
+ label(for='tab-html') HTML
117
+ .preview-email-tab
118
+ iframe(sandbox='allow-popups', referrerpolicy='no-referrer', seamless='seamless', srcdoc=`<base target='_top'>${html}`)#html
119
+ if text
120
+ input(type='radio', name='preview_email', checked=!html)#tab-text
121
+ label(for='tab-text') Plain text
122
+ .preview-email-tab
123
+ iframe(sandbox='allow-popups', referrerpolicy='no-referrer', seamless='seamless', srcdoc=`<pre>${text}</pre>`)#text
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "declarationDir": "./types",
7
+ },
8
+ "exclude": ["test", "types","dist"],
9
+ "ts-node": {
10
+ "esm": true
11
+ },
12
+ "tsc-alias": {
13
+ "resolveFullPaths": true,
14
+ "verbose": false
15
+ }
16
+ }