mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
feat(connector): enable custom headers for SMTP connector (#6256)
This commit is contained in:
parent
0a92bd2fdc
commit
6fca3fe3c4
6 changed files with 47 additions and 2 deletions
5
.changeset/slow-boxes-greet.md
Normal file
5
.changeset/slow-boxes-greet.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"@logto/connector-smtp": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
enable static custom headers for SMTP connector
|
|
@ -198,5 +198,14 @@ export const defaultMetadata: ConnectorMetadata = {
|
||||||
type: ConnectorConfigFormItemType.Switch,
|
type: ConnectorConfigFormItemType.Switch,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'customHeaders',
|
||||||
|
label: 'Custom Headers',
|
||||||
|
type: ConnectorConfigFormItemType.Json,
|
||||||
|
required: false,
|
||||||
|
defaultValue: {},
|
||||||
|
description:
|
||||||
|
'Custom headers to be added to original email headers when sending messages. Both keys and values should be string-typed.',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,6 +79,28 @@ describe('SMTP connector', () => {
|
||||||
to: 'baz',
|
to: 'baz',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should send mail with customer headers', async () => {
|
||||||
|
const connector = await createConnector({
|
||||||
|
getConfig: vi.fn().mockResolvedValue({
|
||||||
|
...mockedConfig,
|
||||||
|
customHeaders: { 'X-Test': 'test', 'X-Test-Another': ['test1', 'test2', 'test3'] },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
await connector.sendMessage({
|
||||||
|
to: 'baz',
|
||||||
|
type: TemplateType.OrganizationInvitation,
|
||||||
|
payload: { code: '345678', link: 'https://example.com' },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(sendMail).toHaveBeenCalledWith({
|
||||||
|
from: '<notice@test.smtp>',
|
||||||
|
subject: 'Organization invitation',
|
||||||
|
text: 'This is for organization invitation. Your link is https://example.com.',
|
||||||
|
to: 'baz',
|
||||||
|
headers: { 'X-Test': 'test', 'X-Test-Another': ['test1', 'test2', 'test3'] },
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Test config guard', () => {
|
describe('Test config guard', () => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { assert } from '@silverhand/essentials';
|
import { assert, conditional } from '@silverhand/essentials';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
GetConnectorConfig,
|
GetConnectorConfig,
|
||||||
|
@ -14,6 +14,7 @@ import {
|
||||||
replaceSendMessageHandlebars,
|
replaceSendMessageHandlebars,
|
||||||
} from '@logto/connector-kit';
|
} from '@logto/connector-kit';
|
||||||
import nodemailer from 'nodemailer';
|
import nodemailer from 'nodemailer';
|
||||||
|
import type Mail from 'nodemailer/lib/mailer';
|
||||||
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
|
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
|
||||||
|
|
||||||
import { defaultMetadata } from './constant.js';
|
import { defaultMetadata } from './constant.js';
|
||||||
|
@ -44,11 +45,17 @@ const sendMessage =
|
||||||
template.contentType
|
template.contentType
|
||||||
);
|
);
|
||||||
|
|
||||||
const mailOptions = {
|
const mailOptions: Mail.Options = {
|
||||||
to,
|
to,
|
||||||
from: config.fromEmail,
|
from: config.fromEmail,
|
||||||
replyTo: config.replyTo,
|
replyTo: config.replyTo,
|
||||||
subject: replaceSendMessageHandlebars(template.subject, payload),
|
subject: replaceSendMessageHandlebars(template.subject, payload),
|
||||||
|
...conditional(
|
||||||
|
config.customHeaders &&
|
||||||
|
Object.entries(config.customHeaders).length > 0 && {
|
||||||
|
headers: config.customHeaders,
|
||||||
|
}
|
||||||
|
),
|
||||||
...contentsObject,
|
...contentsObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ export const mockedConfig = {
|
||||||
usageType: 'OrganizationInvitation',
|
usageType: 'OrganizationInvitation',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
customHeaders: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockedOauth2AuthWithToken = {
|
export const mockedOauth2AuthWithToken = {
|
||||||
|
|
|
@ -125,6 +125,7 @@ export const smtpConfigGuard = z.object({
|
||||||
servername: z.string().optional(),
|
servername: z.string().optional(),
|
||||||
ignoreTLS: z.boolean().optional(),
|
ignoreTLS: z.boolean().optional(),
|
||||||
requireTLS: z.boolean().optional(),
|
requireTLS: z.boolean().optional(),
|
||||||
|
customHeaders: z.record(z.string().or(z.string().array())).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SmtpConfig = z.infer<typeof smtpConfigGuard>;
|
export type SmtpConfig = z.infer<typeof smtpConfigGuard>;
|
||||||
|
|
Loading…
Reference in a new issue