mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat(Send Email Node): New operation sendAndWait (#12775)
This commit is contained in:
@@ -135,7 +135,6 @@ describe('Node Creator', () => {
|
|||||||
'OpenThesaurus',
|
'OpenThesaurus',
|
||||||
'Spontit',
|
'Spontit',
|
||||||
'Vonage',
|
'Vonage',
|
||||||
'Send Email',
|
|
||||||
'Toggl Trigger',
|
'Toggl Trigger',
|
||||||
];
|
];
|
||||||
const doubleActionNode = 'OpenWeatherMap';
|
const doubleActionNode = 'OpenWeatherMap';
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import type { MockProxy } from 'jest-mock-extended';
|
||||||
|
import { mock } from 'jest-mock-extended';
|
||||||
|
import { SEND_AND_WAIT_OPERATION, type IExecuteFunctions } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { EmailSendV2, versionDescription } from '../../v2/EmailSendV2.node';
|
||||||
|
import * as utils from '../../v2/utils';
|
||||||
|
|
||||||
|
const transporter = { sendMail: jest.fn() };
|
||||||
|
|
||||||
|
jest.mock('../../v2/utils', () => {
|
||||||
|
const originalModule = jest.requireActual('../../v2/utils');
|
||||||
|
return {
|
||||||
|
...originalModule,
|
||||||
|
configureTransport: jest.fn(() => transporter),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Test EmailSendV2, email => sendAndWait', () => {
|
||||||
|
let emailSendV2: EmailSendV2;
|
||||||
|
let mockExecuteFunctions: MockProxy<IExecuteFunctions>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
emailSendV2 = new EmailSendV2(versionDescription);
|
||||||
|
mockExecuteFunctions = mock<IExecuteFunctions>();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send message and put execution to wait', async () => {
|
||||||
|
const items = [{ json: { data: 'test' } }];
|
||||||
|
//node
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(SEND_AND_WAIT_OPERATION);
|
||||||
|
|
||||||
|
//operation
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('from@mail.com');
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('to@mail.com');
|
||||||
|
mockExecuteFunctions.getInstanceId.mockReturnValue('instanceId');
|
||||||
|
mockExecuteFunctions.getCredentials.mockResolvedValue({});
|
||||||
|
mockExecuteFunctions.putExecutionToWait.mockImplementation();
|
||||||
|
mockExecuteFunctions.getInputData.mockReturnValue(items);
|
||||||
|
|
||||||
|
//getSendAndWaitConfig
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('my message');
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('my subject');
|
||||||
|
mockExecuteFunctions.evaluateExpression.mockReturnValueOnce('http://localhost/waiting-webhook');
|
||||||
|
mockExecuteFunctions.evaluateExpression.mockReturnValueOnce('nodeID');
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({});
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('approval');
|
||||||
|
|
||||||
|
// configureWaitTillDate
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({}); //options.limitWaitTime.values
|
||||||
|
|
||||||
|
const result = await emailSendV2.execute.call(mockExecuteFunctions);
|
||||||
|
|
||||||
|
expect(result).toEqual([items]);
|
||||||
|
expect(utils.configureTransport).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockExecuteFunctions.putExecutionToWait).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(transporter.sendMail).toHaveBeenCalledWith({
|
||||||
|
from: 'from@mail.com',
|
||||||
|
html: expect.stringContaining('href="http://localhost/waiting-webhook/nodeID?approved=true"'),
|
||||||
|
subject: 'my subject',
|
||||||
|
to: 'to@mail.com',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -5,11 +5,15 @@ import type {
|
|||||||
INodeTypeBaseDescription,
|
INodeTypeBaseDescription,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeConnectionType } from 'n8n-workflow';
|
import { NodeConnectionType, SEND_AND_WAIT_OPERATION } from 'n8n-workflow';
|
||||||
|
|
||||||
import * as send from './send.operation';
|
import * as send from './send.operation';
|
||||||
|
import * as sendAndWait from './sendAndWait.operation';
|
||||||
|
import { smtpConnectionTest } from './utils';
|
||||||
|
import { sendAndWaitWebhooksDescription } from '../../../utils/sendAndWait/descriptions';
|
||||||
|
import { sendAndWaitWebhook } from '../../../utils/sendAndWait/utils';
|
||||||
|
|
||||||
const versionDescription: INodeTypeDescription = {
|
export const versionDescription: INodeTypeDescription = {
|
||||||
displayName: 'Send Email',
|
displayName: 'Send Email',
|
||||||
name: 'emailSend',
|
name: 'emailSend',
|
||||||
icon: 'fa:envelope',
|
icon: 'fa:envelope',
|
||||||
@@ -30,6 +34,7 @@ const versionDescription: INodeTypeDescription = {
|
|||||||
testedBy: 'smtpConnectionTest',
|
testedBy: 'smtpConnectionTest',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
webhooks: sendAndWaitWebhooksDescription,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Resource',
|
displayName: 'Resource',
|
||||||
@@ -47,7 +52,7 @@ const versionDescription: INodeTypeDescription = {
|
|||||||
{
|
{
|
||||||
displayName: 'Operation',
|
displayName: 'Operation',
|
||||||
name: 'operation',
|
name: 'operation',
|
||||||
type: 'hidden',
|
type: 'options',
|
||||||
noDataExpression: true,
|
noDataExpression: true,
|
||||||
default: 'send',
|
default: 'send',
|
||||||
options: [
|
options: [
|
||||||
@@ -56,9 +61,15 @@ const versionDescription: INodeTypeDescription = {
|
|||||||
value: 'send',
|
value: 'send',
|
||||||
action: 'Send an Email',
|
action: 'Send an Email',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Send and Wait for Response',
|
||||||
|
value: SEND_AND_WAIT_OPERATION,
|
||||||
|
action: 'Send message and wait for response',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
...send.description,
|
...send.description,
|
||||||
|
...sendAndWait.description,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,13 +84,22 @@ export class EmailSendV2 implements INodeType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
methods = {
|
methods = {
|
||||||
credentialTest: { smtpConnectionTest: send.smtpConnectionTest },
|
credentialTest: { smtpConnectionTest },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
webhook = sendAndWaitWebhook;
|
||||||
|
|
||||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
let returnData: INodeExecutionData[][] = [];
|
let returnData: INodeExecutionData[][] = [];
|
||||||
|
const operation = this.getNodeParameter('operation', 0) as string;
|
||||||
|
|
||||||
returnData = await send.execute.call(this);
|
if (operation === SEND_AND_WAIT_OPERATION) {
|
||||||
|
returnData = await sendAndWait.execute.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation === 'send') {
|
||||||
|
returnData = await send.execute.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
return returnData;
|
return returnData;
|
||||||
}
|
}
|
||||||
|
|||||||
23
packages/nodes-base/nodes/EmailSend/v2/descriptions.ts
Normal file
23
packages/nodes-base/nodes/EmailSend/v2/descriptions.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import type { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
|
export const fromEmailProperty: INodeProperties = {
|
||||||
|
displayName: 'From Email',
|
||||||
|
name: 'fromEmail',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
placeholder: 'admin@example.com',
|
||||||
|
description:
|
||||||
|
'Email address of the sender. You can also specify a name: Nathan Doe <nate@n8n.io>.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toEmailProperty: INodeProperties = {
|
||||||
|
displayName: 'To Email',
|
||||||
|
name: 'toEmail',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
placeholder: 'info@example.com',
|
||||||
|
description:
|
||||||
|
'Email address of the recipient. You can also specify a name: Nathan Doe <nate@n8n.io>.',
|
||||||
|
};
|
||||||
@@ -1,43 +1,22 @@
|
|||||||
import type {
|
import type {
|
||||||
ICredentialsDecrypted,
|
|
||||||
ICredentialTestFunctions,
|
|
||||||
IDataObject,
|
IDataObject,
|
||||||
IExecuteFunctions,
|
IExecuteFunctions,
|
||||||
INodeCredentialTestResult,
|
|
||||||
INodeExecutionData,
|
INodeExecutionData,
|
||||||
INodeProperties,
|
INodeProperties,
|
||||||
JsonObject,
|
JsonObject,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeApiError } from 'n8n-workflow';
|
import { NodeApiError } from 'n8n-workflow';
|
||||||
import { createTransport } from 'nodemailer';
|
|
||||||
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|
||||||
|
|
||||||
import { updateDisplayOptions } from '@utils/utilities';
|
import { updateDisplayOptions } from '@utils/utilities';
|
||||||
|
|
||||||
|
import { fromEmailProperty, toEmailProperty } from './descriptions';
|
||||||
|
import { configureTransport, type EmailSendOptions } from './utils';
|
||||||
import { appendAttributionOption } from '../../../utils/descriptions';
|
import { appendAttributionOption } from '../../../utils/descriptions';
|
||||||
|
|
||||||
const properties: INodeProperties[] = [
|
const properties: INodeProperties[] = [
|
||||||
// TODO: Add choice for text as text or html (maybe also from name)
|
// TODO: Add choice for text as text or html (maybe also from name)
|
||||||
{
|
fromEmailProperty,
|
||||||
displayName: 'From Email',
|
toEmailProperty,
|
||||||
name: 'fromEmail',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
placeholder: 'admin@example.com',
|
|
||||||
description:
|
|
||||||
'Email address of the sender. You can also specify a name: Nathan Doe <nate@n8n.io>.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'To Email',
|
|
||||||
name: 'toEmail',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
placeholder: 'info@example.com',
|
|
||||||
description:
|
|
||||||
'Email address of the recipient. You can also specify a name: Nathan Doe <nate@n8n.io>.',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Subject',
|
displayName: 'Subject',
|
||||||
@@ -194,72 +173,11 @@ const displayOptions = {
|
|||||||
|
|
||||||
export const description = updateDisplayOptions(displayOptions, properties);
|
export const description = updateDisplayOptions(displayOptions, properties);
|
||||||
|
|
||||||
type EmailSendOptions = {
|
|
||||||
appendAttribution?: boolean;
|
|
||||||
allowUnauthorizedCerts?: boolean;
|
|
||||||
attachments?: string;
|
|
||||||
ccEmail?: string;
|
|
||||||
bccEmail?: string;
|
|
||||||
replyTo?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function configureTransport(credentials: IDataObject, options: EmailSendOptions) {
|
|
||||||
const connectionOptions: SMTPTransport.Options = {
|
|
||||||
host: credentials.host as string,
|
|
||||||
port: credentials.port as number,
|
|
||||||
secure: credentials.secure as boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (credentials.secure === false) {
|
|
||||||
connectionOptions.ignoreTLS = credentials.disableStartTls as boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof credentials.hostName === 'string' && credentials.hostName) {
|
|
||||||
connectionOptions.name = credentials.hostName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (credentials.user || credentials.password) {
|
|
||||||
connectionOptions.auth = {
|
|
||||||
user: credentials.user as string,
|
|
||||||
pass: credentials.password as string,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.allowUnauthorizedCerts === true) {
|
|
||||||
connectionOptions.tls = {
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return createTransport(connectionOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function smtpConnectionTest(
|
|
||||||
this: ICredentialTestFunctions,
|
|
||||||
credential: ICredentialsDecrypted,
|
|
||||||
): Promise<INodeCredentialTestResult> {
|
|
||||||
const credentials = credential.data!;
|
|
||||||
const transporter = configureTransport(credentials, {});
|
|
||||||
try {
|
|
||||||
await transporter.verify();
|
|
||||||
return {
|
|
||||||
status: 'OK',
|
|
||||||
message: 'Connection successful!',
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
status: 'Error',
|
|
||||||
message: error.message,
|
|
||||||
};
|
|
||||||
} finally {
|
|
||||||
transporter.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
export async function execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
const nodeVersion = this.getNode().typeVersion;
|
const nodeVersion = this.getNode().typeVersion;
|
||||||
const instanceId = this.getInstanceId();
|
const instanceId = this.getInstanceId();
|
||||||
|
const credentials = await this.getCredentials('smtp');
|
||||||
|
|
||||||
const returnData: INodeExecutionData[] = [];
|
const returnData: INodeExecutionData[] = [];
|
||||||
let item: INodeExecutionData;
|
let item: INodeExecutionData;
|
||||||
@@ -274,8 +192,6 @@ export async function execute(this: IExecuteFunctions): Promise<INodeExecutionDa
|
|||||||
const emailFormat = this.getNodeParameter('emailFormat', itemIndex) as string;
|
const emailFormat = this.getNodeParameter('emailFormat', itemIndex) as string;
|
||||||
const options = this.getNodeParameter('options', itemIndex, {}) as EmailSendOptions;
|
const options = this.getNodeParameter('options', itemIndex, {}) as EmailSendOptions;
|
||||||
|
|
||||||
const credentials = await this.getCredentials('smtp');
|
|
||||||
|
|
||||||
const transporter = configureTransport(credentials, options);
|
const transporter = configureTransport(credentials, options);
|
||||||
|
|
||||||
const mailOptions: IDataObject = {
|
const mailOptions: IDataObject = {
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import type {
|
||||||
|
IDataObject,
|
||||||
|
IExecuteFunctions,
|
||||||
|
INodeExecutionData,
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
import { fromEmailProperty, toEmailProperty } from './descriptions';
|
||||||
|
import { configureTransport } from './utils';
|
||||||
|
import { createEmailBody } from '../../../utils/sendAndWait/email-templates';
|
||||||
|
import {
|
||||||
|
configureWaitTillDate,
|
||||||
|
createButton,
|
||||||
|
getSendAndWaitConfig,
|
||||||
|
getSendAndWaitProperties,
|
||||||
|
} from '../../../utils/sendAndWait/utils';
|
||||||
|
|
||||||
|
export const description: INodeProperties[] = getSendAndWaitProperties(
|
||||||
|
[fromEmailProperty, toEmailProperty],
|
||||||
|
'email',
|
||||||
|
);
|
||||||
|
|
||||||
|
export async function execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
|
const fromEmail = this.getNodeParameter('fromEmail', 0) as string;
|
||||||
|
const toEmail = this.getNodeParameter('toEmail', 0) as string;
|
||||||
|
|
||||||
|
const config = getSendAndWaitConfig(this);
|
||||||
|
const buttons: string[] = [];
|
||||||
|
for (const option of config.options) {
|
||||||
|
buttons.push(createButton(config.url, option.label, option.value, option.style));
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceId = this.getInstanceId();
|
||||||
|
|
||||||
|
const htmlBody = createEmailBody(config.message, buttons.join('\n'), instanceId);
|
||||||
|
|
||||||
|
const mailOptions: IDataObject = {
|
||||||
|
from: fromEmail,
|
||||||
|
to: toEmail,
|
||||||
|
subject: config.title,
|
||||||
|
html: htmlBody,
|
||||||
|
};
|
||||||
|
|
||||||
|
const credentials = await this.getCredentials('smtp');
|
||||||
|
const transporter = configureTransport(credentials, {});
|
||||||
|
|
||||||
|
await transporter.sendMail(mailOptions);
|
||||||
|
|
||||||
|
const waitTill = configureWaitTillDate(this);
|
||||||
|
|
||||||
|
await this.putExecutionToWait(waitTill);
|
||||||
|
return [this.getInputData()];
|
||||||
|
}
|
||||||
70
packages/nodes-base/nodes/EmailSend/v2/utils.ts
Normal file
70
packages/nodes-base/nodes/EmailSend/v2/utils.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import type {
|
||||||
|
IDataObject,
|
||||||
|
ICredentialsDecrypted,
|
||||||
|
ICredentialTestFunctions,
|
||||||
|
INodeCredentialTestResult,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
import { createTransport } from 'nodemailer';
|
||||||
|
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
|
||||||
|
|
||||||
|
export type EmailSendOptions = {
|
||||||
|
appendAttribution?: boolean;
|
||||||
|
allowUnauthorizedCerts?: boolean;
|
||||||
|
attachments?: string;
|
||||||
|
ccEmail?: string;
|
||||||
|
bccEmail?: string;
|
||||||
|
replyTo?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function configureTransport(credentials: IDataObject, options: EmailSendOptions) {
|
||||||
|
const connectionOptions: SMTPTransport.Options = {
|
||||||
|
host: credentials.host as string,
|
||||||
|
port: credentials.port as number,
|
||||||
|
secure: credentials.secure as boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (credentials.secure === false) {
|
||||||
|
connectionOptions.ignoreTLS = credentials.disableStartTls as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof credentials.hostName === 'string' && credentials.hostName) {
|
||||||
|
connectionOptions.name = credentials.hostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentials.user || credentials.password) {
|
||||||
|
connectionOptions.auth = {
|
||||||
|
user: credentials.user as string,
|
||||||
|
pass: credentials.password as string,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.allowUnauthorizedCerts === true) {
|
||||||
|
connectionOptions.tls = {
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return createTransport(connectionOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function smtpConnectionTest(
|
||||||
|
this: ICredentialTestFunctions,
|
||||||
|
credential: ICredentialsDecrypted,
|
||||||
|
): Promise<INodeCredentialTestResult> {
|
||||||
|
const credentials = credential.data!;
|
||||||
|
const transporter = configureTransport(credentials, {});
|
||||||
|
try {
|
||||||
|
await transporter.verify();
|
||||||
|
return {
|
||||||
|
status: 'OK',
|
||||||
|
message: 'Connection successful!',
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
status: 'Error',
|
||||||
|
message: error.message,
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
transporter.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import { labelFields, labelOperations } from './LabelDescription';
|
|||||||
import { getGmailAliases, getLabels, getThreadMessages } from './loadOptions';
|
import { getGmailAliases, getLabels, getThreadMessages } from './loadOptions';
|
||||||
import { messageFields, messageOperations } from './MessageDescription';
|
import { messageFields, messageOperations } from './MessageDescription';
|
||||||
import { threadFields, threadOperations } from './ThreadDescription';
|
import { threadFields, threadOperations } from './ThreadDescription';
|
||||||
import { sendAndWaitWebhooks } from '../../../../utils/sendAndWait/descriptions';
|
import { sendAndWaitWebhooksDescription } from '../../../../utils/sendAndWait/descriptions';
|
||||||
import type { IEmail } from '../../../../utils/sendAndWait/interfaces';
|
import type { IEmail } from '../../../../utils/sendAndWait/interfaces';
|
||||||
import {
|
import {
|
||||||
configureWaitTillDate,
|
configureWaitTillDate,
|
||||||
@@ -69,7 +69,7 @@ const versionDescription: INodeTypeDescription = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: sendAndWaitWebhooks,
|
webhooks: sendAndWaitWebhooksDescription,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Authentication',
|
displayName: 'Authentication',
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ describe('Test MicrosoftOutlookV2, message => sendAndWait', () => {
|
|||||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({});
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({});
|
||||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('approval');
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('approval');
|
||||||
|
|
||||||
|
// configureWaitTillDate
|
||||||
|
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({}); //options.limitWaitTime.values
|
||||||
|
|
||||||
const result = await microsoftOutlook.execute.call(mockExecuteFunctions);
|
const result = await microsoftOutlook.execute.call(mockExecuteFunctions);
|
||||||
|
|
||||||
expect(result).toEqual([items]);
|
expect(result).toEqual([items]);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import * as folder from './folder';
|
|||||||
import * as folderMessage from './folderMessage';
|
import * as folderMessage from './folderMessage';
|
||||||
import * as message from './message';
|
import * as message from './message';
|
||||||
import * as messageAttachment from './messageAttachment';
|
import * as messageAttachment from './messageAttachment';
|
||||||
import { sendAndWaitWebhooks } from '../../../../../utils/sendAndWait/descriptions';
|
import { sendAndWaitWebhooksDescription } from '../../../../../utils/sendAndWait/descriptions';
|
||||||
|
|
||||||
export const description: INodeTypeDescription = {
|
export const description: INodeTypeDescription = {
|
||||||
displayName: 'Microsoft Outlook',
|
displayName: 'Microsoft Outlook',
|
||||||
@@ -31,7 +31,7 @@ export const description: INodeTypeDescription = {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: sendAndWaitWebhooks,
|
webhooks: sendAndWaitWebhooksDescription,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Resource',
|
displayName: 'Resource',
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||||
import {
|
import { NodeApiError, NodeOperationError, SEND_AND_WAIT_OPERATION } from 'n8n-workflow';
|
||||||
NodeApiError,
|
|
||||||
NodeOperationError,
|
|
||||||
SEND_AND_WAIT_OPERATION,
|
|
||||||
WAIT_INDEFINITELY,
|
|
||||||
} from 'n8n-workflow';
|
|
||||||
|
|
||||||
import * as calendar from './calendar';
|
import * as calendar from './calendar';
|
||||||
import * as contact from './contact';
|
import * as contact from './contact';
|
||||||
@@ -15,6 +10,7 @@ import * as folderMessage from './folderMessage';
|
|||||||
import * as message from './message';
|
import * as message from './message';
|
||||||
import * as messageAttachment from './messageAttachment';
|
import * as messageAttachment from './messageAttachment';
|
||||||
import type { MicrosoftOutlook } from './node.type';
|
import type { MicrosoftOutlook } from './node.type';
|
||||||
|
import { configureWaitTillDate } from '../../../../../utils/sendAndWait/utils';
|
||||||
|
|
||||||
export async function router(this: IExecuteFunctions) {
|
export async function router(this: IExecuteFunctions) {
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
@@ -36,7 +32,9 @@ export async function router(this: IExecuteFunctions) {
|
|||||||
) {
|
) {
|
||||||
await message[microsoftOutlook.operation].execute.call(this, 0, items);
|
await message[microsoftOutlook.operation].execute.call(this, 0, items);
|
||||||
|
|
||||||
await this.putExecutionToWait(WAIT_INDEFINITELY);
|
const waitTill = configureWaitTillDate(this);
|
||||||
|
|
||||||
|
await this.putExecutionToWait(waitTill);
|
||||||
return [items];
|
return [items];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import { reactionFields, reactionOperations } from './ReactionDescription';
|
|||||||
import { starFields, starOperations } from './StarDescription';
|
import { starFields, starOperations } from './StarDescription';
|
||||||
import { userFields, userOperations } from './UserDescription';
|
import { userFields, userOperations } from './UserDescription';
|
||||||
import { userGroupFields, userGroupOperations } from './UserGroupDescription';
|
import { userGroupFields, userGroupOperations } from './UserGroupDescription';
|
||||||
import { sendAndWaitWebhooks } from '../../../utils/sendAndWait/descriptions';
|
import { sendAndWaitWebhooksDescription } from '../../../utils/sendAndWait/descriptions';
|
||||||
import {
|
import {
|
||||||
configureWaitTillDate,
|
configureWaitTillDate,
|
||||||
getSendAndWaitProperties,
|
getSendAndWaitProperties,
|
||||||
@@ -81,7 +81,7 @@ export class SlackV2 implements INodeType {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: sendAndWaitWebhooks,
|
webhooks: sendAndWaitWebhooksDescription,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Authentication',
|
displayName: 'Authentication',
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
getPropertyName,
|
getPropertyName,
|
||||||
} from './GenericFunctions';
|
} from './GenericFunctions';
|
||||||
import { appendAttributionOption } from '../../utils/descriptions';
|
import { appendAttributionOption } from '../../utils/descriptions';
|
||||||
import { sendAndWaitWebhooks } from '../../utils/sendAndWait/descriptions';
|
import { sendAndWaitWebhooksDescription } from '../../utils/sendAndWait/descriptions';
|
||||||
import {
|
import {
|
||||||
configureWaitTillDate,
|
configureWaitTillDate,
|
||||||
getSendAndWaitProperties,
|
getSendAndWaitProperties,
|
||||||
@@ -49,7 +49,7 @@ export class Telegram implements INodeType {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
webhooks: sendAndWaitWebhooks,
|
webhooks: sendAndWaitWebhooksDescription,
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
displayName: 'Resource',
|
displayName: 'Resource',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { IWebhookDescription } from 'n8n-workflow';
|
import type { IWebhookDescription } from 'n8n-workflow';
|
||||||
|
|
||||||
export const sendAndWaitWebhooks: IWebhookDescription[] = [
|
export const sendAndWaitWebhooksDescription: IWebhookDescription[] = [
|
||||||
{
|
{
|
||||||
name: 'default',
|
name: 'default',
|
||||||
httpMethod: 'GET',
|
httpMethod: 'GET',
|
||||||
|
|||||||
Reference in New Issue
Block a user