n8n-nodes-postmark-smtp 0.1.1 → 0.1.3
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
CHANGED
|
@@ -13,15 +13,14 @@ This is an n8n community node. It lets you use Postmark to send transactional em
|
|
|
13
13
|
- Attachments (binary data).
|
|
14
14
|
- CC and BCC recipients.
|
|
15
15
|
- Dynamic sender verification (loads verified domains from your account).
|
|
16
|
-
- **
|
|
17
|
-
- **Send Email with Template**: Use Postmark's template feature to send emails by providing a Template ID and a Model (JSON).
|
|
16
|
+
- **Send Email with Template**: Use Postmark's template feature to send emails with full sender/recipient control.
|
|
18
17
|
|
|
19
18
|
## Credentials
|
|
20
19
|
|
|
21
|
-
This node requires
|
|
20
|
+
This node requires a **Postmark API** credential which includes:
|
|
22
21
|
|
|
23
|
-
1. **
|
|
24
|
-
2. **
|
|
22
|
+
1. **Server Token**: Required for sending emails. You can find this in your Postmark server settings under "API Tokens".
|
|
23
|
+
2. **Account Token**: Required *only* if you want to fetch verified domains dynamically. You can find this in your Postmark account settings.
|
|
25
24
|
|
|
26
25
|
## Installation
|
|
27
26
|
|
|
@@ -37,25 +36,31 @@ docker exec -it n8n npm install n8n-nodes-postmark-smtp
|
|
|
37
36
|
|
|
38
37
|
## Usage
|
|
39
38
|
|
|
40
|
-
###
|
|
39
|
+
### Sending an Email
|
|
41
40
|
1. Select the **Send Email** operation.
|
|
42
|
-
2. Connect your **Postmark Server Token
|
|
43
|
-
3.
|
|
44
|
-
4.
|
|
45
|
-
5.
|
|
46
|
-
6.
|
|
47
|
-
7.
|
|
41
|
+
2. Connect your **Postmark API** credential (fill in Server Token and optionally Account Token).
|
|
42
|
+
3. Select a valid **From Domain** (dynamically loaded).
|
|
43
|
+
4. (Optional) Enter **From Name**.
|
|
44
|
+
5. Enter **From Email**. *Note: This must belong to the selected 'From Domain' or the node will error.*
|
|
45
|
+
6. (Optional) Enter **To Name**.
|
|
46
|
+
7. Enter **To Email**.
|
|
47
|
+
8. Fill in *Subject*, *HTML Body*, and *Text Body*.
|
|
48
48
|
|
|
49
49
|
### Sending with Templates
|
|
50
50
|
1. Select the **Send Email with Template** operation.
|
|
51
|
-
2.
|
|
52
|
-
3.
|
|
51
|
+
2. Connect your **Postmark API** credential.
|
|
52
|
+
3. Select a valid **From Domain**.
|
|
53
|
+
4. Enter **From Name** and **From Email**.
|
|
54
|
+
5. Enter **To Name** and **To Email**.
|
|
55
|
+
6. Enter the **Template ID** (found in Postmark UI).
|
|
56
|
+
7. Provide the **Template Model** as a JSON object matching your template variables.
|
|
53
57
|
```json
|
|
54
58
|
{
|
|
55
59
|
"user_name": "John Doe",
|
|
56
60
|
"action_url": "https://example.com/login"
|
|
57
61
|
}
|
|
58
62
|
```
|
|
63
|
+
8. (Optional) Add **Attachments**.
|
|
59
64
|
|
|
60
65
|
## Development
|
|
61
66
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostmarkApi = void 0;
|
|
4
|
+
class PostmarkApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'postmarkApi';
|
|
7
|
+
this.displayName = 'Postmark API';
|
|
8
|
+
this.documentationUrl = 'https://postmarkapp.com/developer';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'Server Token',
|
|
12
|
+
name: 'serverToken',
|
|
13
|
+
type: 'string',
|
|
14
|
+
default: '',
|
|
15
|
+
typeOptions: {
|
|
16
|
+
password: true,
|
|
17
|
+
},
|
|
18
|
+
description: 'The "Server API Token" found in your server settings.',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
displayName: 'Account Token',
|
|
22
|
+
name: 'accountToken',
|
|
23
|
+
type: 'string',
|
|
24
|
+
default: '',
|
|
25
|
+
typeOptions: {
|
|
26
|
+
password: true,
|
|
27
|
+
},
|
|
28
|
+
description: 'The "Account API Token" found in your account settings. Required fopr fetching verified domains.',
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.PostmarkApi = PostmarkApi;
|
|
@@ -18,11 +18,7 @@ class PostmarkSmtp {
|
|
|
18
18
|
outputs: ['main'],
|
|
19
19
|
credentials: [
|
|
20
20
|
{
|
|
21
|
-
name: '
|
|
22
|
-
required: true,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: 'postmarkAccountToken',
|
|
21
|
+
name: 'postmarkApi',
|
|
26
22
|
required: true,
|
|
27
23
|
},
|
|
28
24
|
],
|
|
@@ -56,11 +52,6 @@ class PostmarkSmtp {
|
|
|
56
52
|
value: 'sendEmail',
|
|
57
53
|
action: 'Send an email',
|
|
58
54
|
},
|
|
59
|
-
{
|
|
60
|
-
name: 'Batch Send Email',
|
|
61
|
-
value: 'batchSendEmail',
|
|
62
|
-
action: 'Send multiple emails in a batch',
|
|
63
|
-
},
|
|
64
55
|
{
|
|
65
56
|
name: 'Send Email with Template',
|
|
66
57
|
value: 'sendEmailWithTemplate',
|
|
@@ -69,44 +60,67 @@ class PostmarkSmtp {
|
|
|
69
60
|
],
|
|
70
61
|
default: 'sendEmail',
|
|
71
62
|
},
|
|
72
|
-
// ----------------------------------
|
|
73
|
-
// sendEmail
|
|
74
|
-
// ----------------------------------
|
|
75
63
|
{
|
|
76
|
-
displayName: 'From
|
|
77
|
-
name: '
|
|
64
|
+
displayName: 'From Domain',
|
|
65
|
+
name: 'fromDomain',
|
|
66
|
+
type: 'options',
|
|
67
|
+
required: true,
|
|
68
|
+
typeOptions: {
|
|
69
|
+
loadOptionsMethod: 'getDomains',
|
|
70
|
+
},
|
|
71
|
+
default: '',
|
|
72
|
+
displayOptions: {
|
|
73
|
+
show: {
|
|
74
|
+
operation: ['sendEmail', 'sendEmailWithTemplate'],
|
|
75
|
+
resource: ['email'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
description: 'Choose a verified domain',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
displayName: 'From Name',
|
|
82
|
+
name: 'fromName',
|
|
78
83
|
type: 'string',
|
|
79
84
|
default: '',
|
|
80
|
-
placeholder: '
|
|
81
|
-
required: true,
|
|
85
|
+
placeholder: 'Sender Name',
|
|
82
86
|
displayOptions: {
|
|
83
87
|
show: {
|
|
84
|
-
operation: ['sendEmail', '
|
|
88
|
+
operation: ['sendEmail', 'sendEmailWithTemplate'],
|
|
85
89
|
resource: ['email'],
|
|
86
90
|
},
|
|
87
91
|
},
|
|
88
|
-
description: 'The local part of the sender email address (before @)',
|
|
89
92
|
},
|
|
90
93
|
{
|
|
91
|
-
displayName: 'From
|
|
92
|
-
name: '
|
|
93
|
-
type: '
|
|
94
|
+
displayName: 'From Email',
|
|
95
|
+
name: 'fromEmail',
|
|
96
|
+
type: 'string',
|
|
97
|
+
default: '',
|
|
98
|
+
placeholder: 'sender@example.com',
|
|
94
99
|
required: true,
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
displayOptions: {
|
|
101
|
+
show: {
|
|
102
|
+
operation: ['sendEmail', 'sendEmailWithTemplate'],
|
|
103
|
+
resource: ['email'],
|
|
104
|
+
},
|
|
97
105
|
},
|
|
106
|
+
description: 'The sender email address. Must be from the selected domain.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: 'To Name',
|
|
110
|
+
name: 'toName',
|
|
111
|
+
type: 'string',
|
|
98
112
|
default: '',
|
|
113
|
+
placeholder: 'Recipient Name',
|
|
99
114
|
displayOptions: {
|
|
100
115
|
show: {
|
|
101
|
-
operation: ['sendEmail', '
|
|
116
|
+
operation: ['sendEmail', 'sendEmailWithTemplate'],
|
|
102
117
|
resource: ['email'],
|
|
103
118
|
},
|
|
104
119
|
},
|
|
105
|
-
description: 'Choose a verified domain',
|
|
106
120
|
},
|
|
107
121
|
{
|
|
108
|
-
displayName: 'To',
|
|
109
|
-
name: '
|
|
122
|
+
displayName: 'To Email',
|
|
123
|
+
name: 'toEmail',
|
|
110
124
|
type: 'string',
|
|
111
125
|
default: '',
|
|
112
126
|
placeholder: 'receiver@example.com',
|
|
@@ -169,7 +183,7 @@ class PostmarkSmtp {
|
|
|
169
183
|
default: false,
|
|
170
184
|
displayOptions: {
|
|
171
185
|
show: {
|
|
172
|
-
operation: ['sendEmail'],
|
|
186
|
+
operation: ['sendEmail', 'sendEmailWithTemplate'],
|
|
173
187
|
resource: ['email'],
|
|
174
188
|
},
|
|
175
189
|
},
|
|
@@ -184,7 +198,7 @@ class PostmarkSmtp {
|
|
|
184
198
|
displayOptions: {
|
|
185
199
|
show: {
|
|
186
200
|
attachmentsToggle: [true],
|
|
187
|
-
operation: ['sendEmail'],
|
|
201
|
+
operation: ['sendEmail', 'sendEmailWithTemplate'],
|
|
188
202
|
resource: ['email'],
|
|
189
203
|
},
|
|
190
204
|
},
|
|
@@ -267,43 +281,12 @@ class PostmarkSmtp {
|
|
|
267
281
|
},
|
|
268
282
|
description: 'JSON object containing the template model values',
|
|
269
283
|
},
|
|
270
|
-
{
|
|
271
|
-
displayName: 'From',
|
|
272
|
-
name: 'from',
|
|
273
|
-
type: 'string',
|
|
274
|
-
default: '',
|
|
275
|
-
required: true,
|
|
276
|
-
displayOptions: {
|
|
277
|
-
show: {
|
|
278
|
-
operation: ['sendEmailWithTemplate'],
|
|
279
|
-
resource: ['email'],
|
|
280
|
-
},
|
|
281
|
-
},
|
|
282
|
-
description: 'The sender email address',
|
|
283
|
-
},
|
|
284
|
-
// ----------------------------------
|
|
285
|
-
// batchSendEmail
|
|
286
|
-
// ----------------------------------
|
|
287
|
-
{
|
|
288
|
-
displayName: 'Batch Input (JSON)',
|
|
289
|
-
name: 'batchInput',
|
|
290
|
-
type: 'json',
|
|
291
|
-
default: '[]',
|
|
292
|
-
required: true,
|
|
293
|
-
displayOptions: {
|
|
294
|
-
show: {
|
|
295
|
-
operation: ['batchSendEmail'],
|
|
296
|
-
resource: ['email'],
|
|
297
|
-
},
|
|
298
|
-
},
|
|
299
|
-
description: 'Array of email objects to send in batch',
|
|
300
|
-
},
|
|
301
284
|
],
|
|
302
285
|
};
|
|
303
286
|
this.methods = {
|
|
304
287
|
loadOptions: {
|
|
305
288
|
async getDomains() {
|
|
306
|
-
const credentials = await this.getCredentials('
|
|
289
|
+
const credentials = await this.getCredentials('postmarkApi');
|
|
307
290
|
const token = credentials.accountToken;
|
|
308
291
|
const options = {
|
|
309
292
|
method: 'GET',
|
|
@@ -328,16 +311,36 @@ class PostmarkSmtp {
|
|
|
328
311
|
const items = this.getInputData();
|
|
329
312
|
const returnData = [];
|
|
330
313
|
const operation = this.getNodeParameter('operation', 0);
|
|
331
|
-
const credentials = await this.getCredentials('
|
|
314
|
+
const credentials = await this.getCredentials('postmarkApi');
|
|
332
315
|
const serverToken = credentials.serverToken;
|
|
333
316
|
for (let i = 0; i < items.length; i++) {
|
|
334
317
|
try {
|
|
335
318
|
let responseData;
|
|
336
319
|
if (operation === 'sendEmail') {
|
|
337
|
-
const fromLocalPart = this.getNodeParameter('fromLocalPart', i);
|
|
338
320
|
const fromDomain = this.getNodeParameter('fromDomain', i);
|
|
339
|
-
const
|
|
340
|
-
const
|
|
321
|
+
const fromName = this.getNodeParameter('fromName', i);
|
|
322
|
+
const fromEmail = this.getNodeParameter('fromEmail', i);
|
|
323
|
+
if (!fromEmail.toLowerCase().endsWith('@' + fromDomain.toLowerCase())) {
|
|
324
|
+
if (this.continueOnFail()) {
|
|
325
|
+
returnData.push({
|
|
326
|
+
json: {
|
|
327
|
+
error: `From Email (${fromEmail}) must belong to the selected domain (${fromDomain})`,
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
throw new Error(`From Email (${fromEmail}) must belong to the selected domain (${fromDomain})`);
|
|
333
|
+
}
|
|
334
|
+
let from = fromEmail;
|
|
335
|
+
if (fromName) {
|
|
336
|
+
from = `"${fromName}" <${fromEmail}>`;
|
|
337
|
+
}
|
|
338
|
+
const toName = this.getNodeParameter('toName', i);
|
|
339
|
+
const toEmail = this.getNodeParameter('toEmail', i);
|
|
340
|
+
let to = toEmail;
|
|
341
|
+
if (toName) {
|
|
342
|
+
to = `"${toName}" <${toEmail}>`;
|
|
343
|
+
}
|
|
341
344
|
const subject = this.getNodeParameter('subject', i);
|
|
342
345
|
const htmlBody = this.getNodeParameter('htmlBody', i);
|
|
343
346
|
const textBody = this.getNodeParameter('textBody', i);
|
|
@@ -387,8 +390,30 @@ class PostmarkSmtp {
|
|
|
387
390
|
responseData = await this.helpers.request(options);
|
|
388
391
|
}
|
|
389
392
|
else if (operation === 'sendEmailWithTemplate') {
|
|
390
|
-
const
|
|
391
|
-
const
|
|
393
|
+
const fromDomain = this.getNodeParameter('fromDomain', i);
|
|
394
|
+
const fromName = this.getNodeParameter('fromName', i);
|
|
395
|
+
const fromEmail = this.getNodeParameter('fromEmail', i);
|
|
396
|
+
if (!fromEmail.toLowerCase().endsWith('@' + fromDomain.toLowerCase())) {
|
|
397
|
+
if (this.continueOnFail()) {
|
|
398
|
+
returnData.push({
|
|
399
|
+
json: {
|
|
400
|
+
error: `From Email (${fromEmail}) must belong to the selected domain (${fromDomain})`,
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
throw new Error(`From Email (${fromEmail}) must belong to the selected domain (${fromDomain})`);
|
|
406
|
+
}
|
|
407
|
+
let from = fromEmail;
|
|
408
|
+
if (fromName) {
|
|
409
|
+
from = `"${fromName}" <${fromEmail}>`;
|
|
410
|
+
}
|
|
411
|
+
const toName = this.getNodeParameter('toName', i);
|
|
412
|
+
const toEmail = this.getNodeParameter('toEmail', i);
|
|
413
|
+
let to = toEmail;
|
|
414
|
+
if (toName) {
|
|
415
|
+
to = `"${toName}" <${toEmail}>`;
|
|
416
|
+
}
|
|
392
417
|
const templateId = this.getNodeParameter('templateId', i);
|
|
393
418
|
const templateModel = this.getNodeParameter('templateModel', i);
|
|
394
419
|
const cc = this.getNodeParameter('cc', i);
|
|
@@ -402,6 +427,27 @@ class PostmarkSmtp {
|
|
|
402
427
|
Bcc: bcc,
|
|
403
428
|
MessageStream: 'outbound',
|
|
404
429
|
};
|
|
430
|
+
// Handle Attachments
|
|
431
|
+
const attachmentsToggle = this.getNodeParameter('attachmentsToggle', i);
|
|
432
|
+
if (attachmentsToggle) {
|
|
433
|
+
const attachmentsConfig = this.getNodeParameter('attachments', i);
|
|
434
|
+
const attachments = [];
|
|
435
|
+
if (attachmentsConfig && attachmentsConfig.attachment) {
|
|
436
|
+
for (const att of attachmentsConfig.attachment) {
|
|
437
|
+
const propertyName = att.propertyName;
|
|
438
|
+
const binaryData = this.helpers.assertBinaryData(i, propertyName);
|
|
439
|
+
const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, propertyName);
|
|
440
|
+
attachments.push({
|
|
441
|
+
Name: att.fileName || binaryData.fileName || 'attachment',
|
|
442
|
+
Content: binaryDataBuffer.toString('base64'),
|
|
443
|
+
ContentType: binaryData.mimeType,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (attachments.length > 0) {
|
|
448
|
+
body.Attachments = attachments;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
405
451
|
const options = {
|
|
406
452
|
method: 'POST',
|
|
407
453
|
uri: 'https://api.postmarkapp.com/email/withTemplate',
|
|
@@ -414,20 +460,6 @@ class PostmarkSmtp {
|
|
|
414
460
|
};
|
|
415
461
|
responseData = await this.helpers.request(options);
|
|
416
462
|
}
|
|
417
|
-
else if (operation === 'batchSendEmail') {
|
|
418
|
-
const batchInput = this.getNodeParameter('batchInput', i);
|
|
419
|
-
const options = {
|
|
420
|
-
method: 'POST',
|
|
421
|
-
uri: 'https://api.postmarkapp.com/email/batch',
|
|
422
|
-
headers: {
|
|
423
|
-
'X-Postmark-Server-Token': serverToken,
|
|
424
|
-
'Accept': 'application/json',
|
|
425
|
-
},
|
|
426
|
-
body: batchInput,
|
|
427
|
-
json: true,
|
|
428
|
-
};
|
|
429
|
-
responseData = await this.helpers.request(options);
|
|
430
|
-
}
|
|
431
463
|
returnData.push({
|
|
432
464
|
json: responseData,
|
|
433
465
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-postmark-smtp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Postmark SMTP node for n8n",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package"
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"dist/nodes/PostmarkSmtp/PostmarkSmtp.node.js"
|
|
33
33
|
],
|
|
34
34
|
"credentials": [
|
|
35
|
-
"dist/credentials/
|
|
36
|
-
"dist/credentials/PostmarkAccountToken.credentials.js"
|
|
35
|
+
"dist/credentials/PostmarkApi.credentials.js"
|
|
37
36
|
]
|
|
38
37
|
},
|
|
39
38
|
"devDependencies": {
|