@pixelplex/mail-service 0.2.7 → 0.2.10
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/.gitlab-ci.yml +2 -2
- package/README.md +99 -60
- package/dist/constants/mail.constants.d.ts +2 -1
- package/dist/constants/mail.constants.js +1 -0
- package/dist/constants/mail.constants.js.map +1 -1
- package/dist/factories/gateway.factory.js +1 -0
- package/dist/factories/gateway.factory.js.map +1 -1
- package/dist/gateways/index.d.ts +1 -0
- package/dist/gateways/index.js +1 -0
- package/dist/gateways/index.js.map +1 -1
- package/dist/gateways/resend.gateway.d.ts +12 -0
- package/dist/gateways/resend.gateway.js +66 -0
- package/dist/gateways/resend.gateway.js.map +1 -0
- package/dist/gateways/sendgrid.gateway.d.ts +1 -0
- package/dist/gateways/sendgrid.gateway.js +12 -6
- package/dist/gateways/sendgrid.gateway.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/options.types.d.ts +4 -1
- package/dist/types/resend.types.d.ts +4 -0
- package/dist/types/resend.types.js +3 -0
- package/dist/types/resend.types.js.map +1 -0
- package/dist/types/sendgrid.types.d.ts +5 -0
- package/package.json +42 -34
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +3 -1
- package/dist/tsconfig.build.tsbuildinfo +0 -1
- package/eslint.config.js +0 -128
package/.gitlab-ci.yml
CHANGED
|
@@ -2,13 +2,13 @@ stages:
|
|
|
2
2
|
- 📦 package
|
|
3
3
|
|
|
4
4
|
📦 package:
|
|
5
|
-
image: node:
|
|
5
|
+
image: node:22.22.1-alpine
|
|
6
6
|
stage: 📦 package
|
|
7
7
|
tags:
|
|
8
8
|
- docker
|
|
9
9
|
script:
|
|
10
10
|
- echo "//registry.yarnpkg.com/:_authToken=$NPM_TOKEN" >>~/.npmrc
|
|
11
|
-
- yarn
|
|
11
|
+
- yarn install --frozen-lockfile
|
|
12
12
|
- yarn build
|
|
13
13
|
- yarn publish --non-interactive
|
|
14
14
|
only:
|
package/README.md
CHANGED
|
@@ -1,98 +1,115 @@
|
|
|
1
1
|
# Mail Service
|
|
2
2
|
|
|
3
|
-
Library for
|
|
3
|
+
Library for sending email messages through configured gateways.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## How to use
|
|
8
|
-
|
|
9
|
-
1. create template for html, plain text and subject
|
|
10
|
-
2. add `@pixelplex/mail-service` to your application
|
|
11
|
-
3. Call `MailModule.forRoot` from `@pixelplex/mail-service`
|
|
12
|
-
with specified gateways and options
|
|
13
|
-
4. send a message by calling `this.mailSenderService.sendEmail('test@gmail.com', { htmlPath: htmlTemplatePath, plainPath: plainTextTemplatePath, subjectPath: subjectTemplatePath }, {year: 20});` where `mailSenderService` is `MailSenderService`
|
|
14
|
-
|
|
15
|
-
Currently supported gateways:
|
|
5
|
+
## Supported gateways
|
|
16
6
|
|
|
17
7
|
- slack
|
|
18
8
|
- console
|
|
19
9
|
- smtp
|
|
20
10
|
- sendgrid
|
|
11
|
+
- resend
|
|
21
12
|
|
|
22
|
-
|
|
13
|
+
## Templates
|
|
23
14
|
|
|
24
|
-
|
|
15
|
+
The service uses Handlebars as the template engine.
|
|
25
16
|
|
|
26
|
-
|
|
17
|
+
Expected template files:
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
- `{name}.handlebars` for HTML body
|
|
20
|
+
- `{name}.subject.handlebars` for subject
|
|
21
|
+
- `{name}.plain.handlebars` for plain-text body
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
- `{name}.subject.handlebars` - subject (title) of your email. You can use subject field to specify subject directly. It will override subjectPath
|
|
32
|
-
- `{name}.plain.handlebars` - subject (title) of your email. You can use plain field to specify plain directly. It will override plainPath
|
|
23
|
+
Example:
|
|
33
24
|
|
|
34
25
|
```handlebars
|
|
35
|
-
# welcome.subject.handlebars Welcome, {{name}}!
|
|
26
|
+
# welcome.subject.handlebars Welcome, {{name}}!
|
|
36
27
|
```
|
|
37
28
|
|
|
38
29
|
```handlebars
|
|
39
30
|
# welcome.handlebars
|
|
40
|
-
|
|
41
31
|
<html>
|
|
42
32
|
<head></head>
|
|
43
33
|
<body>
|
|
44
34
|
<p>Welcome, {{name}}!</p>
|
|
45
|
-
<p>How are you?</p>
|
|
46
35
|
</body>
|
|
47
36
|
</html>
|
|
48
37
|
```
|
|
49
38
|
|
|
50
39
|
```handlebars
|
|
51
|
-
# welcome.plain.handlebars
|
|
52
|
-
|
|
53
|
-
<html>
|
|
54
|
-
<head></head>
|
|
55
|
-
<body>
|
|
56
|
-
<p>Welcome, {{name}}!</p>
|
|
57
|
-
<p>How are you?</p>
|
|
58
|
-
</body>
|
|
59
|
-
</html>
|
|
40
|
+
# welcome.plain.handlebars Welcome, {{name}}!
|
|
60
41
|
```
|
|
61
42
|
|
|
62
43
|
## Configuration
|
|
63
44
|
|
|
64
|
-
| Name
|
|
65
|
-
|
|
|
66
|
-
| gateways
|
|
67
|
-
| customGateways
|
|
68
|
-
| smtp.host
|
|
69
|
-
| smtp.port
|
|
70
|
-
| smtp.username
|
|
71
|
-
| smtp.password
|
|
72
|
-
| \*.sender
|
|
73
|
-
| slack.url
|
|
74
|
-
| sendgrid.apiKey
|
|
45
|
+
| Name | Description | Example |
|
|
46
|
+
| ------------------------- | -------------------------------------------------------- | ------------------------- |
|
|
47
|
+
| gateways | Array of gateways to send email | `['resend']` |
|
|
48
|
+
| customGateways | Array of custom gateways classes | `[CustomGateway]` |
|
|
49
|
+
| smtp.host | Mail gateway host address | `smtp.gmail.com` |
|
|
50
|
+
| smtp.port | Mail gateway port number | `586` |
|
|
51
|
+
| smtp.username | Mail gateway username | `username` |
|
|
52
|
+
| smtp.password | Mail gateway password | `qh05780c2qcm034579` |
|
|
53
|
+
| \*.sender | Mail sender address | `postmail@pixelplex.io` |
|
|
54
|
+
| slack.url | Hook URL in case you want to duplicate messages to Slack | `https://hooks.slack.com` |
|
|
55
|
+
| sendgrid.apiKey | Sendgrid API key | `oiqur9823uiofhaoafoe` |
|
|
56
|
+
| sendgrid.senderName | Optional sender display name | `Acme` |
|
|
57
|
+
| sendgrid.replyTo | Optional reply-to email address | `support@example.com` |
|
|
58
|
+
| sendgrid.timeoutMs | Optional HTTP request timeout in milliseconds | `12000` |
|
|
59
|
+
| sendgrid.trackingSettings | Optional SendGrid SDK tracking settings | See example below |
|
|
60
|
+
| resend.apiKey | Resend API key | `re_xxxxxxxxx` |
|
|
61
|
+
|
|
62
|
+
### SendGrid config
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
export const mailConfig = {
|
|
66
|
+
gateways: ['sendgrid'],
|
|
67
|
+
sendgrid: {
|
|
68
|
+
apiKey: process.env.SENDGRID_API_KEY,
|
|
69
|
+
sender: 'noreply@example.com',
|
|
70
|
+
senderName: 'Acme',
|
|
71
|
+
replyTo: 'support@example.com',
|
|
72
|
+
timeoutMs: 12000,
|
|
73
|
+
trackingSettings: {
|
|
74
|
+
clickTracking: { enable: false, enableText: false },
|
|
75
|
+
openTracking: { enable: false },
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
All new SendGrid options are optional. Existing string senders, including formatted addresses,
|
|
82
|
+
continue to work. Each gateway instance owns its SendGrid client, so modules with different
|
|
83
|
+
keys and timeouts do not affect one another. Provider errors are propagated to the caller;
|
|
84
|
+
the gateway does not retry automatically.
|
|
85
|
+
|
|
86
|
+
### Resend config
|
|
75
87
|
|
|
76
|
-
|
|
88
|
+
```typescript
|
|
89
|
+
export const mailConfig = {
|
|
90
|
+
gateways: ['resend'],
|
|
91
|
+
resend: {
|
|
92
|
+
apiKey: process.env.RESEND_API_KEY,
|
|
93
|
+
sender: process.env.MAIL_SENDER,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
```
|
|
77
97
|
|
|
78
|
-
|
|
98
|
+
## Usage
|
|
79
99
|
|
|
80
100
|
```bash
|
|
81
101
|
yarn add @pixelplex/mail-service
|
|
82
102
|
```
|
|
83
103
|
|
|
84
|
-
**2. Import MailModule** in your module you'll send mail from:
|
|
85
|
-
|
|
86
104
|
```typescript
|
|
87
105
|
import { Module } from '@nestjs/common';
|
|
88
106
|
import { MailModule } from '@pixelplex/mail-service';
|
|
89
107
|
import { AppService } from './app.service';
|
|
90
108
|
|
|
91
109
|
@Module({
|
|
92
|
-
controllers: [],
|
|
93
110
|
imports: [
|
|
94
111
|
MailModule.forRoot({
|
|
95
|
-
gateways: ['slack', 'smtp', 'console'],
|
|
112
|
+
gateways: ['slack', 'smtp', 'console', 'resend'],
|
|
96
113
|
slack: { url: 'hooks.slack.com' },
|
|
97
114
|
smtp: {
|
|
98
115
|
username: 'postmail@pixelplex.io',
|
|
@@ -101,6 +118,10 @@ import { AppService } from './app.service';
|
|
|
101
118
|
port: 678,
|
|
102
119
|
password: 'password',
|
|
103
120
|
},
|
|
121
|
+
resend: {
|
|
122
|
+
apiKey: RESEND_API_KEY,
|
|
123
|
+
sender: MAIL_SENDER,
|
|
124
|
+
},
|
|
104
125
|
}),
|
|
105
126
|
],
|
|
106
127
|
providers: [AppService],
|
|
@@ -108,35 +129,50 @@ import { AppService } from './app.service';
|
|
|
108
129
|
export class AppModule {}
|
|
109
130
|
```
|
|
110
131
|
|
|
111
|
-
**3. Call sendEmail** to send your mail:
|
|
112
|
-
|
|
113
132
|
```typescript
|
|
114
133
|
import { Injectable } from '@nestjs/common';
|
|
115
134
|
import { MailSenderService } from '@pixelplex/mail-service';
|
|
116
135
|
|
|
117
136
|
@Injectable()
|
|
118
137
|
export class AppService {
|
|
119
|
-
constructor(private mailSenderService: MailSenderService) {}
|
|
138
|
+
constructor(private readonly mailSenderService: MailSenderService) {}
|
|
120
139
|
|
|
121
|
-
async
|
|
122
|
-
this.mailSenderService.sendEmail(
|
|
140
|
+
async sendWelcomeEmail() {
|
|
141
|
+
await this.mailSenderService.sendEmail(
|
|
123
142
|
'test@gmail.com',
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
{
|
|
144
|
+
htmlPath: htmlTemplatePath,
|
|
145
|
+
plainPath: plainTextTemplatePath,
|
|
146
|
+
subjectPath: subjectTemplatePath,
|
|
147
|
+
},
|
|
127
148
|
{ year: 20 },
|
|
128
149
|
);
|
|
129
150
|
}
|
|
130
151
|
}
|
|
131
152
|
```
|
|
132
153
|
|
|
133
|
-
`{year: 20}` is the
|
|
154
|
+
`{ year: 20 }` is the Handlebars context passed into the templates.
|
|
155
|
+
|
|
156
|
+
React templates are not supported at the moment. The package supports the same Handlebars-based flow as before, including for the new `resend` gateway.
|
|
157
|
+
|
|
158
|
+
## 0.2.10 compatibility
|
|
159
|
+
|
|
160
|
+
Dependency updates include Nodemailer 10.3.1 for security fixes. It bundles its own types and requires Node.js 20+
|
|
161
|
+
(the existing NestJS 11 dependency already requires Node.js 20+). SMTP text, HTML and attachments are covered by MIME tests.
|
|
162
|
+
ESLint stays on 9.39.5 because the installed `eslint-plugin-import` does not support ESLint 10.
|
|
134
163
|
|
|
135
|
-
|
|
164
|
+
The release audit has no high/critical findings. Remaining advisories: moderate `glob`/`minimatch` in development
|
|
165
|
+
tools (fixes require incompatible major updates), and low `deepmerge` including SendGrid's runtime dependencies
|
|
166
|
+
(no patched release available). Run `yarn audit` for all dependencies or `yarn audit --groups dependencies` for runtime only.
|
|
136
167
|
|
|
137
|
-
|
|
168
|
+
## Custom gateways
|
|
169
|
+
|
|
170
|
+
To add a custom gateway, provide a class that implements `IGateway` in `customGateways`.
|
|
138
171
|
|
|
139
172
|
```typescript
|
|
173
|
+
import { Injectable } from '@nestjs/common';
|
|
174
|
+
import { Content, IGateway } from '@pixelplex/mail-service';
|
|
175
|
+
|
|
140
176
|
@Injectable()
|
|
141
177
|
class CustomGateway implements IGateway {
|
|
142
178
|
async send(to: string, content: Content): Promise<void> {
|
|
@@ -144,5 +180,8 @@ class CustomGateway implements IGateway {
|
|
|
144
180
|
}
|
|
145
181
|
}
|
|
146
182
|
|
|
147
|
-
MailModule.forRoot({
|
|
183
|
+
MailModule.forRoot({
|
|
184
|
+
gateways: ['console'],
|
|
185
|
+
customGateways: [CustomGateway],
|
|
186
|
+
});
|
|
148
187
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mail.constants.js","sourceRoot":"","sources":["../../src/constants/mail.constants.ts"],"names":[],"mappings":";;;AAAA,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,uDAA8B,CAAA;IAC9B,iEAAwC,CAAA;IACxC,mEAA0C,CAAA;AAC5C,CAAC,EAJW,qBAAqB,qCAArB,qBAAqB,QAIhC;AAED,IAAY,
|
|
1
|
+
{"version":3,"file":"mail.constants.js","sourceRoot":"","sources":["../../src/constants/mail.constants.ts"],"names":[],"mappings":";;;AAAA,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,uDAA8B,CAAA;IAC9B,iEAAwC,CAAA;IACxC,mEAA0C,CAAA;AAC5C,CAAC,EAJW,qBAAqB,qCAArB,qBAAqB,QAIhC;AAED,IAAY,OAMX;AAND,WAAY,OAAO;IACjB,wBAAa,CAAA;IACb,0BAAe,CAAA;IACf,8BAAmB,CAAA;IACnB,gCAAqB,CAAA;IACrB,4BAAiB,CAAA;AACnB,CAAC,EANW,OAAO,uBAAP,OAAO,QAMlB"}
|
|
@@ -10,6 +10,7 @@ class GatewayFactory {
|
|
|
10
10
|
[constants_1.GATEWAY.CONSOLE]: gateways_1.ConsoleGateway,
|
|
11
11
|
[constants_1.GATEWAY.SMTP]: gateways_1.SmtpGateway,
|
|
12
12
|
[constants_1.GATEWAY.SENDGRID]: gateways_1.SendgridGateway,
|
|
13
|
+
[constants_1.GATEWAY.RESEND]: gateways_1.ResendGateway,
|
|
13
14
|
};
|
|
14
15
|
return gateways[gateway];
|
|
15
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.factory.js","sourceRoot":"","sources":["../../src/factories/gateway.factory.ts"],"names":[],"mappings":";;;AAAA,4CAAuC;AACvC,
|
|
1
|
+
{"version":3,"file":"gateway.factory.js","sourceRoot":"","sources":["../../src/factories/gateway.factory.ts"],"names":[],"mappings":";;;AAAA,4CAAuC;AACvC,0CAAwG;AAGxG,MAAa,cAAc;IACzB,MAAM,CAAC,UAAU,CAAC,OAAgB;QAChC,MAAM,QAAQ,GAAG;YACf,CAAC,mBAAO,CAAC,KAAK,CAAC,EAAE,uBAAY;YAC7B,CAAC,mBAAO,CAAC,OAAO,CAAC,EAAE,yBAAc;YACjC,CAAC,mBAAO,CAAC,IAAI,CAAC,EAAE,sBAAW;YAC3B,CAAC,mBAAO,CAAC,QAAQ,CAAC,EAAE,0BAAe;YACnC,CAAC,mBAAO,CAAC,MAAM,CAAC,EAAE,wBAAa;SAChC,CAAC;QAEF,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;CACF;AAZD,wCAYC"}
|
package/dist/gateways/index.d.ts
CHANGED
package/dist/gateways/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./console.gateway"), exports);
|
|
18
|
+
__exportStar(require("./resend.gateway"), exports);
|
|
18
19
|
__exportStar(require("./sendgrid.gateway"), exports);
|
|
19
20
|
__exportStar(require("./slack.gateway"), exports);
|
|
20
21
|
__exportStar(require("./smtp.gateway"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,qDAAmC;AACnC,kDAAgC;AAChC,iDAA+B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,mDAAiC;AACjC,qDAAmC;AACnC,kDAAgC;AAChC,iDAA+B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IGateway } from '../interfaces';
|
|
2
|
+
import { Content, ResendOptions } from '../types';
|
|
3
|
+
export declare class ResendGateway implements IGateway {
|
|
4
|
+
private readonly resendOptions;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private readonly client;
|
|
7
|
+
constructor(resendOptions: ResendOptions);
|
|
8
|
+
send(to: string, content: Content): Promise<void>;
|
|
9
|
+
private prepareAttachments;
|
|
10
|
+
private getAttachmentContent;
|
|
11
|
+
private createSendError;
|
|
12
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ResendGateway = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const constants_1 = require("../constants");
|
|
18
|
+
const decorators_1 = require("../decorators");
|
|
19
|
+
const utils_1 = require("../utils");
|
|
20
|
+
const { Resend } = require('resend');
|
|
21
|
+
let ResendGateway = class ResendGateway {
|
|
22
|
+
constructor(resendOptions) {
|
|
23
|
+
this.resendOptions = resendOptions;
|
|
24
|
+
this.logger = new common_1.Logger('Mail::ResendGateway');
|
|
25
|
+
if (!(resendOptions === null || resendOptions === void 0 ? void 0 : resendOptions.apiKey)) {
|
|
26
|
+
throw new Error('Resend gateway requires "resend.apiKey"');
|
|
27
|
+
}
|
|
28
|
+
if (!(resendOptions === null || resendOptions === void 0 ? void 0 : resendOptions.sender)) {
|
|
29
|
+
throw new Error('Resend gateway requires "resend.sender"');
|
|
30
|
+
}
|
|
31
|
+
this.client = new Resend(resendOptions.apiKey);
|
|
32
|
+
}
|
|
33
|
+
async send(to, content) {
|
|
34
|
+
const { error } = await this.client.emails.send(Object.assign(Object.assign({ to, from: this.resendOptions.sender, subject: content.subject, html: content.html }, (content.plain ? { text: content.plain } : {})), (content.attachments ? { attachments: this.prepareAttachments(content.attachments) } : {})));
|
|
35
|
+
if (error) {
|
|
36
|
+
throw this.createSendError(error);
|
|
37
|
+
}
|
|
38
|
+
this.logger.debug(`Message to ${to} sent with resend`);
|
|
39
|
+
}
|
|
40
|
+
prepareAttachments(attachments) {
|
|
41
|
+
return attachments.map((attachment) => ({
|
|
42
|
+
content: this.getAttachmentContent(attachment),
|
|
43
|
+
filename: attachment.filename,
|
|
44
|
+
contentType: attachment.mimeType,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
getAttachmentContent(attachment) {
|
|
48
|
+
if ((0, utils_1.isBuffer)(attachment.content)) {
|
|
49
|
+
return attachment.content.toString('base64');
|
|
50
|
+
}
|
|
51
|
+
return attachment.encoding === 'base64' ? attachment.content : Buffer.from(attachment.content).toString('base64');
|
|
52
|
+
}
|
|
53
|
+
createSendError(error) {
|
|
54
|
+
const sendError = new Error(`Failed to send mail with resend: ${error.message}`);
|
|
55
|
+
sendError.name = 'ResendGatewayError';
|
|
56
|
+
Object.assign(sendError, { cause: error });
|
|
57
|
+
return sendError;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.ResendGateway = ResendGateway;
|
|
61
|
+
exports.ResendGateway = ResendGateway = __decorate([
|
|
62
|
+
(0, common_1.Injectable)(),
|
|
63
|
+
__param(0, (0, decorators_1.InjectGatewayOptions)(constants_1.GATEWAY.RESEND)),
|
|
64
|
+
__metadata("design:paramtypes", [Object])
|
|
65
|
+
], ResendGateway);
|
|
66
|
+
//# sourceMappingURL=resend.gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resend.gateway.js","sourceRoot":"","sources":["../../src/gateways/resend.gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { Attachment, Content, SendGridAttachment, SendgridOptions } from '../typ
|
|
|
3
3
|
export declare class SendgridGateway implements IGateway {
|
|
4
4
|
private readonly sendgridOptions;
|
|
5
5
|
private readonly logger;
|
|
6
|
+
private readonly client;
|
|
6
7
|
constructor(sendgridOptions: SendgridOptions);
|
|
7
8
|
send(to: string, content: Content): Promise<void>;
|
|
8
9
|
prepareAttachments(attachments: Attachment[]): SendGridAttachment[];
|
|
@@ -11,13 +11,10 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
-
};
|
|
17
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
15
|
exports.SendgridGateway = void 0;
|
|
19
16
|
const common_1 = require("@nestjs/common");
|
|
20
|
-
const mail_1 =
|
|
17
|
+
const mail_1 = require("@sendgrid/mail");
|
|
21
18
|
const constants_1 = require("../constants");
|
|
22
19
|
const decorators_1 = require("../decorators");
|
|
23
20
|
const utils_1 = require("../utils");
|
|
@@ -25,10 +22,19 @@ let SendgridGateway = class SendgridGateway {
|
|
|
25
22
|
constructor(sendgridOptions) {
|
|
26
23
|
this.sendgridOptions = sendgridOptions;
|
|
27
24
|
this.logger = new common_1.Logger('Mail::SendgridGateway');
|
|
28
|
-
mail_1.
|
|
25
|
+
this.client = new mail_1.MailService();
|
|
26
|
+
this.client.setApiKey(sendgridOptions.apiKey);
|
|
27
|
+
if (sendgridOptions.timeoutMs !== undefined) {
|
|
28
|
+
this.client.setTimeout(sendgridOptions.timeoutMs);
|
|
29
|
+
}
|
|
29
30
|
}
|
|
30
31
|
async send(to, content) {
|
|
31
|
-
|
|
32
|
+
if (!this.sendgridOptions.apiKey) {
|
|
33
|
+
throw new Error('SendGrid gateway requires "sendgrid.apiKey"');
|
|
34
|
+
}
|
|
35
|
+
await this.client.send(Object.assign(Object.assign(Object.assign({ to, from: this.sendgridOptions.senderName
|
|
36
|
+
? { email: this.sendgridOptions.sender, name: this.sendgridOptions.senderName }
|
|
37
|
+
: this.sendgridOptions.sender, subject: content.subject, html: content.html, text: content.plain }, (this.sendgridOptions.replyTo ? { replyTo: this.sendgridOptions.replyTo } : {})), (this.sendgridOptions.trackingSettings ? { trackingSettings: this.sendgridOptions.trackingSettings } : {})), (content.attachments ? { attachments: this.prepareAttachments(content.attachments) } : {})));
|
|
32
38
|
this.logger.debug(`Message to ${to} sent with sendgrid`);
|
|
33
39
|
}
|
|
34
40
|
prepareAttachments(attachments) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sendgrid.gateway.js","sourceRoot":"","sources":["../../src/gateways/sendgrid.gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sendgrid.gateway.js","sourceRoot":"","sources":["../../src/gateways/sendgrid.gateway.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,yCAA6C;AAE7C,4CAAuC;AACvC,8CAAqD;AAGrD,oCAAoC;AAG7B,IAAM,eAAe,GAArB,MAAM,eAAe;IAI1B,YAAoD,eAAiD;QAAhC,oBAAe,GAAf,eAAe,CAAiB;QAHpF,WAAM,GAAG,IAAI,eAAM,CAAC,uBAAuB,CAAC,CAAC;QAC7C,WAAM,GAAG,IAAI,kBAAW,EAAE,CAAC;QAG1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAE9C,IAAI,eAAe,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU,EAAE,OAAgB;QACrC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,6CACpB,EAAE,EACF,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU;gBACnC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE;gBAC/E,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAC/B,OAAO,EAAE,OAAO,CAAC,OAAO,EACxB,IAAI,EAAE,OAAO,CAAC,IAAI,EAClB,IAAI,EAAE,OAAO,CAAC,KAAK,IAChB,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAC/E,CAAC,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAC1G,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC7F,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;IAC3D,CAAC;IAED,kBAAkB,CAAC,WAAyB;QAC1C,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACtC,OAAO,EAAE,IAAA,gBAAQ,EAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO;YAClG,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,IAAI,EAAE,UAAU,CAAC,QAAQ;SAC1B,CAAC,CAAC,CAAC;IACN,CAAC;CACF,CAAA;AAxCY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;IAKE,WAAA,IAAA,iCAAoB,EAAC,mBAAO,CAAC,QAAQ,CAAC,CAAA;;GAJxC,eAAe,CAwC3B"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './mail.types';
|
|
|
2
2
|
export * from './decorators.types';
|
|
3
3
|
export * from './gateway.class';
|
|
4
4
|
export * from './options.types';
|
|
5
|
+
export * from './resend.types';
|
|
5
6
|
export * from './sendgrid.types';
|
|
6
7
|
export * from './slack.types';
|
|
7
8
|
export * from './smtp.types';
|
package/dist/types/index.js
CHANGED
|
@@ -18,6 +18,7 @@ __exportStar(require("./mail.types"), exports);
|
|
|
18
18
|
__exportStar(require("./decorators.types"), exports);
|
|
19
19
|
__exportStar(require("./gateway.class"), exports);
|
|
20
20
|
__exportStar(require("./options.types"), exports);
|
|
21
|
+
__exportStar(require("./resend.types"), exports);
|
|
21
22
|
__exportStar(require("./sendgrid.types"), exports);
|
|
22
23
|
__exportStar(require("./slack.types"), exports);
|
|
23
24
|
__exportStar(require("./smtp.types"), exports);
|
package/dist/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,qDAAmC;AACnC,kDAAgC;AAChC,kDAAgC;AAChC,mDAAiC;AACjC,gDAA8B;AAC9B,+CAA6B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,qDAAmC;AACnC,kDAAgC;AAChC,kDAAgC;AAChC,iDAA+B;AAC/B,mDAAiC;AACjC,gDAA8B;AAC9B,+CAA6B"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ExtendsOrEmpty } from '../utils';
|
|
2
2
|
import { GatewayClass } from './gateway.class';
|
|
3
|
+
import { ResendOptions } from './resend.types';
|
|
3
4
|
import { SendgridOptions } from './sendgrid.types';
|
|
4
5
|
import { SlackOptions } from './slack.types';
|
|
5
6
|
import { SmtpOptions } from './smtp.types';
|
|
6
|
-
export type Gateway = 'smtp' | 'console' | 'slack' | 'sendgrid';
|
|
7
|
+
export type Gateway = 'smtp' | 'console' | 'slack' | 'sendgrid' | 'resend';
|
|
7
8
|
export type MailOptions<TGateway extends Gateway = Gateway> = {
|
|
8
9
|
readonly gateways: [TGateway, ...TGateway[]];
|
|
9
10
|
readonly customGateways?: [GatewayClass, ...GatewayClass[]];
|
|
@@ -13,4 +14,6 @@ export type MailOptions<TGateway extends Gateway = Gateway> = {
|
|
|
13
14
|
slack: SlackOptions;
|
|
14
15
|
}> & ExtendsOrEmpty<'sendgrid', TGateway, {
|
|
15
16
|
sendgrid: SendgridOptions;
|
|
17
|
+
}> & ExtendsOrEmpty<'resend', TGateway, {
|
|
18
|
+
resend: ResendOptions;
|
|
16
19
|
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resend.types.js","sourceRoot":"","sources":["../../src/types/resend.types.ts"],"names":[],"mappings":""}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import type { MailDataRequired } from '@sendgrid/mail';
|
|
1
2
|
export type SendgridOptions = {
|
|
2
3
|
readonly apiKey: string;
|
|
3
4
|
readonly sender: string;
|
|
5
|
+
readonly senderName?: string;
|
|
6
|
+
readonly replyTo?: string;
|
|
7
|
+
readonly timeoutMs?: number;
|
|
8
|
+
readonly trackingSettings?: MailDataRequired['trackingSettings'];
|
|
4
9
|
};
|
|
5
10
|
export type SendGridAttachment = {
|
|
6
11
|
content: string;
|