@strapi/provider-email-amazon-ses
Version:
Amazon SES provider for strapi email
133 lines (131 loc) • 5.18 kB
JavaScript
/** Default SES API host when `amazon` is omitted (same as legacy node-ses). */ const DEFAULT_SES_ENDPOINT = 'https://email.us-east-1.amazonaws.com';
const SES_ENDPOINT_REGION_PATTERN = /email\.([a-z0-9-]+)\.amazonaws\.com/i;
const resolveEndpointUrl = (endpoint)=>{
if (!endpoint) {
return undefined;
}
if (typeof endpoint === 'string') {
return endpoint;
}
if (typeof endpoint === 'object' && 'url' in endpoint && typeof endpoint.url === 'string') {
return endpoint.url;
}
return undefined;
};
const regionFromEndpoint = (endpoint)=>{
const endpointUrl = resolveEndpointUrl(endpoint);
if (!endpointUrl) {
return undefined;
}
try {
const match = new URL(endpointUrl).hostname.match(SES_ENDPOINT_REGION_PATTERN);
return match?.[1];
} catch {
return undefined;
}
};
/** Matches node-ses `extractRecipient`: arrays pass through, strings become a single entry. */ const toAddressList = (value)=>{
if (!value) {
return undefined;
}
if (Array.isArray(value)) {
return value;
}
return [
value
];
};
const mapLegacyMessageTags = (messageTags)=>{
if (!Array.isArray(messageTags)) {
return undefined;
}
return messageTags.filter((tag)=>typeof tag === 'object' && tag !== null && 'name' in tag && 'value' in tag && typeof tag.name === 'string' && typeof tag.value === 'string').map((tag)=>({
Name: tag.name,
Value: tag.value
}));
};
/**
* Maps legacy node-ses `providerOptions` and AWS SDK v3 `SESClient` config.
*
* Rewrites:
* - `key` / `secret` → `credentials.accessKeyId` / `credentials.secretAccessKey`
* - `credentials: { key, secret }` → AWS credential object
* - `amazon` → `endpoint`
* - region from `amazon` / `endpoint` host (`email.<region>.amazonaws.com`)
* - `key` + `secret` only → `region: us-east-1` (node-ses default endpoint behavior)
*/ const getClientConfig = (providerOptions)=>{
const { key, secret, amazon, credentials, region, ...clientConfig } = providerOptions;
const hasLegacyStaticCredentials = Boolean(key && secret);
const endpoint = amazon || providerOptions.endpoint || (hasLegacyStaticCredentials ? DEFAULT_SES_ENDPOINT : undefined);
const parsedRegionFromEndpoint = regionFromEndpoint(endpoint);
const explicitCredentials = (credentials && typeof credentials === 'object' && 'key' in credentials ? {
accessKeyId: credentials.key,
secretAccessKey: credentials.secret,
...credentials.sessionToken ? {
sessionToken: credentials.sessionToken
} : {}
} : credentials) || (key && secret ? {
accessKeyId: key,
secretAccessKey: secret
} : undefined);
const unparseableLegacyAmazon = Boolean(amazon && hasLegacyStaticCredentials && !parsedRegionFromEndpoint);
const resolvedRegion = region || parsedRegionFromEndpoint || (unparseableLegacyAmazon || hasLegacyStaticCredentials && !parsedRegionFromEndpoint && !endpoint) && 'us-east-1' || undefined;
// node-ses createClient only consumed key, secret, and amazon — ignore stray options.
const sdkOnlyOptions = hasLegacyStaticCredentials ? {} : clientConfig;
return {
...sdkOnlyOptions,
...resolvedRegion ? {
region: resolvedRegion
} : {},
...endpoint ? {
endpoint
} : {},
...explicitCredentials ? {
credentials: explicitCredentials
} : {}
};
};
/** Builds SendEmail input (html → Html body, text → Text body; legacy node-ses message/altText). */ const buildSendEmailCommandInput = (options, settings)=>{
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
const { configurationSet, messageTags, ...sdkRest } = rest;
const commandInput = {
Source: from || settings.defaultFrom,
Destination: {
ToAddresses: toAddressList(to),
CcAddresses: toAddressList(cc),
BccAddresses: toAddressList(bcc)
},
ReplyToAddresses: toAddressList(replyTo !== undefined ? replyTo : settings.defaultReplyTo),
Message: {
Subject: {
Data: subject,
Charset: 'UTF-8'
},
Body: {
...html ? {
Html: {
Data: html,
Charset: 'UTF-8'
}
} : {},
...text ? {
Text: {
Data: text,
Charset: 'UTF-8'
}
} : {}
}
},
...sdkRest
};
if (typeof configurationSet === 'string') {
commandInput.ConfigurationSetName = configurationSet;
}
const tags = mapLegacyMessageTags(messageTags);
if (tags?.length) {
commandInput.Tags = tags;
}
return commandInput;
};
export { DEFAULT_SES_ENDPOINT, SES_ENDPOINT_REGION_PATTERN, buildSendEmailCommandInput, getClientConfig, regionFromEndpoint, toAddressList };
//# sourceMappingURL=utils.mjs.map