n8n-nodes-base 1.90.1 → 1.91.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/dist/credentials/GSuiteAdminOAuth2Api.credentials.js +3 -1
- package/dist/credentials/GSuiteAdminOAuth2Api.credentials.js.map +1 -1
- package/dist/methods/defined.json +2 -1
- package/dist/methods/referenced.json +1 -0
- package/dist/nodes/Calendly/CalendlyTrigger.node.js +11 -0
- package/dist/nodes/Calendly/CalendlyTrigger.node.js.map +1 -1
- package/dist/nodes/EmailReadImap/v1/EmailReadImapV1.node.js +2 -2
- package/dist/nodes/EmailReadImap/v1/EmailReadImapV1.node.js.map +1 -1
- package/dist/nodes/EmailReadImap/v2/EmailReadImapV2.node.js +2 -2
- package/dist/nodes/EmailReadImap/v2/EmailReadImapV2.node.js.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js +0 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js.map +1 -1
- package/dist/nodes/Form/utils.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/DeviceDescription.js +381 -0
- package/dist/nodes/Google/GSuiteAdmin/DeviceDescription.js.map +1 -0
- package/dist/nodes/Google/GSuiteAdmin/GSuiteAdmin.node.js +395 -88
- package/dist/nodes/Google/GSuiteAdmin/GSuiteAdmin.node.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/GenericFunctions.js +6 -2
- package/dist/nodes/Google/GSuiteAdmin/GenericFunctions.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/GroupDescripion.js +112 -88
- package/dist/nodes/Google/GSuiteAdmin/GroupDescripion.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/SearchFunctions.js +101 -0
- package/dist/nodes/Google/GSuiteAdmin/SearchFunctions.js.map +1 -0
- package/dist/nodes/Google/GSuiteAdmin/UserDescription.js +538 -195
- package/dist/nodes/Google/GSuiteAdmin/UserDescription.js.map +1 -1
- package/dist/nodes/Google/GSuiteAdmin/gSuiteAdmin.svg +1 -0
- package/dist/nodes/HttpRequest/V2/HttpRequestV2.node.js +11 -0
- package/dist/nodes/HttpRequest/V2/HttpRequestV2.node.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js +8 -0
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js.map +1 -1
- package/dist/nodes/Jira/GenericFunctions.js +25 -12
- package/dist/nodes/Jira/GenericFunctions.js.map +1 -1
- package/dist/nodes/Jira/Jira.node.js +11 -7
- package/dist/nodes/Jira/Jira.node.js.map +1 -1
- package/dist/nodes/LocalFileTrigger/LocalFileTrigger.node.js +2 -2
- package/dist/nodes/LocalFileTrigger/LocalFileTrigger.node.js.map +1 -1
- package/dist/nodes/MQTT/MqttTrigger.node.js +2 -2
- package/dist/nodes/MQTT/MqttTrigger.node.js.map +1 -1
- package/dist/nodes/Postgres/PostgresTrigger.node.js +2 -2
- package/dist/nodes/Postgres/PostgresTrigger.node.js.map +1 -1
- package/dist/nodes/RabbitMQ/RabbitMQTrigger.node.js +2 -2
- package/dist/nodes/RabbitMQ/RabbitMQTrigger.node.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/asset/upload.operation.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/row/get.operation.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/row/list.operation.js.map +1 -1
- package/dist/nodes/SeaTable/v2/actions/row/search.operation.js.map +1 -1
- package/dist/nodes/SseTrigger/SseTrigger.node.js +2 -2
- package/dist/nodes/SseTrigger/SseTrigger.node.js.map +1 -1
- package/dist/test/nodes/Helpers.d.ts +5 -0
- package/dist/test/nodes/Helpers.js +16 -170
- package/dist/test/nodes/Helpers.js.map +1 -1
- package/dist/types/credentials.json +1 -1
- package/dist/types/nodes.json +11 -11
- package/package.json +5 -5
- package/dist/nodes/Google/GSuiteAdmin/google-workspace-admin.png +0 -0
- package/dist/test/nodes/ExecuteWorkflow.js +0 -120
- package/dist/test/nodes/ExecuteWorkflow.js.map +0 -1
- package/dist/test/nodes/credential-types.js +0 -57
- package/dist/test/nodes/credential-types.js.map +0 -1
- package/dist/test/nodes/credentials-helper.js +0 -76
- package/dist/test/nodes/credentials-helper.js.map +0 -1
- package/dist/test/nodes/load-nodes-and-credentials.js +0 -68
- package/dist/test/nodes/load-nodes-and-credentials.js.map +0 -1
- package/dist/test/nodes/node-types.js +0 -56
- package/dist/test/nodes/node-types.js.map +0 -1
|
@@ -25,7 +25,9 @@ const scopes = [
|
|
|
25
25
|
"https://www.googleapis.com/auth/admin.directory.group",
|
|
26
26
|
"https://www.googleapis.com/auth/admin.directory.user",
|
|
27
27
|
"https://www.googleapis.com/auth/admin.directory.domain.readonly",
|
|
28
|
-
"https://www.googleapis.com/auth/admin.directory.userschema.readonly"
|
|
28
|
+
"https://www.googleapis.com/auth/admin.directory.userschema.readonly",
|
|
29
|
+
"https://www.googleapis.com/auth/admin.directory.device.chromeos",
|
|
30
|
+
"https://www.googleapis.com/auth/admin.directory.orgunit.readonly"
|
|
29
31
|
];
|
|
30
32
|
class GSuiteAdminOAuth2Api {
|
|
31
33
|
constructor() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../credentials/GSuiteAdminOAuth2Api.credentials.ts"],"sourcesContent":["import type { ICredentialType, INodeProperties } from 'n8n-workflow';\n\nconst scopes = [\n\t'https://www.googleapis.com/auth/admin.directory.group',\n\t'https://www.googleapis.com/auth/admin.directory.user',\n\t'https://www.googleapis.com/auth/admin.directory.domain.readonly',\n\t'https://www.googleapis.com/auth/admin.directory.userschema.readonly',\n];\n\nexport class GSuiteAdminOAuth2Api implements ICredentialType {\n\tname = 'gSuiteAdminOAuth2Api';\n\n\textends = ['googleOAuth2Api'];\n\n\tdisplayName = 'Google Workspace Admin OAuth2 API';\n\n\tdocumentationUrl = 'google';\n\n\tproperties: INodeProperties[] = [\n\t\t{\n\t\t\tdisplayName: 'Scope',\n\t\t\tname: 'scope',\n\t\t\ttype: 'hidden',\n\t\t\tdefault: scopes.join(' '),\n\t\t},\n\t];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,MAAM,SAAS;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,MAAM,qBAAgD;AAAA,EAAtD;AACN,gBAAO;AAEP,mBAAU,CAAC,iBAAiB;AAE5B,uBAAc;AAEd,4BAAmB;AAEnB,sBAAgC;AAAA,MAC/B;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,OAAO,KAAK,GAAG;AAAA,MACzB;AAAA,IACD;AAAA;AACD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../credentials/GSuiteAdminOAuth2Api.credentials.ts"],"sourcesContent":["import type { ICredentialType, INodeProperties } from 'n8n-workflow';\n\nconst scopes = [\n\t'https://www.googleapis.com/auth/admin.directory.group',\n\t'https://www.googleapis.com/auth/admin.directory.user',\n\t'https://www.googleapis.com/auth/admin.directory.domain.readonly',\n\t'https://www.googleapis.com/auth/admin.directory.userschema.readonly',\n\t'https://www.googleapis.com/auth/admin.directory.device.chromeos',\n\t'https://www.googleapis.com/auth/admin.directory.orgunit.readonly',\n];\n\nexport class GSuiteAdminOAuth2Api implements ICredentialType {\n\tname = 'gSuiteAdminOAuth2Api';\n\n\textends = ['googleOAuth2Api'];\n\n\tdisplayName = 'Google Workspace Admin OAuth2 API';\n\n\tdocumentationUrl = 'google';\n\n\tproperties: INodeProperties[] = [\n\t\t{\n\t\t\tdisplayName: 'Scope',\n\t\t\tname: 'scope',\n\t\t\ttype: 'hidden',\n\t\t\tdefault: scopes.join(' '),\n\t\t},\n\t];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,MAAM,SAAS;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,MAAM,qBAAgD;AAAA,EAAtD;AACN,gBAAO;AAEP,mBAAU,CAAC,iBAAiB;AAE5B,uBAAc;AAEd,4BAAmB;AAEnB,sBAAgC;AAAA,MAC/B;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,OAAO,KAAK,GAAG;AAAA,MACzB;AAAA,IACD;AAAA;AACD;","names":[]}
|
|
@@ -83,6 +83,17 @@ class CalendlyTrigger {
|
|
|
83
83
|
],
|
|
84
84
|
default: "apiKey"
|
|
85
85
|
},
|
|
86
|
+
{
|
|
87
|
+
displayName: "Action required: Calendly will discontinue API Key authentication on May 31, 2025. Update node to use OAuth2 authentication now to ensure your workflows continue to work.",
|
|
88
|
+
name: "deprecationNotice",
|
|
89
|
+
type: "notice",
|
|
90
|
+
default: "",
|
|
91
|
+
displayOptions: {
|
|
92
|
+
show: {
|
|
93
|
+
authentication: ["apiKey"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
86
97
|
{
|
|
87
98
|
displayName: "Scope",
|
|
88
99
|
name: "scope",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../nodes/Calendly/CalendlyTrigger.node.ts"],"sourcesContent":["import type {\n\tIHookFunctions,\n\tIWebhookFunctions,\n\tIDataObject,\n\tINodeType,\n\tINodeTypeDescription,\n\tIWebhookResponseData,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { calendlyApiRequest, getAuthenticationType } from './GenericFunctions';\n\nexport class CalendlyTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Calendly Trigger',\n\t\tname: 'calendlyTrigger',\n\t\ticon: 'file:calendly.svg',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Starts the workflow when Calendly events occur',\n\t\tdefaults: {\n\t\t\tname: 'Calendly Trigger',\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'calendlyApi',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['apiKey'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'calendlyOAuth2Api',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['oAuth2'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twebhooks: [\n\t\t\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'POST',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tpath: 'webhook',\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Authentication',\n\t\t\t\tname: 'authentication',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased\n\t\t\t\t\t\tname: 'OAuth2 (recommended)',\n\t\t\t\t\t\tvalue: 'oAuth2',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'API Key or Personal Access Token',\n\t\t\t\t\t\tvalue: 'apiKey',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'apiKey',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Scope',\n\t\t\t\tname: 'scope',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'user',\n\t\t\t\trequired: true,\n\t\t\t\thint: 'Ignored if you are using an API Key',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Organization',\n\t\t\t\t\t\tvalue: 'organization',\n\t\t\t\t\t\tdescription: 'Triggers the webhook for all subscribed events within the organization',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'User',\n\t\t\t\t\t\tvalue: 'user',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Triggers the webhook for subscribed events that belong to the current user',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Events',\n\t\t\t\tname: 'events',\n\t\t\t\ttype: 'multiOptions',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Event Created',\n\t\t\t\t\t\tvalue: 'invitee.created',\n\t\t\t\t\t\tdescription: 'Receive notifications when a new Calendly event is created',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Event Canceled',\n\t\t\t\t\t\tvalue: 'invitee.canceled',\n\t\t\t\t\t\tdescription: 'Receive notifications when a Calendly event is canceled',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: [],\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t};\n\n\twebhookMethods = {\n\t\tdefault: {\n\t\t\tasync checkExists(this: IHookFunctions): Promise<boolean> {\n\t\t\t\tconst webhookUrl = this.getNodeWebhookUrl('default');\n\t\t\t\tconst webhookData = this.getWorkflowStaticData('node');\n\t\t\t\tconst events = this.getNodeParameter('events') as string[];\n\n\t\t\t\tconst authenticationType = await getAuthenticationType.call(this);\n\n\t\t\t\t// remove condition once API Keys are deprecated\n\t\t\t\tif (authenticationType === 'apiKey') {\n\t\t\t\t\tconst endpoint = '/hooks';\n\t\t\t\t\tconst { data } = await calendlyApiRequest.call(this, 'GET', endpoint, {});\n\n\t\t\t\t\tfor (const webhook of data) {\n\t\t\t\t\t\tif (webhook.attributes.url === webhookUrl) {\n\t\t\t\t\t\t\tfor (const event of events) {\n\t\t\t\t\t\t\t\tif (!webhook.attributes.events.includes(event)) {\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Set webhook-id to be sure that it can be deleted\n\t\t\t\t\t\twebhookData.webhookId = webhook.id as string;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (authenticationType === 'accessToken') {\n\t\t\t\t\tconst scope = this.getNodeParameter('scope', 0) as string;\n\t\t\t\t\tconst { resource } = await calendlyApiRequest.call(this, 'GET', '/users/me');\n\n\t\t\t\t\tconst qs: IDataObject = {};\n\n\t\t\t\t\tif (scope === 'user') {\n\t\t\t\t\t\tqs.scope = 'user';\n\t\t\t\t\t\tqs.organization = resource.current_organization;\n\t\t\t\t\t\tqs.user = resource.uri;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (scope === 'organization') {\n\t\t\t\t\t\tqs.scope = 'organization';\n\t\t\t\t\t\tqs.organization = resource.current_organization;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst endpoint = '/webhook_subscriptions';\n\t\t\t\t\tconst { collection } = await calendlyApiRequest.call(this, 'GET', endpoint, {}, qs);\n\n\t\t\t\t\tfor (const webhook of collection) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\twebhook.callback_url === webhookUrl &&\n\t\t\t\t\t\t\tevents.length === webhook.events.length &&\n\t\t\t\t\t\t\tevents.every((event: string) => webhook.events.includes(event))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twebhookData.webhookURI = webhook.uri;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tasync create(this: IHookFunctions): Promise<boolean> {\n\t\t\t\tconst webhookData = this.getWorkflowStaticData('node');\n\t\t\t\tconst webhookUrl = this.getNodeWebhookUrl('default');\n\t\t\t\tconst events = this.getNodeParameter('events') as string[];\n\n\t\t\t\tconst authenticationType = await getAuthenticationType.call(this);\n\n\t\t\t\t// remove condition once API Keys are deprecated\n\t\t\t\tif (authenticationType === 'apiKey') {\n\t\t\t\t\tconst endpoint = '/hooks';\n\n\t\t\t\t\tconst body = {\n\t\t\t\t\t\turl: webhookUrl,\n\t\t\t\t\t\tevents,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst responseData = await calendlyApiRequest.call(this, 'POST', endpoint, body);\n\n\t\t\t\t\tif (responseData.id === undefined) {\n\t\t\t\t\t\t// Required data is missing so was not successful\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\twebhookData.webhookId = responseData.id as string;\n\t\t\t\t}\n\n\t\t\t\tif (authenticationType === 'accessToken') {\n\t\t\t\t\tconst scope = this.getNodeParameter('scope', 0) as string;\n\t\t\t\t\tconst { resource } = await calendlyApiRequest.call(this, 'GET', '/users/me');\n\n\t\t\t\t\tconst body: IDataObject = {\n\t\t\t\t\t\turl: webhookUrl,\n\t\t\t\t\t\tevents,\n\t\t\t\t\t\torganization: resource.current_organization,\n\t\t\t\t\t\tscope,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (scope === 'user') {\n\t\t\t\t\t\tbody.user = resource.uri;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst endpoint = '/webhook_subscriptions';\n\t\t\t\t\tconst responseData = await calendlyApiRequest.call(this, 'POST', endpoint, body);\n\n\t\t\t\t\tif (responseData?.resource === undefined || responseData?.resource?.uri === undefined) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\twebhookData.webhookURI = responseData.resource.uri;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tasync delete(this: IHookFunctions): Promise<boolean> {\n\t\t\t\tconst webhookData = this.getWorkflowStaticData('node');\n\t\t\t\tconst authenticationType = await getAuthenticationType.call(this);\n\n\t\t\t\t// remove condition once API Keys are deprecated\n\t\t\t\tif (authenticationType === 'apiKey') {\n\t\t\t\t\tif (webhookData.webhookId !== undefined) {\n\t\t\t\t\t\tconst endpoint = `/hooks/${webhookData.webhookId}`;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait calendlyApiRequest.call(this, 'DELETE', endpoint);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Remove from the static workflow data so that it is clear\n\t\t\t\t\t\t// that no webhooks are registered anymore\n\t\t\t\t\t\tdelete webhookData.webhookId;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (authenticationType === 'accessToken') {\n\t\t\t\t\tif (webhookData.webhookURI !== undefined) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait calendlyApiRequest.call(\n\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t'DELETE',\n\t\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t\twebhookData.webhookURI as string,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdelete webhookData.webhookURI;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t};\n\n\tasync webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {\n\t\tconst bodyData = this.getBodyData();\n\t\treturn {\n\t\t\tworkflowData: [this.helpers.returnJsonArray(bodyData)],\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../nodes/Calendly/CalendlyTrigger.node.ts"],"sourcesContent":["import type {\n\tIHookFunctions,\n\tIWebhookFunctions,\n\tIDataObject,\n\tINodeType,\n\tINodeTypeDescription,\n\tIWebhookResponseData,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { calendlyApiRequest, getAuthenticationType } from './GenericFunctions';\n\nexport class CalendlyTrigger implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Calendly Trigger',\n\t\tname: 'calendlyTrigger',\n\t\ticon: 'file:calendly.svg',\n\t\tgroup: ['trigger'],\n\t\tversion: 1,\n\t\tdescription: 'Starts the workflow when Calendly events occur',\n\t\tdefaults: {\n\t\t\tname: 'Calendly Trigger',\n\t\t},\n\t\tinputs: [],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [\n\t\t\t{\n\t\t\t\tname: 'calendlyApi',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['apiKey'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'calendlyOAuth2Api',\n\t\t\t\trequired: true,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['oAuth2'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twebhooks: [\n\t\t\t{\n\t\t\t\tname: 'default',\n\t\t\t\thttpMethod: 'POST',\n\t\t\t\tresponseMode: 'onReceived',\n\t\t\t\tpath: 'webhook',\n\t\t\t},\n\t\t],\n\t\tproperties: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Authentication',\n\t\t\t\tname: 'authentication',\n\t\t\t\ttype: 'options',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased\n\t\t\t\t\t\tname: 'OAuth2 (recommended)',\n\t\t\t\t\t\tvalue: 'oAuth2',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'API Key or Personal Access Token',\n\t\t\t\t\t\tvalue: 'apiKey',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: 'apiKey',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName:\n\t\t\t\t\t'Action required: Calendly will discontinue API Key authentication on May 31, 2025. Update node to use OAuth2 authentication now to ensure your workflows continue to work.',\n\t\t\t\tname: 'deprecationNotice',\n\t\t\t\ttype: 'notice',\n\t\t\t\tdefault: '',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tauthentication: ['apiKey'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Scope',\n\t\t\t\tname: 'scope',\n\t\t\t\ttype: 'options',\n\t\t\t\tdefault: 'user',\n\t\t\t\trequired: true,\n\t\t\t\thint: 'Ignored if you are using an API Key',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Organization',\n\t\t\t\t\t\tvalue: 'organization',\n\t\t\t\t\t\tdescription: 'Triggers the webhook for all subscribed events within the organization',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'User',\n\t\t\t\t\t\tvalue: 'user',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Triggers the webhook for subscribed events that belong to the current user',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Events',\n\t\t\t\tname: 'events',\n\t\t\t\ttype: 'multiOptions',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Event Created',\n\t\t\t\t\t\tvalue: 'invitee.created',\n\t\t\t\t\t\tdescription: 'Receive notifications when a new Calendly event is created',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Event Canceled',\n\t\t\t\t\t\tvalue: 'invitee.canceled',\n\t\t\t\t\t\tdescription: 'Receive notifications when a Calendly event is canceled',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdefault: [],\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t};\n\n\twebhookMethods = {\n\t\tdefault: {\n\t\t\tasync checkExists(this: IHookFunctions): Promise<boolean> {\n\t\t\t\tconst webhookUrl = this.getNodeWebhookUrl('default');\n\t\t\t\tconst webhookData = this.getWorkflowStaticData('node');\n\t\t\t\tconst events = this.getNodeParameter('events') as string[];\n\n\t\t\t\tconst authenticationType = await getAuthenticationType.call(this);\n\n\t\t\t\t// remove condition once API Keys are deprecated\n\t\t\t\tif (authenticationType === 'apiKey') {\n\t\t\t\t\tconst endpoint = '/hooks';\n\t\t\t\t\tconst { data } = await calendlyApiRequest.call(this, 'GET', endpoint, {});\n\n\t\t\t\t\tfor (const webhook of data) {\n\t\t\t\t\t\tif (webhook.attributes.url === webhookUrl) {\n\t\t\t\t\t\t\tfor (const event of events) {\n\t\t\t\t\t\t\t\tif (!webhook.attributes.events.includes(event)) {\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Set webhook-id to be sure that it can be deleted\n\t\t\t\t\t\twebhookData.webhookId = webhook.id as string;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (authenticationType === 'accessToken') {\n\t\t\t\t\tconst scope = this.getNodeParameter('scope', 0) as string;\n\t\t\t\t\tconst { resource } = await calendlyApiRequest.call(this, 'GET', '/users/me');\n\n\t\t\t\t\tconst qs: IDataObject = {};\n\n\t\t\t\t\tif (scope === 'user') {\n\t\t\t\t\t\tqs.scope = 'user';\n\t\t\t\t\t\tqs.organization = resource.current_organization;\n\t\t\t\t\t\tqs.user = resource.uri;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (scope === 'organization') {\n\t\t\t\t\t\tqs.scope = 'organization';\n\t\t\t\t\t\tqs.organization = resource.current_organization;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst endpoint = '/webhook_subscriptions';\n\t\t\t\t\tconst { collection } = await calendlyApiRequest.call(this, 'GET', endpoint, {}, qs);\n\n\t\t\t\t\tfor (const webhook of collection) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\twebhook.callback_url === webhookUrl &&\n\t\t\t\t\t\t\tevents.length === webhook.events.length &&\n\t\t\t\t\t\t\tevents.every((event: string) => webhook.events.includes(event))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\twebhookData.webhookURI = webhook.uri;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tasync create(this: IHookFunctions): Promise<boolean> {\n\t\t\t\tconst webhookData = this.getWorkflowStaticData('node');\n\t\t\t\tconst webhookUrl = this.getNodeWebhookUrl('default');\n\t\t\t\tconst events = this.getNodeParameter('events') as string[];\n\n\t\t\t\tconst authenticationType = await getAuthenticationType.call(this);\n\n\t\t\t\t// remove condition once API Keys are deprecated\n\t\t\t\tif (authenticationType === 'apiKey') {\n\t\t\t\t\tconst endpoint = '/hooks';\n\n\t\t\t\t\tconst body = {\n\t\t\t\t\t\turl: webhookUrl,\n\t\t\t\t\t\tevents,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst responseData = await calendlyApiRequest.call(this, 'POST', endpoint, body);\n\n\t\t\t\t\tif (responseData.id === undefined) {\n\t\t\t\t\t\t// Required data is missing so was not successful\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\twebhookData.webhookId = responseData.id as string;\n\t\t\t\t}\n\n\t\t\t\tif (authenticationType === 'accessToken') {\n\t\t\t\t\tconst scope = this.getNodeParameter('scope', 0) as string;\n\t\t\t\t\tconst { resource } = await calendlyApiRequest.call(this, 'GET', '/users/me');\n\n\t\t\t\t\tconst body: IDataObject = {\n\t\t\t\t\t\turl: webhookUrl,\n\t\t\t\t\t\tevents,\n\t\t\t\t\t\torganization: resource.current_organization,\n\t\t\t\t\t\tscope,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (scope === 'user') {\n\t\t\t\t\t\tbody.user = resource.uri;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst endpoint = '/webhook_subscriptions';\n\t\t\t\t\tconst responseData = await calendlyApiRequest.call(this, 'POST', endpoint, body);\n\n\t\t\t\t\tif (responseData?.resource === undefined || responseData?.resource?.uri === undefined) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\twebhookData.webhookURI = responseData.resource.uri;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tasync delete(this: IHookFunctions): Promise<boolean> {\n\t\t\t\tconst webhookData = this.getWorkflowStaticData('node');\n\t\t\t\tconst authenticationType = await getAuthenticationType.call(this);\n\n\t\t\t\t// remove condition once API Keys are deprecated\n\t\t\t\tif (authenticationType === 'apiKey') {\n\t\t\t\t\tif (webhookData.webhookId !== undefined) {\n\t\t\t\t\t\tconst endpoint = `/hooks/${webhookData.webhookId}`;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait calendlyApiRequest.call(this, 'DELETE', endpoint);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Remove from the static workflow data so that it is clear\n\t\t\t\t\t\t// that no webhooks are registered anymore\n\t\t\t\t\t\tdelete webhookData.webhookId;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (authenticationType === 'accessToken') {\n\t\t\t\t\tif (webhookData.webhookURI !== undefined) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait calendlyApiRequest.call(\n\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t'DELETE',\n\t\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t\twebhookData.webhookURI as string,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdelete webhookData.webhookURI;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t},\n\t};\n\n\tasync webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {\n\t\tconst bodyData = this.getBodyData();\n\t\treturn {\n\t\t\tworkflowData: [this.helpers.returnJsonArray(bodyData)],\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -77,8 +77,8 @@ const versionDescription = {
|
|
|
77
77
|
triggerPanel: {
|
|
78
78
|
header: "",
|
|
79
79
|
executionsHelp: {
|
|
80
|
-
inactive: "<b>While building your workflow</b>, click the '
|
|
81
|
-
active: "<b>While building your workflow</b>, click the '
|
|
80
|
+
inactive: "<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time an email is received, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.",
|
|
81
|
+
active: "<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time an email is received, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor."
|
|
82
82
|
},
|
|
83
83
|
activationHint: "Once you\u2019ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won\u2019t see those executions here)."
|
|
84
84
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/EmailReadImap/v1/EmailReadImapV1.node.ts"],"sourcesContent":["import type { ImapSimple, ImapSimpleOptions, Message } from '@n8n/imap';\nimport { connect as imapConnect, getParts } from '@n8n/imap';\nimport find from 'lodash/find';\nimport isEmpty from 'lodash/isEmpty';\nimport type { Source as ParserSource } from 'mailparser';\nimport { simpleParser } from 'mailparser';\nimport { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\nimport type {\n\tITriggerFunctions,\n\tIBinaryData,\n\tIBinaryKeyData,\n\tICredentialDataDecryptedObject,\n\tICredentialsDecrypted,\n\tICredentialTestFunctions,\n\tIDataObject,\n\tINodeCredentialTestResult,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeBaseDescription,\n\tINodeTypeDescription,\n\tITriggerResponse,\n} from 'n8n-workflow';\n\nexport async function parseRawEmail(\n\tthis: ITriggerFunctions,\n\tmessageEncoded: ParserSource,\n\tdataPropertyNameDownload: string,\n): Promise<INodeExecutionData> {\n\tconst responseData = await simpleParser(messageEncoded);\n\tconst headers: IDataObject = {};\n\tfor (const header of responseData.headerLines) {\n\t\theaders[header.key] = header.line;\n\t}\n\n\t// @ts-ignore\n\tresponseData.headers = headers;\n\t// @ts-ignore\n\tresponseData.headerLines = undefined;\n\n\tconst binaryData: IBinaryKeyData = {};\n\tif (responseData.attachments) {\n\t\tfor (let i = 0; i < responseData.attachments.length; i++) {\n\t\t\tconst attachment = responseData.attachments[i];\n\t\t\tbinaryData[`${dataPropertyNameDownload}${i}`] = await this.helpers.prepareBinaryData(\n\t\t\t\tattachment.content,\n\t\t\t\tattachment.filename,\n\t\t\t\tattachment.contentType,\n\t\t\t);\n\t\t}\n\t\t// @ts-ignore\n\t\tresponseData.attachments = undefined;\n\t}\n\n\treturn {\n\t\tjson: responseData as unknown as IDataObject,\n\t\tbinary: Object.keys(binaryData).length ? binaryData : undefined,\n\t} as INodeExecutionData;\n}\n\nconst versionDescription: INodeTypeDescription = {\n\tdisplayName: 'Email Trigger (IMAP)',\n\tname: 'emailReadImap',\n\ticon: 'fa:inbox',\n\tgroup: ['trigger'],\n\tversion: 1,\n\tdescription: 'Triggers the workflow when a new email is received',\n\teventTriggerDescription: 'Waiting for you to receive an email',\n\tdefaults: {\n\t\tname: 'Email Trigger (IMAP)',\n\t\tcolor: '#44AA22',\n\t},\n\ttriggerPanel: {\n\t\theader: '',\n\t\texecutionsHelp: {\n\t\t\tinactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time an email is received, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\tactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time an email is received, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t},\n\t\tactivationHint:\n\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t},\n\n\tinputs: [],\n\toutputs: [NodeConnectionTypes.Main],\n\tcredentials: [\n\t\t{\n\t\t\tname: 'imap',\n\t\t\trequired: true,\n\t\t\ttestedBy: 'imapConnectionTest',\n\t\t},\n\t],\n\tproperties: [\n\t\t{\n\t\t\tdisplayName: 'Mailbox Name',\n\t\t\tname: 'mailbox',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'INBOX',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Action',\n\t\t\tname: 'postProcessAction',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Mark as Read',\n\t\t\t\t\tvalue: 'read',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Nothing',\n\t\t\t\t\tvalue: 'nothing',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'read',\n\t\t\tdescription:\n\t\t\t\t'What to do after the email has been received. If \"nothing\" gets selected it will be processed multiple times.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Download Attachments',\n\t\t\tname: 'downloadAttachments',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Whether attachments of emails should be downloaded. Only set if needed as it increases processing.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Format',\n\t\t\tname: 'format',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'RAW',\n\t\t\t\t\tvalue: 'raw',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email message data with body content in the raw field as a base64url encoded string; the payload field is not used',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Resolved',\n\t\t\t\t\tvalue: 'resolved',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email with all data resolved and attachments saved as binary data',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Simple',\n\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email; do not use if you wish to gather inline attachments',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'simple',\n\t\t\tdescription: 'The format to return the message in',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['resolved'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t\tdownloadAttachments: [true],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Custom Email Rules',\n\t\t\t\t\tname: 'customEmailConfig',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '[\"UNSEEN\"]',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Custom email fetching rules. See <a href=\"https://github.com/mscdex/node-imap\">node-imap</a>\\'s search function for more details.',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Ignore SSL Issues (Insecure)',\n\t\t\t\t\tname: 'allowUnauthorizedCerts',\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: 'Whether to connect even if SSL certificate validation is not possible',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Force Reconnect',\n\t\t\t\t\tname: 'forceReconnect',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tdescription: 'Sets an interval (in minutes) to force a reconnection',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n};\n\nexport class EmailReadImapV1 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\t...versionDescription,\n\t\t};\n\t}\n\n\tmethods = {\n\t\tcredentialTest: {\n\t\t\tasync imapConnectionTest(\n\t\t\t\tthis: ICredentialTestFunctions,\n\t\t\t\tcredential: ICredentialsDecrypted,\n\t\t\t): Promise<INodeCredentialTestResult> {\n\t\t\t\tconst credentials = credential.data as ICredentialDataDecryptedObject;\n\t\t\t\ttry {\n\t\t\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\t\t\timap: {\n\t\t\t\t\t\t\tuser: credentials.user as string,\n\t\t\t\t\t\t\tpassword: credentials.password as string,\n\t\t\t\t\t\t\thost: (credentials.host as string).trim(),\n\t\t\t\t\t\t\tport: credentials.port as number,\n\t\t\t\t\t\t\ttls: credentials.secure as boolean,\n\t\t\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\t\t\tif (credentials.secure) {\n\t\t\t\t\t\ttlsOptions.servername = (credentials.host as string).trim();\n\t\t\t\t\t}\n\t\t\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t\t\t}\n\t\t\t\t\tconst connection = await imapConnect(config);\n\t\t\t\t\tawait connection.getBoxes();\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'Error',\n\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 'OK',\n\t\t\t\t\tmessage: 'Connection successful!',\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst credentials = await this.getCredentials('imap');\n\n\t\tconst mailbox = this.getNodeParameter('mailbox') as string;\n\t\tconst postProcessAction = this.getNodeParameter('postProcessAction') as string;\n\t\tconst options = this.getNodeParameter('options', {}) as IDataObject;\n\n\t\tconst staticData = this.getWorkflowStaticData('node');\n\t\tthis.logger.debug('Loaded static data for node \"EmailReadImap\"', { staticData });\n\n\t\tlet connection: ImapSimple;\n\n\t\t// Returns the email text\n\n\t\tconst getText = async (parts: any[], message: Message, subtype: string): Promise<string> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst textParts = parts.filter((part) => {\n\t\t\t\treturn (\n\t\t\t\t\tpart.type.toUpperCase() === 'TEXT' && part.subtype.toUpperCase() === subtype.toUpperCase()\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tconst part = textParts[0];\n\t\t\tif (!part) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst partData = await connection.getPartData(message, part);\n\t\t\t\treturn partData.toString();\n\t\t\t} catch {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t};\n\n\t\t// Returns the email attachments\n\t\tconst getAttachment = async (\n\t\t\timapConnection: ImapSimple,\n\t\t\tparts: any[],\n\t\t\tmessage: Message,\n\t\t): Promise<IBinaryData[]> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\t// Check if the message has attachments and if so get them\n\t\t\tconst attachmentParts = parts.filter((part) => {\n\t\t\t\treturn part.disposition && part.disposition.type.toUpperCase() === 'ATTACHMENT';\n\t\t\t});\n\n\t\t\tconst attachmentPromises = [];\n\t\t\tlet attachmentPromise;\n\t\t\tfor (const attachmentPart of attachmentParts) {\n\t\t\t\tattachmentPromise = imapConnection\n\t\t\t\t\t.getPartData(message, attachmentPart)\n\t\t\t\t\t.then(async (partData) => {\n\t\t\t\t\t\t// Return it in the format n8n expects\n\t\t\t\t\t\treturn await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tpartData.buffer,\n\t\t\t\t\t\t\tattachmentPart.disposition.params.filename as string,\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\tattachmentPromises.push(attachmentPromise);\n\t\t\t}\n\n\t\t\treturn await Promise.all(attachmentPromises);\n\t\t};\n\n\t\t// Returns all the new unseen messages\n\t\tconst getNewEmails = async (\n\t\t\timapConnection: ImapSimple,\n\t\t\tsearchCriteria: Array<string | string[]>,\n\t\t): Promise<INodeExecutionData[]> => {\n\t\t\tconst format = this.getNodeParameter('format', 0) as string;\n\n\t\t\tlet fetchOptions = {};\n\n\t\t\tif (format === 'simple' || format === 'raw') {\n\t\t\t\tfetchOptions = {\n\t\t\t\t\tbodies: ['TEXT', 'HEADER'],\n\t\t\t\t\tmarkSeen: false,\n\t\t\t\t\tstruct: true,\n\t\t\t\t};\n\t\t\t} else if (format === 'resolved') {\n\t\t\t\tfetchOptions = {\n\t\t\t\t\tbodies: [''],\n\t\t\t\t\tmarkSeen: false,\n\t\t\t\t\tstruct: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst results = await imapConnection.search(searchCriteria, fetchOptions);\n\n\t\t\tconst newEmails: INodeExecutionData[] = [];\n\t\t\tlet newEmail: INodeExecutionData;\n\t\t\tlet attachments: IBinaryData[];\n\t\t\tlet propertyName: string;\n\n\t\t\t// All properties get by default moved to metadata except the ones\n\t\t\t// which are defined here which get set on the top level.\n\t\t\tconst topLevelProperties = ['cc', 'date', 'from', 'subject', 'to'];\n\n\t\t\tif (format === 'resolved') {\n\t\t\t\tconst dataPropertyAttachmentsPrefixName = this.getNodeParameter(\n\t\t\t\t\t'dataPropertyAttachmentsPrefixName',\n\t\t\t\t) as string;\n\n\t\t\t\tfor (const message of results) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid !== undefined &&\n\t\t\t\t\t\tmessage.attributes.uid <= (staticData.lastMessageUid as number)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid === undefined ||\n\t\t\t\t\t\t(staticData.lastMessageUid as number) < message.attributes.uid\n\t\t\t\t\t) {\n\t\t\t\t\t\tstaticData.lastMessageUid = message.attributes.uid;\n\t\t\t\t\t}\n\t\t\t\t\tconst part = find(message.parts, { which: '' });\n\n\t\t\t\t\tif (part === undefined) {\n\t\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Email part could not be parsed.');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedEmail = await parseRawEmail.call(\n\t\t\t\t\t\tthis,\n\t\t\t\t\t\tpart.body as Buffer,\n\t\t\t\t\t\tdataPropertyAttachmentsPrefixName,\n\t\t\t\t\t);\n\n\t\t\t\t\tnewEmails.push(parsedEmail);\n\t\t\t\t}\n\t\t\t} else if (format === 'simple') {\n\t\t\t\tconst downloadAttachments = this.getNodeParameter('downloadAttachments') as boolean;\n\n\t\t\t\tlet dataPropertyAttachmentsPrefixName = '';\n\t\t\t\tif (downloadAttachments) {\n\t\t\t\t\tdataPropertyAttachmentsPrefixName = this.getNodeParameter(\n\t\t\t\t\t\t'dataPropertyAttachmentsPrefixName',\n\t\t\t\t\t) as string;\n\t\t\t\t}\n\n\t\t\t\tfor (const message of results) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid !== undefined &&\n\t\t\t\t\t\tmessage.attributes.uid <= (staticData.lastMessageUid as number)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid === undefined ||\n\t\t\t\t\t\t(staticData.lastMessageUid as number) < message.attributes.uid\n\t\t\t\t\t) {\n\t\t\t\t\t\tstaticData.lastMessageUid = message.attributes.uid;\n\t\t\t\t\t}\n\t\t\t\t\tconst parts = getParts(message.attributes.struct!);\n\n\t\t\t\t\tnewEmail = {\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\ttextHtml: await getText(parts, message, 'html'),\n\t\t\t\t\t\t\ttextPlain: await getText(parts, message, 'plain'),\n\t\t\t\t\t\t\tmetadata: {} as IDataObject,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tconst messageHeader = message.parts.filter((part) => part.which === 'HEADER');\n\n\t\t\t\t\tconst messageBody = messageHeader[0].body as Record<string, string[]>;\n\t\t\t\t\tfor (propertyName of Object.keys(messageBody as IDataObject)) {\n\t\t\t\t\t\tif (messageBody[propertyName].length) {\n\t\t\t\t\t\t\tif (topLevelProperties.includes(propertyName)) {\n\t\t\t\t\t\t\t\tnewEmail.json[propertyName] = messageBody[propertyName][0];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t(newEmail.json.metadata as IDataObject)[propertyName] =\n\t\t\t\t\t\t\t\t\tmessageBody[propertyName][0];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (downloadAttachments) {\n\t\t\t\t\t\t// Get attachments and add them if any get found\n\t\t\t\t\t\tattachments = await getAttachment(imapConnection, parts, message);\n\t\t\t\t\t\tif (attachments.length) {\n\t\t\t\t\t\t\tnewEmail.binary = {};\n\t\t\t\t\t\t\tfor (let i = 0; i < attachments.length; i++) {\n\t\t\t\t\t\t\t\tnewEmail.binary[`${dataPropertyAttachmentsPrefixName}${i}`] = attachments[i];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tnewEmails.push(newEmail);\n\t\t\t\t}\n\t\t\t} else if (format === 'raw') {\n\t\t\t\tfor (const message of results) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid !== undefined &&\n\t\t\t\t\t\tmessage.attributes.uid <= (staticData.lastMessageUid as number)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid === undefined ||\n\t\t\t\t\t\t(staticData.lastMessageUid as number) < message.attributes.uid\n\t\t\t\t\t) {\n\t\t\t\t\t\tstaticData.lastMessageUid = message.attributes.uid;\n\t\t\t\t\t}\n\t\t\t\t\tconst part = find(message.parts, { which: 'TEXT' });\n\n\t\t\t\t\tif (part === undefined) {\n\t\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Email part could not be parsed.');\n\t\t\t\t\t}\n\t\t\t\t\t// Return base64 string\n\t\t\t\t\tnewEmail = {\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\traw: part.body,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tnewEmails.push(newEmail);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// only mark messages as seen once processing has finished\n\t\t\tif (postProcessAction === 'read') {\n\t\t\t\tconst uidList = results.map((e) => e.attributes.uid);\n\t\t\t\tif (uidList.length > 0) {\n\t\t\t\t\tawait imapConnection.addFlags(uidList, '\\\\SEEN');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn newEmails;\n\t\t};\n\n\t\tconst returnedPromise = this.helpers.createDeferredPromise();\n\n\t\tconst establishConnection = async (): Promise<ImapSimple> => {\n\t\t\tlet searchCriteria = ['UNSEEN'] as Array<string | string[]>;\n\t\t\tif (options.customEmailConfig !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tsearchCriteria = JSON.parse(options.customEmailConfig as string);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Custom email config is not valid JSON.');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\timap: {\n\t\t\t\t\tuser: credentials.user as string,\n\t\t\t\t\tpassword: credentials.password as string,\n\t\t\t\t\thost: (credentials.host as string).trim(),\n\t\t\t\t\tport: credentials.port as number,\n\t\t\t\t\ttls: credentials.secure as boolean,\n\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t},\n\t\t\t\tonMail: async () => {\n\t\t\t\t\tif (connection) {\n\t\t\t\t\t\tif (staticData.lastMessageUid !== undefined) {\n\t\t\t\t\t\t\tsearchCriteria.push(['UID', `${staticData.lastMessageUid as number}:*`]);\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * A short explanation about UIDs and how they work\n\t\t\t\t\t\t\t * can be found here: https://dev.to/kehers/imap-new-messages-since-last-check-44gm\n\t\t\t\t\t\t\t * TL;DR:\n\t\t\t\t\t\t\t * - You cannot filter using ['UID', 'CURRENT ID + 1:*'] because IMAP\n\t\t\t\t\t\t\t * won't return correct results if current id + 1 does not yet exist.\n\t\t\t\t\t\t\t * - UIDs can change but this is not being treated here.\n\t\t\t\t\t\t\t * If the mailbox is recreated (lets say you remove all emails, remove\n\t\t\t\t\t\t\t * the mail box and create another with same name, UIDs will change)\n\t\t\t\t\t\t\t * - You can check if UIDs changed in the above example\n\t\t\t\t\t\t\t * by checking UIDValidity.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.logger.debug('Querying for new messages on node \"EmailReadImap\"', {\n\t\t\t\t\t\t\t\tsearchCriteria,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst returnData = await getNewEmails(connection, searchCriteria);\n\t\t\t\t\t\t\tif (returnData.length) {\n\t\t\t\t\t\t\t\tthis.emit([returnData]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tthis.logger.error('Email Read Imap node encountered an error fetching new emails', {\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t// Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy\n\t\t\t\t\t\t\t// if it receives an error before the workflow got activated\n\t\t\t\t\t\t\tawait returnedPromise.promise.then(() => {\n\t\t\t\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\tif (options.allowUnauthorizedCerts === true) {\n\t\t\t\ttlsOptions.rejectUnauthorized = false;\n\t\t\t}\n\n\t\t\tif (credentials.secure) {\n\t\t\t\ttlsOptions.servername = (credentials.host as string).trim();\n\t\t\t}\n\n\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t}\n\n\t\t\t// Connect to the IMAP server and open the mailbox\n\t\t\t// that we get informed whenever a new email arrives\n\t\t\treturn await imapConnect(config).then(async (conn) => {\n\t\t\t\tconn.on('error', async (error) => {\n\t\t\t\t\tconst errorCode = error.code.toUpperCase();\n\t\t\t\t\tif (['ECONNRESET', 'EPIPE'].includes(errorCode as string)) {\n\t\t\t\t\t\tthis.logger.debug(`IMAP connection was reset (${errorCode}) - reconnecting.`, {\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconnection = await establishConnection();\n\t\t\t\t\t\t\tawait connection.openBox(mailbox);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthis.logger.error('IMAP reconnect did fail', { error: e });\n\t\t\t\t\t\t\t// If something goes wrong we want to run emitError\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.logger.error('Email Read Imap node encountered a connection error', { error });\n\t\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn conn;\n\t\t\t});\n\t\t};\n\n\t\tconnection = await establishConnection();\n\n\t\tawait connection.openBox(mailbox);\n\n\t\tlet reconnectionInterval: NodeJS.Timeout | undefined;\n\n\t\tif (options.forceReconnect !== undefined) {\n\t\t\treconnectionInterval = setInterval(\n\t\t\t\tasync () => {\n\t\t\t\t\tthis.logger.debug('Forcing reconnection of IMAP node.');\n\t\t\t\t\tconnection.end();\n\t\t\t\t\tconnection = await establishConnection();\n\t\t\t\t\tawait connection.openBox(mailbox);\n\t\t\t\t},\n\t\t\t\t(options.forceReconnect as number) * 1000 * 60,\n\t\t\t);\n\t\t}\n\n\t\t// When workflow and so node gets set to inactive close the connectoin\n\t\tasync function closeFunction() {\n\t\t\tif (reconnectionInterval) {\n\t\t\t\tclearInterval(reconnectionInterval);\n\t\t\t}\n\t\t\tconnection.end();\n\t\t}\n\n\t\t// Resolve returned-promise so that waiting errors can be emitted\n\t\treturnedPromise.resolve();\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["isEmpty","imapConnect","part","find"]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/EmailReadImap/v1/EmailReadImapV1.node.ts"],"sourcesContent":["import type { ImapSimple, ImapSimpleOptions, Message } from '@n8n/imap';\nimport { connect as imapConnect, getParts } from '@n8n/imap';\nimport find from 'lodash/find';\nimport isEmpty from 'lodash/isEmpty';\nimport type { Source as ParserSource } from 'mailparser';\nimport { simpleParser } from 'mailparser';\nimport { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';\nimport type {\n\tITriggerFunctions,\n\tIBinaryData,\n\tIBinaryKeyData,\n\tICredentialDataDecryptedObject,\n\tICredentialsDecrypted,\n\tICredentialTestFunctions,\n\tIDataObject,\n\tINodeCredentialTestResult,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeBaseDescription,\n\tINodeTypeDescription,\n\tITriggerResponse,\n} from 'n8n-workflow';\n\nexport async function parseRawEmail(\n\tthis: ITriggerFunctions,\n\tmessageEncoded: ParserSource,\n\tdataPropertyNameDownload: string,\n): Promise<INodeExecutionData> {\n\tconst responseData = await simpleParser(messageEncoded);\n\tconst headers: IDataObject = {};\n\tfor (const header of responseData.headerLines) {\n\t\theaders[header.key] = header.line;\n\t}\n\n\t// @ts-ignore\n\tresponseData.headers = headers;\n\t// @ts-ignore\n\tresponseData.headerLines = undefined;\n\n\tconst binaryData: IBinaryKeyData = {};\n\tif (responseData.attachments) {\n\t\tfor (let i = 0; i < responseData.attachments.length; i++) {\n\t\t\tconst attachment = responseData.attachments[i];\n\t\t\tbinaryData[`${dataPropertyNameDownload}${i}`] = await this.helpers.prepareBinaryData(\n\t\t\t\tattachment.content,\n\t\t\t\tattachment.filename,\n\t\t\t\tattachment.contentType,\n\t\t\t);\n\t\t}\n\t\t// @ts-ignore\n\t\tresponseData.attachments = undefined;\n\t}\n\n\treturn {\n\t\tjson: responseData as unknown as IDataObject,\n\t\tbinary: Object.keys(binaryData).length ? binaryData : undefined,\n\t} as INodeExecutionData;\n}\n\nconst versionDescription: INodeTypeDescription = {\n\tdisplayName: 'Email Trigger (IMAP)',\n\tname: 'emailReadImap',\n\ticon: 'fa:inbox',\n\tgroup: ['trigger'],\n\tversion: 1,\n\tdescription: 'Triggers the workflow when a new email is received',\n\teventTriggerDescription: 'Waiting for you to receive an email',\n\tdefaults: {\n\t\tname: 'Email Trigger (IMAP)',\n\t\tcolor: '#44AA22',\n\t},\n\ttriggerPanel: {\n\t\theader: '',\n\t\texecutionsHelp: {\n\t\t\tinactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time an email is received, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\tactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time an email is received, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t},\n\t\tactivationHint:\n\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t},\n\n\tinputs: [],\n\toutputs: [NodeConnectionTypes.Main],\n\tcredentials: [\n\t\t{\n\t\t\tname: 'imap',\n\t\t\trequired: true,\n\t\t\ttestedBy: 'imapConnectionTest',\n\t\t},\n\t],\n\tproperties: [\n\t\t{\n\t\t\tdisplayName: 'Mailbox Name',\n\t\t\tname: 'mailbox',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'INBOX',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Action',\n\t\t\tname: 'postProcessAction',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Mark as Read',\n\t\t\t\t\tvalue: 'read',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Nothing',\n\t\t\t\t\tvalue: 'nothing',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'read',\n\t\t\tdescription:\n\t\t\t\t'What to do after the email has been received. If \"nothing\" gets selected it will be processed multiple times.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Download Attachments',\n\t\t\tname: 'downloadAttachments',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Whether attachments of emails should be downloaded. Only set if needed as it increases processing.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Format',\n\t\t\tname: 'format',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'RAW',\n\t\t\t\t\tvalue: 'raw',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email message data with body content in the raw field as a base64url encoded string; the payload field is not used',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Resolved',\n\t\t\t\t\tvalue: 'resolved',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email with all data resolved and attachments saved as binary data',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Simple',\n\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email; do not use if you wish to gather inline attachments',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'simple',\n\t\t\tdescription: 'The format to return the message in',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['resolved'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t\tdownloadAttachments: [true],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Custom Email Rules',\n\t\t\t\t\tname: 'customEmailConfig',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '[\"UNSEEN\"]',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Custom email fetching rules. See <a href=\"https://github.com/mscdex/node-imap\">node-imap</a>\\'s search function for more details.',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Ignore SSL Issues (Insecure)',\n\t\t\t\t\tname: 'allowUnauthorizedCerts',\n\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tdefault: false,\n\t\t\t\t\tdescription: 'Whether to connect even if SSL certificate validation is not possible',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Force Reconnect',\n\t\t\t\t\tname: 'forceReconnect',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tdescription: 'Sets an interval (in minutes) to force a reconnection',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n};\n\nexport class EmailReadImapV1 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\t...versionDescription,\n\t\t};\n\t}\n\n\tmethods = {\n\t\tcredentialTest: {\n\t\t\tasync imapConnectionTest(\n\t\t\t\tthis: ICredentialTestFunctions,\n\t\t\t\tcredential: ICredentialsDecrypted,\n\t\t\t): Promise<INodeCredentialTestResult> {\n\t\t\t\tconst credentials = credential.data as ICredentialDataDecryptedObject;\n\t\t\t\ttry {\n\t\t\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\t\t\timap: {\n\t\t\t\t\t\t\tuser: credentials.user as string,\n\t\t\t\t\t\t\tpassword: credentials.password as string,\n\t\t\t\t\t\t\thost: (credentials.host as string).trim(),\n\t\t\t\t\t\t\tport: credentials.port as number,\n\t\t\t\t\t\t\ttls: credentials.secure as boolean,\n\t\t\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\t\t\tif (credentials.secure) {\n\t\t\t\t\t\ttlsOptions.servername = (credentials.host as string).trim();\n\t\t\t\t\t}\n\t\t\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t\t\t}\n\t\t\t\t\tconst connection = await imapConnect(config);\n\t\t\t\t\tawait connection.getBoxes();\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'Error',\n\t\t\t\t\t\tmessage: error.message,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 'OK',\n\t\t\t\t\tmessage: 'Connection successful!',\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst credentials = await this.getCredentials('imap');\n\n\t\tconst mailbox = this.getNodeParameter('mailbox') as string;\n\t\tconst postProcessAction = this.getNodeParameter('postProcessAction') as string;\n\t\tconst options = this.getNodeParameter('options', {}) as IDataObject;\n\n\t\tconst staticData = this.getWorkflowStaticData('node');\n\t\tthis.logger.debug('Loaded static data for node \"EmailReadImap\"', { staticData });\n\n\t\tlet connection: ImapSimple;\n\n\t\t// Returns the email text\n\n\t\tconst getText = async (parts: any[], message: Message, subtype: string): Promise<string> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst textParts = parts.filter((part) => {\n\t\t\t\treturn (\n\t\t\t\t\tpart.type.toUpperCase() === 'TEXT' && part.subtype.toUpperCase() === subtype.toUpperCase()\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tconst part = textParts[0];\n\t\t\tif (!part) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst partData = await connection.getPartData(message, part);\n\t\t\t\treturn partData.toString();\n\t\t\t} catch {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t};\n\n\t\t// Returns the email attachments\n\t\tconst getAttachment = async (\n\t\t\timapConnection: ImapSimple,\n\t\t\tparts: any[],\n\t\t\tmessage: Message,\n\t\t): Promise<IBinaryData[]> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\t// Check if the message has attachments and if so get them\n\t\t\tconst attachmentParts = parts.filter((part) => {\n\t\t\t\treturn part.disposition && part.disposition.type.toUpperCase() === 'ATTACHMENT';\n\t\t\t});\n\n\t\t\tconst attachmentPromises = [];\n\t\t\tlet attachmentPromise;\n\t\t\tfor (const attachmentPart of attachmentParts) {\n\t\t\t\tattachmentPromise = imapConnection\n\t\t\t\t\t.getPartData(message, attachmentPart)\n\t\t\t\t\t.then(async (partData) => {\n\t\t\t\t\t\t// Return it in the format n8n expects\n\t\t\t\t\t\treturn await this.helpers.prepareBinaryData(\n\t\t\t\t\t\t\tpartData.buffer,\n\t\t\t\t\t\t\tattachmentPart.disposition.params.filename as string,\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\tattachmentPromises.push(attachmentPromise);\n\t\t\t}\n\n\t\t\treturn await Promise.all(attachmentPromises);\n\t\t};\n\n\t\t// Returns all the new unseen messages\n\t\tconst getNewEmails = async (\n\t\t\timapConnection: ImapSimple,\n\t\t\tsearchCriteria: Array<string | string[]>,\n\t\t): Promise<INodeExecutionData[]> => {\n\t\t\tconst format = this.getNodeParameter('format', 0) as string;\n\n\t\t\tlet fetchOptions = {};\n\n\t\t\tif (format === 'simple' || format === 'raw') {\n\t\t\t\tfetchOptions = {\n\t\t\t\t\tbodies: ['TEXT', 'HEADER'],\n\t\t\t\t\tmarkSeen: false,\n\t\t\t\t\tstruct: true,\n\t\t\t\t};\n\t\t\t} else if (format === 'resolved') {\n\t\t\t\tfetchOptions = {\n\t\t\t\t\tbodies: [''],\n\t\t\t\t\tmarkSeen: false,\n\t\t\t\t\tstruct: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst results = await imapConnection.search(searchCriteria, fetchOptions);\n\n\t\t\tconst newEmails: INodeExecutionData[] = [];\n\t\t\tlet newEmail: INodeExecutionData;\n\t\t\tlet attachments: IBinaryData[];\n\t\t\tlet propertyName: string;\n\n\t\t\t// All properties get by default moved to metadata except the ones\n\t\t\t// which are defined here which get set on the top level.\n\t\t\tconst topLevelProperties = ['cc', 'date', 'from', 'subject', 'to'];\n\n\t\t\tif (format === 'resolved') {\n\t\t\t\tconst dataPropertyAttachmentsPrefixName = this.getNodeParameter(\n\t\t\t\t\t'dataPropertyAttachmentsPrefixName',\n\t\t\t\t) as string;\n\n\t\t\t\tfor (const message of results) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid !== undefined &&\n\t\t\t\t\t\tmessage.attributes.uid <= (staticData.lastMessageUid as number)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid === undefined ||\n\t\t\t\t\t\t(staticData.lastMessageUid as number) < message.attributes.uid\n\t\t\t\t\t) {\n\t\t\t\t\t\tstaticData.lastMessageUid = message.attributes.uid;\n\t\t\t\t\t}\n\t\t\t\t\tconst part = find(message.parts, { which: '' });\n\n\t\t\t\t\tif (part === undefined) {\n\t\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Email part could not be parsed.');\n\t\t\t\t\t}\n\t\t\t\t\tconst parsedEmail = await parseRawEmail.call(\n\t\t\t\t\t\tthis,\n\t\t\t\t\t\tpart.body as Buffer,\n\t\t\t\t\t\tdataPropertyAttachmentsPrefixName,\n\t\t\t\t\t);\n\n\t\t\t\t\tnewEmails.push(parsedEmail);\n\t\t\t\t}\n\t\t\t} else if (format === 'simple') {\n\t\t\t\tconst downloadAttachments = this.getNodeParameter('downloadAttachments') as boolean;\n\n\t\t\t\tlet dataPropertyAttachmentsPrefixName = '';\n\t\t\t\tif (downloadAttachments) {\n\t\t\t\t\tdataPropertyAttachmentsPrefixName = this.getNodeParameter(\n\t\t\t\t\t\t'dataPropertyAttachmentsPrefixName',\n\t\t\t\t\t) as string;\n\t\t\t\t}\n\n\t\t\t\tfor (const message of results) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid !== undefined &&\n\t\t\t\t\t\tmessage.attributes.uid <= (staticData.lastMessageUid as number)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid === undefined ||\n\t\t\t\t\t\t(staticData.lastMessageUid as number) < message.attributes.uid\n\t\t\t\t\t) {\n\t\t\t\t\t\tstaticData.lastMessageUid = message.attributes.uid;\n\t\t\t\t\t}\n\t\t\t\t\tconst parts = getParts(message.attributes.struct!);\n\n\t\t\t\t\tnewEmail = {\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\ttextHtml: await getText(parts, message, 'html'),\n\t\t\t\t\t\t\ttextPlain: await getText(parts, message, 'plain'),\n\t\t\t\t\t\t\tmetadata: {} as IDataObject,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tconst messageHeader = message.parts.filter((part) => part.which === 'HEADER');\n\n\t\t\t\t\tconst messageBody = messageHeader[0].body as Record<string, string[]>;\n\t\t\t\t\tfor (propertyName of Object.keys(messageBody as IDataObject)) {\n\t\t\t\t\t\tif (messageBody[propertyName].length) {\n\t\t\t\t\t\t\tif (topLevelProperties.includes(propertyName)) {\n\t\t\t\t\t\t\t\tnewEmail.json[propertyName] = messageBody[propertyName][0];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t(newEmail.json.metadata as IDataObject)[propertyName] =\n\t\t\t\t\t\t\t\t\tmessageBody[propertyName][0];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (downloadAttachments) {\n\t\t\t\t\t\t// Get attachments and add them if any get found\n\t\t\t\t\t\tattachments = await getAttachment(imapConnection, parts, message);\n\t\t\t\t\t\tif (attachments.length) {\n\t\t\t\t\t\t\tnewEmail.binary = {};\n\t\t\t\t\t\t\tfor (let i = 0; i < attachments.length; i++) {\n\t\t\t\t\t\t\t\tnewEmail.binary[`${dataPropertyAttachmentsPrefixName}${i}`] = attachments[i];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tnewEmails.push(newEmail);\n\t\t\t\t}\n\t\t\t} else if (format === 'raw') {\n\t\t\t\tfor (const message of results) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid !== undefined &&\n\t\t\t\t\t\tmessage.attributes.uid <= (staticData.lastMessageUid as number)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (\n\t\t\t\t\t\tstaticData.lastMessageUid === undefined ||\n\t\t\t\t\t\t(staticData.lastMessageUid as number) < message.attributes.uid\n\t\t\t\t\t) {\n\t\t\t\t\t\tstaticData.lastMessageUid = message.attributes.uid;\n\t\t\t\t\t}\n\t\t\t\t\tconst part = find(message.parts, { which: 'TEXT' });\n\n\t\t\t\t\tif (part === undefined) {\n\t\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Email part could not be parsed.');\n\t\t\t\t\t}\n\t\t\t\t\t// Return base64 string\n\t\t\t\t\tnewEmail = {\n\t\t\t\t\t\tjson: {\n\t\t\t\t\t\t\traw: part.body,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tnewEmails.push(newEmail);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// only mark messages as seen once processing has finished\n\t\t\tif (postProcessAction === 'read') {\n\t\t\t\tconst uidList = results.map((e) => e.attributes.uid);\n\t\t\t\tif (uidList.length > 0) {\n\t\t\t\t\tawait imapConnection.addFlags(uidList, '\\\\SEEN');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn newEmails;\n\t\t};\n\n\t\tconst returnedPromise = this.helpers.createDeferredPromise();\n\n\t\tconst establishConnection = async (): Promise<ImapSimple> => {\n\t\t\tlet searchCriteria = ['UNSEEN'] as Array<string | string[]>;\n\t\t\tif (options.customEmailConfig !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tsearchCriteria = JSON.parse(options.customEmailConfig as string);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Custom email config is not valid JSON.');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\timap: {\n\t\t\t\t\tuser: credentials.user as string,\n\t\t\t\t\tpassword: credentials.password as string,\n\t\t\t\t\thost: (credentials.host as string).trim(),\n\t\t\t\t\tport: credentials.port as number,\n\t\t\t\t\ttls: credentials.secure as boolean,\n\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t},\n\t\t\t\tonMail: async () => {\n\t\t\t\t\tif (connection) {\n\t\t\t\t\t\tif (staticData.lastMessageUid !== undefined) {\n\t\t\t\t\t\t\tsearchCriteria.push(['UID', `${staticData.lastMessageUid as number}:*`]);\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * A short explanation about UIDs and how they work\n\t\t\t\t\t\t\t * can be found here: https://dev.to/kehers/imap-new-messages-since-last-check-44gm\n\t\t\t\t\t\t\t * TL;DR:\n\t\t\t\t\t\t\t * - You cannot filter using ['UID', 'CURRENT ID + 1:*'] because IMAP\n\t\t\t\t\t\t\t * won't return correct results if current id + 1 does not yet exist.\n\t\t\t\t\t\t\t * - UIDs can change but this is not being treated here.\n\t\t\t\t\t\t\t * If the mailbox is recreated (lets say you remove all emails, remove\n\t\t\t\t\t\t\t * the mail box and create another with same name, UIDs will change)\n\t\t\t\t\t\t\t * - You can check if UIDs changed in the above example\n\t\t\t\t\t\t\t * by checking UIDValidity.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.logger.debug('Querying for new messages on node \"EmailReadImap\"', {\n\t\t\t\t\t\t\t\tsearchCriteria,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst returnData = await getNewEmails(connection, searchCriteria);\n\t\t\t\t\t\t\tif (returnData.length) {\n\t\t\t\t\t\t\t\tthis.emit([returnData]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tthis.logger.error('Email Read Imap node encountered an error fetching new emails', {\n\t\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t// Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy\n\t\t\t\t\t\t\t// if it receives an error before the workflow got activated\n\t\t\t\t\t\t\tawait returnedPromise.promise.then(() => {\n\t\t\t\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\tif (options.allowUnauthorizedCerts === true) {\n\t\t\t\ttlsOptions.rejectUnauthorized = false;\n\t\t\t}\n\n\t\t\tif (credentials.secure) {\n\t\t\t\ttlsOptions.servername = (credentials.host as string).trim();\n\t\t\t}\n\n\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t}\n\n\t\t\t// Connect to the IMAP server and open the mailbox\n\t\t\t// that we get informed whenever a new email arrives\n\t\t\treturn await imapConnect(config).then(async (conn) => {\n\t\t\t\tconn.on('error', async (error) => {\n\t\t\t\t\tconst errorCode = error.code.toUpperCase();\n\t\t\t\t\tif (['ECONNRESET', 'EPIPE'].includes(errorCode as string)) {\n\t\t\t\t\t\tthis.logger.debug(`IMAP connection was reset (${errorCode}) - reconnecting.`, {\n\t\t\t\t\t\t\terror,\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconnection = await establishConnection();\n\t\t\t\t\t\t\tawait connection.openBox(mailbox);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tthis.logger.error('IMAP reconnect did fail', { error: e });\n\t\t\t\t\t\t\t// If something goes wrong we want to run emitError\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.logger.error('Email Read Imap node encountered a connection error', { error });\n\t\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn conn;\n\t\t\t});\n\t\t};\n\n\t\tconnection = await establishConnection();\n\n\t\tawait connection.openBox(mailbox);\n\n\t\tlet reconnectionInterval: NodeJS.Timeout | undefined;\n\n\t\tif (options.forceReconnect !== undefined) {\n\t\t\treconnectionInterval = setInterval(\n\t\t\t\tasync () => {\n\t\t\t\t\tthis.logger.debug('Forcing reconnection of IMAP node.');\n\t\t\t\t\tconnection.end();\n\t\t\t\t\tconnection = await establishConnection();\n\t\t\t\t\tawait connection.openBox(mailbox);\n\t\t\t\t},\n\t\t\t\t(options.forceReconnect as number) * 1000 * 60,\n\t\t\t);\n\t\t}\n\n\t\t// When workflow and so node gets set to inactive close the connectoin\n\t\tasync function closeFunction() {\n\t\t\tif (reconnectionInterval) {\n\t\t\t\tclearInterval(reconnectionInterval);\n\t\t\t}\n\t\t\tconnection.end();\n\t\t}\n\n\t\t// Resolve returned-promise so that waiting errors can be emitted\n\t\treturnedPromise.resolve();\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["isEmpty","imapConnect","part","find"]}
|
|
@@ -53,8 +53,8 @@ const versionDescription = {
|
|
|
53
53
|
triggerPanel: {
|
|
54
54
|
header: "",
|
|
55
55
|
executionsHelp: {
|
|
56
|
-
inactive: "<b>While building your workflow</b>, click the '
|
|
57
|
-
active: "<b>While building your workflow</b>, click the '
|
|
56
|
+
inactive: "<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time an email is received, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.",
|
|
57
|
+
active: "<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time an email is received, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor."
|
|
58
58
|
},
|
|
59
59
|
activationHint: "Once you\u2019ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won\u2019t see those executions here)."
|
|
60
60
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/EmailReadImap/v2/EmailReadImapV2.node.ts"],"sourcesContent":["import type { ImapSimple, ImapSimpleOptions, Message, MessagePart } from '@n8n/imap';\nimport { connect as imapConnect } from '@n8n/imap';\nimport isEmpty from 'lodash/isEmpty';\nimport type {\n\tITriggerFunctions,\n\tIBinaryData,\n\tICredentialsDecrypted,\n\tICredentialTestFunctions,\n\tIDataObject,\n\tINodeCredentialTestResult,\n\tINodeType,\n\tINodeTypeBaseDescription,\n\tINodeTypeDescription,\n\tITriggerResponse,\n\tJsonObject,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, NodeOperationError, TriggerCloseError } from 'n8n-workflow';\nimport rfc2047 from 'rfc2047';\n\nimport type { ICredentialsDataImap } from '@credentials/Imap.credentials';\nimport { isCredentialsDataImap } from '@credentials/Imap.credentials';\n\nimport { getNewEmails } from './utils';\n\nconst versionDescription: INodeTypeDescription = {\n\tdisplayName: 'Email Trigger (IMAP)',\n\tname: 'emailReadImap',\n\ticon: 'fa:inbox',\n\ticonColor: 'green',\n\tgroup: ['trigger'],\n\tversion: 2,\n\tdescription: 'Triggers the workflow when a new email is received',\n\teventTriggerDescription: 'Waiting for you to receive an email',\n\tdefaults: {\n\t\tname: 'Email Trigger (IMAP)',\n\t\tcolor: '#44AA22',\n\t},\n\ttriggerPanel: {\n\t\theader: '',\n\t\texecutionsHelp: {\n\t\t\tinactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time an email is received, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\tactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'listen' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time an email is received, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t},\n\t\tactivationHint:\n\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t},\n\tusableAsTool: true,\n\tinputs: [],\n\toutputs: [NodeConnectionTypes.Main],\n\tcredentials: [\n\t\t{\n\t\t\tname: 'imap',\n\t\t\trequired: true,\n\t\t\ttestedBy: 'imapConnectionTest',\n\t\t},\n\t],\n\tproperties: [\n\t\t{\n\t\t\tdisplayName: 'Mailbox Name',\n\t\t\tname: 'mailbox',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'INBOX',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Action',\n\t\t\tname: 'postProcessAction',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Mark as Read',\n\t\t\t\t\tvalue: 'read',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Nothing',\n\t\t\t\t\tvalue: 'nothing',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'read',\n\t\t\tdescription:\n\t\t\t\t'What to do after the email has been received. If \"nothing\" gets selected it will be processed multiple times.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Download Attachments',\n\t\t\tname: 'downloadAttachments',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Whether attachments of emails should be downloaded. Only set if needed as it increases processing.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Format',\n\t\t\tname: 'format',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'RAW',\n\t\t\t\t\tvalue: 'raw',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email message data with body content in the raw field as a base64url encoded string; the payload field is not used',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Resolved',\n\t\t\t\t\tvalue: 'resolved',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email with all data resolved and attachments saved as binary data',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Simple',\n\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email; do not use if you wish to gather inline attachments',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'simple',\n\t\t\tdescription: 'The format to return the message in',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['resolved'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t\tdownloadAttachments: [true],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Custom Email Rules',\n\t\t\t\t\tname: 'customEmailConfig',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '[\"UNSEEN\"]',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Custom email fetching rules. See <a href=\"https://github.com/mscdex/node-imap\">node-imap</a>\\'s search function for more details.',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Force Reconnect Every Minutes',\n\t\t\t\t\tname: 'forceReconnect',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tdescription: 'Sets an interval (in minutes) to force a reconnection',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n};\n\nexport class EmailReadImapV2 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\t...versionDescription,\n\t\t};\n\t}\n\n\tmethods = {\n\t\tcredentialTest: {\n\t\t\tasync imapConnectionTest(\n\t\t\t\tthis: ICredentialTestFunctions,\n\t\t\t\tcredential: ICredentialsDecrypted,\n\t\t\t): Promise<INodeCredentialTestResult> {\n\t\t\t\tif (isCredentialsDataImap(credential.data)) {\n\t\t\t\t\tconst credentials = credential.data as ICredentialsDataImap;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\t\t\t\timap: {\n\t\t\t\t\t\t\t\tuser: credentials.user,\n\t\t\t\t\t\t\t\tpassword: credentials.password,\n\t\t\t\t\t\t\t\thost: credentials.host.trim(),\n\t\t\t\t\t\t\t\tport: credentials.port,\n\t\t\t\t\t\t\t\ttls: credentials.secure,\n\t\t\t\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\t\t\t\tif (credentials.allowUnauthorizedCerts) {\n\t\t\t\t\t\t\ttlsOptions.rejectUnauthorized = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (credentials.secure) {\n\t\t\t\t\t\t\ttlsOptions.servername = credentials.host.trim();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst connection = await imapConnect(config);\n\t\t\t\t\t\tawait connection.getBoxes();\n\t\t\t\t\t\tconnection.end();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstatus: 'Error',\n\t\t\t\t\t\t\tmessage: (error as Error).message,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'OK',\n\t\t\t\t\t\tmessage: 'Connection successful!',\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'Error',\n\t\t\t\t\t\tmessage: 'Credentials are no IMAP credentials.',\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst credentialsObject = await this.getCredentials('imap');\n\t\tconst credentials = isCredentialsDataImap(credentialsObject) ? credentialsObject : undefined;\n\t\tif (!credentials) {\n\t\t\tthrow new NodeOperationError(this.getNode(), 'Credentials are not valid for imap node.');\n\t\t}\n\t\tconst mailbox = this.getNodeParameter('mailbox') as string;\n\t\tconst postProcessAction = this.getNodeParameter('postProcessAction') as string;\n\t\tconst options = this.getNodeParameter('options', {}) as IDataObject;\n\n\t\tconst staticData = this.getWorkflowStaticData('node');\n\t\tthis.logger.debug('Loaded static data for node \"EmailReadImap\"', { staticData });\n\n\t\tlet connection: ImapSimple;\n\t\tlet closeFunctionWasCalled = false;\n\t\tlet isCurrentlyReconnecting = false;\n\n\t\t// Returns the email text\n\n\t\tconst getText = async (\n\t\t\tparts: MessagePart[],\n\t\t\tmessage: Message,\n\t\t\tsubtype: string,\n\t\t): Promise<string> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst textParts = parts.filter((part) => {\n\t\t\t\treturn (\n\t\t\t\t\tpart.type.toUpperCase() === 'TEXT' && part.subtype.toUpperCase() === subtype.toUpperCase()\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tconst part = textParts[0];\n\t\t\tif (!part) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst partData = await connection.getPartData(message, part);\n\t\t\t\treturn partData.toString();\n\t\t\t} catch {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t};\n\n\t\t// Returns the email attachments\n\t\tconst getAttachment = async (\n\t\t\timapConnection: ImapSimple,\n\t\t\tparts: MessagePart[],\n\t\t\tmessage: Message,\n\t\t): Promise<IBinaryData[]> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\t// Check if the message has attachments and if so get them\n\t\t\tconst attachmentParts = parts.filter(\n\t\t\t\t(part) => part.disposition?.type?.toUpperCase() === 'ATTACHMENT',\n\t\t\t);\n\n\t\t\tconst decodeFilename = (filename: string) => {\n\t\t\t\tconst regex = /=\\?([\\w-]+)\\?Q\\?.*\\?=/i;\n\t\t\t\tif (regex.test(filename)) {\n\t\t\t\t\treturn rfc2047.decode(filename);\n\t\t\t\t}\n\t\t\t\treturn filename;\n\t\t\t};\n\n\t\t\tconst attachmentPromises = [];\n\t\t\tlet attachmentPromise;\n\t\t\tfor (const attachmentPart of attachmentParts) {\n\t\t\t\tattachmentPromise = imapConnection\n\t\t\t\t\t.getPartData(message, attachmentPart)\n\t\t\t\t\t.then(async (partData) => {\n\t\t\t\t\t\t// if filename contains utf-8 encoded characters, decode it\n\t\t\t\t\t\tconst fileName = decodeFilename(\n\t\t\t\t\t\t\t((attachmentPart.disposition as IDataObject)?.params as IDataObject)\n\t\t\t\t\t\t\t\t?.filename as string,\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// Return it in the format n8n expects\n\t\t\t\t\t\treturn await this.helpers.prepareBinaryData(partData.buffer, fileName);\n\t\t\t\t\t});\n\n\t\t\t\tattachmentPromises.push(attachmentPromise);\n\t\t\t}\n\n\t\t\treturn await Promise.all(attachmentPromises);\n\t\t};\n\n\t\tconst returnedPromise = this.helpers.createDeferredPromise();\n\n\t\tconst establishConnection = async (): Promise<ImapSimple> => {\n\t\t\tlet searchCriteria = ['UNSEEN'] as Array<string | string[]>;\n\t\t\tif (options.customEmailConfig !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tsearchCriteria = JSON.parse(options.customEmailConfig as string) as Array<\n\t\t\t\t\t\tstring | string[]\n\t\t\t\t\t>;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Custom email config is not valid JSON.');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\timap: {\n\t\t\t\t\tuser: credentials.user,\n\t\t\t\t\tpassword: credentials.password,\n\t\t\t\t\thost: credentials.host.trim(),\n\t\t\t\t\tport: credentials.port,\n\t\t\t\t\ttls: credentials.secure,\n\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t},\n\t\t\t\tonMail: async () => {\n\t\t\t\t\tif (connection) {\n\t\t\t\t\t\tif (staticData.lastMessageUid !== undefined) {\n\t\t\t\t\t\t\tsearchCriteria.push(['UID', `${staticData.lastMessageUid as number}:*`]);\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * A short explanation about UIDs and how they work\n\t\t\t\t\t\t\t * can be found here: https://dev.to/kehers/imap-new-messages-since-last-check-44gm\n\t\t\t\t\t\t\t * TL;DR:\n\t\t\t\t\t\t\t * - You cannot filter using ['UID', 'CURRENT ID + 1:*'] because IMAP\n\t\t\t\t\t\t\t * won't return correct results if current id + 1 does not yet exist.\n\t\t\t\t\t\t\t * - UIDs can change but this is not being treated here.\n\t\t\t\t\t\t\t * If the mailbox is recreated (lets say you remove all emails, remove\n\t\t\t\t\t\t\t * the mail box and create another with same name, UIDs will change)\n\t\t\t\t\t\t\t * - You can check if UIDs changed in the above example\n\t\t\t\t\t\t\t * by checking UIDValidity.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.logger.debug('Querying for new messages on node \"EmailReadImap\"', {\n\t\t\t\t\t\t\t\tsearchCriteria,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst returnData = await getNewEmails.call(\n\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\tconnection,\n\t\t\t\t\t\t\t\tsearchCriteria,\n\t\t\t\t\t\t\t\tstaticData,\n\t\t\t\t\t\t\t\tpostProcessAction,\n\t\t\t\t\t\t\t\tgetText,\n\t\t\t\t\t\t\t\tgetAttachment,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (returnData.length) {\n\t\t\t\t\t\t\t\tthis.emit([returnData]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tthis.logger.error('Email Read Imap node encountered an error fetching new emails', {\n\t\t\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t// Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy\n\t\t\t\t\t\t\t// if it receives an error before the workflow got activated\n\t\t\t\t\t\t\tawait returnedPromise.promise.then(() => {\n\t\t\t\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonUpdate: async (seqNo: number, info) => {\n\t\t\t\t\tthis.logger.debug(`Email Read Imap:update ${seqNo}`, info);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\tif (credentials.allowUnauthorizedCerts) {\n\t\t\t\ttlsOptions.rejectUnauthorized = false;\n\t\t\t}\n\n\t\t\tif (credentials.secure) {\n\t\t\t\ttlsOptions.servername = credentials.host.trim();\n\t\t\t}\n\n\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t}\n\n\t\t\t// Connect to the IMAP server and open the mailbox\n\t\t\t// that we get informed whenever a new email arrives\n\t\t\treturn await imapConnect(config).then(async (conn) => {\n\t\t\t\tconn.on('close', async (_hadError: boolean) => {\n\t\t\t\t\tif (isCurrentlyReconnecting) {\n\t\t\t\t\t\tthis.logger.debug('Email Read Imap: Connected closed for forced reconnecting');\n\t\t\t\t\t} else if (closeFunctionWasCalled) {\n\t\t\t\t\t\tthis.logger.debug('Email Read Imap: Shutting down workflow - connected closed');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.logger.error('Email Read Imap: Connected closed unexpectedly');\n\t\t\t\t\t\tthis.emitError(new Error('Imap connection closed unexpectedly'));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconn.on('error', async (error) => {\n\t\t\t\t\tconst errorCode = ((error as JsonObject).code as string).toUpperCase();\n\t\t\t\t\tthis.logger.debug(`IMAP connection experienced an error: (${errorCode})`, {\n\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t});\n\t\t\t\treturn conn;\n\t\t\t});\n\t\t};\n\n\t\tconnection = await establishConnection();\n\n\t\tawait connection.openBox(mailbox);\n\n\t\tlet reconnectionInterval: NodeJS.Timeout | undefined;\n\n\t\tconst handleReconnect = async () => {\n\t\t\tthis.logger.debug('Forcing reconnect to IMAP server');\n\t\t\ttry {\n\t\t\t\tisCurrentlyReconnecting = true;\n\t\t\t\tif (connection.closeBox) await connection.closeBox(false);\n\t\t\t\tconnection.end();\n\t\t\t\tconnection = await establishConnection();\n\t\t\t\tawait connection.openBox(mailbox);\n\t\t\t} catch (error) {\n\t\t\t\tthis.logger.error(error as string);\n\t\t\t} finally {\n\t\t\t\tisCurrentlyReconnecting = false;\n\t\t\t}\n\t\t};\n\n\t\tif (options.forceReconnect !== undefined) {\n\t\t\treconnectionInterval = setInterval(\n\t\t\t\thandleReconnect,\n\t\t\t\t(options.forceReconnect as number) * 1000 * 60,\n\t\t\t);\n\t\t}\n\n\t\t// When workflow and so node gets set to inactive close the connection\n\t\tconst closeFunction = async () => {\n\t\t\tcloseFunctionWasCalled = true;\n\t\t\tif (reconnectionInterval) {\n\t\t\t\tclearInterval(reconnectionInterval);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (connection.closeBox) await connection.closeBox(false);\n\t\t\t\tconnection.end();\n\t\t\t} catch (error) {\n\t\t\t\tthrow new TriggerCloseError(this.getNode(), { cause: error as Error, level: 'warning' });\n\t\t\t}\n\t\t};\n\n\t\t// Resolve returned-promise so that waiting errors can be emitted\n\t\treturnedPromise.resolve();\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["isEmpty","imapConnect","part","rfc2047"]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/EmailReadImap/v2/EmailReadImapV2.node.ts"],"sourcesContent":["import type { ImapSimple, ImapSimpleOptions, Message, MessagePart } from '@n8n/imap';\nimport { connect as imapConnect } from '@n8n/imap';\nimport isEmpty from 'lodash/isEmpty';\nimport type {\n\tITriggerFunctions,\n\tIBinaryData,\n\tICredentialsDecrypted,\n\tICredentialTestFunctions,\n\tIDataObject,\n\tINodeCredentialTestResult,\n\tINodeType,\n\tINodeTypeBaseDescription,\n\tINodeTypeDescription,\n\tITriggerResponse,\n\tJsonObject,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, NodeOperationError, TriggerCloseError } from 'n8n-workflow';\nimport rfc2047 from 'rfc2047';\n\nimport type { ICredentialsDataImap } from '@credentials/Imap.credentials';\nimport { isCredentialsDataImap } from '@credentials/Imap.credentials';\n\nimport { getNewEmails } from './utils';\n\nconst versionDescription: INodeTypeDescription = {\n\tdisplayName: 'Email Trigger (IMAP)',\n\tname: 'emailReadImap',\n\ticon: 'fa:inbox',\n\ticonColor: 'green',\n\tgroup: ['trigger'],\n\tversion: 2,\n\tdescription: 'Triggers the workflow when a new email is received',\n\teventTriggerDescription: 'Waiting for you to receive an email',\n\tdefaults: {\n\t\tname: 'Email Trigger (IMAP)',\n\t\tcolor: '#44AA22',\n\t},\n\ttriggerPanel: {\n\t\theader: '',\n\t\texecutionsHelp: {\n\t\t\tinactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Once you're happy with your workflow</b>, <a data-key='activate'>activate</a> it. Then every time an email is received, the workflow will execute. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t\tactive:\n\t\t\t\t\"<b>While building your workflow</b>, click the 'test step' button, then send an email to make an event happen. This will trigger an execution, which will show up in this editor.<br /> <br /><b>Your workflow will also execute automatically</b>, since it's activated. Every time an email is received, this node will trigger an execution. These executions will show up in the <a data-key='executions'>executions list</a>, but not in the editor.\",\n\t\t},\n\t\tactivationHint:\n\t\t\t\"Once you’ve finished building your workflow, <a data-key='activate'>activate</a> it to have it also listen continuously (you just won’t see those executions here).\",\n\t},\n\tusableAsTool: true,\n\tinputs: [],\n\toutputs: [NodeConnectionTypes.Main],\n\tcredentials: [\n\t\t{\n\t\t\tname: 'imap',\n\t\t\trequired: true,\n\t\t\ttestedBy: 'imapConnectionTest',\n\t\t},\n\t],\n\tproperties: [\n\t\t{\n\t\t\tdisplayName: 'Mailbox Name',\n\t\t\tname: 'mailbox',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'INBOX',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Action',\n\t\t\tname: 'postProcessAction',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'Mark as Read',\n\t\t\t\t\tvalue: 'read',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Nothing',\n\t\t\t\t\tvalue: 'nothing',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'read',\n\t\t\tdescription:\n\t\t\t\t'What to do after the email has been received. If \"nothing\" gets selected it will be processed multiple times.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Download Attachments',\n\t\t\tname: 'downloadAttachments',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Whether attachments of emails should be downloaded. Only set if needed as it increases processing.',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Format',\n\t\t\tname: 'format',\n\t\t\ttype: 'options',\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tname: 'RAW',\n\t\t\t\t\tvalue: 'raw',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email message data with body content in the raw field as a base64url encoded string; the payload field is not used',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Resolved',\n\t\t\t\t\tvalue: 'resolved',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email with all data resolved and attachments saved as binary data',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: 'Simple',\n\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Returns the full email; do not use if you wish to gather inline attachments',\n\t\t\t\t},\n\t\t\t],\n\t\t\tdefault: 'simple',\n\t\t\tdescription: 'The format to return the message in',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['resolved'],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Property Prefix Name',\n\t\t\tname: 'dataPropertyAttachmentsPrefixName',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'attachment_',\n\t\t\tdisplayOptions: {\n\t\t\t\tshow: {\n\t\t\t\t\tformat: ['simple'],\n\t\t\t\t\tdownloadAttachments: [true],\n\t\t\t\t},\n\t\t\t},\n\t\t\tdescription:\n\t\t\t\t'Prefix for name of the binary property to which to write the attachments. An index starting with 0 will be added. So if name is \"attachment_\" the first attachment is saved to \"attachment_0\"',\n\t\t},\n\t\t{\n\t\t\tdisplayName: 'Options',\n\t\t\tname: 'options',\n\t\t\ttype: 'collection',\n\t\t\tplaceholder: 'Add option',\n\t\t\tdefault: {},\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Custom Email Rules',\n\t\t\t\t\tname: 'customEmailConfig',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdefault: '[\"UNSEEN\"]',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Custom email fetching rules. See <a href=\"https://github.com/mscdex/node-imap\">node-imap</a>\\'s search function for more details.',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Force Reconnect Every Minutes',\n\t\t\t\t\tname: 'forceReconnect',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 60,\n\t\t\t\t\tdescription: 'Sets an interval (in minutes) to force a reconnection',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n};\n\nexport class EmailReadImapV2 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\t...versionDescription,\n\t\t};\n\t}\n\n\tmethods = {\n\t\tcredentialTest: {\n\t\t\tasync imapConnectionTest(\n\t\t\t\tthis: ICredentialTestFunctions,\n\t\t\t\tcredential: ICredentialsDecrypted,\n\t\t\t): Promise<INodeCredentialTestResult> {\n\t\t\t\tif (isCredentialsDataImap(credential.data)) {\n\t\t\t\t\tconst credentials = credential.data as ICredentialsDataImap;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\t\t\t\timap: {\n\t\t\t\t\t\t\t\tuser: credentials.user,\n\t\t\t\t\t\t\t\tpassword: credentials.password,\n\t\t\t\t\t\t\t\thost: credentials.host.trim(),\n\t\t\t\t\t\t\t\tport: credentials.port,\n\t\t\t\t\t\t\t\ttls: credentials.secure,\n\t\t\t\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\t\t\t\tif (credentials.allowUnauthorizedCerts) {\n\t\t\t\t\t\t\ttlsOptions.rejectUnauthorized = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (credentials.secure) {\n\t\t\t\t\t\t\ttlsOptions.servername = credentials.host.trim();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst connection = await imapConnect(config);\n\t\t\t\t\t\tawait connection.getBoxes();\n\t\t\t\t\t\tconnection.end();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstatus: 'Error',\n\t\t\t\t\t\t\tmessage: (error as Error).message,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'OK',\n\t\t\t\t\t\tmessage: 'Connection successful!',\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 'Error',\n\t\t\t\t\t\tmessage: 'Credentials are no IMAP credentials.',\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t};\n\n\tasync trigger(this: ITriggerFunctions): Promise<ITriggerResponse> {\n\t\tconst credentialsObject = await this.getCredentials('imap');\n\t\tconst credentials = isCredentialsDataImap(credentialsObject) ? credentialsObject : undefined;\n\t\tif (!credentials) {\n\t\t\tthrow new NodeOperationError(this.getNode(), 'Credentials are not valid for imap node.');\n\t\t}\n\t\tconst mailbox = this.getNodeParameter('mailbox') as string;\n\t\tconst postProcessAction = this.getNodeParameter('postProcessAction') as string;\n\t\tconst options = this.getNodeParameter('options', {}) as IDataObject;\n\n\t\tconst staticData = this.getWorkflowStaticData('node');\n\t\tthis.logger.debug('Loaded static data for node \"EmailReadImap\"', { staticData });\n\n\t\tlet connection: ImapSimple;\n\t\tlet closeFunctionWasCalled = false;\n\t\tlet isCurrentlyReconnecting = false;\n\n\t\t// Returns the email text\n\n\t\tconst getText = async (\n\t\t\tparts: MessagePart[],\n\t\t\tmessage: Message,\n\t\t\tsubtype: string,\n\t\t): Promise<string> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst textParts = parts.filter((part) => {\n\t\t\t\treturn (\n\t\t\t\t\tpart.type.toUpperCase() === 'TEXT' && part.subtype.toUpperCase() === subtype.toUpperCase()\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tconst part = textParts[0];\n\t\t\tif (!part) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst partData = await connection.getPartData(message, part);\n\t\t\t\treturn partData.toString();\n\t\t\t} catch {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t};\n\n\t\t// Returns the email attachments\n\t\tconst getAttachment = async (\n\t\t\timapConnection: ImapSimple,\n\t\t\tparts: MessagePart[],\n\t\t\tmessage: Message,\n\t\t): Promise<IBinaryData[]> => {\n\t\t\tif (!message.attributes.struct) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\t// Check if the message has attachments and if so get them\n\t\t\tconst attachmentParts = parts.filter(\n\t\t\t\t(part) => part.disposition?.type?.toUpperCase() === 'ATTACHMENT',\n\t\t\t);\n\n\t\t\tconst decodeFilename = (filename: string) => {\n\t\t\t\tconst regex = /=\\?([\\w-]+)\\?Q\\?.*\\?=/i;\n\t\t\t\tif (regex.test(filename)) {\n\t\t\t\t\treturn rfc2047.decode(filename);\n\t\t\t\t}\n\t\t\t\treturn filename;\n\t\t\t};\n\n\t\t\tconst attachmentPromises = [];\n\t\t\tlet attachmentPromise;\n\t\t\tfor (const attachmentPart of attachmentParts) {\n\t\t\t\tattachmentPromise = imapConnection\n\t\t\t\t\t.getPartData(message, attachmentPart)\n\t\t\t\t\t.then(async (partData) => {\n\t\t\t\t\t\t// if filename contains utf-8 encoded characters, decode it\n\t\t\t\t\t\tconst fileName = decodeFilename(\n\t\t\t\t\t\t\t((attachmentPart.disposition as IDataObject)?.params as IDataObject)\n\t\t\t\t\t\t\t\t?.filename as string,\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// Return it in the format n8n expects\n\t\t\t\t\t\treturn await this.helpers.prepareBinaryData(partData.buffer, fileName);\n\t\t\t\t\t});\n\n\t\t\t\tattachmentPromises.push(attachmentPromise);\n\t\t\t}\n\n\t\t\treturn await Promise.all(attachmentPromises);\n\t\t};\n\n\t\tconst returnedPromise = this.helpers.createDeferredPromise();\n\n\t\tconst establishConnection = async (): Promise<ImapSimple> => {\n\t\t\tlet searchCriteria = ['UNSEEN'] as Array<string | string[]>;\n\t\t\tif (options.customEmailConfig !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tsearchCriteria = JSON.parse(options.customEmailConfig as string) as Array<\n\t\t\t\t\t\tstring | string[]\n\t\t\t\t\t>;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'Custom email config is not valid JSON.');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst config: ImapSimpleOptions = {\n\t\t\t\timap: {\n\t\t\t\t\tuser: credentials.user,\n\t\t\t\t\tpassword: credentials.password,\n\t\t\t\t\thost: credentials.host.trim(),\n\t\t\t\t\tport: credentials.port,\n\t\t\t\t\ttls: credentials.secure,\n\t\t\t\t\tauthTimeout: 20000,\n\t\t\t\t},\n\t\t\t\tonMail: async () => {\n\t\t\t\t\tif (connection) {\n\t\t\t\t\t\tif (staticData.lastMessageUid !== undefined) {\n\t\t\t\t\t\t\tsearchCriteria.push(['UID', `${staticData.lastMessageUid as number}:*`]);\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * A short explanation about UIDs and how they work\n\t\t\t\t\t\t\t * can be found here: https://dev.to/kehers/imap-new-messages-since-last-check-44gm\n\t\t\t\t\t\t\t * TL;DR:\n\t\t\t\t\t\t\t * - You cannot filter using ['UID', 'CURRENT ID + 1:*'] because IMAP\n\t\t\t\t\t\t\t * won't return correct results if current id + 1 does not yet exist.\n\t\t\t\t\t\t\t * - UIDs can change but this is not being treated here.\n\t\t\t\t\t\t\t * If the mailbox is recreated (lets say you remove all emails, remove\n\t\t\t\t\t\t\t * the mail box and create another with same name, UIDs will change)\n\t\t\t\t\t\t\t * - You can check if UIDs changed in the above example\n\t\t\t\t\t\t\t * by checking UIDValidity.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.logger.debug('Querying for new messages on node \"EmailReadImap\"', {\n\t\t\t\t\t\t\t\tsearchCriteria,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst returnData = await getNewEmails.call(\n\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\tconnection,\n\t\t\t\t\t\t\t\tsearchCriteria,\n\t\t\t\t\t\t\t\tstaticData,\n\t\t\t\t\t\t\t\tpostProcessAction,\n\t\t\t\t\t\t\t\tgetText,\n\t\t\t\t\t\t\t\tgetAttachment,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (returnData.length) {\n\t\t\t\t\t\t\t\tthis.emit([returnData]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tthis.logger.error('Email Read Imap node encountered an error fetching new emails', {\n\t\t\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t// Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy\n\t\t\t\t\t\t\t// if it receives an error before the workflow got activated\n\t\t\t\t\t\t\tawait returnedPromise.promise.then(() => {\n\t\t\t\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonUpdate: async (seqNo: number, info) => {\n\t\t\t\t\tthis.logger.debug(`Email Read Imap:update ${seqNo}`, info);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst tlsOptions: IDataObject = {};\n\n\t\t\tif (credentials.allowUnauthorizedCerts) {\n\t\t\t\ttlsOptions.rejectUnauthorized = false;\n\t\t\t}\n\n\t\t\tif (credentials.secure) {\n\t\t\t\ttlsOptions.servername = credentials.host.trim();\n\t\t\t}\n\n\t\t\tif (!isEmpty(tlsOptions)) {\n\t\t\t\tconfig.imap.tlsOptions = tlsOptions;\n\t\t\t}\n\n\t\t\t// Connect to the IMAP server and open the mailbox\n\t\t\t// that we get informed whenever a new email arrives\n\t\t\treturn await imapConnect(config).then(async (conn) => {\n\t\t\t\tconn.on('close', async (_hadError: boolean) => {\n\t\t\t\t\tif (isCurrentlyReconnecting) {\n\t\t\t\t\t\tthis.logger.debug('Email Read Imap: Connected closed for forced reconnecting');\n\t\t\t\t\t} else if (closeFunctionWasCalled) {\n\t\t\t\t\t\tthis.logger.debug('Email Read Imap: Shutting down workflow - connected closed');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.logger.error('Email Read Imap: Connected closed unexpectedly');\n\t\t\t\t\t\tthis.emitError(new Error('Imap connection closed unexpectedly'));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconn.on('error', async (error) => {\n\t\t\t\t\tconst errorCode = ((error as JsonObject).code as string).toUpperCase();\n\t\t\t\t\tthis.logger.debug(`IMAP connection experienced an error: (${errorCode})`, {\n\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emitError(error as Error);\n\t\t\t\t});\n\t\t\t\treturn conn;\n\t\t\t});\n\t\t};\n\n\t\tconnection = await establishConnection();\n\n\t\tawait connection.openBox(mailbox);\n\n\t\tlet reconnectionInterval: NodeJS.Timeout | undefined;\n\n\t\tconst handleReconnect = async () => {\n\t\t\tthis.logger.debug('Forcing reconnect to IMAP server');\n\t\t\ttry {\n\t\t\t\tisCurrentlyReconnecting = true;\n\t\t\t\tif (connection.closeBox) await connection.closeBox(false);\n\t\t\t\tconnection.end();\n\t\t\t\tconnection = await establishConnection();\n\t\t\t\tawait connection.openBox(mailbox);\n\t\t\t} catch (error) {\n\t\t\t\tthis.logger.error(error as string);\n\t\t\t} finally {\n\t\t\t\tisCurrentlyReconnecting = false;\n\t\t\t}\n\t\t};\n\n\t\tif (options.forceReconnect !== undefined) {\n\t\t\treconnectionInterval = setInterval(\n\t\t\t\thandleReconnect,\n\t\t\t\t(options.forceReconnect as number) * 1000 * 60,\n\t\t\t);\n\t\t}\n\n\t\t// When workflow and so node gets set to inactive close the connection\n\t\tconst closeFunction = async () => {\n\t\t\tcloseFunctionWasCalled = true;\n\t\t\tif (reconnectionInterval) {\n\t\t\t\tclearInterval(reconnectionInterval);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tif (connection.closeBox) await connection.closeBox(false);\n\t\t\t\tconnection.end();\n\t\t\t} catch (error) {\n\t\t\t\tthrow new TriggerCloseError(this.getNode(), { cause: error as Error, level: 'warning' });\n\t\t\t}\n\t\t};\n\n\t\t// Resolve returned-promise so that waiting errors can be emitted\n\t\treturnedPromise.resolve();\n\n\t\treturn {\n\t\t\tcloseFunction,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["isEmpty","imapConnect","part","rfc2047"]}
|
|
@@ -134,7 +134,6 @@ async function execute(items) {
|
|
|
134
134
|
mimeType: binaryData.mimeType,
|
|
135
135
|
fileType: binaryData.fileType,
|
|
136
136
|
fileName: binaryData.fileName,
|
|
137
|
-
directory: binaryData.directory,
|
|
138
137
|
fileExtension: binaryData.fileExtension,
|
|
139
138
|
fileSize: binaryData.fileSize
|
|
140
139
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../nodes/Files/ReadWriteFile/actions/read.operation.ts"],"sourcesContent":["import glob from 'fast-glob';\nimport { NodeApiError } from 'n8n-workflow';\nimport type {\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeProperties,\n\tJsonObject,\n} from 'n8n-workflow';\n\nimport { updateDisplayOptions } from '@utils/utilities';\n\nimport { errorMapper, escapeSpecialCharacters } from '../helpers/utils';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'File(s) Selector',\n\t\tname: 'fileSelector',\n\t\ttype: 'string',\n\t\tdefault: '',\n\t\trequired: true,\n\t\tplaceholder: 'e.g. /home/user/Pictures/**/*.png',\n\t\thint: 'Supports patterns, learn more <a href=\"https://github.com/micromatch/picomatch#basic-globbing\" target=\"_blank\">here</a>',\n\t\tdescription:\n\t\t\t\"Specify a file's path or path pattern to read multiple files. Always use forward-slashes for path separator even on Windows.\",\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'File Extension',\n\t\t\t\tname: 'fileExtension',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. zip',\n\t\t\t\tdescription: 'Extension of the file in the output binary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'File Name',\n\t\t\t\tname: 'fileName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. data.zip',\n\t\t\t\tdescription: 'Name of the file in the output binary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Mime Type',\n\t\t\t\tname: 'mimeType',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. application/zip',\n\t\t\t\tdescription: 'Mime type of the file in the output binary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Put Output File in Field',\n\t\t\t\tname: 'dataPropertyName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'data',\n\t\t\t\tplaceholder: 'e.g. data',\n\t\t\t\tdescription: \"By default 'data' is used\",\n\t\t\t\thint: 'The name of the output binary field to put the file in',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\toperation: ['read'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(this: IExecuteFunctions, items: INodeExecutionData[]) {\n\tconst returnData: INodeExecutionData[] = [];\n\tlet fileSelector;\n\n\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\ttry {\n\t\t\tfileSelector = String(this.getNodeParameter('fileSelector', itemIndex));\n\n\t\t\tfileSelector = escapeSpecialCharacters(fileSelector);\n\n\t\t\tif (/^[a-zA-Z]:/.test(fileSelector)) {\n\t\t\t\tfileSelector = fileSelector.replace(/\\\\\\\\/g, '/');\n\t\t\t}\n\n\t\t\tconst options = this.getNodeParameter('options', itemIndex, {});\n\n\t\t\tlet dataPropertyName = 'data';\n\n\t\t\tif (options.dataPropertyName) {\n\t\t\t\tdataPropertyName = options.dataPropertyName as string;\n\t\t\t}\n\n\t\t\tconst files = await glob(fileSelector);\n\n\t\t\tconst newItems: INodeExecutionData[] = [];\n\t\t\tfor (const filePath of files) {\n\t\t\t\tconst stream = await this.helpers.createReadStream(filePath);\n\t\t\t\tconst binaryData = await this.helpers.prepareBinaryData(stream, filePath);\n\n\t\t\t\tif (options.fileName !== undefined) {\n\t\t\t\t\tbinaryData.fileName = options.fileName as string;\n\t\t\t\t}\n\n\t\t\t\tif (options.fileExtension !== undefined) {\n\t\t\t\t\tbinaryData.fileExtension = options.fileExtension as string;\n\t\t\t\t}\n\n\t\t\t\tif (options.mimeType !== undefined) {\n\t\t\t\t\tbinaryData.mimeType = options.mimeType as string;\n\t\t\t\t}\n\n\t\t\t\tnewItems.push({\n\t\t\t\t\tbinary: {\n\t\t\t\t\t\t[dataPropertyName]: binaryData,\n\t\t\t\t\t},\n\t\t\t\t\tjson: {\n\t\t\t\t\t\tmimeType: binaryData.mimeType,\n\t\t\t\t\t\tfileType: binaryData.fileType,\n\t\t\t\t\t\tfileName: binaryData.fileName,\n\t\t\t\t\t\
|
|
1
|
+
{"version":3,"sources":["../../../../../nodes/Files/ReadWriteFile/actions/read.operation.ts"],"sourcesContent":["import glob from 'fast-glob';\nimport { NodeApiError } from 'n8n-workflow';\nimport type {\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeProperties,\n\tJsonObject,\n} from 'n8n-workflow';\n\nimport { updateDisplayOptions } from '@utils/utilities';\n\nimport { errorMapper, escapeSpecialCharacters } from '../helpers/utils';\n\nexport const properties: INodeProperties[] = [\n\t{\n\t\tdisplayName: 'File(s) Selector',\n\t\tname: 'fileSelector',\n\t\ttype: 'string',\n\t\tdefault: '',\n\t\trequired: true,\n\t\tplaceholder: 'e.g. /home/user/Pictures/**/*.png',\n\t\thint: 'Supports patterns, learn more <a href=\"https://github.com/micromatch/picomatch#basic-globbing\" target=\"_blank\">here</a>',\n\t\tdescription:\n\t\t\t\"Specify a file's path or path pattern to read multiple files. Always use forward-slashes for path separator even on Windows.\",\n\t},\n\t{\n\t\tdisplayName: 'Options',\n\t\tname: 'options',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add option',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'File Extension',\n\t\t\t\tname: 'fileExtension',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. zip',\n\t\t\t\tdescription: 'Extension of the file in the output binary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'File Name',\n\t\t\t\tname: 'fileName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. data.zip',\n\t\t\t\tdescription: 'Name of the file in the output binary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Mime Type',\n\t\t\t\tname: 'mimeType',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. application/zip',\n\t\t\t\tdescription: 'Mime type of the file in the output binary',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Put Output File in Field',\n\t\t\t\tname: 'dataPropertyName',\n\t\t\t\ttype: 'string',\n\t\t\t\tdefault: 'data',\n\t\t\t\tplaceholder: 'e.g. data',\n\t\t\t\tdescription: \"By default 'data' is used\",\n\t\t\t\thint: 'The name of the output binary field to put the file in',\n\t\t\t},\n\t\t],\n\t},\n];\n\nconst displayOptions = {\n\tshow: {\n\t\toperation: ['read'],\n\t},\n};\n\nexport const description = updateDisplayOptions(displayOptions, properties);\n\nexport async function execute(this: IExecuteFunctions, items: INodeExecutionData[]) {\n\tconst returnData: INodeExecutionData[] = [];\n\tlet fileSelector;\n\n\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\ttry {\n\t\t\tfileSelector = String(this.getNodeParameter('fileSelector', itemIndex));\n\n\t\t\tfileSelector = escapeSpecialCharacters(fileSelector);\n\n\t\t\tif (/^[a-zA-Z]:/.test(fileSelector)) {\n\t\t\t\tfileSelector = fileSelector.replace(/\\\\\\\\/g, '/');\n\t\t\t}\n\n\t\t\tconst options = this.getNodeParameter('options', itemIndex, {});\n\n\t\t\tlet dataPropertyName = 'data';\n\n\t\t\tif (options.dataPropertyName) {\n\t\t\t\tdataPropertyName = options.dataPropertyName as string;\n\t\t\t}\n\n\t\t\tconst files = await glob(fileSelector);\n\n\t\t\tconst newItems: INodeExecutionData[] = [];\n\t\t\tfor (const filePath of files) {\n\t\t\t\tconst stream = await this.helpers.createReadStream(filePath);\n\t\t\t\tconst binaryData = await this.helpers.prepareBinaryData(stream, filePath);\n\n\t\t\t\tif (options.fileName !== undefined) {\n\t\t\t\t\tbinaryData.fileName = options.fileName as string;\n\t\t\t\t}\n\n\t\t\t\tif (options.fileExtension !== undefined) {\n\t\t\t\t\tbinaryData.fileExtension = options.fileExtension as string;\n\t\t\t\t}\n\n\t\t\t\tif (options.mimeType !== undefined) {\n\t\t\t\t\tbinaryData.mimeType = options.mimeType as string;\n\t\t\t\t}\n\n\t\t\t\tnewItems.push({\n\t\t\t\t\tbinary: {\n\t\t\t\t\t\t[dataPropertyName]: binaryData,\n\t\t\t\t\t},\n\t\t\t\t\tjson: {\n\t\t\t\t\t\tmimeType: binaryData.mimeType,\n\t\t\t\t\t\tfileType: binaryData.fileType,\n\t\t\t\t\t\tfileName: binaryData.fileName,\n\t\t\t\t\t\tfileExtension: binaryData.fileExtension,\n\t\t\t\t\t\tfileSize: binaryData.fileSize,\n\t\t\t\t\t},\n\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\titem: itemIndex,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturnData.push(...newItems);\n\t\t} catch (error) {\n\t\t\tconst nodeOperatioinError = errorMapper.call(this, error, itemIndex, {\n\t\t\t\tfilePath: fileSelector,\n\t\t\t\toperation: 'read',\n\t\t\t});\n\t\t\tif (this.continueOnFail()) {\n\t\t\t\treturnData.push({\n\t\t\t\t\tjson: {\n\t\t\t\t\t\terror: nodeOperatioinError.message,\n\t\t\t\t\t},\n\t\t\t\t\tpairedItem: {\n\t\t\t\t\t\titem: itemIndex,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new NodeApiError(this.getNode(), error as JsonObject, { itemIndex });\n\t\t}\n\t}\n\n\treturn returnData;\n}\n"],"mappings":"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","names":["glob"]}
|