fix(EmailReadImap Node): Fix issue that crashed process if node was configured wrong (#3079)

* 🐛 Fix issue that IMAP node can crash n8n

* 👕 Fix lint issue
This commit is contained in:
Jan Oberhauser 2022-04-02 17:33:31 +02:00 committed by GitHub
parent 2c72584b55
commit 85f15d4989
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 8 deletions

View file

@ -682,6 +682,15 @@ export class ActiveWorkflowRunner {
(error) => console.error(error),
);
};
returnFunctions.emitError = async (error: Error): Promise<void> => {
await this.activeWorkflows?.remove(workflowData.id.toString());
this.activationErrors[workflowData.id.toString()] = {
time: new Date().getTime(),
error: {
message: error.message,
},
};
};
return returnFunctions;
};
}

View file

@ -1750,6 +1750,9 @@ export function getExecuteTriggerFunctions(
emit: (data: INodeExecutionData[][]): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!');
},
emitError: (error: Error): void => {
throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!');
},
async getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined> {
return getCredentials(workflow, node, type, additionalData, mode);
},

View file

@ -1,13 +1,15 @@
import { ITriggerFunctions } from 'n8n-core';
import {
createDeferredPromise,
IBinaryData,
IBinaryKeyData,
IDataObject,
IDeferredPromise,
INodeExecutionData,
INodeType,
INodeTypeDescription,
ITriggerResponse,
LoggerProxy,
LoggerProxy as Logger,
NodeOperationError,
} from 'n8n-workflow';
@ -25,10 +27,6 @@ import {
import * as lodash from 'lodash';
import {
LoggerProxy as Logger
} from 'n8n-workflow';
export class EmailReadImap implements INodeType {
description: INodeTypeDescription = {
displayName: 'EmailReadImap',
@ -377,6 +375,8 @@ export class EmailReadImap implements INodeType {
return newEmails;
};
const returnedPromise: IDeferredPromise<void> | undefined = await createDeferredPromise<void>();
const establishConnection = (): Promise<ImapSimple> => {
let searchCriteria = [
@ -425,7 +425,11 @@ export class EmailReadImap implements INodeType {
}
} catch (error) {
Logger.error('Email Read Imap node encountered an error fetching new emails', { error });
throw error;
// Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy
// if it receives an error before the workflow got activated
returnedPromise.promise().then(() => {
this.emitError(error as Error);
});
}
}
},
@ -475,10 +479,12 @@ export class EmailReadImap implements INodeType {
await connection.end();
}
// Resolve returned-promise so that waiting errors can be emitted
returnedPromise.resolve();
return {
closeFunction,
};
}
}

View file

@ -683,6 +683,7 @@ export interface ITriggerFunctions {
data: INodeExecutionData[][],
responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>,
): void;
emitError(error: Error, responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>): void;
getCredentials(type: string): Promise<ICredentialDataDecryptedObject | undefined>;
getMode(): WorkflowExecuteMode;
getActivationMode(): WorkflowActivateMode;

View file

@ -949,7 +949,7 @@ export class Workflow {
const triggerResponse = await nodeType.trigger.call(triggerFunctions);
// Add the manual trigger response which resolves when the first time data got emitted
triggerResponse!.manualTriggerResponse = new Promise((resolve) => {
triggerResponse!.manualTriggerResponse = new Promise((resolve, reject) => {
triggerFunctions.emit = (
(resolveEmit) =>
(
@ -967,6 +967,20 @@ export class Workflow {
resolveEmit(data);
}
)(resolve);
triggerFunctions.emitError = (
(rejectEmit) =>
(error: Error, responsePromise?: IDeferredPromise<IExecuteResponsePromiseData>) => {
additionalData.hooks!.hookFunctions.sendResponse = [
async (): Promise<void> => {
if (responsePromise) {
responsePromise.reject(error);
}
},
];
rejectEmit(error);
}
)(reject);
});
return triggerResponse;