fix(AWS SES Node): Fix issue with email aliases not working for sending from or sending to (#9811)

Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
Jon 2024-06-20 15:42:52 +01:00 committed by GitHub
parent 223488f190
commit e1e8a75763
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 122 additions and 18 deletions

View file

@ -1,3 +1,4 @@
import qs from 'node:querystring';
import type {
IExecuteFunctions,
IDataObject,
@ -13,7 +14,7 @@ import { awsApiRequestSOAP, awsApiRequestSOAPAllItems } from './GenericFunctions
function setParameter(params: string[], base: string, values: string[]) {
for (let i = 0; i < values.length; i++) {
params.push(`${base}.${i + 1}=${values[i]}`);
params.push(`${base}.${i + 1}=${encodeURIComponent(values[i])}`);
}
}
@ -843,22 +844,20 @@ export class AwsSes implements INodeType {
const templateSubject = this.getNodeParameter('templateSubject', i) as string;
const params = [
'Action=CreateCustomVerificationEmailTemplate',
`FailureRedirectionURL=${failureRedirectionURL}`,
`FromEmailAddress=${email}`,
`SuccessRedirectionURL=${successRedirectionURL}`,
`TemplateContent=${templateContent}`,
`TemplateName=${templateName}`,
`TemplateSubject=${templateSubject}`,
];
responseData = await awsApiRequestSOAP.call(
this,
'email',
'POST',
'',
params.join('&'),
qs.stringify({
Action: 'CreateCustomVerificationEmailTemplate',
FromEmailAddress: email,
SuccessRedirectionURL: successRedirectionURL,
FailureRedirectionURL: failureRedirectionURL,
TemplateName: templateName,
TemplateSubject: templateSubject,
TemplateContent: templateContent,
}),
);
responseData = responseData.CreateCustomVerificationEmailTemplateResponse;
@ -1012,7 +1011,7 @@ export class AwsSes implements INodeType {
const params = [
`Message.Subject.Data=${encodeURIComponent(subject)}`,
`Source=${fromEmail}`,
`Source=${encodeURIComponent(fromEmail)}`,
];
if (isBodyHtml) {

View file

@ -0,0 +1,104 @@
import qs from 'node:querystring';
import assert from 'node:assert';
import { NodeConnectionType } from 'n8n-workflow';
import type { WorkflowTestData } from '@test/nodes/types';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers';
describe('AwsSes Node', () => {
const tests: WorkflowTestData[] = [
{
description: 'should create customVerificationEmail',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '61c910d6-9997-4bc0-b95d-2b2771c3110f',
name: 'When clicking Test workflow',
type: 'n8n-nodes-base.manualTrigger',
typeVersion: 1,
position: [720, 380],
},
{
parameters: {
resource: 'customVerificationEmail',
fromEmailAddress: 'test+user@example.com',
templateName: 'testTemplate',
templateContent: 'testContent',
templateSubject: 'testSubject',
successRedirectionURL: 'http://success.url/',
failureRedirectionURL: 'http://failure.url/',
},
id: '5780c7b2-7e7f-44d2-980d-a162d28bf152',
name: 'AWS SES',
type: 'n8n-nodes-base.awsSes',
typeVersion: 1,
position: [940, 380],
credentials: {
aws: {
id: '1',
name: 'AWS',
},
},
},
],
connections: {
'When clicking Test workflow': {
main: [
[
{
node: 'AWS SES',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
'AWS SES': [[{ json: { success: 'true' } }]],
},
},
nock: {
baseUrl: 'https://email.eu-central-1.amazonaws.com',
mocks: [
{
method: 'post',
path: '/',
requestBody: (body: any) => {
assert.deepEqual(qs.parse(body), {
Action: 'CreateCustomVerificationEmailTemplate',
FromEmailAddress: 'test+user@example.com',
SuccessRedirectionURL: 'http://success.url/',
FailureRedirectionURL: 'http://failure.url/',
TemplateName: 'testTemplate',
TemplateSubject: 'testSubject',
TemplateContent: 'testContent',
});
return true;
},
statusCode: 200,
responseBody:
'<CreateCustomVerificationEmailTemplateResponse><success>true</success></CreateCustomVerificationEmailTemplateResponse>',
},
],
},
},
];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes);
const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]),
);
expect(result.finished).toEqual(true);
});
});

View file

@ -9,9 +9,8 @@ export async function executeWorkflow(testData: WorkflowTestData, nodeTypes: INo
if (testData.nock) {
const { baseUrl, mocks } = testData.nock;
const agent = nock(baseUrl);
mocks.forEach(({ method, path, statusCode, responseBody }) =>
// @ts-expect-error
agent[method](path).reply(statusCode, responseBody),
mocks.forEach(({ method, path, statusCode, requestBody, responseBody }) =>
agent[method](path, requestBody).reply(statusCode, responseBody),
);
}
const executionMode = testData.trigger?.mode ?? 'manual';

View file

@ -7,6 +7,7 @@ import type { IncomingHttpHeaders } from 'http';
import type { SecureContextOptions } from 'tls';
import type { Readable } from 'stream';
import type { URLSearchParams } from 'url';
import type { RequestBodyMatcher } from 'nock';
import type { AuthenticationMethod } from './Authentication';
import type { CODE_EXECUTION_MODES, CODE_LANGUAGES, LOG_LEVELS } from './Constants';
@ -2213,10 +2214,11 @@ export interface WorkflowTestData {
nock?: {
baseUrl: string;
mocks: Array<{
method: string;
method: 'get' | 'post';
path: string;
requestBody?: RequestBodyMatcher;
statusCode: number;
responseBody: any;
responseBody: string | object;
}>;
};
trigger?: {