Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEVEXP-642: Update types and refactor transformers #151

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/mailgun/src/models/v1/emails/request/enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type YesNoEnum = boolean | 'yes' | 'no';

export type YesNoHtmlonlyEnum = YesNoEnum | 'htmlonly';
17 changes: 17 additions & 0 deletions packages/mailgun/src/models/v1/emails/request/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import FormData = require('form-data');

export const appendFilteredPropertiesToFormData = (
obj: Record<string, any>,
prefix: string,
formData: FormData,
) => {
for (const [key, value] of Object.entries(obj)) {
if (key.startsWith(prefix) && value != null) {
if (value instanceof Date) {
formData.append(key, value.toUTCString());
} else {
formData.append(key, String(value));
}
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { OverrideProperties } from './override-properties';
import FormData = require('form-data');

// eslint-disable-next-line valid-jsdoc
/**
* ** INTERNAL METHOD ** IT SHOULD NOT BE USED DIRECTLY BY SDK USERS AS IT CAN BE REMOVED OR MODIFIED WITHOUT NOTICE
*/
export const appendOverridePropertiesToFormData = (overrideProperties: OverrideProperties, formData: FormData) => {
if (overrideProperties['tag'] != null) {
formData.append('o:tag', overrideProperties['tag']);
}
if (overrideProperties['deliveryTimeOptimizePeriod'] != null) {
formData.append('o:deliverytime-optimize-period', `${overrideProperties['deliveryTimeOptimizePeriod']}h`);
}
if (overrideProperties['enableDkimSignature'] != null) {
formData.append('o:dkim', String(overrideProperties['enableDkimSignature']));
}
if (overrideProperties['secondaryDkim'] != null) {
formData.append('o:secondary-dkim', overrideProperties['secondaryDkim']);
}
if (overrideProperties['secondaryDkimPublic'] != null) {
formData.append('o:secondary-dkim-public', overrideProperties['secondaryDkimPublic']);
}
if (overrideProperties['deliveryTime'] != null) {
formData.append('o:deliverytime', overrideProperties['deliveryTime']);
}
if (overrideProperties['timeZoneLocalize'] != null) {
formData.append('o:time-zone-localize', overrideProperties['timeZoneLocalize']);
}
if (overrideProperties['tracking'] != null) {
formData.append('o:tracking', String(overrideProperties['tracking']));
}
if (overrideProperties['trackingClicks'] != null) {
formData.append('o:tracking-clicks', String(overrideProperties['trackingClicks']));
}
if (overrideProperties['trackingOpens'] != null) {
formData.append('o:tracking-opens', String(overrideProperties['trackingOpens']));
}
if (overrideProperties['trackingPixelLocationTop'] != null) {
formData.append('o:tracking-pixel-location-top', String(overrideProperties['trackingPixelLocationTop']));
}
if (overrideProperties['sendingIp'] != null) {
formData.append('o:sending-ip', overrideProperties['sendingIp']);
}
if (overrideProperties['sendingIpPool'] != null) {
formData.append('o:sending-ip-pool', overrideProperties['sendingIpPool']);
}
if (overrideProperties['requireTls'] != null) {
formData.append('o:require-tls', String(overrideProperties['requireTls']));
}
if (overrideProperties['skipVerification'] != null) {
formData.append('o:skip-verification', String(overrideProperties['skipVerification']));
}
if (overrideProperties['isTestMode'] != null) {
formData.append('o:testmode', String(overrideProperties['isTestMode']));
}
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { YesNoEnum, YesNoHtmlonlyEnum } from '../enum';

export interface OverrideProperties {
/** Tag string. See **Tagging** for more information */
tag?: string;
/** Toggles Send Time Optimization (STO) on a per-message basis. String should be set to the number of hours in `[0-9]+h` format, with the minimum being `24h` and the maximum being `72h`. This value defines the time window in which Mailgun will run the optimization algorithm based on prior engagement data of a given recipient. See **Sending a Message with STO** for details. *Please note that STO is only available on certain plans. See www.mailgun.com/pricing for more info* */
deliveryTimeOptimizePeriod?: string;
deliveryTimeOptimizePeriod?: number;
/** Enables/disables DKIM signatures on a per-message basis. Pass `yes` or `no`, `true` or `false` */
enableDkimSignature?: string;
enableDkimSignature?: YesNoEnum;
/** Specify a second domain key to sign the email with. The value is formatted as `signing_domain/selector`, e.g. `example.com/s1`. This tells Mailgun to sign the message with the signing domain `example.com` using the selector `s1`. Note: the domain key specified must have been previously created and activated. */
secondaryDkim?: string;
/** Specify an alias of the domain key specified in `o:secondary-dkim`. Also formatted as `public_signing_domain/selector`. `o:secondary-dkim` option must also be provided. Mailgun will sign the message with the provided key of the secondary DKIM, but use the public secondary DKIM name and selector. Note: We will perform a DNS check prior to signing the message to ensure the public keys matches the secondary DKIM. */
Expand All @@ -14,21 +16,21 @@ export interface OverrideProperties {
/** Toggles Timezone Optimization (TZO) on a per message basis. String should be set to preferred delivery time in `HH:mm` or `hh:mmaa` format, where `HH:mm` is used for 24 hour format without AM/PM and hh:mmaa is used for 12 hour format with AM/PM. See **Sending a Message with TZO** for details. *Please note that TZO is only available on certain plans. See www.mailgun.com/pricing for more info* */
timeZoneLocalize?: string;
/** Toggles click tracking on a per-message basis. Has higher priority than domain-level setting. Pass `yes` or `no`, `true` or `false`, or `htmlonly` if you only want links rewritten in the HTML part of the message */
trackingClicks?: string;
trackingClicks?: YesNoHtmlonlyEnum;
/** Toggles both click and open tracking on a per-message basis, see **Tracking Messages** for details. Pass `yes` or `no`, `true` or `false`, or `htmlonly` if you only want links rewritten in the HTML part of the message */
tracking?: string;
tracking?: YesNoHtmlonlyEnum;
/** Toggles opens tracking on a per-message basis. Has higher priority than domain-level setting. Pass `yes` or `no`, `true` or `false` */
trackingOpens?: string;
trackingOpens?: YesNoEnum;
/** If you send long emails that experience truncation or other rendering issues at the recipient, you can ensure opens are being tracked accurately with placement of the tracking pixel at the top of your emails */
trackingPixelLocationTop?: string;
trackingPixelLocationTop?: YesNoEnum;
/** Used to specify an IP Address to send an email that is owned by your account */
sendingIp?: string;
/** If an IP Pool ID is provided, the email will be delivered with an IP that belongs in that pool */
sendingIpPool?: string;
/** If set to `true` or `yes` this requires the message only be sent over a TLS connection. If a TLS connection can not be established, Mailgun will not deliver the message. If set to `false` or `no`, Mailgun will still try and upgrade the connection, but if Mailgun cannot, the message will be delivered over a plaintext SMTP connection. The default is `false` */
requireTls?: string;
requireTls?: YesNoEnum;
/** If set to `true` or `yes`, the certificate and hostname of the resolved MX Host will not be verified when trying to establish a TLS connection. If set to `false` or `no`, Mailgun will verify the certificate and hostname. If either one can not be verified, a TLS connection will not be established. The default is `false` */
skipVerification?: string;
skipVerification?: YesNoEnum;
/** Enables sending in test mode. Pass `yes` if needed. See **Sending in Test Mode** */
isTestMode?: boolean;
isTestMode?: YesNoEnum;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { appendOverridePropertiesToFormData } from '../override-properties/override-properties.transform';
import { appendTemplatePropertiesToFormData } from '../template-properties/template-properties.transform';
import { appendFilteredPropertiesToFormData } from '../helper';
import { SendEmailRequest } from './send-email-request';
import FormData = require('form-data');

// eslint-disable-next-line valid-jsdoc
/**
* ** INTERNAL METHOD ** IT SHOULD NOT BE USED DIRECTLY BY SDK USERS AS IT CAN BE REMOVED OR MODIFIED WITHOUT NOTICE
*/
export const transformSendEmailRequestIntoApiRequestBody = (sdkRequest: SendEmailRequest): FormData => {
const formData = new FormData();
if (sdkRequest.html != null) {
formData.append('html', sdkRequest.html);
}
if (sdkRequest.ampHtml != null) {
formData.append('amp-html', sdkRequest['ampHtml']);
}
if (sdkRequest.text!= null) {
formData.append('text', sdkRequest.text);
}
if (sdkRequest.to != null) {
formData.append('to', sdkRequest.to);
}
if (sdkRequest.from != null) {
formData.append('from', sdkRequest.from);
}
if (sdkRequest.cc != null) {
formData.append('cc', sdkRequest.cc);
}
if (sdkRequest.bcc != null) {
formData.append('bcc', sdkRequest.bcc);
}
if (sdkRequest.subject != null) {
formData.append('subject', sdkRequest.subject);
}
if (sdkRequest.attachment != null) {
formData.append('attachment', sdkRequest.attachment);
}
if (sdkRequest.inline != null) {
formData.append('inline', sdkRequest.inline);
}
if (sdkRequest.overrideProperties != null) {
appendOverridePropertiesToFormData(sdkRequest.overrideProperties, formData);
}
if (sdkRequest.template != null) {
formData.append('template', sdkRequest.template);
}
if (sdkRequest.templateProperties != null) {
appendTemplatePropertiesToFormData(sdkRequest.templateProperties, formData);
}
appendFilteredPropertiesToFormData(sdkRequest, 'h:', formData);
appendFilteredPropertiesToFormData(sdkRequest, 'v:', formData);
return formData;
};
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
import { TemplateProperties } from '../template-properties';
import { OverrideProperties } from '../override-properties';
import FormData = require('form-data');

export type MessageContentWhereHtmlContentCanBeInlineOnly = {

export type MessageContentWithHtmlInline = {
/** Body of the message (HTML version) */
html?: string;
/** AMP part of the message. Please follow Google guidelines to compose and send AMP emails */
amp_html?: string;
/** Body of the message (text version) */
text?: string;
/** Name of a template stored via template API to use to render the email body. See **Templates** for more information */
template?: never;
/** @see TemplateProperties */
templateProperties?: never;
} & CommonEmailProperties;

export type MessageContentWhereHtmlContentCanBeFromTemplateOnly = {
export type MessageContentWithHtmlInTemplate = {
/** Name of a template stored via template API to use to render the email body. See **Templates** for more information */
template?: string;
/** AMP part of the message. Please follow Google guidelines to compose and send AMP emails */
amp_html?: string;
/** Body of the message (text version) */
text?: string;
/** Body of the message (HTML version) */
html?: never;
/** @see TemplateProperties */
Expand All @@ -37,6 +31,10 @@ export interface CommonEmailProperties {
bcc?: string;
/** Message subject */
subject: string;
/** Body of the message (text version) */
text?: string;
/** AMP part of the message. Please follow Google guidelines to compose and send AMP emails */
ampHtml?: string;
/** File attachment. You can post multiple `attachment` values. **Important:** You must use `multipart/form-data` encoding for sending attachments */
attachment?: string;
/** Attachment with `inline` disposition. Can be used to send inline images (see example). You can post multiple `inline` values */
Expand All @@ -46,123 +44,8 @@ export interface CommonEmailProperties {
/** h: prefix followed by a Header/Value pair. For example: h:X-Mailgun-Sending-Ip-Pool=xx.xx.xxx.x. */
[key: `h:${string}`]: string;
/** `v:` prefix followed by an arbitrary name allows to attach a custom JSON data to the message. See **Attaching Data to Messages** for more information */
[key: `v:${string}`]: string | number;
[key: `v:${string}`]: string | number | Date;
}

export type SendEmailRequest = MessageContentWhereHtmlContentCanBeInlineOnly
| MessageContentWhereHtmlContentCanBeFromTemplateOnly;

export const transformSendEmailRequestIntoApiRequestBody = (sdkRequest: SendEmailRequest): FormData => {
const formData = new FormData();
if ('html' in sdkRequest && sdkRequest['html'] !== undefined && sdkRequest['html'] !== null) {
formData.append('html', sdkRequest['html']);
}
if ('template' in sdkRequest && sdkRequest['template'] !== undefined && sdkRequest['template'] !== null) {
formData.append('template', sdkRequest['template']);
}
if (sdkRequest['amp_html'] !== undefined && sdkRequest['amp_html'] !== null) {
formData.append('amp-html', sdkRequest['amp_html']);
}
if (sdkRequest['text'] !== undefined && sdkRequest['text'] !== null) {
formData.append('text', sdkRequest['text']);
}
if (sdkRequest['to'] !== undefined && sdkRequest['to'] !== null) {
formData.append('to', sdkRequest['to']);
}
if (sdkRequest['from'] !== undefined && sdkRequest['from'] !== null) {
formData.append('from', sdkRequest['from']);
}
if (sdkRequest['cc'] !== undefined && sdkRequest['cc'] !== null) {
formData.append('cc', sdkRequest['cc']);
}
if (sdkRequest['bcc'] !== undefined && sdkRequest['bcc'] !== null) {
formData.append('bcc', sdkRequest['bcc']);
}
if (sdkRequest['subject'] !== undefined && sdkRequest['subject'] !== null) {
formData.append('subject', sdkRequest['subject']);
}
if (sdkRequest['attachment'] !== undefined && sdkRequest['attachment'] !== null) {
formData.append('attachment', sdkRequest['attachment']);
}
if (sdkRequest['inline'] !== undefined && sdkRequest['inline'] !== null) {
formData.append('inline', sdkRequest['inline']);
}
if ('templateProperties' in sdkRequest
&& sdkRequest.templateProperties !== null
&& sdkRequest.templateProperties !== undefined) {
const templateProperties = sdkRequest.templateProperties;
if (templateProperties['text'] !== undefined && templateProperties['text'] !== null) {
formData.append('t:text', templateProperties['text']);
}
if (templateProperties['version'] !== undefined && templateProperties['version'] !== null) {
formData.append('t:version', templateProperties['version']);
}
if (templateProperties['variables'] !== undefined && templateProperties['variables'] !== null) {
formData.append('t:variables', templateProperties['variables']);
}
}
if (sdkRequest['overrideProperties'] !== undefined && sdkRequest['overrideProperties'] !== null) {
const overrideProperties = sdkRequest['overrideProperties'];
if (overrideProperties['tag'] !== undefined && overrideProperties['tag'] !== null) {
formData.append('o:tag', overrideProperties['tag']);
}
if (overrideProperties['deliveryTimeOptimizePeriod'] !== undefined
&& overrideProperties['deliveryTimeOptimizePeriod'] !== null) {
formData.append('o:deliverytime-optimize-period', overrideProperties['deliveryTimeOptimizePeriod']);
}
if (overrideProperties['enableDkimSignature'] !== undefined && overrideProperties['enableDkimSignature'] !== null) {
formData.append('o:dkim', overrideProperties['enableDkimSignature']);
}
if (overrideProperties['secondaryDkim'] !== undefined && overrideProperties['secondaryDkim'] !== null) {
formData.append('o:secondary-dkim', overrideProperties['secondaryDkim']);
}
if (overrideProperties['secondaryDkimPublic'] !== undefined && overrideProperties['secondaryDkimPublic'] !== null) {
formData.append('o:secondary-dkim-public', overrideProperties['secondaryDkimPublic']);
}
if (overrideProperties['deliveryTime'] !== undefined && overrideProperties['deliveryTime'] !== null) {
formData.append('o:deliverytime', overrideProperties['deliveryTime']);
}
if (overrideProperties['timeZoneLocalize'] !== undefined && overrideProperties['timeZoneLocalize'] !== null) {
formData.append('o:time-zone-localize', overrideProperties['timeZoneLocalize']);
}
if (overrideProperties['tracking'] !== undefined && overrideProperties['tracking'] !== null) {
formData.append('o:tracking', overrideProperties['tracking']);
}
if (overrideProperties['trackingClicks'] !== undefined && overrideProperties['trackingClicks'] !== null) {
formData.append('o:tracking-clicks', overrideProperties['trackingClicks']);
}
if (overrideProperties['trackingOpens'] !== undefined && overrideProperties['trackingOpens'] !== null) {
formData.append('o:tracking-opens', overrideProperties['trackingOpens']);
}
if (overrideProperties['trackingPixelLocationTop'] !== undefined
&& overrideProperties['trackingPixelLocationTop'] !== null) {
formData.append('o:tracking-pixel-location-top', overrideProperties['trackingPixelLocationTop']);
}
if (overrideProperties['sendingIp'] !== undefined && overrideProperties['sendingIp'] !== null) {
formData.append('o:sending-ip', overrideProperties['sendingIp']);
}
if (overrideProperties['sendingIpPool'] !== undefined && overrideProperties['sendingIpPool'] !== null) {
formData.append('o:sending-ip-pool', overrideProperties['sendingIpPool']);
}
if (overrideProperties['requireTls'] !== undefined && overrideProperties['requireTls'] !== null) {
formData.append('o:require-tls', overrideProperties['requireTls']);
}
if (overrideProperties['skipVerification'] !== undefined && overrideProperties['skipVerification'] !== null) {
formData.append('o:skip-verification', overrideProperties['skipVerification']);
}
if (overrideProperties['isTestMode'] !== undefined && overrideProperties['isTestMode'] !== null) {
formData.append('o:testmode', overrideProperties['isTestMode']);
}
}
addPropertiesToFormData(sdkRequest, 'h:', formData);
addPropertiesToFormData(sdkRequest, 'v:', formData);
return formData;
};

const addPropertiesToFormData = (obj: SendEmailRequest, prefix: string, formData: FormData) => {
for (const [key, value] of Object.entries(obj)) {
if (key.startsWith(prefix) && !!value) {
formData.append(key, value);
}
}
};
export type SendEmailRequest = MessageContentWithHtmlInline
| MessageContentWithHtmlInTemplate;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { appendTemplatePropertiesToFormData } from '../template-properties/template-properties.transform';
import { appendOverridePropertiesToFormData } from '../override-properties/override-properties.transform';
import { appendFilteredPropertiesToFormData } from '../helper';
import { SendMimeEmailRequest } from './send-mime-email-request';
import FormData = require('form-data');

// eslint-disable-next-line valid-jsdoc
/**
* ** INTERNAL METHOD ** IT SHOULD NOT BE USED DIRECTLY BY SDK USERS AS IT CAN BE REMOVED OR MODIFIED WITHOUT NOTICE
*/
export const transformSendMimeEmailRequestIntoApiRequestBody = (sdkRequest: SendMimeEmailRequest): FormData => {
const formData = new FormData();
if (sdkRequest.to != null) {
formData.append('to', sdkRequest.to);
}
if (sdkRequest.message != null) {
formData.append('message', sdkRequest.message, { filename: 'MimeMessage' });
}
if (sdkRequest.template != null) {
formData.append('template', sdkRequest['template']);
}
if (sdkRequest.templateProperties != null) {
appendTemplatePropertiesToFormData(sdkRequest.templateProperties, formData);
}
if (sdkRequest.overrideProperties != null) {
appendOverridePropertiesToFormData(sdkRequest.overrideProperties, formData);
}
appendFilteredPropertiesToFormData(sdkRequest, 'h:', formData);
appendFilteredPropertiesToFormData(sdkRequest, 'v:', formData);
return formData;
};
Loading
Loading