@limetech/n8n-nodes-lime 3.10.3 → 3.11.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/CHANGELOG.md +20 -0
- package/credentials/LimeCrmApi.credentials.ts +1 -0
- package/credentials/LimeFormsApi.credentials.ts +1 -0
- package/credentials/LimeMarketingApi.credentials.ts +92 -0
- package/credentials/assets/lime-crm.svg +1 -0
- package/credentials/index.ts +1 -0
- package/dist/credentials/LimeCrmApi.credentials.d.ts +1 -0
- package/dist/credentials/LimeCrmApi.credentials.js +1 -0
- package/dist/credentials/LimeCrmApi.credentials.js.map +1 -1
- package/dist/credentials/LimeFormsApi.credentials.d.ts +1 -0
- package/dist/credentials/LimeFormsApi.credentials.js +1 -0
- package/dist/credentials/LimeFormsApi.credentials.js.map +1 -1
- package/dist/credentials/LimeMarketingApi.credentials.d.ts +9 -0
- package/dist/credentials/LimeMarketingApi.credentials.js +64 -0
- package/dist/credentials/LimeMarketingApi.credentials.js.map +1 -0
- package/dist/credentials/assets/lime-crm.svg +1 -0
- package/dist/credentials/index.d.ts +1 -0
- package/dist/credentials/index.js +1 -0
- package/dist/credentials/index.js.map +1 -1
- package/dist/nodes/index.d.ts +1 -0
- package/dist/nodes/index.js +1 -0
- package/dist/nodes/index.js.map +1 -1
- package/dist/nodes/lime-crm/assets/lime-crm.svg +0 -0
- package/dist/nodes/lime-forms/assets/lime-crm.svg +0 -0
- package/dist/nodes/lime-marketing/LimeMarketing.node.d.ts +16 -0
- package/dist/nodes/lime-marketing/LimeMarketing.node.js +121 -0
- package/dist/nodes/lime-marketing/LimeMarketing.node.js.map +1 -0
- package/dist/nodes/lime-marketing/assets/lime-crm.svg +1 -0
- package/dist/nodes/lime-marketing/index.d.ts +1 -0
- package/dist/nodes/lime-marketing/index.js +18 -0
- package/dist/nodes/lime-marketing/index.js.map +1 -0
- package/dist/nodes/lime-marketing/methods/getTemplateMergeCodeMappingColumns.d.ts +3 -0
- package/dist/nodes/lime-marketing/methods/getTemplateMergeCodeMappingColumns.js +52 -0
- package/dist/nodes/lime-marketing/methods/getTemplateMergeCodeMappingColumns.js.map +1 -0
- package/dist/nodes/lime-marketing/methods/getTemplates.d.ts +2 -0
- package/dist/nodes/lime-marketing/methods/getTemplates.js +24 -0
- package/dist/nodes/lime-marketing/methods/getTemplates.js.map +1 -0
- package/dist/nodes/lime-marketing/methods/index.d.ts +2 -0
- package/dist/nodes/lime-marketing/methods/index.js +8 -0
- package/dist/nodes/lime-marketing/methods/index.js.map +1 -0
- package/dist/nodes/lime-marketing/models/constants.d.ts +9 -0
- package/dist/nodes/lime-marketing/models/constants.js +13 -0
- package/dist/nodes/lime-marketing/models/constants.js.map +1 -0
- package/dist/nodes/lime-marketing/models/index.d.ts +6 -0
- package/dist/nodes/lime-marketing/models/index.js +14 -0
- package/dist/nodes/lime-marketing/models/index.js.map +1 -0
- package/dist/nodes/lime-marketing/models/operationInputs.d.ts +36 -0
- package/dist/nodes/lime-marketing/models/operationInputs.js +3 -0
- package/dist/nodes/lime-marketing/models/operationInputs.js.map +1 -0
- package/dist/nodes/lime-marketing/models/template.d.ts +10 -0
- package/dist/nodes/lime-marketing/models/template.js +3 -0
- package/dist/nodes/lime-marketing/models/template.js.map +1 -0
- package/dist/nodes/lime-marketing/models/transactionMail.d.ts +60 -0
- package/dist/nodes/lime-marketing/models/transactionMail.js +3 -0
- package/dist/nodes/lime-marketing/models/transactionMail.js.map +1 -0
- package/dist/nodes/lime-marketing/models/transactionSms.d.ts +20 -0
- package/dist/nodes/lime-marketing/models/transactionSms.js +3 -0
- package/dist/nodes/lime-marketing/models/transactionSms.js.map +1 -0
- package/dist/nodes/lime-marketing/models/transportError.d.ts +7 -0
- package/dist/nodes/lime-marketing/models/transportError.js +3 -0
- package/dist/nodes/lime-marketing/models/transportError.js.map +1 -0
- package/dist/nodes/lime-marketing/resources/transactionmail/index.d.ts +6 -0
- package/dist/nodes/lime-marketing/resources/transactionmail/index.js +56 -0
- package/dist/nodes/lime-marketing/resources/transactionmail/index.js.map +1 -0
- package/dist/nodes/lime-marketing/resources/transactionmail/operations/send.operation.d.ts +10 -0
- package/dist/nodes/lime-marketing/resources/transactionmail/operations/send.operation.js +543 -0
- package/dist/nodes/lime-marketing/resources/transactionmail/operations/send.operation.js.map +1 -0
- package/dist/nodes/lime-marketing/resources/transactionsms/index.d.ts +6 -0
- package/dist/nodes/lime-marketing/resources/transactionsms/index.js +56 -0
- package/dist/nodes/lime-marketing/resources/transactionsms/index.js.map +1 -0
- package/dist/nodes/lime-marketing/resources/transactionsms/operations/send.operation.d.ts +10 -0
- package/dist/nodes/lime-marketing/resources/transactionsms/operations/send.operation.js +171 -0
- package/dist/nodes/lime-marketing/resources/transactionsms/operations/send.operation.js.map +1 -0
- package/dist/nodes/lime-marketing/transport/index.d.ts +7 -0
- package/dist/nodes/lime-marketing/transport/index.js +34 -0
- package/dist/nodes/lime-marketing/transport/index.js.map +1 -0
- package/dist/nodes/lime-marketing/utils/index.d.ts +8 -0
- package/dist/nodes/lime-marketing/utils/index.js +62 -0
- package/dist/nodes/lime-marketing/utils/index.js.map +1 -0
- package/dist/nodes/lime-marketing/utils/mergeCodes.d.ts +26 -0
- package/dist/nodes/lime-marketing/utils/mergeCodes.js +85 -0
- package/dist/nodes/lime-marketing/utils/mergeCodes.js.map +1 -0
- package/dist/package.json +5 -3
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/nodes/index.ts +1 -0
- package/nodes/lime-crm/assets/lime-crm.svg +0 -0
- package/nodes/lime-forms/assets/lime-crm.svg +0 -0
- package/nodes/lime-marketing/LimeMarketing.node.ts +180 -0
- package/nodes/lime-marketing/assets/lime-crm.svg +1 -0
- package/nodes/lime-marketing/index.ts +1 -0
- package/nodes/lime-marketing/methods/getTemplateMergeCodeMappingColumns.ts +70 -0
- package/nodes/lime-marketing/methods/getTemplates.ts +33 -0
- package/nodes/lime-marketing/methods/index.ts +2 -0
- package/nodes/lime-marketing/models/constants.ts +12 -0
- package/nodes/lime-marketing/models/index.ts +32 -0
- package/nodes/lime-marketing/models/operationInputs.ts +40 -0
- package/nodes/lime-marketing/models/template.ts +10 -0
- package/nodes/lime-marketing/models/transactionMail.ts +65 -0
- package/nodes/lime-marketing/models/transactionSms.ts +22 -0
- package/nodes/lime-marketing/models/transportError.ts +6 -0
- package/nodes/lime-marketing/resources/transactionmail/index.ts +22 -0
- package/nodes/lime-marketing/resources/transactionmail/operations/send.operation.ts +664 -0
- package/nodes/lime-marketing/resources/transactionsms/index.ts +22 -0
- package/nodes/lime-marketing/resources/transactionsms/operations/send.operation.ts +228 -0
- package/nodes/lime-marketing/transport/index.ts +68 -0
- package/nodes/lime-marketing/utils/index.ts +139 -0
- package/nodes/lime-marketing/utils/mergeCodes.ts +121 -0
- package/package.json +6 -4
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IExecuteFunctions,
|
|
3
|
+
INodeProperties,
|
|
4
|
+
NodeOperationError,
|
|
5
|
+
ResourceMapperValue,
|
|
6
|
+
} from 'n8n-workflow';
|
|
7
|
+
import {
|
|
8
|
+
TRANSACTIONAL_EMAIL_RESOURCE,
|
|
9
|
+
SendTransactionMailArgs,
|
|
10
|
+
SendTransactionMailBase,
|
|
11
|
+
SendTransactionMailTemplateArgs,
|
|
12
|
+
TransactionMailModel,
|
|
13
|
+
TagModel,
|
|
14
|
+
AttachmentModel,
|
|
15
|
+
CONTENT_TYPE_TEMPLATE,
|
|
16
|
+
CONTENT_TYPE_CUSTOM,
|
|
17
|
+
CONTENT_TYPE_TEXT,
|
|
18
|
+
MERGE_CODES_INPUT_FIELDS,
|
|
19
|
+
MERGE_CODES_INPUT_JSON,
|
|
20
|
+
SEND_OPERATION,
|
|
21
|
+
TagListInput,
|
|
22
|
+
AttachmentsInput,
|
|
23
|
+
AdditionalMailOptions,
|
|
24
|
+
} from '../../../models';
|
|
25
|
+
import { buildAttachment, assertValidEmail, omitEmpty } from '../../../utils';
|
|
26
|
+
import {
|
|
27
|
+
mergeCodesInputMethodProperty,
|
|
28
|
+
mergeCodesTagFieldOptions,
|
|
29
|
+
parseMergeCodesJson,
|
|
30
|
+
readFreeFormTagModels,
|
|
31
|
+
} from '../../../utils/mergeCodes';
|
|
32
|
+
import { limeMarketingRequest } from '../../../transport';
|
|
33
|
+
import { isMergeCodePlaceholder } from '../../../methods/getTemplateMergeCodeMappingColumns';
|
|
34
|
+
|
|
35
|
+
/** @public */
|
|
36
|
+
export const description = {
|
|
37
|
+
name: 'Send',
|
|
38
|
+
value: SEND_OPERATION,
|
|
39
|
+
description: 'Send an email',
|
|
40
|
+
action: 'Send an email',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** @public */
|
|
44
|
+
export const properties: INodeProperties[] = [
|
|
45
|
+
{
|
|
46
|
+
displayName: 'Content Type',
|
|
47
|
+
name: 'contentType',
|
|
48
|
+
type: 'options',
|
|
49
|
+
options: [
|
|
50
|
+
{
|
|
51
|
+
name: 'Lime Marketing Template',
|
|
52
|
+
value: CONTENT_TYPE_TEMPLATE,
|
|
53
|
+
description: 'Use a predefined template in Lime Marketing',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'Custom HTML',
|
|
57
|
+
value: CONTENT_TYPE_CUSTOM,
|
|
58
|
+
description: 'Provide custom HTML content for the email',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Plain Text',
|
|
62
|
+
value: CONTENT_TYPE_TEXT,
|
|
63
|
+
description: 'Provide plain text content for the email',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
default: CONTENT_TYPE_TEMPLATE,
|
|
67
|
+
required: true,
|
|
68
|
+
displayOptions: {
|
|
69
|
+
show: {
|
|
70
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
71
|
+
operation: [SEND_OPERATION],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
displayName: 'Template',
|
|
77
|
+
name: 'templateId',
|
|
78
|
+
type: 'options',
|
|
79
|
+
required: true,
|
|
80
|
+
default: '',
|
|
81
|
+
description: 'The Lime Marketing template to send',
|
|
82
|
+
typeOptions: {
|
|
83
|
+
loadOptionsMethod: 'getTemplates',
|
|
84
|
+
},
|
|
85
|
+
displayOptions: {
|
|
86
|
+
show: {
|
|
87
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
88
|
+
operation: [SEND_OPERATION],
|
|
89
|
+
contentType: [CONTENT_TYPE_TEMPLATE],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
displayName: 'HTML Content',
|
|
95
|
+
name: 'htmlContent',
|
|
96
|
+
type: 'string',
|
|
97
|
+
typeOptions: { rows: 5 },
|
|
98
|
+
required: true,
|
|
99
|
+
default: '',
|
|
100
|
+
description:
|
|
101
|
+
'The raw HTML body. Will be encoded as a UTF-8 byte array before sending.',
|
|
102
|
+
displayOptions: {
|
|
103
|
+
show: {
|
|
104
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
105
|
+
operation: [SEND_OPERATION],
|
|
106
|
+
contentType: [CONTENT_TYPE_CUSTOM],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
displayName: 'Text Content',
|
|
112
|
+
name: 'textContent',
|
|
113
|
+
type: 'string',
|
|
114
|
+
typeOptions: { rows: 5 },
|
|
115
|
+
required: true,
|
|
116
|
+
default: '',
|
|
117
|
+
description:
|
|
118
|
+
'The plain text body. Will be encoded as a UTF-8 byte array before sending.',
|
|
119
|
+
displayOptions: {
|
|
120
|
+
show: {
|
|
121
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
122
|
+
operation: [SEND_OPERATION],
|
|
123
|
+
contentType: [CONTENT_TYPE_TEXT],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
displayName: 'From Name',
|
|
129
|
+
name: 'fromName',
|
|
130
|
+
type: 'string',
|
|
131
|
+
default: '',
|
|
132
|
+
description: 'The name of the sender',
|
|
133
|
+
displayOptions: {
|
|
134
|
+
show: {
|
|
135
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
136
|
+
operation: [SEND_OPERATION],
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
displayName: 'From Email',
|
|
142
|
+
name: 'fromEmail',
|
|
143
|
+
type: 'string',
|
|
144
|
+
default: '',
|
|
145
|
+
required: true,
|
|
146
|
+
placeholder: 'e.g. name@your-verified-domain.com',
|
|
147
|
+
description:
|
|
148
|
+
'The sender email address. The domain must be verified in Lime Marketing.',
|
|
149
|
+
displayOptions: {
|
|
150
|
+
show: {
|
|
151
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
152
|
+
operation: [SEND_OPERATION],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
displayName: 'Recipient Name',
|
|
158
|
+
name: 'recipientName',
|
|
159
|
+
type: 'string',
|
|
160
|
+
default: '',
|
|
161
|
+
description: 'The name of the recipient',
|
|
162
|
+
displayOptions: {
|
|
163
|
+
show: {
|
|
164
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
165
|
+
operation: [SEND_OPERATION],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
displayName: 'Recipient Email',
|
|
171
|
+
name: 'recipientEmail',
|
|
172
|
+
type: 'string',
|
|
173
|
+
required: true,
|
|
174
|
+
default: '',
|
|
175
|
+
placeholder: 'e.g. name@example.com',
|
|
176
|
+
description: 'The email address of the recipient',
|
|
177
|
+
displayOptions: {
|
|
178
|
+
show: {
|
|
179
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
180
|
+
operation: [SEND_OPERATION],
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
displayName: 'Subject',
|
|
186
|
+
name: 'subject',
|
|
187
|
+
type: 'string',
|
|
188
|
+
default: '',
|
|
189
|
+
placeholder: 'e.g. Your order has shipped',
|
|
190
|
+
description: 'The subject line of the email',
|
|
191
|
+
displayOptions: {
|
|
192
|
+
show: {
|
|
193
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
194
|
+
operation: [SEND_OPERATION],
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
displayName: 'Track Openings',
|
|
200
|
+
name: 'trackOpenings',
|
|
201
|
+
type: 'boolean',
|
|
202
|
+
default: false,
|
|
203
|
+
description: 'Whether to track when recipients open the email',
|
|
204
|
+
displayOptions: {
|
|
205
|
+
show: {
|
|
206
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
207
|
+
operation: [SEND_OPERATION],
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
displayName: 'Track Link Clicks',
|
|
213
|
+
name: 'trackLinkClicks',
|
|
214
|
+
type: 'boolean',
|
|
215
|
+
default: false,
|
|
216
|
+
description:
|
|
217
|
+
'Whether to track when recipients click links in the email',
|
|
218
|
+
displayOptions: {
|
|
219
|
+
show: {
|
|
220
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
221
|
+
operation: [SEND_OPERATION],
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
mergeCodesInputMethodProperty({
|
|
226
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
227
|
+
operation: [SEND_OPERATION],
|
|
228
|
+
contentType: [
|
|
229
|
+
CONTENT_TYPE_TEMPLATE,
|
|
230
|
+
CONTENT_TYPE_CUSTOM,
|
|
231
|
+
CONTENT_TYPE_TEXT,
|
|
232
|
+
],
|
|
233
|
+
}),
|
|
234
|
+
{
|
|
235
|
+
displayName: 'Merge Code Mapping',
|
|
236
|
+
name: 'templateMergeCodes',
|
|
237
|
+
type: 'resourceMapper',
|
|
238
|
+
noDataExpression: true,
|
|
239
|
+
default: { mappingMode: 'defineBelow', value: null },
|
|
240
|
+
description:
|
|
241
|
+
'Each merge code from the selected template is shown below. Provide a value for the codes you want to replace.',
|
|
242
|
+
typeOptions: {
|
|
243
|
+
resourceMapper: {
|
|
244
|
+
resourceMapperMethod: 'getTemplateMergeCodeMappingColumns',
|
|
245
|
+
mode: 'add',
|
|
246
|
+
addAllFields: true,
|
|
247
|
+
supportAutoMap: false,
|
|
248
|
+
fieldWords: { singular: 'merge code', plural: 'merge codes' },
|
|
249
|
+
},
|
|
250
|
+
loadOptionsDependsOn: ['templateId'],
|
|
251
|
+
},
|
|
252
|
+
displayOptions: {
|
|
253
|
+
show: {
|
|
254
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
255
|
+
operation: [SEND_OPERATION],
|
|
256
|
+
contentType: [CONTENT_TYPE_TEMPLATE],
|
|
257
|
+
mergeCodesInputMethod: [MERGE_CODES_INPUT_FIELDS],
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
displayName: 'Merge Code Mapping',
|
|
263
|
+
name: 'mergeCodesFreeForm',
|
|
264
|
+
type: 'fixedCollection',
|
|
265
|
+
typeOptions: { multipleValues: true },
|
|
266
|
+
placeholder: 'Add Merge Code',
|
|
267
|
+
default: {},
|
|
268
|
+
description: 'Merge codes and values to substitute into the content.',
|
|
269
|
+
displayOptions: {
|
|
270
|
+
show: {
|
|
271
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
272
|
+
operation: [SEND_OPERATION],
|
|
273
|
+
contentType: [CONTENT_TYPE_CUSTOM, CONTENT_TYPE_TEXT],
|
|
274
|
+
mergeCodesInputMethod: [MERGE_CODES_INPUT_FIELDS],
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
options: mergeCodesTagFieldOptions,
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
displayName: 'Merge Codes (JSON)',
|
|
281
|
+
name: 'mergeCodesJson',
|
|
282
|
+
type: 'json',
|
|
283
|
+
required: true,
|
|
284
|
+
default: '{\n "{{mergecode}}": ""\n}',
|
|
285
|
+
description:
|
|
286
|
+
'Object mapping each merge code (with braces) to its replacement value. Example: {"{{mergecode}}": "value"}',
|
|
287
|
+
typeOptions: {
|
|
288
|
+
alwaysOpenEditWindow: true,
|
|
289
|
+
},
|
|
290
|
+
displayOptions: {
|
|
291
|
+
show: {
|
|
292
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
293
|
+
operation: [SEND_OPERATION],
|
|
294
|
+
contentType: [
|
|
295
|
+
CONTENT_TYPE_TEMPLATE,
|
|
296
|
+
CONTENT_TYPE_CUSTOM,
|
|
297
|
+
CONTENT_TYPE_TEXT,
|
|
298
|
+
],
|
|
299
|
+
mergeCodesInputMethod: [MERGE_CODES_INPUT_JSON],
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
displayName: 'Attachments',
|
|
305
|
+
name: 'attachments',
|
|
306
|
+
type: 'fixedCollection',
|
|
307
|
+
typeOptions: { multipleValues: true },
|
|
308
|
+
placeholder: 'Add Attachment',
|
|
309
|
+
default: {},
|
|
310
|
+
displayOptions: {
|
|
311
|
+
show: {
|
|
312
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
313
|
+
operation: [SEND_OPERATION],
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
options: [
|
|
317
|
+
{
|
|
318
|
+
name: 'attachment',
|
|
319
|
+
displayName: 'Attachment',
|
|
320
|
+
values: [
|
|
321
|
+
{
|
|
322
|
+
displayName: 'Binary Property Name',
|
|
323
|
+
name: 'binaryPropertyName',
|
|
324
|
+
type: 'string',
|
|
325
|
+
default: 'data',
|
|
326
|
+
required: true,
|
|
327
|
+
description:
|
|
328
|
+
'Name of the binary property on the incoming item (e.g. "data"). The upstream node — HTTP Request, Read Binary File, etc. — attaches files under this key.',
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
displayName: 'File Name Override',
|
|
332
|
+
name: 'fileNameOverride',
|
|
333
|
+
type: 'string',
|
|
334
|
+
default: '',
|
|
335
|
+
description:
|
|
336
|
+
'Optional. If the upstream binary does not have a fileName set, provide one here (must include extension, e.g. "report.pdf").',
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
displayName: 'Additional Options',
|
|
344
|
+
name: 'additionalOptions',
|
|
345
|
+
type: 'collection',
|
|
346
|
+
placeholder: 'Add Option',
|
|
347
|
+
default: {},
|
|
348
|
+
displayOptions: {
|
|
349
|
+
show: {
|
|
350
|
+
resource: [TRANSACTIONAL_EMAIL_RESOURCE],
|
|
351
|
+
operation: [SEND_OPERATION],
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
options: [
|
|
355
|
+
{
|
|
356
|
+
displayName: 'Sender Name',
|
|
357
|
+
name: 'senderName',
|
|
358
|
+
type: 'string',
|
|
359
|
+
default: '',
|
|
360
|
+
description: 'Display name shown as the sender',
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
displayName: 'Sender Email',
|
|
364
|
+
name: 'senderEmail',
|
|
365
|
+
type: 'string',
|
|
366
|
+
placeholder: 'e.g. name@example.com',
|
|
367
|
+
default: '',
|
|
368
|
+
description:
|
|
369
|
+
'Email address shown as the sender. Must be on a verified domain.',
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
displayName: 'Reply-To',
|
|
373
|
+
name: 'replyTo',
|
|
374
|
+
type: 'string',
|
|
375
|
+
placeholder: 'e.g. name@example.com',
|
|
376
|
+
default: '',
|
|
377
|
+
description: 'Email address recipients will reply to',
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
displayName: 'Scheduled Send Date',
|
|
381
|
+
name: 'scheduledSendDate',
|
|
382
|
+
type: 'dateTime',
|
|
383
|
+
default: '',
|
|
384
|
+
description:
|
|
385
|
+
'When to send the email. Leave empty to send immediately.',
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
displayName: 'External ID',
|
|
389
|
+
name: 'externalId',
|
|
390
|
+
type: 'string',
|
|
391
|
+
default: '',
|
|
392
|
+
description: 'Your own identifier for tracking this email',
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
displayName: 'Exclude Publication Opt-Outs',
|
|
396
|
+
name: 'excludePublicationOptouts',
|
|
397
|
+
type: 'boolean',
|
|
398
|
+
default: false,
|
|
399
|
+
description:
|
|
400
|
+
'Whether to skip recipients who opted out of this publication',
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
displayName: 'Exclude Total Opt-Outs',
|
|
404
|
+
name: 'excludeTotalOptouts',
|
|
405
|
+
type: 'boolean',
|
|
406
|
+
default: false,
|
|
407
|
+
description:
|
|
408
|
+
'Whether to skip recipients who opted out of all email',
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
displayName: 'Exclude Previously Bounced',
|
|
412
|
+
name: 'excludePreviousBounce',
|
|
413
|
+
type: 'boolean',
|
|
414
|
+
default: false,
|
|
415
|
+
description:
|
|
416
|
+
'Whether to skip recipients whose previous emails bounced',
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
displayName: 'Link Base URL',
|
|
420
|
+
name: 'linkBaseUrl',
|
|
421
|
+
type: 'string',
|
|
422
|
+
default: '',
|
|
423
|
+
placeholder: 'e.g. https://links.example.com',
|
|
424
|
+
description:
|
|
425
|
+
'Base URL used for click-tracked links. Leave empty to use the default.',
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
displayName: 'Include Email Data In Webhook Payload',
|
|
429
|
+
name: 'includeEmailDataInWebhookPayload',
|
|
430
|
+
type: 'boolean',
|
|
431
|
+
default: false,
|
|
432
|
+
description:
|
|
433
|
+
'Whether delivery webhooks should include the full email body',
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
displayName: 'Headers',
|
|
437
|
+
name: 'headers',
|
|
438
|
+
type: 'fixedCollection',
|
|
439
|
+
typeOptions: { multipleValues: true },
|
|
440
|
+
placeholder: 'Add Header',
|
|
441
|
+
default: {},
|
|
442
|
+
description: 'Custom email headers to include',
|
|
443
|
+
options: [
|
|
444
|
+
{
|
|
445
|
+
name: 'header',
|
|
446
|
+
displayName: 'Header',
|
|
447
|
+
values: [
|
|
448
|
+
{
|
|
449
|
+
displayName: 'Name',
|
|
450
|
+
name: 'name',
|
|
451
|
+
type: 'string',
|
|
452
|
+
default: '',
|
|
453
|
+
placeholder: 'e.g. X-Custom-Header',
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
displayName: 'Value',
|
|
457
|
+
name: 'value',
|
|
458
|
+
type: 'string',
|
|
459
|
+
default: '',
|
|
460
|
+
},
|
|
461
|
+
],
|
|
462
|
+
},
|
|
463
|
+
],
|
|
464
|
+
},
|
|
465
|
+
],
|
|
466
|
+
},
|
|
467
|
+
];
|
|
468
|
+
|
|
469
|
+
// Read merge codes from whichever UI surface is active (JSON, template
|
|
470
|
+
// resource-mapper, or free-form fixedCollection) and return them as TagModels.
|
|
471
|
+
function readMergeCodes(
|
|
472
|
+
ctx: IExecuteFunctions,
|
|
473
|
+
i: number,
|
|
474
|
+
contentType: string
|
|
475
|
+
): TagModel[] {
|
|
476
|
+
const method = ctx.getNodeParameter(
|
|
477
|
+
'mergeCodesInputMethod',
|
|
478
|
+
i,
|
|
479
|
+
MERGE_CODES_INPUT_FIELDS
|
|
480
|
+
) as string;
|
|
481
|
+
if (method === MERGE_CODES_INPUT_JSON) return parseMergeCodesJson(ctx, i);
|
|
482
|
+
if (contentType === CONTENT_TYPE_TEMPLATE) {
|
|
483
|
+
const input = ctx.getNodeParameter(
|
|
484
|
+
'templateMergeCodes',
|
|
485
|
+
i,
|
|
486
|
+
{}
|
|
487
|
+
) as ResourceMapperValue;
|
|
488
|
+
const value = input.value ?? {};
|
|
489
|
+
// Emit only the merge codes the user kept in the resource mapper.
|
|
490
|
+
// Removed rows aren't in `value`, so the API leaves their placeholder
|
|
491
|
+
// literal. Blank values stay in `value` as `''` and replace with
|
|
492
|
+
// empty string.
|
|
493
|
+
return Object.entries(value)
|
|
494
|
+
.filter(([Name]) => !isMergeCodePlaceholder(Name))
|
|
495
|
+
.map(([Name, v]) => ({
|
|
496
|
+
Name,
|
|
497
|
+
Value: v === undefined || v === null ? '' : String(v),
|
|
498
|
+
}));
|
|
499
|
+
}
|
|
500
|
+
return readFreeFormTagModels(
|
|
501
|
+
ctx.getNodeParameter('mergeCodesFreeForm', i, {}) as TagListInput
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async function readAttachments(
|
|
506
|
+
ctx: IExecuteFunctions,
|
|
507
|
+
i: number
|
|
508
|
+
): Promise<AttachmentModel[]> {
|
|
509
|
+
const input = ctx.getNodeParameter(
|
|
510
|
+
'attachments',
|
|
511
|
+
i,
|
|
512
|
+
{}
|
|
513
|
+
) as AttachmentsInput;
|
|
514
|
+
const attachments: AttachmentModel[] = [];
|
|
515
|
+
for (const row of input.attachment ?? []) {
|
|
516
|
+
attachments.push(
|
|
517
|
+
await buildAttachment(
|
|
518
|
+
ctx,
|
|
519
|
+
i,
|
|
520
|
+
row.binaryPropertyName,
|
|
521
|
+
row.fileNameOverride
|
|
522
|
+
)
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
return attachments;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Flatten the Headers fixedCollection rows into a name → value record,
|
|
529
|
+
// skipping rows with an empty name.
|
|
530
|
+
function buildCustomHeaders(
|
|
531
|
+
additional: AdditionalMailOptions
|
|
532
|
+
): Record<string, string> {
|
|
533
|
+
const headers: Record<string, string> = {};
|
|
534
|
+
for (const h of additional.headers?.header ?? []) {
|
|
535
|
+
if (h.name) headers[h.name] = h.value;
|
|
536
|
+
}
|
|
537
|
+
return headers;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Encode a string as the UTF-8 byte array Lime Marketing's send endpoint expects
|
|
541
|
+
// for HtmlContent / TextContent.
|
|
542
|
+
function encodeUtf8Bytes(content: string): number[] {
|
|
543
|
+
return Array.from(Buffer.from(content, 'utf8'));
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Pick the right send endpoint and shape the request body based on the
|
|
547
|
+
// content type: template → /sendtemplate with TemplateId; custom HTML / plain
|
|
548
|
+
// text → /send with HtmlContent or TextContent as a UTF-8 byte array.
|
|
549
|
+
function buildContentRequest(
|
|
550
|
+
ctx: IExecuteFunctions,
|
|
551
|
+
i: number,
|
|
552
|
+
contentType: string,
|
|
553
|
+
body: SendTransactionMailBase
|
|
554
|
+
): {
|
|
555
|
+
url: string;
|
|
556
|
+
body: SendTransactionMailArgs | SendTransactionMailTemplateArgs;
|
|
557
|
+
} {
|
|
558
|
+
if (contentType === CONTENT_TYPE_TEMPLATE) {
|
|
559
|
+
const templateIdRaw = ctx.getNodeParameter('templateId', i);
|
|
560
|
+
const templateId = Number(templateIdRaw);
|
|
561
|
+
if (!Number.isFinite(templateId) || templateId <= 0) {
|
|
562
|
+
throw new NodeOperationError(
|
|
563
|
+
ctx.getNode(),
|
|
564
|
+
`Template is not a valid template id: ${String(templateIdRaw)}`,
|
|
565
|
+
{
|
|
566
|
+
itemIndex: i,
|
|
567
|
+
description:
|
|
568
|
+
'Expected a positive integer matching a template in Lime Marketing. Pick one from the Template dropdown, or ensure any upstream expression resolves to a numeric template id.',
|
|
569
|
+
}
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
const templateBody: SendTransactionMailTemplateArgs = {
|
|
573
|
+
...body,
|
|
574
|
+
TemplateId: templateId,
|
|
575
|
+
};
|
|
576
|
+
return { url: 'transactionmail/sendtemplate', body: templateBody };
|
|
577
|
+
}
|
|
578
|
+
const isText = contentType === CONTENT_TYPE_TEXT;
|
|
579
|
+
const paramName = isText ? 'textContent' : 'htmlContent';
|
|
580
|
+
const raw = ctx.getNodeParameter(paramName, i) as string;
|
|
581
|
+
const content = encodeUtf8Bytes(raw);
|
|
582
|
+
const customBody: SendTransactionMailArgs = isText
|
|
583
|
+
? { ...body, TextContent: content }
|
|
584
|
+
: { ...body, HtmlContent: content };
|
|
585
|
+
return { url: 'transactionmail/send', body: customBody };
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export async function execute(
|
|
589
|
+
this: IExecuteFunctions,
|
|
590
|
+
i: number,
|
|
591
|
+
baseURL?: string
|
|
592
|
+
) {
|
|
593
|
+
const contentType = this.getNodeParameter('contentType', i) as string;
|
|
594
|
+
const fromEmail = (this.getNodeParameter('fromEmail', i) as string).trim();
|
|
595
|
+
if (!fromEmail) {
|
|
596
|
+
throw new NodeOperationError(
|
|
597
|
+
this.getNode(),
|
|
598
|
+
'From Email is required.',
|
|
599
|
+
{
|
|
600
|
+
itemIndex: i,
|
|
601
|
+
description:
|
|
602
|
+
'Set a verified sender address. If From Email is wired to an upstream expression, make sure it resolves to a non-empty string.',
|
|
603
|
+
}
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const additional = this.getNodeParameter(
|
|
608
|
+
'additionalOptions',
|
|
609
|
+
i,
|
|
610
|
+
{}
|
|
611
|
+
) as AdditionalMailOptions;
|
|
612
|
+
|
|
613
|
+
const recipientEmail = this.getNodeParameter('recipientEmail', i) as string;
|
|
614
|
+
assertValidEmail(this, recipientEmail, 'Recipient Email', i);
|
|
615
|
+
assertValidEmail(this, fromEmail, 'From Email', i);
|
|
616
|
+
if (additional.senderEmail)
|
|
617
|
+
assertValidEmail(this, additional.senderEmail, 'Sender Email', i);
|
|
618
|
+
if (additional.replyTo)
|
|
619
|
+
assertValidEmail(this, additional.replyTo, 'Reply-To', i);
|
|
620
|
+
|
|
621
|
+
const tagModels = readMergeCodes(this, i, contentType);
|
|
622
|
+
const tagModelsField = tagModels.length > 0 ? tagModels : undefined;
|
|
623
|
+
const attachments = await readAttachments(this, i);
|
|
624
|
+
const customHeaders = buildCustomHeaders(additional);
|
|
625
|
+
|
|
626
|
+
const baseBody: SendTransactionMailBase = {
|
|
627
|
+
RecipientEmail: recipientEmail,
|
|
628
|
+
RecipientName: omitEmpty(
|
|
629
|
+
this.getNodeParameter('recipientName', i) as string
|
|
630
|
+
),
|
|
631
|
+
Subject: omitEmpty(this.getNodeParameter('subject', i) as string),
|
|
632
|
+
FromName: omitEmpty(this.getNodeParameter('fromName', i) as string),
|
|
633
|
+
FromEmail: fromEmail,
|
|
634
|
+
SenderName: omitEmpty(additional.senderName),
|
|
635
|
+
SenderEmail: omitEmpty(additional.senderEmail),
|
|
636
|
+
TrackLinkClicks: this.getNodeParameter('trackLinkClicks', i) as boolean,
|
|
637
|
+
TrackOpenings: this.getNodeParameter('trackOpenings', i) as boolean,
|
|
638
|
+
HtmlContentTagModels: tagModelsField,
|
|
639
|
+
TextContentTagModels: tagModelsField,
|
|
640
|
+
Attachments: attachments.length > 0 ? attachments : undefined,
|
|
641
|
+
ReplyTo: omitEmpty(additional.replyTo),
|
|
642
|
+
ScheduledSendDate: omitEmpty(additional.scheduledSendDate),
|
|
643
|
+
ExternalId: omitEmpty(additional.externalId),
|
|
644
|
+
ExcludePublicationOptouts: additional.excludePublicationOptouts,
|
|
645
|
+
ExcludeTotaloptouts: additional.excludeTotalOptouts,
|
|
646
|
+
ExcludePreviousBounce: additional.excludePreviousBounce,
|
|
647
|
+
LinkBaseUrl: omitEmpty(additional.linkBaseUrl),
|
|
648
|
+
IncludeEmailDataInWebhookPayload:
|
|
649
|
+
additional.includeEmailDataInWebhookPayload,
|
|
650
|
+
Headers:
|
|
651
|
+
Object.keys(customHeaders).length > 0 ? customHeaders : undefined,
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
const { url, body } = buildContentRequest(this, i, contentType, baseBody);
|
|
655
|
+
|
|
656
|
+
return limeMarketingRequest<TransactionMailModel>(this, {
|
|
657
|
+
method: 'POST',
|
|
658
|
+
url,
|
|
659
|
+
body,
|
|
660
|
+
json: true,
|
|
661
|
+
errorContext: 'send email',
|
|
662
|
+
baseURL,
|
|
663
|
+
});
|
|
664
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { INodeProperties } from 'n8n-workflow';
|
|
2
|
+
import { SEND_OPERATION, TRANSACTIONAL_SMS_RESOURCE } from '../../models';
|
|
3
|
+
import * as send from './operations/send.operation';
|
|
4
|
+
|
|
5
|
+
export const transactionSmsFields: INodeProperties[] = [
|
|
6
|
+
{
|
|
7
|
+
displayName: 'Operation',
|
|
8
|
+
name: 'operation',
|
|
9
|
+
type: 'options',
|
|
10
|
+
noDataExpression: true,
|
|
11
|
+
displayOptions: {
|
|
12
|
+
show: { resource: [TRANSACTIONAL_SMS_RESOURCE] },
|
|
13
|
+
},
|
|
14
|
+
options: [send.description],
|
|
15
|
+
default: SEND_OPERATION,
|
|
16
|
+
},
|
|
17
|
+
...send.properties,
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export const transactionSmsOperations = {
|
|
21
|
+
[SEND_OPERATION]: send.execute,
|
|
22
|
+
};
|