mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[ResponseOps] provide config to turn off email action footer (#154919)
resolves https://github.com/elastic/kibana/issues/135402 Allows deployments to not have the default footer added to alerting emails via the new `xpack.actions.enableFooterInEmail` config setting. The default value is `true`, which renders the footer. Setting the value to `false` will cause no footer to be rendered. Also changes the footer separator from `--` to `---`, which renders nicer in HTML, as a `<hr>` element.
This commit is contained in:
parent
70d5dad847
commit
bcfe4b0005
18 changed files with 96 additions and 20 deletions
|
@ -130,6 +130,9 @@ A list of allowed email domains which can be used with the email connector. When
|
||||||
|
|
||||||
WARNING: This feature is available in {kib} 7.17.4 and 8.3.0 onwards but is not supported in {kib} 8.0, 8.1 or 8.2. As such, this setting should be removed before upgrading from 7.17 to 8.0, 8.1 or 8.2. It is possible to configure the settings in 7.17.4 and then upgrade to 8.3.0 directly.
|
WARNING: This feature is available in {kib} 7.17.4 and 8.3.0 onwards but is not supported in {kib} 8.0, 8.1 or 8.2. As such, this setting should be removed before upgrading from 7.17 to 8.0, 8.1 or 8.2. It is possible to configure the settings in 7.17.4 and then upgrade to 8.3.0 directly.
|
||||||
|
|
||||||
|
`xpack.actions.enableFooterInEmail` {ess-icon}::
|
||||||
|
A boolean value indicating that a footer with a relevant link should be added to emails sent as alerting actions. Default: true.
|
||||||
|
|
||||||
`xpack.actions.enabledActionTypes` {ess-icon}::
|
`xpack.actions.enabledActionTypes` {ess-icon}::
|
||||||
A list of action types that are enabled. It defaults to `[*]`, enabling all types. The names for built-in {kib} action types are prefixed with a `.` and include: `.email`, `.index`, `.jira`, `.opsgenie`, `.pagerduty`, `.resilient`, `.server-log`, `.servicenow`, .`servicenow-itom`, `.servicenow-sir`, `.slack`, `.swimlane`, `.teams`, `.tines`, `.torq`, `.xmatters`, and `.webhook`. An empty list `[]` will disable all action types.
|
A list of action types that are enabled. It defaults to `[*]`, enabling all types. The names for built-in {kib} action types are prefixed with a `.` and include: `.email`, `.index`, `.jira`, `.opsgenie`, `.pagerduty`, `.resilient`, `.server-log`, `.servicenow`, .`servicenow-itom`, `.servicenow-sir`, `.slack`, `.swimlane`, `.teams`, `.tines`, `.torq`, `.xmatters`, and `.webhook`. An empty list `[]` will disable all action types.
|
||||||
+
|
+
|
||||||
|
|
|
@ -580,6 +580,7 @@ describe('create()', () => {
|
||||||
verificationMode: 'full',
|
verificationMode: 'full',
|
||||||
proxyVerificationMode: 'full',
|
proxyVerificationMode: 'full',
|
||||||
},
|
},
|
||||||
|
enableFooterInEmail: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const localActionTypeRegistryParams = {
|
const localActionTypeRegistryParams = {
|
||||||
|
|
|
@ -27,6 +27,7 @@ const createActionsConfigMock = () => {
|
||||||
getMicrosoftGraphApiUrl: jest.fn().mockReturnValue(undefined),
|
getMicrosoftGraphApiUrl: jest.fn().mockReturnValue(undefined),
|
||||||
validateEmailAddresses: jest.fn().mockReturnValue(undefined),
|
validateEmailAddresses: jest.fn().mockReturnValue(undefined),
|
||||||
getMaxAttempts: jest.fn().mockReturnValue(3),
|
getMaxAttempts: jest.fn().mockReturnValue(3),
|
||||||
|
enableFooterInEmail: jest.fn().mockReturnValue(true),
|
||||||
};
|
};
|
||||||
return mocked;
|
return mocked;
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,7 @@ const defaultActionsConfig: ActionsConfig = {
|
||||||
proxyVerificationMode: 'full',
|
proxyVerificationMode: 'full',
|
||||||
verificationMode: 'full',
|
verificationMode: 'full',
|
||||||
},
|
},
|
||||||
|
enableFooterInEmail: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('ensureUriAllowed', () => {
|
describe('ensureUriAllowed', () => {
|
||||||
|
|
|
@ -53,6 +53,7 @@ export interface ActionsConfigurationUtilities {
|
||||||
addresses: string[],
|
addresses: string[],
|
||||||
options?: ValidateEmailAddressesOptions
|
options?: ValidateEmailAddressesOptions
|
||||||
): string | undefined;
|
): string | undefined;
|
||||||
|
enableFooterInEmail: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowListErrorMessage(field: AllowListingField, value: string) {
|
function allowListErrorMessage(field: AllowListingField, value: string) {
|
||||||
|
@ -215,5 +216,6 @@ export function getActionsConfigurationUtilities(
|
||||||
DEFAULT_MAX_ATTEMPTS
|
DEFAULT_MAX_ATTEMPTS
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
enableFooterInEmail: () => config.enableFooterInEmail,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ describe('config validation', () => {
|
||||||
"allowedHosts": Array [
|
"allowedHosts": Array [
|
||||||
"*",
|
"*",
|
||||||
],
|
],
|
||||||
|
"enableFooterInEmail": true,
|
||||||
"enabledActionTypes": Array [
|
"enabledActionTypes": Array [
|
||||||
"*",
|
"*",
|
||||||
],
|
],
|
||||||
|
@ -57,6 +58,7 @@ describe('config validation', () => {
|
||||||
"allowedHosts": Array [
|
"allowedHosts": Array [
|
||||||
"*",
|
"*",
|
||||||
],
|
],
|
||||||
|
"enableFooterInEmail": true,
|
||||||
"enabledActionTypes": Array [
|
"enabledActionTypes": Array [
|
||||||
"*",
|
"*",
|
||||||
],
|
],
|
||||||
|
@ -198,6 +200,7 @@ describe('config validation', () => {
|
||||||
"allowedHosts": Array [
|
"allowedHosts": Array [
|
||||||
"*",
|
"*",
|
||||||
],
|
],
|
||||||
|
"enableFooterInEmail": true,
|
||||||
"enabledActionTypes": Array [
|
"enabledActionTypes": Array [
|
||||||
"*",
|
"*",
|
||||||
],
|
],
|
||||||
|
|
|
@ -125,6 +125,7 @@ export const configSchema = schema.object({
|
||||||
connectorTypeOverrides: schema.maybe(schema.arrayOf(connectorTypeSchema)),
|
connectorTypeOverrides: schema.maybe(schema.arrayOf(connectorTypeSchema)),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
enableFooterInEmail: schema.boolean({ defaultValue: true }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type ActionsConfig = TypeOf<typeof configSchema>;
|
export type ActionsConfig = TypeOf<typeof configSchema>;
|
||||||
|
|
|
@ -580,6 +580,7 @@ const BaseActionsConfig: ActionsConfig = {
|
||||||
maxResponseContentLength: ByteSizeValue.parse('1mb'),
|
maxResponseContentLength: ByteSizeValue.parse('1mb'),
|
||||||
responseTimeout: momentDuration(1000 * 30),
|
responseTimeout: momentDuration(1000 * 30),
|
||||||
customHostSettings: undefined,
|
customHostSettings: undefined,
|
||||||
|
enableFooterInEmail: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getACUfromConfig(config: Partial<ActionsConfig> = {}): ActionsConfigurationUtilities {
|
function getACUfromConfig(config: Partial<ActionsConfig> = {}): ActionsConfigurationUtilities {
|
||||||
|
|
|
@ -592,6 +592,7 @@ const BaseActionsConfig: ActionsConfig = {
|
||||||
maxResponseContentLength: ByteSizeValue.parse('1mb'),
|
maxResponseContentLength: ByteSizeValue.parse('1mb'),
|
||||||
responseTimeout: momentDuration(1000 * 30),
|
responseTimeout: momentDuration(1000 * 30),
|
||||||
customHostSettings: undefined,
|
customHostSettings: undefined,
|
||||||
|
enableFooterInEmail: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getACUfromConfig(config: Partial<ActionsConfig> = {}): ActionsConfigurationUtilities {
|
function getACUfromConfig(config: Partial<ActionsConfig> = {}): ActionsConfigurationUtilities {
|
||||||
|
|
|
@ -73,6 +73,7 @@ describe('custom_host_settings', () => {
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
maxResponseContentLength: new ByteSizeValue(1000000),
|
maxResponseContentLength: new ByteSizeValue(1000000),
|
||||||
responseTimeout: moment.duration(60000),
|
responseTimeout: moment.duration(60000),
|
||||||
|
enableFooterInEmail: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
test('ensure it copies over the config parts that it does not touch', () => {
|
test('ensure it copies over the config parts that it does not touch', () => {
|
||||||
|
|
|
@ -46,6 +46,7 @@ describe('Actions Plugin', () => {
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
maxResponseContentLength: new ByteSizeValue(1000000),
|
maxResponseContentLength: new ByteSizeValue(1000000),
|
||||||
responseTimeout: moment.duration(60000),
|
responseTimeout: moment.duration(60000),
|
||||||
|
enableFooterInEmail: true,
|
||||||
});
|
});
|
||||||
plugin = new ActionsPlugin(context);
|
plugin = new ActionsPlugin(context);
|
||||||
coreSetup = coreMock.createSetup();
|
coreSetup = coreMock.createSetup();
|
||||||
|
@ -218,6 +219,7 @@ describe('Actions Plugin', () => {
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
maxResponseContentLength: new ByteSizeValue(1000000),
|
maxResponseContentLength: new ByteSizeValue(1000000),
|
||||||
responseTimeout: moment.duration('60s'),
|
responseTimeout: moment.duration('60s'),
|
||||||
|
enableFooterInEmail: true,
|
||||||
...overrides,
|
...overrides,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -273,6 +275,7 @@ describe('Actions Plugin', () => {
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
maxResponseContentLength: new ByteSizeValue(1000000),
|
maxResponseContentLength: new ByteSizeValue(1000000),
|
||||||
responseTimeout: moment.duration(60000),
|
responseTimeout: moment.duration(60000),
|
||||||
|
enableFooterInEmail: true,
|
||||||
});
|
});
|
||||||
plugin = new ActionsPlugin(context);
|
plugin = new ActionsPlugin(context);
|
||||||
coreSetup = coreMock.createSetup();
|
coreSetup = coreMock.createSetup();
|
||||||
|
@ -341,6 +344,7 @@ describe('Actions Plugin', () => {
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
maxResponseContentLength: new ByteSizeValue(1000000),
|
maxResponseContentLength: new ByteSizeValue(1000000),
|
||||||
responseTimeout: moment.duration('60s'),
|
responseTimeout: moment.duration('60s'),
|
||||||
|
enableFooterInEmail: true,
|
||||||
...overrides,
|
...overrides,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,6 +523,10 @@ describe('execute()', () => {
|
||||||
logger: mockedLogger,
|
logger: mockedLogger,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
executorOptions.configurationUtilities = actionsConfigMock.create();
|
||||||
|
});
|
||||||
|
|
||||||
test('ensure parameters are as expected', async () => {
|
test('ensure parameters are as expected', async () => {
|
||||||
sendEmailMock.mockReset();
|
sendEmailMock.mockReset();
|
||||||
const result = await connectorType.executor(executorOptions);
|
const result = await connectorType.executor(executorOptions);
|
||||||
|
@ -540,7 +544,7 @@ describe('execute()', () => {
|
||||||
"content": Object {
|
"content": Object {
|
||||||
"message": "a message to you
|
"message": "a message to you
|
||||||
|
|
||||||
--
|
---
|
||||||
|
|
||||||
This message was sent by Elastic.",
|
This message was sent by Elastic.",
|
||||||
"subject": "the subject",
|
"subject": "the subject",
|
||||||
|
@ -591,7 +595,7 @@ describe('execute()', () => {
|
||||||
"content": Object {
|
"content": Object {
|
||||||
"message": "a message to you
|
"message": "a message to you
|
||||||
|
|
||||||
--
|
---
|
||||||
|
|
||||||
This message was sent by Elastic.",
|
This message was sent by Elastic.",
|
||||||
"subject": "the subject",
|
"subject": "the subject",
|
||||||
|
@ -642,7 +646,7 @@ describe('execute()', () => {
|
||||||
"content": Object {
|
"content": Object {
|
||||||
"message": "a message to you
|
"message": "a message to you
|
||||||
|
|
||||||
--
|
---
|
||||||
|
|
||||||
This message was sent by Elastic.",
|
This message was sent by Elastic.",
|
||||||
"subject": "the subject",
|
"subject": "the subject",
|
||||||
|
@ -738,6 +742,28 @@ describe('execute()', () => {
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('provides no footer link when enableFooterInEmail is false', async () => {
|
||||||
|
const customExecutorOptions: EmailConnectorTypeExecutorOptions = {
|
||||||
|
...executorOptions,
|
||||||
|
configurationUtilities: {
|
||||||
|
...configurationUtilities,
|
||||||
|
enableFooterInEmail: jest.fn().mockReturnValue(false),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const connectorTypeWithPublicUrl = getConnectorType({
|
||||||
|
publicBaseUrl: 'https://localhost:1234/foo/bar',
|
||||||
|
});
|
||||||
|
|
||||||
|
await connectorTypeWithPublicUrl.executor(customExecutorOptions);
|
||||||
|
|
||||||
|
expect(customExecutorOptions.configurationUtilities.enableFooterInEmail).toHaveBeenCalledTimes(
|
||||||
|
1
|
||||||
|
);
|
||||||
|
const sendMailCall = sendEmailMock.mock.calls[0][1];
|
||||||
|
expect(sendMailCall.content.message).toMatchInlineSnapshot(`"a message to you"`);
|
||||||
|
});
|
||||||
|
|
||||||
test('provides a footer link to Elastic when publicBaseUrl is defined', async () => {
|
test('provides a footer link to Elastic when publicBaseUrl is defined', async () => {
|
||||||
const connectorTypeWithPublicUrl = getConnectorType({
|
const connectorTypeWithPublicUrl = getConnectorType({
|
||||||
publicBaseUrl: 'https://localhost:1234/foo/bar',
|
publicBaseUrl: 'https://localhost:1234/foo/bar',
|
||||||
|
@ -750,7 +776,7 @@ describe('execute()', () => {
|
||||||
expect(sendMailCall.content.message).toMatchInlineSnapshot(`
|
expect(sendMailCall.content.message).toMatchInlineSnapshot(`
|
||||||
"a message to you
|
"a message to you
|
||||||
|
|
||||||
--
|
---
|
||||||
|
|
||||||
This message was sent by Elastic. [Go to Elastic](https://localhost:1234/foo/bar)."
|
This message was sent by Elastic. [Go to Elastic](https://localhost:1234/foo/bar)."
|
||||||
`);
|
`);
|
||||||
|
@ -779,7 +805,7 @@ describe('execute()', () => {
|
||||||
expect(sendMailCall.content.message).toMatchInlineSnapshot(`
|
expect(sendMailCall.content.message).toMatchInlineSnapshot(`
|
||||||
"a message to you
|
"a message to you
|
||||||
|
|
||||||
--
|
---
|
||||||
|
|
||||||
This message was sent by Elastic. [View this in Elastic](https://localhost:1234/foo/bar/my/app)."
|
This message was sent by Elastic. [View this in Elastic](https://localhost:1234/foo/bar/my/app)."
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -54,7 +54,7 @@ export const ELASTIC_CLOUD_SERVICE: SMTPConnection.Options = {
|
||||||
secure: false,
|
secure: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const EMAIL_FOOTER_DIVIDER = '\n\n--\n\n';
|
const EMAIL_FOOTER_DIVIDER = '\n\n---\n\n';
|
||||||
|
|
||||||
const ConfigSchemaProps = {
|
const ConfigSchemaProps = {
|
||||||
service: schema.string({ defaultValue: 'other' }),
|
service: schema.string({ defaultValue: 'other' }),
|
||||||
|
@ -319,10 +319,14 @@ async function executor(
|
||||||
transport.service = config.service;
|
transport.service = config.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
const footerMessage = getFooterMessage({
|
let actualMessage = params.message;
|
||||||
publicBaseUrl,
|
if (configurationUtilities.enableFooterInEmail()) {
|
||||||
kibanaFooterLink: params.kibanaFooterLink,
|
const footerMessage = getFooterMessage({
|
||||||
});
|
publicBaseUrl,
|
||||||
|
kibanaFooterLink: params.kibanaFooterLink,
|
||||||
|
});
|
||||||
|
actualMessage = `${params.message}${EMAIL_FOOTER_DIVIDER}${footerMessage}`;
|
||||||
|
}
|
||||||
|
|
||||||
const sendEmailOptions: SendEmailOptions = {
|
const sendEmailOptions: SendEmailOptions = {
|
||||||
connectorId: actionId,
|
connectorId: actionId,
|
||||||
|
@ -335,7 +339,7 @@ async function executor(
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
subject: params.subject,
|
subject: params.subject,
|
||||||
message: `${params.message}${EMAIL_FOOTER_DIVIDER}${footerMessage}`,
|
message: actualMessage,
|
||||||
},
|
},
|
||||||
hasAuth: config.hasAuth,
|
hasAuth: config.hasAuth,
|
||||||
configurationUtilities,
|
configurationUtilities,
|
||||||
|
|
|
@ -27,6 +27,7 @@ interface CreateTestConfigOptions {
|
||||||
testFiles?: string[];
|
testFiles?: string[];
|
||||||
reportName?: string;
|
reportName?: string;
|
||||||
useDedicatedTaskRunner: boolean;
|
useDedicatedTaskRunner: boolean;
|
||||||
|
enableFooterInEmail?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test.not-enabled is specifically not enabled
|
// test.not-enabled is specifically not enabled
|
||||||
|
@ -75,6 +76,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
|
||||||
testFiles = undefined,
|
testFiles = undefined,
|
||||||
reportName = undefined,
|
reportName = undefined,
|
||||||
useDedicatedTaskRunner,
|
useDedicatedTaskRunner,
|
||||||
|
enableFooterInEmail = true,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
return async ({ readConfigFile }: FtrConfigProviderContext) => {
|
return async ({ readConfigFile }: FtrConfigProviderContext) => {
|
||||||
|
@ -173,6 +175,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
|
||||||
'some.non.existent.com',
|
'some.non.existent.com',
|
||||||
'smtp.live.com',
|
'smtp.live.com',
|
||||||
])}`,
|
])}`,
|
||||||
|
`--xpack.actions.enableFooterInEmail=${enableFooterInEmail}`,
|
||||||
'--xpack.encryptedSavedObjects.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"',
|
'--xpack.encryptedSavedObjects.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"',
|
||||||
'--xpack.alerting.invalidateApiKeysTask.interval="15s"',
|
'--xpack.alerting.invalidateApiKeysTask.interval="15s"',
|
||||||
'--xpack.alerting.healthCheck.interval="1s"',
|
'--xpack.alerting.healthCheck.interval="1s"',
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function initPlugin(router: IRouter, path: string) {
|
||||||
cc: null,
|
cc: null,
|
||||||
bcc: null,
|
bcc: null,
|
||||||
subject: 'email-subject',
|
subject: 'email-subject',
|
||||||
html: `<p>email-message</p>\n<p>--</p>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`,
|
html: `<p>email-message</p>\n<hr>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`,
|
||||||
text: 'email-message\n\n--\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).',
|
text: 'email-message\n\n--\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).',
|
||||||
headers: {},
|
headers: {},
|
||||||
},
|
},
|
||||||
|
|
|
@ -124,8 +124,8 @@ export default function emailTest({ getService }: FtrProviderContext) {
|
||||||
cc: null,
|
cc: null,
|
||||||
bcc: null,
|
bcc: null,
|
||||||
subject: 'email-subject',
|
subject: 'email-subject',
|
||||||
html: `<p>email-message</p>\n<p>--</p>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`,
|
html: `<p>email-message</p>\n<hr>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`,
|
||||||
text: 'email-message\n\n--\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).',
|
text: 'email-message\n\n---\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).',
|
||||||
headers: {},
|
headers: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -147,10 +147,10 @@ export default function emailTest({ getService }: FtrProviderContext) {
|
||||||
.then((resp: any) => {
|
.then((resp: any) => {
|
||||||
const { text, html } = resp.body.data.message;
|
const { text, html } = resp.body.data.message;
|
||||||
expect(text).to.eql(
|
expect(text).to.eql(
|
||||||
'_italic_ **bold** https://elastic.co link\n\n--\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).'
|
'_italic_ **bold** https://elastic.co link\n\n---\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).'
|
||||||
);
|
);
|
||||||
expect(html).to.eql(
|
expect(html).to.eql(
|
||||||
`<p><em>italic</em> <strong>bold</strong> <a href="https://elastic.co">https://elastic.co</a> link</p>\n<p>--</p>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`
|
`<p><em>italic</em> <strong>bold</strong> <a href="https://elastic.co">https://elastic.co</a> link</p>\n<hr>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -174,10 +174,10 @@ export default function emailTest({ getService }: FtrProviderContext) {
|
||||||
.then((resp: any) => {
|
.then((resp: any) => {
|
||||||
const { text, html } = resp.body.data.message;
|
const { text, html } = resp.body.data.message;
|
||||||
expect(text).to.eql(
|
expect(text).to.eql(
|
||||||
'message\n\n--\n\nThis message was sent by Elastic. [View my path in Elastic](https://localhost:5601/my/path).'
|
'message\n\n---\n\nThis message was sent by Elastic. [View my path in Elastic](https://localhost:5601/my/path).'
|
||||||
);
|
);
|
||||||
expect(html).to.eql(
|
expect(html).to.eql(
|
||||||
`<p>message</p>\n<p>--</p>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601/my/path\">View my path in Elastic</a>.</p>\n`
|
`<p>message</p>\n<hr>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601/my/path\">View my path in Elastic</a>.</p>\n`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -325,8 +325,8 @@ export default function emailTest({ getService }: FtrProviderContext) {
|
||||||
cc: null,
|
cc: null,
|
||||||
bcc: null,
|
bcc: null,
|
||||||
subject: 'email-subject',
|
subject: 'email-subject',
|
||||||
html: `<p>email-message</p>\n<p>--</p>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`,
|
html: `<p>email-message</p>\n<hr>\n<p>This message was sent by Elastic. <a href=\"https://localhost:5601\">Go to Elastic</a>.</p>\n`,
|
||||||
text: 'email-message\n\n--\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).',
|
text: 'email-message\n\n---\n\nThis message was sent by Elastic. [Go to Elastic](https://localhost:5601).',
|
||||||
headers: {},
|
headers: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,4 +21,5 @@ export default createTestConfig('spaces_only', {
|
||||||
useDedicatedTaskRunner: true,
|
useDedicatedTaskRunner: true,
|
||||||
testFiles: [require.resolve('.')],
|
testFiles: [require.resolve('.')],
|
||||||
reportName: 'X-Pack Alerting API Integration Tests - Actions',
|
reportName: 'X-Pack Alerting API Integration Tests - Actions',
|
||||||
|
enableFooterInEmail: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -54,6 +54,29 @@ export default function emailTest({ getService }: FtrProviderContext) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not have a footer', async () => {
|
||||||
|
const from = `bob@${EmailDomainAllowed}`;
|
||||||
|
const conn = await createConnector(from);
|
||||||
|
expect(conn.status).to.be(200);
|
||||||
|
|
||||||
|
const { id } = conn.body;
|
||||||
|
expect(id).to.be.a('string');
|
||||||
|
|
||||||
|
const to = EmailDomainsAllowed.map((domain) => `jeb@${domain}`).sort();
|
||||||
|
const cc = EmailDomainsAllowed.map((domain) => `jim@${domain}`).sort();
|
||||||
|
const bcc = EmailDomainsAllowed.map((domain) => `joe@${domain}`).sort();
|
||||||
|
|
||||||
|
const ccNames = cc.map((email) => `Jimmy Jack <${email}>`);
|
||||||
|
|
||||||
|
const run = await runConnector(id, to, ccNames, bcc);
|
||||||
|
expect(run.status).to.be(200);
|
||||||
|
|
||||||
|
const { status } = run.body || {};
|
||||||
|
expect(status).to.be('ok');
|
||||||
|
|
||||||
|
expect(run.body.data.message.text).to.be('email-message');
|
||||||
|
});
|
||||||
|
|
||||||
describe('fails for invalid email domains', () => {
|
describe('fails for invalid email domains', () => {
|
||||||
it('in create when invalid "from" used', async () => {
|
it('in create when invalid "from" used', async () => {
|
||||||
const from = `bob@not.allowed`;
|
const from = `bob@not.allowed`;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue