@simplens/nodemailer-gmail 1.0.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.
- package/README.md +90 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +185 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @simplens/nodemailer-gmail
|
|
2
|
+
|
|
3
|
+
Gmail/SMTP email provider plugin for SimpleNS using Nodemailer.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @simplens/nodemailer-gmail simplens-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Add to your `simplens.config.yaml`:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
providers:
|
|
17
|
+
- package: "@simplens/nodemailer-gmail"
|
|
18
|
+
id: "gmail"
|
|
19
|
+
credentials:
|
|
20
|
+
EMAIL_HOST: "${EMAIL_HOST}" # Optional, default: smtp.gmail.com
|
|
21
|
+
EMAIL_PORT: "${EMAIL_PORT}" # Optional, default: 587
|
|
22
|
+
EMAIL_USER: "${EMAIL_USER}" # Required: your Gmail address
|
|
23
|
+
EMAIL_PASS: "${EMAIL_PASS}" # Required: Gmail App Password
|
|
24
|
+
EMAIL_FROM: "${EMAIL_FROM}" # Optional, defaults to EMAIL_USER
|
|
25
|
+
options:
|
|
26
|
+
priority: 1
|
|
27
|
+
rateLimit:
|
|
28
|
+
maxTokens: 100 # Token bucket size
|
|
29
|
+
refillRate: 10 # Tokens per second
|
|
30
|
+
|
|
31
|
+
channels:
|
|
32
|
+
email:
|
|
33
|
+
default: "gmail"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Gmail App Password
|
|
37
|
+
|
|
38
|
+
For Gmail, you need to use an App Password, not your regular password:
|
|
39
|
+
|
|
40
|
+
1. Enable 2-Factor Authentication on your Google account
|
|
41
|
+
2. Go to: https://myaccount.google.com/apppasswords
|
|
42
|
+
3. Generate an app password for "Mail"
|
|
43
|
+
4. Use that password as `EMAIL_PASS`
|
|
44
|
+
|
|
45
|
+
## Environment Variables
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
EMAIL_HOST=smtp.gmail.com
|
|
49
|
+
EMAIL_PORT=587
|
|
50
|
+
EMAIL_USER=your-email@gmail.com
|
|
51
|
+
EMAIL_PASS=your-app-password
|
|
52
|
+
EMAIL_FROM=your-email@gmail.com
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Notification Format
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"notification_id": "...",
|
|
60
|
+
"request_id": "uuid-v4",
|
|
61
|
+
"client_id": "uuid-v4",
|
|
62
|
+
"channel": "email",
|
|
63
|
+
"recipient": {
|
|
64
|
+
"user_id": "user-123",
|
|
65
|
+
"email": "recipient@example.com"
|
|
66
|
+
},
|
|
67
|
+
"content": {
|
|
68
|
+
"subject": "Hello!",
|
|
69
|
+
"message": "Hello {{name}}, welcome!"
|
|
70
|
+
},
|
|
71
|
+
"variables": {
|
|
72
|
+
"name": "World"
|
|
73
|
+
},
|
|
74
|
+
"webhook_url": "https://your-app.com/webhook",
|
|
75
|
+
"retry_count": 0,
|
|
76
|
+
"created_at": "2024-01-01T00:00:00Z"
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Features
|
|
81
|
+
|
|
82
|
+
- ✅ HTML and plain text emails (auto-detected)
|
|
83
|
+
- ✅ Template variable substitution (`{{key}}` syntax)
|
|
84
|
+
- ✅ Configurable rate limiting
|
|
85
|
+
- ✅ Automatic retry classification
|
|
86
|
+
- ✅ Gmail and any SMTP server support
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @simplens/gmail
|
|
3
|
+
*
|
|
4
|
+
* Gmail/SMTP email provider plugin for SimpleNS.
|
|
5
|
+
* Uses Nodemailer for email delivery.
|
|
6
|
+
*/
|
|
7
|
+
import { z, type SimpleNSProvider, type ProviderManifest, type ProviderConfig, type DeliveryResult, type RateLimitConfig } from 'simplens-sdk';
|
|
8
|
+
/**
|
|
9
|
+
* Complete Gmail notification schema
|
|
10
|
+
*/
|
|
11
|
+
declare const gmailNotificationSchema: z.ZodObject<{
|
|
12
|
+
notification_id: z.ZodString;
|
|
13
|
+
request_id: z.ZodString;
|
|
14
|
+
client_id: z.ZodString;
|
|
15
|
+
variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
16
|
+
webhook_url: z.ZodString;
|
|
17
|
+
retry_count: z.ZodNumber;
|
|
18
|
+
created_at: z.ZodDate;
|
|
19
|
+
} & {
|
|
20
|
+
channel: z.ZodLiteral<"email">;
|
|
21
|
+
recipient: z.ZodObject<{
|
|
22
|
+
user_id: z.ZodString;
|
|
23
|
+
email: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
user_id: string;
|
|
26
|
+
email: string;
|
|
27
|
+
}, {
|
|
28
|
+
user_id: string;
|
|
29
|
+
email: string;
|
|
30
|
+
}>;
|
|
31
|
+
content: z.ZodObject<{
|
|
32
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
33
|
+
message: z.ZodString;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
message: string;
|
|
36
|
+
subject?: string | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
message: string;
|
|
39
|
+
subject?: string | undefined;
|
|
40
|
+
}>;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
channel: "email";
|
|
43
|
+
recipient: {
|
|
44
|
+
user_id: string;
|
|
45
|
+
email: string;
|
|
46
|
+
};
|
|
47
|
+
content: {
|
|
48
|
+
message: string;
|
|
49
|
+
subject?: string | undefined;
|
|
50
|
+
};
|
|
51
|
+
notification_id: string;
|
|
52
|
+
request_id: string;
|
|
53
|
+
client_id: string;
|
|
54
|
+
webhook_url: string;
|
|
55
|
+
retry_count: number;
|
|
56
|
+
created_at: Date;
|
|
57
|
+
variables?: Record<string, string> | undefined;
|
|
58
|
+
}, {
|
|
59
|
+
channel: "email";
|
|
60
|
+
recipient: {
|
|
61
|
+
user_id: string;
|
|
62
|
+
email: string;
|
|
63
|
+
};
|
|
64
|
+
content: {
|
|
65
|
+
message: string;
|
|
66
|
+
subject?: string | undefined;
|
|
67
|
+
};
|
|
68
|
+
notification_id: string;
|
|
69
|
+
request_id: string;
|
|
70
|
+
client_id: string;
|
|
71
|
+
webhook_url: string;
|
|
72
|
+
retry_count: number;
|
|
73
|
+
created_at: Date;
|
|
74
|
+
variables?: Record<string, string> | undefined;
|
|
75
|
+
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Gmail notification type
|
|
78
|
+
*/
|
|
79
|
+
export type GmailNotification = z.infer<typeof gmailNotificationSchema>;
|
|
80
|
+
/**
|
|
81
|
+
* Gmail Provider
|
|
82
|
+
*
|
|
83
|
+
* Sends emails using Gmail SMTP via Nodemailer.
|
|
84
|
+
*
|
|
85
|
+
* Required credentials:
|
|
86
|
+
* - EMAIL_HOST: SMTP host (default: smtp.gmail.com)
|
|
87
|
+
* - EMAIL_PORT: SMTP port (default: 587)
|
|
88
|
+
* - EMAIL_USER: Gmail address
|
|
89
|
+
* - EMAIL_PASS: App password (not regular password)
|
|
90
|
+
*
|
|
91
|
+
* Optional:
|
|
92
|
+
* - EMAIL_FROM: From address (defaults to EMAIL_USER)
|
|
93
|
+
*/
|
|
94
|
+
export declare class GmailProvider implements SimpleNSProvider<GmailNotification> {
|
|
95
|
+
private transporter;
|
|
96
|
+
private fromEmail;
|
|
97
|
+
private config;
|
|
98
|
+
readonly manifest: ProviderManifest;
|
|
99
|
+
getNotificationSchema(): z.ZodObject<{
|
|
100
|
+
notification_id: z.ZodString;
|
|
101
|
+
request_id: z.ZodString;
|
|
102
|
+
client_id: z.ZodString;
|
|
103
|
+
variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
104
|
+
webhook_url: z.ZodString;
|
|
105
|
+
retry_count: z.ZodNumber;
|
|
106
|
+
created_at: z.ZodDate;
|
|
107
|
+
} & {
|
|
108
|
+
channel: z.ZodLiteral<"email">;
|
|
109
|
+
recipient: z.ZodObject<{
|
|
110
|
+
user_id: z.ZodString;
|
|
111
|
+
email: z.ZodString;
|
|
112
|
+
}, "strip", z.ZodTypeAny, {
|
|
113
|
+
user_id: string;
|
|
114
|
+
email: string;
|
|
115
|
+
}, {
|
|
116
|
+
user_id: string;
|
|
117
|
+
email: string;
|
|
118
|
+
}>;
|
|
119
|
+
content: z.ZodObject<{
|
|
120
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
121
|
+
message: z.ZodString;
|
|
122
|
+
}, "strip", z.ZodTypeAny, {
|
|
123
|
+
message: string;
|
|
124
|
+
subject?: string | undefined;
|
|
125
|
+
}, {
|
|
126
|
+
message: string;
|
|
127
|
+
subject?: string | undefined;
|
|
128
|
+
}>;
|
|
129
|
+
}, "strip", z.ZodTypeAny, {
|
|
130
|
+
channel: "email";
|
|
131
|
+
recipient: {
|
|
132
|
+
user_id: string;
|
|
133
|
+
email: string;
|
|
134
|
+
};
|
|
135
|
+
content: {
|
|
136
|
+
message: string;
|
|
137
|
+
subject?: string | undefined;
|
|
138
|
+
};
|
|
139
|
+
notification_id: string;
|
|
140
|
+
request_id: string;
|
|
141
|
+
client_id: string;
|
|
142
|
+
webhook_url: string;
|
|
143
|
+
retry_count: number;
|
|
144
|
+
created_at: Date;
|
|
145
|
+
variables?: Record<string, string> | undefined;
|
|
146
|
+
}, {
|
|
147
|
+
channel: "email";
|
|
148
|
+
recipient: {
|
|
149
|
+
user_id: string;
|
|
150
|
+
email: string;
|
|
151
|
+
};
|
|
152
|
+
content: {
|
|
153
|
+
message: string;
|
|
154
|
+
subject?: string | undefined;
|
|
155
|
+
};
|
|
156
|
+
notification_id: string;
|
|
157
|
+
request_id: string;
|
|
158
|
+
client_id: string;
|
|
159
|
+
webhook_url: string;
|
|
160
|
+
retry_count: number;
|
|
161
|
+
created_at: Date;
|
|
162
|
+
variables?: Record<string, string> | undefined;
|
|
163
|
+
}>;
|
|
164
|
+
getRecipientSchema(): z.ZodObject<{
|
|
165
|
+
user_id: z.ZodString;
|
|
166
|
+
email: z.ZodString;
|
|
167
|
+
}, "strip", z.ZodTypeAny, {
|
|
168
|
+
user_id: string;
|
|
169
|
+
email: string;
|
|
170
|
+
}, {
|
|
171
|
+
user_id: string;
|
|
172
|
+
email: string;
|
|
173
|
+
}>;
|
|
174
|
+
getContentSchema(): z.ZodObject<{
|
|
175
|
+
subject: z.ZodOptional<z.ZodString>;
|
|
176
|
+
message: z.ZodString;
|
|
177
|
+
}, "strip", z.ZodTypeAny, {
|
|
178
|
+
message: string;
|
|
179
|
+
subject?: string | undefined;
|
|
180
|
+
}, {
|
|
181
|
+
message: string;
|
|
182
|
+
subject?: string | undefined;
|
|
183
|
+
}>;
|
|
184
|
+
getRateLimitConfig(): RateLimitConfig;
|
|
185
|
+
initialize(config: ProviderConfig): Promise<void>;
|
|
186
|
+
healthCheck(): Promise<boolean>;
|
|
187
|
+
send(notification: GmailNotification): Promise<DeliveryResult>;
|
|
188
|
+
shutdown(): Promise<void>;
|
|
189
|
+
}
|
|
190
|
+
export default GmailProvider;
|
|
191
|
+
export declare function createProvider(): GmailProvider;
|
|
192
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACH,CAAC,EACD,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EAIvB,MAAM,cAAc,CAAC;AAkBtB;;GAEG;AACH,QAAA,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI3B,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,YAAW,gBAAgB,CAAC,iBAAiB,CAAC;IACrE,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,MAAM,CAA+B;IAE7C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAUjC;IAEF,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAIrB,kBAAkB;;;;;;;;;;IAIlB,gBAAgB;;;;;;;;;;IAIhB,kBAAkB,IAAI,eAAe;IAa/B,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BjD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAe/B,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;IAqE9D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAOlC;AAGD,eAAe,aAAa,CAAC;AAG7B,wBAAgB,cAAc,IAAI,aAAa,CAE9C"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @simplens/gmail
|
|
3
|
+
*
|
|
4
|
+
* Gmail/SMTP email provider plugin for SimpleNS.
|
|
5
|
+
* Uses Nodemailer for email delivery.
|
|
6
|
+
*/
|
|
7
|
+
import nodemailer from 'nodemailer';
|
|
8
|
+
import { z, baseNotificationSchema, replaceVariables, isHtmlContent, } from 'simplens-sdk';
|
|
9
|
+
/**
|
|
10
|
+
* Email recipient schema
|
|
11
|
+
*/
|
|
12
|
+
const recipientSchema = z.object({
|
|
13
|
+
user_id: z.string(),
|
|
14
|
+
email: z.string().email(),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Email content schema
|
|
18
|
+
*/
|
|
19
|
+
const contentSchema = z.object({
|
|
20
|
+
subject: z.string().optional(),
|
|
21
|
+
message: z.string(),
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Complete Gmail notification schema
|
|
25
|
+
*/
|
|
26
|
+
const gmailNotificationSchema = baseNotificationSchema.extend({
|
|
27
|
+
channel: z.literal('email'),
|
|
28
|
+
recipient: recipientSchema,
|
|
29
|
+
content: contentSchema,
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Gmail Provider
|
|
33
|
+
*
|
|
34
|
+
* Sends emails using Gmail SMTP via Nodemailer.
|
|
35
|
+
*
|
|
36
|
+
* Required credentials:
|
|
37
|
+
* - EMAIL_HOST: SMTP host (default: smtp.gmail.com)
|
|
38
|
+
* - EMAIL_PORT: SMTP port (default: 587)
|
|
39
|
+
* - EMAIL_USER: Gmail address
|
|
40
|
+
* - EMAIL_PASS: App password (not regular password)
|
|
41
|
+
*
|
|
42
|
+
* Optional:
|
|
43
|
+
* - EMAIL_FROM: From address (defaults to EMAIL_USER)
|
|
44
|
+
*/
|
|
45
|
+
export class GmailProvider {
|
|
46
|
+
transporter = null;
|
|
47
|
+
fromEmail = '';
|
|
48
|
+
config = null;
|
|
49
|
+
manifest = {
|
|
50
|
+
name: 'simplens-plugin-nodemailer-gmail',
|
|
51
|
+
version: '1.0.0',
|
|
52
|
+
channel: 'email',
|
|
53
|
+
displayName: 'Gmail (Nodemailer)',
|
|
54
|
+
description: 'Send emails via Gmail SMTP using Nodemailer',
|
|
55
|
+
author: 'Adhish Krishna S',
|
|
56
|
+
homepage: 'https://github.com/SimpleNotificationSystem/plugin-nodemailer-gmail',
|
|
57
|
+
requiredCredentials: ['EMAIL_USER', 'EMAIL_PASS'],
|
|
58
|
+
optionalConfig: ['EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_FROM'],
|
|
59
|
+
};
|
|
60
|
+
getNotificationSchema() {
|
|
61
|
+
return gmailNotificationSchema;
|
|
62
|
+
}
|
|
63
|
+
getRecipientSchema() {
|
|
64
|
+
return recipientSchema;
|
|
65
|
+
}
|
|
66
|
+
getContentSchema() {
|
|
67
|
+
return contentSchema;
|
|
68
|
+
}
|
|
69
|
+
getRateLimitConfig() {
|
|
70
|
+
// Gmail limits: ~500 emails/day for regular accounts
|
|
71
|
+
// ~2000/day for Google Workspace
|
|
72
|
+
// Default: 100 tokens, refill 10/second (~100/min max)
|
|
73
|
+
const options = this.config?.options;
|
|
74
|
+
const rateLimit = options?.rateLimit;
|
|
75
|
+
return {
|
|
76
|
+
maxTokens: rateLimit?.maxTokens || 100,
|
|
77
|
+
refillRate: rateLimit?.refillRate || 10,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async initialize(config) {
|
|
81
|
+
this.config = config;
|
|
82
|
+
const host = config.credentials['EMAIL_HOST'] || 'smtp.gmail.com';
|
|
83
|
+
const port = parseInt(config.credentials['EMAIL_PORT'] || '587', 10);
|
|
84
|
+
const user = config.credentials['EMAIL_USER'];
|
|
85
|
+
const pass = config.credentials['EMAIL_PASS'];
|
|
86
|
+
if (!user || !pass) {
|
|
87
|
+
throw new Error('EMAIL_USER and EMAIL_PASS are required');
|
|
88
|
+
}
|
|
89
|
+
this.fromEmail = config.credentials['EMAIL_FROM'] || user;
|
|
90
|
+
this.transporter = nodemailer.createTransport({
|
|
91
|
+
host,
|
|
92
|
+
port,
|
|
93
|
+
secure: port === 465,
|
|
94
|
+
auth: { user, pass },
|
|
95
|
+
connectionTimeout: 10000,
|
|
96
|
+
greetingTimeout: 10000,
|
|
97
|
+
socketTimeout: 30000,
|
|
98
|
+
});
|
|
99
|
+
console.log(`[GmailProvider] Initialized with host: ${host}:${port}`);
|
|
100
|
+
}
|
|
101
|
+
async healthCheck() {
|
|
102
|
+
if (!this.transporter) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
await this.transporter.verify();
|
|
107
|
+
console.log('[GmailProvider] SMTP connection verified');
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.error('[GmailProvider] Health check failed:', err);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async send(notification) {
|
|
116
|
+
if (!this.transporter) {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error: {
|
|
120
|
+
code: 'NOT_INITIALIZED',
|
|
121
|
+
message: 'Transporter not initialized',
|
|
122
|
+
retryable: false,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
let message = notification.content.message;
|
|
128
|
+
// Replace template variables
|
|
129
|
+
if (notification.variables) {
|
|
130
|
+
message = replaceVariables(message, notification.variables);
|
|
131
|
+
}
|
|
132
|
+
// Detect if message is HTML
|
|
133
|
+
const isHtml = isHtmlContent(message);
|
|
134
|
+
const mailOptions = {
|
|
135
|
+
from: this.fromEmail,
|
|
136
|
+
to: notification.recipient.email,
|
|
137
|
+
subject: notification.content.subject || 'Notification',
|
|
138
|
+
...(isHtml ? { html: message } : { text: message }),
|
|
139
|
+
};
|
|
140
|
+
const info = await this.transporter.sendMail(mailOptions);
|
|
141
|
+
console.log(`[GmailProvider] Email sent: ${info.messageId} to ${notification.recipient.email}`);
|
|
142
|
+
return {
|
|
143
|
+
success: true,
|
|
144
|
+
messageId: info.messageId,
|
|
145
|
+
providerResponse: info,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
150
|
+
// Determine if retryable
|
|
151
|
+
// Common non-retryable errors: invalid address, auth failure
|
|
152
|
+
const nonRetryablePatterns = [
|
|
153
|
+
'Invalid login',
|
|
154
|
+
'Authentication',
|
|
155
|
+
'Invalid mail',
|
|
156
|
+
'No recipients',
|
|
157
|
+
'Invalid email',
|
|
158
|
+
];
|
|
159
|
+
const retryable = !nonRetryablePatterns.some(p => errorMessage.toLowerCase().includes(p.toLowerCase()));
|
|
160
|
+
console.error(`[GmailProvider] Send failed:`, err);
|
|
161
|
+
return {
|
|
162
|
+
success: false,
|
|
163
|
+
error: {
|
|
164
|
+
code: 'SEND_FAILED',
|
|
165
|
+
message: errorMessage,
|
|
166
|
+
retryable,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async shutdown() {
|
|
172
|
+
if (this.transporter) {
|
|
173
|
+
this.transporter.close();
|
|
174
|
+
this.transporter = null;
|
|
175
|
+
console.log('[GmailProvider] Transporter closed');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Export the provider class as default
|
|
180
|
+
export default GmailProvider;
|
|
181
|
+
// Also export a factory function for convenience
|
|
182
|
+
export function createProvider() {
|
|
183
|
+
return new GmailProvider();
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@simplens/nodemailer-gmail",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Gmail/SMTP email provider plugin for SimpleNS using Nodemailer",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"simplens",
|
|
14
|
+
"plugin",
|
|
15
|
+
"email",
|
|
16
|
+
"gmail",
|
|
17
|
+
"nodemailer",
|
|
18
|
+
"smtp"
|
|
19
|
+
],
|
|
20
|
+
"author": "SimpleNS Team",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"simplens-sdk": "^1.0.1"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"nodemailer": "^6.9.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/nodemailer": "^6.4.0",
|
|
30
|
+
"typescript": "^5.0.0"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/SimpleNotificationSystem/plugin-nodemailer-gmail"
|
|
39
|
+
}
|
|
40
|
+
}
|