0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00
logto/packages/connector-sendgrid-mail/src/index.ts

95 lines
2.6 KiB
TypeScript

import {
ConnectorError,
ConnectorErrorCodes,
ConnectorMetadata,
EmailSendMessageFunction,
ValidateConfig,
EmailConnector,
GetConnectorConfig,
} from '@logto/connector-types';
import { assert } from '@silverhand/essentials';
import got, { HTTPError } from 'got';
import { defaultMetadata, endpoint } from './constant';
import {
sendGridMailConfigGuard,
SendGridMailConfig,
EmailData,
Personalization,
Content,
PublicParameters,
} from './types';
export default class SendGridMailConnector implements EmailConnector {
public metadata: ConnectorMetadata = defaultMetadata;
constructor(public readonly getConfig: GetConnectorConfig<SendGridMailConfig>) {}
public validateConfig: ValidateConfig = async (config: unknown) => {
const result = sendGridMailConfigGuard.safeParse(config);
if (!result.success) {
throw new ConnectorError(ConnectorErrorCodes.InvalidConfig, result.error.message);
}
};
public sendMessage: EmailSendMessageFunction = async (address, type, data) => {
const config = await this.getConfig(this.metadata.id);
await this.validateConfig(config);
const { apiKey, fromEmail, fromName, templates } = config;
const template = templates.find((template) => template.usageType === type);
assert(
template,
new ConnectorError(
ConnectorErrorCodes.TemplateNotFound,
`Template not found for type: ${type}`
)
);
const toEmailData: EmailData[] = [{ email: address }];
const fromEmailData: EmailData = fromName
? { email: fromEmail, name: fromName }
: { email: fromEmail };
const personalizations: Personalization = { to: toEmailData };
const content: Content = {
type: template.type,
value:
typeof data.code === 'string'
? template.content.replace(/{{code}}/g, data.code)
: template.content,
};
const { subject } = template;
const parameters: PublicParameters = {
personalizations: [personalizations],
from: fromEmailData,
subject,
content: [content],
};
try {
return await got.post(endpoint, {
headers: {
Authorization: 'Bearer ' + apiKey,
'Content-Type': 'application/json',
},
json: parameters,
});
} catch (error: unknown) {
if (error instanceof HTTPError) {
const {
response: { body: rawBody },
} = error;
assert(
typeof rawBody === 'string',
new ConnectorError(ConnectorErrorCodes.InvalidResponse)
);
throw new ConnectorError(ConnectorErrorCodes.General, rawBody);
}
throw error;
}
};
}