n8n-nodes-postmark-smtp 0.1.1 → 0.1.4

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,13 @@ 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
- - **Batch Send Email**: Send multiple emails in a single API request for better performance.
17
- - **Send Email with Template**: Use Postmark's template feature to send emails by providing a Template ID and a Model (JSON).
18
16
 
19
17
  ## Credentials
20
18
 
21
- This node requires two types of credentials:
19
+ This node requires a **Postmark API** credential which includes:
22
20
 
23
- 1. **Postmark Server Token**: Required for sending emails. You can find this in your Postmark server settings under "API Tokens".
24
- 2. **Postmark Account Token**: Required *only* if you want to use the "From (Domain)" dropdown to fetch verified domains. You can find this in your Postmark account settings.
21
+ 1. **Server Token**: Required for sending emails. You can find this in your Postmark server settings under "API Tokens".
22
+ 2. **Account Token**: Required *only* if you want to fetch verified domains dynamically. You can find this in your Postmark account settings.
25
23
 
26
24
  ## Installation
27
25
 
@@ -37,25 +35,16 @@ docker exec -it n8n npm install n8n-nodes-postmark-smtp
37
35
 
38
36
  ## Usage
39
37
 
40
- ### sending an Email
41
- 1. Select the **Send Email** operation.
42
- 2. Connect your **Postmark Server Token**.
43
- 3. (Optional) Connect your **Postmark Account Token** to auto-populate the *From (Domain)* field.
44
- 4. Enter the *From (Local Part)* (e.g., `info` for `info@example.com`).
45
- 5. Select a valid *From (Domain)*.
46
- 6. Enter the recipient(s) in *To*.
47
- 7. Fill in *Subject*, *HTML Body*, and *Text Body*.
48
-
49
- ### Sending with Templates
50
- 1. Select the **Send Email with Template** operation.
51
- 2. Enter the **Template ID** (found in Postmark UI).
52
- 3. Provide the **Template Model** as a JSON object matching your template variables.
53
- ```json
54
- {
55
- "user_name": "John Doe",
56
- "action_url": "https://example.com/login"
57
- }
58
- ```
38
+ ### Sending an Email
39
+ 1. Connect your **Postmark API** credential (fill in Server Token and optionally Account Token).
40
+ 2. Select a valid **From Domain** (dynamically loaded).
41
+ 3. (Optional) Enter **From Name**.
42
+ 4. Enter **From Email**. *Note: This must belong to the selected 'From Domain' or the node will error.*
43
+ 5. (Optional) Enter **To Name**.
44
+ 6. Enter **To Email**.
45
+ 7. (Optional) Enter **Cc** and **Bcc**.
46
+ 8. Fill in **Subject**, **HTML Body**, and **Text Body**.
47
+ 9. (Optional) Toggle **Attachments** to add files.
59
48
 
60
49
  ## Development
61
50
 
@@ -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;
@@ -9,7 +9,7 @@ class PostmarkSmtp {
9
9
  icon: 'file:postmark.svg',
10
10
  group: ['transform'],
11
11
  version: 1,
12
- subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
12
+ subtitle: 'Send Email',
13
13
  description: 'Send emails via Postmark API',
14
14
  defaults: {
15
15
  name: 'Postmark SMTP',
@@ -18,119 +18,74 @@ class PostmarkSmtp {
18
18
  outputs: ['main'],
19
19
  credentials: [
20
20
  {
21
- name: 'postmarkServerToken',
22
- required: true,
23
- },
24
- {
25
- name: 'postmarkAccountToken',
21
+ name: 'postmarkApi',
26
22
  required: true,
27
23
  },
28
24
  ],
29
25
  properties: [
30
26
  {
31
- displayName: 'Resource',
32
- name: 'resource',
27
+ displayName: 'From Domain',
28
+ name: 'fromDomain',
33
29
  type: 'options',
34
- noDataExpression: true,
35
- options: [
36
- {
37
- name: 'Email',
38
- value: 'email',
39
- },
40
- ],
41
- default: 'email',
30
+ required: true,
31
+ typeOptions: {
32
+ loadOptionsMethod: 'getDomains',
33
+ },
34
+ default: '',
35
+ description: 'Choose a verified domain',
42
36
  },
43
37
  {
44
- displayName: 'Operation',
45
- name: 'operation',
46
- type: 'options',
47
- noDataExpression: true,
48
- displayOptions: {
49
- show: {
50
- resource: ['email'],
51
- },
52
- },
53
- options: [
54
- {
55
- name: 'Send Email',
56
- value: 'sendEmail',
57
- action: 'Send an email',
58
- },
59
- {
60
- name: 'Batch Send Email',
61
- value: 'batchSendEmail',
62
- action: 'Send multiple emails in a batch',
63
- },
64
- {
65
- name: 'Send Email with Template',
66
- value: 'sendEmailWithTemplate',
67
- action: 'Send an email using a template',
68
- },
69
- ],
70
- default: 'sendEmail',
38
+ displayName: 'From Name',
39
+ name: 'fromName',
40
+ type: 'string',
41
+ default: '',
42
+ placeholder: 'Sender Name',
71
43
  },
72
- // ----------------------------------
73
- // sendEmail
74
- // ----------------------------------
75
44
  {
76
- displayName: 'From (Local Part)',
77
- name: 'fromLocalPart',
45
+ displayName: 'From Email',
46
+ name: 'fromEmail',
78
47
  type: 'string',
79
48
  default: '',
80
- placeholder: 'sender',
49
+ placeholder: 'sender@example.com',
81
50
  required: true,
82
- displayOptions: {
83
- show: {
84
- operation: ['sendEmail', 'batchSendEmail'],
85
- resource: ['email'],
86
- },
87
- },
88
- description: 'The local part of the sender email address (before @)',
51
+ description: 'The sender email address. Must be from the selected domain.',
89
52
  },
90
53
  {
91
- displayName: 'From (Domain)',
92
- name: 'fromDomain',
93
- type: 'options',
94
- required: true,
95
- typeOptions: {
96
- loadOptionsMethod: 'getDomains',
97
- },
54
+ displayName: 'To Name',
55
+ name: 'toName',
56
+ type: 'string',
98
57
  default: '',
99
- displayOptions: {
100
- show: {
101
- operation: ['sendEmail', 'batchSendEmail'],
102
- resource: ['email'],
103
- },
104
- },
105
- description: 'Choose a verified domain',
58
+ placeholder: 'Recipient Name',
106
59
  },
107
60
  {
108
- displayName: 'To',
109
- name: 'to',
61
+ displayName: 'To Email',
62
+ name: 'toEmail',
110
63
  type: 'string',
111
64
  default: '',
112
65
  placeholder: 'receiver@example.com',
113
66
  required: true,
114
- displayOptions: {
115
- show: {
116
- operation: ['sendEmail', 'sendEmailWithTemplate'],
117
- resource: ['email'],
118
- },
119
- },
120
67
  description: 'Comma separated list of recipients',
121
68
  },
69
+ {
70
+ displayName: 'Cc',
71
+ name: 'cc',
72
+ type: 'string',
73
+ default: '',
74
+ placeholder: 'cc@example.com',
75
+ },
76
+ {
77
+ displayName: 'Bcc',
78
+ name: 'bcc',
79
+ type: 'string',
80
+ default: '',
81
+ placeholder: 'bcc@example.com',
82
+ },
122
83
  {
123
84
  displayName: 'Subject',
124
85
  name: 'subject',
125
86
  type: 'string',
126
87
  default: '',
127
88
  required: true,
128
- displayOptions: {
129
- show: {
130
- operation: ['sendEmail'],
131
- resource: ['email'],
132
- },
133
- },
134
89
  },
135
90
  {
136
91
  displayName: 'HTML Body',
@@ -140,12 +95,6 @@ class PostmarkSmtp {
140
95
  rows: 5,
141
96
  },
142
97
  default: '',
143
- displayOptions: {
144
- show: {
145
- operation: ['sendEmail'],
146
- resource: ['email'],
147
- },
148
- },
149
98
  },
150
99
  {
151
100
  displayName: 'Text Body',
@@ -155,39 +104,26 @@ class PostmarkSmtp {
155
104
  rows: 5,
156
105
  },
157
106
  default: '',
158
- displayOptions: {
159
- show: {
160
- operation: ['sendEmail'],
161
- resource: ['email'],
162
- },
163
- },
164
107
  },
165
108
  {
166
109
  displayName: 'Attachments',
167
110
  name: 'attachmentsToggle',
168
111
  type: 'boolean',
169
112
  default: false,
170
- displayOptions: {
171
- show: {
172
- operation: ['sendEmail'],
173
- resource: ['email'],
174
- },
175
- },
113
+ description: 'Whether to add attachments',
176
114
  },
177
115
  {
178
116
  displayName: 'Attachments',
179
117
  name: 'attachments',
180
118
  type: 'fixedCollection',
181
- typeOptions: {
182
- multipleValues: true,
183
- },
184
119
  displayOptions: {
185
120
  show: {
186
121
  attachmentsToggle: [true],
187
- operation: ['sendEmail'],
188
- resource: ['email'],
189
122
  },
190
123
  },
124
+ typeOptions: {
125
+ multipleValues: true,
126
+ },
191
127
  options: [
192
128
  {
193
129
  name: 'attachment',
@@ -212,98 +148,12 @@ class PostmarkSmtp {
212
148
  ],
213
149
  default: {},
214
150
  },
215
- // Additional fields for Send Email
216
- {
217
- displayName: 'Cc',
218
- name: 'cc',
219
- type: 'string',
220
- default: '',
221
- displayOptions: {
222
- show: {
223
- operation: ['sendEmail', 'sendEmailWithTemplate'],
224
- resource: ['email'],
225
- },
226
- },
227
- },
228
- {
229
- displayName: 'Bcc',
230
- name: 'bcc',
231
- type: 'string',
232
- default: '',
233
- displayOptions: {
234
- show: {
235
- operation: ['sendEmail', 'sendEmailWithTemplate'],
236
- resource: ['email'],
237
- },
238
- },
239
- },
240
- // ----------------------------------
241
- // sendEmailWithTemplate
242
- // ----------------------------------
243
- {
244
- displayName: 'Template ID',
245
- name: 'templateId',
246
- type: 'string',
247
- default: '',
248
- required: true,
249
- displayOptions: {
250
- show: {
251
- operation: ['sendEmailWithTemplate'],
252
- resource: ['email'],
253
- },
254
- },
255
- },
256
- {
257
- displayName: 'Template Model',
258
- name: 'templateModel',
259
- type: 'json',
260
- default: '{}',
261
- required: true,
262
- displayOptions: {
263
- show: {
264
- operation: ['sendEmailWithTemplate'],
265
- resource: ['email'],
266
- },
267
- },
268
- description: 'JSON object containing the template model values',
269
- },
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
151
  ],
302
152
  };
303
153
  this.methods = {
304
154
  loadOptions: {
305
155
  async getDomains() {
306
- const credentials = await this.getCredentials('postmarkAccountToken');
156
+ const credentials = await this.getCredentials('postmarkApi');
307
157
  const token = credentials.accountToken;
308
158
  const options = {
309
159
  method: 'GET',
@@ -327,107 +177,81 @@ class PostmarkSmtp {
327
177
  async execute() {
328
178
  const items = this.getInputData();
329
179
  const returnData = [];
330
- const operation = this.getNodeParameter('operation', 0);
331
- const credentials = await this.getCredentials('postmarkServerToken');
180
+ const credentials = await this.getCredentials('postmarkApi');
332
181
  const serverToken = credentials.serverToken;
333
182
  for (let i = 0; i < items.length; i++) {
334
183
  try {
335
- let responseData;
336
- if (operation === 'sendEmail') {
337
- const fromLocalPart = this.getNodeParameter('fromLocalPart', i);
338
- const fromDomain = this.getNodeParameter('fromDomain', i);
339
- const from = `${fromLocalPart}@${fromDomain}`;
340
- const to = this.getNodeParameter('to', i);
341
- const subject = this.getNodeParameter('subject', i);
342
- const htmlBody = this.getNodeParameter('htmlBody', i);
343
- const textBody = this.getNodeParameter('textBody', i);
344
- const cc = this.getNodeParameter('cc', i);
345
- const bcc = this.getNodeParameter('bcc', i);
346
- const body = {
347
- From: from,
348
- To: to,
349
- Subject: subject,
350
- HtmlBody: htmlBody,
351
- TextBody: textBody,
352
- Cc: cc,
353
- Bcc: bcc,
354
- MessageStream: 'outbound',
355
- };
356
- // Handle Attachments
357
- const attachmentsToggle = this.getNodeParameter('attachmentsToggle', i);
358
- if (attachmentsToggle) {
359
- const attachmentsConfig = this.getNodeParameter('attachments', i);
360
- const attachments = [];
361
- if (attachmentsConfig && attachmentsConfig.attachment) {
362
- for (const att of attachmentsConfig.attachment) {
363
- const propertyName = att.propertyName;
364
- const binaryData = this.helpers.assertBinaryData(i, propertyName);
365
- const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, propertyName);
366
- attachments.push({
367
- Name: att.fileName || binaryData.fileName || 'attachment',
368
- Content: binaryDataBuffer.toString('base64'),
369
- ContentType: binaryData.mimeType,
370
- });
371
- }
372
- }
373
- if (attachments.length > 0) {
374
- body.Attachments = attachments;
375
- }
184
+ const fromDomain = this.getNodeParameter('fromDomain', i);
185
+ const fromName = this.getNodeParameter('fromName', i);
186
+ const fromEmail = this.getNodeParameter('fromEmail', i);
187
+ if (!fromEmail.toLowerCase().endsWith('@' + fromDomain.toLowerCase())) {
188
+ if (this.continueOnFail()) {
189
+ returnData.push({
190
+ json: {
191
+ error: `From Email (${fromEmail}) must belong to the selected domain (${fromDomain})`,
192
+ },
193
+ });
194
+ continue;
376
195
  }
377
- const options = {
378
- method: 'POST',
379
- uri: 'https://api.postmarkapp.com/email',
380
- headers: {
381
- 'X-Postmark-Server-Token': serverToken,
382
- 'Accept': 'application/json',
383
- },
384
- body: body,
385
- json: true,
386
- };
387
- responseData = await this.helpers.request(options);
196
+ throw new Error(`From Email (${fromEmail}) must belong to the selected domain (${fromDomain})`);
388
197
  }
389
- else if (operation === 'sendEmailWithTemplate') {
390
- const from = this.getNodeParameter('from', i);
391
- const to = this.getNodeParameter('to', i);
392
- const templateId = this.getNodeParameter('templateId', i);
393
- const templateModel = this.getNodeParameter('templateModel', i);
394
- const cc = this.getNodeParameter('cc', i);
395
- const bcc = this.getNodeParameter('bcc', i);
396
- const body = {
397
- From: from,
398
- To: to,
399
- TemplateId: templateId,
400
- TemplateModel: templateModel,
401
- Cc: cc,
402
- Bcc: bcc,
403
- MessageStream: 'outbound',
404
- };
405
- const options = {
406
- method: 'POST',
407
- uri: 'https://api.postmarkapp.com/email/withTemplate',
408
- headers: {
409
- 'X-Postmark-Server-Token': serverToken,
410
- 'Accept': 'application/json',
411
- },
412
- body: body,
413
- json: true,
414
- };
415
- responseData = await this.helpers.request(options);
198
+ let from = fromEmail;
199
+ if (fromName) {
200
+ from = `"${fromName}" <${fromEmail}>`;
416
201
  }
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);
202
+ const toName = this.getNodeParameter('toName', i);
203
+ const toEmail = this.getNodeParameter('toEmail', i);
204
+ let to = toEmail;
205
+ if (toName) {
206
+ to = `"${toName}" <${toEmail}>`;
430
207
  }
208
+ const cc = this.getNodeParameter('cc', i);
209
+ const bcc = this.getNodeParameter('bcc', i);
210
+ const subject = this.getNodeParameter('subject', i);
211
+ const htmlBody = this.getNodeParameter('htmlBody', i);
212
+ const textBody = this.getNodeParameter('textBody', i);
213
+ const body = {
214
+ From: from,
215
+ To: to,
216
+ Subject: subject,
217
+ HtmlBody: htmlBody,
218
+ TextBody: textBody,
219
+ Cc: cc,
220
+ Bcc: bcc,
221
+ MessageStream: 'outbound',
222
+ };
223
+ // Handle Attachments
224
+ const attachmentsToggle = this.getNodeParameter('attachmentsToggle', i);
225
+ if (attachmentsToggle) {
226
+ const attachmentsConfig = this.getNodeParameter('attachments', i);
227
+ const attachments = [];
228
+ if (attachmentsConfig && attachmentsConfig.attachment) {
229
+ for (const att of attachmentsConfig.attachment) {
230
+ const propertyName = att.propertyName;
231
+ const binaryData = this.helpers.assertBinaryData(i, propertyName);
232
+ const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, propertyName);
233
+ attachments.push({
234
+ Name: att.fileName || binaryData.fileName || 'attachment',
235
+ Content: binaryDataBuffer.toString('base64'),
236
+ ContentType: binaryData.mimeType,
237
+ });
238
+ }
239
+ }
240
+ if (attachments.length > 0) {
241
+ body.Attachments = attachments;
242
+ }
243
+ }
244
+ const options = {
245
+ method: 'POST',
246
+ uri: 'https://api.postmarkapp.com/email',
247
+ headers: {
248
+ 'X-Postmark-Server-Token': serverToken,
249
+ 'Accept': 'application/json',
250
+ },
251
+ body: body,
252
+ json: true,
253
+ };
254
+ const responseData = await this.helpers.request(options);
431
255
  returnData.push({
432
256
  json: responseData,
433
257
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-postmark-smtp",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
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/PostmarkServerToken.credentials.js",
36
- "dist/credentials/PostmarkAccountToken.credentials.js"
35
+ "dist/credentials/PostmarkApi.credentials.js"
37
36
  ]
38
37
  },
39
38
  "devDependencies": {