mailisk 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -101,6 +101,42 @@ var MailiskClient = class {
101
101
  async sendVirtualSms(params) {
102
102
  return (await this.axiosInstance.post("api/sms/virtual", params)).data;
103
103
  }
104
+ /**
105
+ * Create and queue a new outbound email from a namespace.
106
+ *
107
+ * @example
108
+ * Send an outbound email
109
+ * ```typescript
110
+ * const email = await client.sendEmail("mynamespace", {
111
+ * to: ["verified@example.com"],
112
+ * subject: "Hello",
113
+ * text: "Hello from Mailisk",
114
+ * });
115
+ * ```
116
+ */
117
+ async sendEmail(namespace, params) {
118
+ return (await this.axiosInstance.post("api/emails/send", params, {
119
+ params: { namespace }
120
+ })).data;
121
+ }
122
+ /**
123
+ * Get current delivery state for an outbound email.
124
+ */
125
+ async getOutboundEmail(outboundEmailId) {
126
+ return (await this.axiosInstance.get(`api/emails/outbound/${outboundEmailId}`)).data;
127
+ }
128
+ /**
129
+ * Create and queue a reply to an inbound email.
130
+ */
131
+ async replyToEmail(emailId, params) {
132
+ return (await this.axiosInstance.post(`api/emails/${emailId}/reply`, params)).data;
133
+ }
134
+ /**
135
+ * Create and queue a forwarded copy of an inbound email.
136
+ */
137
+ async forwardEmail(emailId, params) {
138
+ return (await this.axiosInstance.post(`api/emails/${emailId}/forward`, params)).data;
139
+ }
104
140
  /**
105
141
  * List saved TOTP devices.
106
142
  *
@@ -240,6 +276,8 @@ var MailiskClient = class {
240
276
  *
241
277
  * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net
242
278
  *
279
+ * @deprecated Use sendEmail(namespace, params) for outbound email. This method remains available for existing Virtual SMTP tests.
280
+ *
243
281
  * @example
244
282
  * For example, sending a test email:
245
283
  * ```typescript
@@ -328,6 +366,8 @@ var MailiskClient = class {
328
366
  }
329
367
  /**
330
368
  * Get the SMTP settings for a namespace.
369
+ *
370
+ * @deprecated Virtual SMTP is deprecated. Use sendEmail(namespace, params) for outbound email instead.
331
371
  */
332
372
  async getSmtpSettings(namespace) {
333
373
  const result = await this.axiosInstance.get(`api/smtp/${namespace}`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/mailisk.ts"],"sourcesContent":["export * from \"./mailisk\";\nexport * from \"./mailisk.interfaces\";\n","import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport {\n CreateBase32SecretKeyTotpDeviceParams,\n CreateCustomTotpDeviceParams,\n CreateOtpAuthUrlTotpDeviceParams,\n CreateTotpDeviceParams,\n GetAttachmentResponse,\n GetTotpOtpParams,\n ListNamespacesResponse,\n ListSmsNumbersResponse,\n ListTotpDevicesParams,\n ListTotpDevicesResponse,\n SearchInboxParams,\n SearchInboxResponse,\n SearchSmsMessagesParams,\n SearchSmsMessagesResponse,\n SendVirtualEmailParams,\n SendVirtualSmsParams,\n SmtpSettings,\n TotpDevice,\n TotpOtpResponse,\n} from \"./mailisk.interfaces\";\nimport nodemailer from \"nodemailer\";\n\nexport class MailiskClient {\n constructor({ apiKey, baseUrl, auth }: { apiKey: string; baseUrl?: string; auth?: AxiosBasicCredentials }) {\n this.axiosInstance = axios.create({\n headers: {\n \"X-Api-Key\": apiKey,\n },\n baseURL: baseUrl || \"https://api.mailisk.com/\",\n auth,\n });\n }\n\n private readonly axiosInstance: AxiosInstance;\n\n /**\n * Search SMS messages sent to a phone number.\n *\n * @example\n * Search for SMS messages sent to a phone number\n * ```typescript\n * const { data: smsMessages } = await client.searchSmsMessages(\"1234567890\");\n * ```\n */\n async searchSmsMessages(\n phoneNumber: string,\n params?: SearchSmsMessagesParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchSmsMessagesResponse> {\n let _params: SearchSmsMessagesParams = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_date === undefined || params?.from_date === null) {\n _params.from_date = new Date(Date.now() - 15 * 60 * 1000).toISOString();\n }\n\n // by default wait for sms\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n const requestParams = {\n ..._params,\n from_date: _params.from_date ?? undefined,\n to_date: _params.to_date ?? undefined,\n };\n\n return (\n await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {\n ..._config,\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * List all SMS phone numbers associated with the current account.\n *\n * @example\n * List all SMS phone numbers\n * ```typescript\n * const { data: smsNumbers } = await client.listSmsNumbers();\n * ```\n */\n async listSmsNumbers(): Promise<ListSmsNumbersResponse> {\n return (await this.axiosInstance.get(\"api/sms/numbers\")).data;\n }\n\n async sendVirtualSms(params: SendVirtualSmsParams): Promise<void> {\n return (await this.axiosInstance.post(\"api/sms/virtual\", params)).data;\n }\n\n /**\n * List saved TOTP devices.\n *\n * @example\n * List saved TOTP devices for an issuer and username\n * ```typescript\n * const { items: devices } = await client.listTotpDevices({\n * issuer: \"GitHub\",\n * username: \"qa@example.com\",\n * });\n * ```\n */\n async listTotpDevices(params?: ListTotpDevicesParams): Promise<ListTotpDevicesResponse> {\n const requestParams: ListTotpDevicesParams = {\n ...params,\n username: params?.username?.trim(),\n issuer: params?.issuer?.trim(),\n };\n\n return (\n await this.axiosInstance.get(\"api/devices\", {\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 shared secret using default TOTP settings.\n *\n * @example\n * Create a saved TOTP device from a shared secret\n * ```typescript\n * const device = await client.createTotpDevice({\n * name: \"GitHub staging\",\n * shared_secret: \"JBSWY3DPEHPK3PXP\",\n * });\n * ```\n */\n async createTotpDevice(params: CreateTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices\", params)).data;\n }\n\n /**\n * Create a saved TOTP device with custom settings.\n *\n * @example\n * Create a saved TOTP device with custom settings\n * ```typescript\n * const device = await client.createCustomTotpDevice({\n * name: \"GitHub staging\",\n * secret: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * digits: 6,\n * period: 30,\n * algorithm: \"SHA1\",\n * });\n * ```\n */\n async createCustomTotpDevice(params: CreateCustomTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/custom\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 secret key.\n *\n * @example\n * Create a saved TOTP device from a Base32 secret key\n * ```typescript\n * const device = await client.createTotpDeviceFromBase32SecretKey({\n * base32_secret_key: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromBase32SecretKey(params: CreateBase32SecretKeyTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/base32-secret-key\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from an otpauth://totp URL.\n *\n * @example\n * Create a saved TOTP device from an otpauth URL\n * ```typescript\n * const device = await client.createTotpDeviceFromOtpAuthUrl({\n * otp_auth_url: \"otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromOtpAuthUrl(params: CreateOtpAuthUrlTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/otpauth-url\", params)).data;\n }\n\n /**\n * Generate a TOTP code from a shared secret without saving a device.\n *\n * @example\n * Generate a TOTP code from a shared secret\n * ```typescript\n * const { code } = await client.getTotpOtpBySharedSecret(\"JBSWY3DPEHPK3PXP\", {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpBySharedSecret(sharedSecret: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n return (await this.axiosInstance.post(\"api/devices/otp\", { shared_secret: sharedSecret, ...params })).data;\n }\n\n /**\n * Generate a TOTP code for a saved device.\n *\n * @example\n * Generate a TOTP code for a saved device\n * ```typescript\n * const { code } = await client.getTotpOtpByDeviceId(device.id, {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpByDeviceId(deviceId: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n const url = `api/devices/${deviceId}/otp`;\n\n return params ? (await this.axiosInstance.get(url, { params })).data : (await this.axiosInstance.get(url)).data;\n }\n\n /**\n * Delete a saved TOTP device.\n *\n * @example\n * Delete a saved TOTP device\n * ```typescript\n * await client.deleteTotpDevice(device.id);\n * ```\n */\n async deleteTotpDevice(deviceId: string): Promise<void> {\n await this.axiosInstance.delete(`api/devices/${deviceId}`);\n }\n\n /**\n * List all namespaces that belong to the current account (API key).\n */\n async listNamespaces(): Promise<ListNamespacesResponse> {\n return (await this.axiosInstance.get(\"api/namespaces\")).data;\n }\n\n /**\n * Send an email using the Virtual SMTP.\n *\n * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net\n *\n * @example\n * For example, sending a test email:\n * ```typescript\n * client.sendVirtualEmail(namespace, {\n * from: \"test@example.com\",\n * to: `john@${namespace}.mailisk.net`,\n * subject: \"This is a test\",\n * text: \"Testing\",\n * });\n * ```\n */\n async sendVirtualEmail(namespace: string, params: SendVirtualEmailParams): Promise<void> {\n const smtpSettings = await this.getSmtpSettings(namespace);\n\n const transport = nodemailer.createTransport({\n host: smtpSettings.data.host,\n port: smtpSettings.data.port,\n secure: false,\n auth: {\n user: smtpSettings.data.username,\n pass: smtpSettings.data.password,\n },\n });\n\n const { from, to, subject, text, html, headers, attachments } = params;\n\n await transport.sendMail({\n from,\n to,\n subject,\n text,\n html,\n headers,\n attachments,\n });\n\n transport.close();\n }\n\n /**\n * Search inbox of a namespace.\n *\n * By default, this calls the api using the `wait` flag. This means the call won't timeout until at least one email is received or 5 minutes pass.\n * It also uses a default `from_timestamp` of **current timestamp - 15 minutes**. This means that older emails will be ignored.\n *\n * Both of these settings can be overriden by passing them in the `params` object.\n *\n * @example\n * Get the latest emails\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace);\n * ```\n *\n * @example\n * Get the latest emails for a specific email address\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace, {\n * to_addr_prefix: 'john@mynamespace.mailisk.net'\n * });\n * ```\n *\n * @example\n * Get the last 20 emails in the namespace\n * ```typescript\n * const { data: emails } = await mailisk.searchInbox(namespace, {\n * wait: false,\n * from_timestamp: 0,\n * limit: 20\n * });\n * ```\n */\n async searchInbox(\n namespace: string,\n params?: SearchInboxParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchInboxResponse> {\n let _params = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_timestamp === undefined || params?.from_timestamp === null) {\n _params.from_timestamp = Math.floor(new Date().getTime() / 1000) - 15 * 60;\n }\n\n // by default wait for email\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n return (\n await this.axiosInstance.get(`api/emails/${namespace}/inbox`, {\n ..._config,\n params: _params,\n })\n ).data;\n }\n\n /**\n * Get the SMTP settings for a namespace.\n */\n async getSmtpSettings(namespace: string): Promise<SmtpSettings> {\n const result = await this.axiosInstance.get(`api/smtp/${namespace}`);\n return result.data;\n }\n\n async getAttachment(attachmentId: string): Promise<GetAttachmentResponse> {\n const result = await this.axiosInstance.get(`api/attachments/${attachmentId}`);\n return result.data;\n }\n\n /**\n * Download an attachment from an attachment ID.\n *\n * @example\n * Download an attachment from an email\n * ```typescript\n * const attachment = email.attachments[0];\n * const attachmentBuffer = await client.downloadAttachment(attachment.id);\n *\n * // save to file\n * fs.writeFileSync(attachment.filename, attachmentBuffer);\n * ```\n */\n async downloadAttachment(attachmentId: string): Promise<Buffer> {\n const result = await this.getAttachment(attachmentId);\n\n const response = await axios.get(result.data.download_url, { responseType: \"arraybuffer\" });\n return Buffer.from(response.data);\n }\n}\n"],"mappings":"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","names":["axios","nodemailer"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/mailisk.ts"],"sourcesContent":["export * from \"./mailisk\";\nexport * from \"./mailisk.interfaces\";\n","import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport {\n CreateBase32SecretKeyTotpDeviceParams,\n CreateCustomTotpDeviceParams,\n CreateOtpAuthUrlTotpDeviceParams,\n CreateTotpDeviceParams,\n GetAttachmentResponse,\n GetTotpOtpParams,\n ListNamespacesResponse,\n ListSmsNumbersResponse,\n ListTotpDevicesParams,\n ListTotpDevicesResponse,\n ForwardEmailParams,\n OutboundEmailDetailResponse,\n OutboundEmailResponse,\n ReplyToEmailParams,\n SearchInboxParams,\n SearchInboxResponse,\n SearchSmsMessagesParams,\n SearchSmsMessagesResponse,\n SendEmailParams,\n SendVirtualEmailParams,\n SendVirtualSmsParams,\n SmtpSettings,\n TotpDevice,\n TotpOtpResponse,\n} from \"./mailisk.interfaces\";\nimport nodemailer from \"nodemailer\";\n\nexport class MailiskClient {\n constructor({ apiKey, baseUrl, auth }: { apiKey: string; baseUrl?: string; auth?: AxiosBasicCredentials }) {\n this.axiosInstance = axios.create({\n headers: {\n \"X-Api-Key\": apiKey,\n },\n baseURL: baseUrl || \"https://api.mailisk.com/\",\n auth,\n });\n }\n\n private readonly axiosInstance: AxiosInstance;\n\n /**\n * Search SMS messages sent to a phone number.\n *\n * @example\n * Search for SMS messages sent to a phone number\n * ```typescript\n * const { data: smsMessages } = await client.searchSmsMessages(\"1234567890\");\n * ```\n */\n async searchSmsMessages(\n phoneNumber: string,\n params?: SearchSmsMessagesParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchSmsMessagesResponse> {\n let _params: SearchSmsMessagesParams = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_date === undefined || params?.from_date === null) {\n _params.from_date = new Date(Date.now() - 15 * 60 * 1000).toISOString();\n }\n\n // by default wait for sms\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n const requestParams = {\n ..._params,\n from_date: _params.from_date ?? undefined,\n to_date: _params.to_date ?? undefined,\n };\n\n return (\n await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {\n ..._config,\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * List all SMS phone numbers associated with the current account.\n *\n * @example\n * List all SMS phone numbers\n * ```typescript\n * const { data: smsNumbers } = await client.listSmsNumbers();\n * ```\n */\n async listSmsNumbers(): Promise<ListSmsNumbersResponse> {\n return (await this.axiosInstance.get(\"api/sms/numbers\")).data;\n }\n\n async sendVirtualSms(params: SendVirtualSmsParams): Promise<void> {\n return (await this.axiosInstance.post(\"api/sms/virtual\", params)).data;\n }\n\n /**\n * Create and queue a new outbound email from a namespace.\n *\n * @example\n * Send an outbound email\n * ```typescript\n * const email = await client.sendEmail(\"mynamespace\", {\n * to: [\"verified@example.com\"],\n * subject: \"Hello\",\n * text: \"Hello from Mailisk\",\n * });\n * ```\n */\n async sendEmail(namespace: string, params: SendEmailParams): Promise<OutboundEmailResponse> {\n return (\n await this.axiosInstance.post(\"api/emails/send\", params, {\n params: { namespace },\n })\n ).data;\n }\n\n /**\n * Get current delivery state for an outbound email.\n */\n async getOutboundEmail(outboundEmailId: string): Promise<OutboundEmailDetailResponse> {\n return (await this.axiosInstance.get(`api/emails/outbound/${outboundEmailId}`)).data;\n }\n\n /**\n * Create and queue a reply to an inbound email.\n */\n async replyToEmail(emailId: string, params: ReplyToEmailParams): Promise<OutboundEmailResponse> {\n return (await this.axiosInstance.post(`api/emails/${emailId}/reply`, params)).data;\n }\n\n /**\n * Create and queue a forwarded copy of an inbound email.\n */\n async forwardEmail(emailId: string, params: ForwardEmailParams): Promise<OutboundEmailResponse> {\n return (await this.axiosInstance.post(`api/emails/${emailId}/forward`, params)).data;\n }\n\n /**\n * List saved TOTP devices.\n *\n * @example\n * List saved TOTP devices for an issuer and username\n * ```typescript\n * const { items: devices } = await client.listTotpDevices({\n * issuer: \"GitHub\",\n * username: \"qa@example.com\",\n * });\n * ```\n */\n async listTotpDevices(params?: ListTotpDevicesParams): Promise<ListTotpDevicesResponse> {\n const requestParams: ListTotpDevicesParams = {\n ...params,\n username: params?.username?.trim(),\n issuer: params?.issuer?.trim(),\n };\n\n return (\n await this.axiosInstance.get(\"api/devices\", {\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 shared secret using default TOTP settings.\n *\n * @example\n * Create a saved TOTP device from a shared secret\n * ```typescript\n * const device = await client.createTotpDevice({\n * name: \"GitHub staging\",\n * shared_secret: \"JBSWY3DPEHPK3PXP\",\n * });\n * ```\n */\n async createTotpDevice(params: CreateTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices\", params)).data;\n }\n\n /**\n * Create a saved TOTP device with custom settings.\n *\n * @example\n * Create a saved TOTP device with custom settings\n * ```typescript\n * const device = await client.createCustomTotpDevice({\n * name: \"GitHub staging\",\n * secret: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * digits: 6,\n * period: 30,\n * algorithm: \"SHA1\",\n * });\n * ```\n */\n async createCustomTotpDevice(params: CreateCustomTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/custom\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 secret key.\n *\n * @example\n * Create a saved TOTP device from a Base32 secret key\n * ```typescript\n * const device = await client.createTotpDeviceFromBase32SecretKey({\n * base32_secret_key: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromBase32SecretKey(params: CreateBase32SecretKeyTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/base32-secret-key\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from an otpauth://totp URL.\n *\n * @example\n * Create a saved TOTP device from an otpauth URL\n * ```typescript\n * const device = await client.createTotpDeviceFromOtpAuthUrl({\n * otp_auth_url: \"otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromOtpAuthUrl(params: CreateOtpAuthUrlTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/otpauth-url\", params)).data;\n }\n\n /**\n * Generate a TOTP code from a shared secret without saving a device.\n *\n * @example\n * Generate a TOTP code from a shared secret\n * ```typescript\n * const { code } = await client.getTotpOtpBySharedSecret(\"JBSWY3DPEHPK3PXP\", {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpBySharedSecret(sharedSecret: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n return (await this.axiosInstance.post(\"api/devices/otp\", { shared_secret: sharedSecret, ...params })).data;\n }\n\n /**\n * Generate a TOTP code for a saved device.\n *\n * @example\n * Generate a TOTP code for a saved device\n * ```typescript\n * const { code } = await client.getTotpOtpByDeviceId(device.id, {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpByDeviceId(deviceId: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n const url = `api/devices/${deviceId}/otp`;\n\n return params ? (await this.axiosInstance.get(url, { params })).data : (await this.axiosInstance.get(url)).data;\n }\n\n /**\n * Delete a saved TOTP device.\n *\n * @example\n * Delete a saved TOTP device\n * ```typescript\n * await client.deleteTotpDevice(device.id);\n * ```\n */\n async deleteTotpDevice(deviceId: string): Promise<void> {\n await this.axiosInstance.delete(`api/devices/${deviceId}`);\n }\n\n /**\n * List all namespaces that belong to the current account (API key).\n */\n async listNamespaces(): Promise<ListNamespacesResponse> {\n return (await this.axiosInstance.get(\"api/namespaces\")).data;\n }\n\n /**\n * Send an email using the Virtual SMTP.\n *\n * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net\n *\n * @deprecated Use sendEmail(namespace, params) for outbound email. This method remains available for existing Virtual SMTP tests.\n *\n * @example\n * For example, sending a test email:\n * ```typescript\n * client.sendVirtualEmail(namespace, {\n * from: \"test@example.com\",\n * to: `john@${namespace}.mailisk.net`,\n * subject: \"This is a test\",\n * text: \"Testing\",\n * });\n * ```\n */\n async sendVirtualEmail(namespace: string, params: SendVirtualEmailParams): Promise<void> {\n const smtpSettings = await this.getSmtpSettings(namespace);\n\n const transport = nodemailer.createTransport({\n host: smtpSettings.data.host,\n port: smtpSettings.data.port,\n secure: false,\n auth: {\n user: smtpSettings.data.username,\n pass: smtpSettings.data.password,\n },\n });\n\n const { from, to, subject, text, html, headers, attachments } = params;\n\n await transport.sendMail({\n from,\n to,\n subject,\n text,\n html,\n headers,\n attachments,\n });\n\n transport.close();\n }\n\n /**\n * Search inbox of a namespace.\n *\n * By default, this calls the api using the `wait` flag. This means the call won't timeout until at least one email is received or 5 minutes pass.\n * It also uses a default `from_timestamp` of **current timestamp - 15 minutes**. This means that older emails will be ignored.\n *\n * Both of these settings can be overriden by passing them in the `params` object.\n *\n * @example\n * Get the latest emails\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace);\n * ```\n *\n * @example\n * Get the latest emails for a specific email address\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace, {\n * to_addr_prefix: 'john@mynamespace.mailisk.net'\n * });\n * ```\n *\n * @example\n * Get the last 20 emails in the namespace\n * ```typescript\n * const { data: emails } = await mailisk.searchInbox(namespace, {\n * wait: false,\n * from_timestamp: 0,\n * limit: 20\n * });\n * ```\n */\n async searchInbox(\n namespace: string,\n params?: SearchInboxParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchInboxResponse> {\n let _params = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_timestamp === undefined || params?.from_timestamp === null) {\n _params.from_timestamp = Math.floor(new Date().getTime() / 1000) - 15 * 60;\n }\n\n // by default wait for email\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n return (\n await this.axiosInstance.get(`api/emails/${namespace}/inbox`, {\n ..._config,\n params: _params,\n })\n ).data;\n }\n\n /**\n * Get the SMTP settings for a namespace.\n *\n * @deprecated Virtual SMTP is deprecated. Use sendEmail(namespace, params) for outbound email instead.\n */\n async getSmtpSettings(namespace: string): Promise<SmtpSettings> {\n const result = await this.axiosInstance.get(`api/smtp/${namespace}`);\n return result.data;\n }\n\n async getAttachment(attachmentId: string): Promise<GetAttachmentResponse> {\n const result = await this.axiosInstance.get(`api/attachments/${attachmentId}`);\n return result.data;\n }\n\n /**\n * Download an attachment from an attachment ID.\n *\n * @example\n * Download an attachment from an email\n * ```typescript\n * const attachment = email.attachments[0];\n * const attachmentBuffer = await client.downloadAttachment(attachment.id);\n *\n * // save to file\n * fs.writeFileSync(attachment.filename, attachmentBuffer);\n * ```\n */\n async downloadAttachment(attachmentId: string): Promise<Buffer> {\n const result = await this.getAttachment(attachmentId);\n\n const response = await axios.get(result.data.download_url, { responseType: \"arraybuffer\" });\n return Buffer.from(response.data);\n }\n}\n"],"mappings":"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","names":["axios","nodemailer"]}
package/dist/index.mjs CHANGED
@@ -67,6 +67,42 @@ var MailiskClient = class {
67
67
  async sendVirtualSms(params) {
68
68
  return (await this.axiosInstance.post("api/sms/virtual", params)).data;
69
69
  }
70
+ /**
71
+ * Create and queue a new outbound email from a namespace.
72
+ *
73
+ * @example
74
+ * Send an outbound email
75
+ * ```typescript
76
+ * const email = await client.sendEmail("mynamespace", {
77
+ * to: ["verified@example.com"],
78
+ * subject: "Hello",
79
+ * text: "Hello from Mailisk",
80
+ * });
81
+ * ```
82
+ */
83
+ async sendEmail(namespace, params) {
84
+ return (await this.axiosInstance.post("api/emails/send", params, {
85
+ params: { namespace }
86
+ })).data;
87
+ }
88
+ /**
89
+ * Get current delivery state for an outbound email.
90
+ */
91
+ async getOutboundEmail(outboundEmailId) {
92
+ return (await this.axiosInstance.get(`api/emails/outbound/${outboundEmailId}`)).data;
93
+ }
94
+ /**
95
+ * Create and queue a reply to an inbound email.
96
+ */
97
+ async replyToEmail(emailId, params) {
98
+ return (await this.axiosInstance.post(`api/emails/${emailId}/reply`, params)).data;
99
+ }
100
+ /**
101
+ * Create and queue a forwarded copy of an inbound email.
102
+ */
103
+ async forwardEmail(emailId, params) {
104
+ return (await this.axiosInstance.post(`api/emails/${emailId}/forward`, params)).data;
105
+ }
70
106
  /**
71
107
  * List saved TOTP devices.
72
108
  *
@@ -206,6 +242,8 @@ var MailiskClient = class {
206
242
  *
207
243
  * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net
208
244
  *
245
+ * @deprecated Use sendEmail(namespace, params) for outbound email. This method remains available for existing Virtual SMTP tests.
246
+ *
209
247
  * @example
210
248
  * For example, sending a test email:
211
249
  * ```typescript
@@ -294,6 +332,8 @@ var MailiskClient = class {
294
332
  }
295
333
  /**
296
334
  * Get the SMTP settings for a namespace.
335
+ *
336
+ * @deprecated Virtual SMTP is deprecated. Use sendEmail(namespace, params) for outbound email instead.
297
337
  */
298
338
  async getSmtpSettings(namespace) {
299
339
  const result = await this.axiosInstance.get(`api/smtp/${namespace}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mailisk.ts"],"sourcesContent":["import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport {\n CreateBase32SecretKeyTotpDeviceParams,\n CreateCustomTotpDeviceParams,\n CreateOtpAuthUrlTotpDeviceParams,\n CreateTotpDeviceParams,\n GetAttachmentResponse,\n GetTotpOtpParams,\n ListNamespacesResponse,\n ListSmsNumbersResponse,\n ListTotpDevicesParams,\n ListTotpDevicesResponse,\n SearchInboxParams,\n SearchInboxResponse,\n SearchSmsMessagesParams,\n SearchSmsMessagesResponse,\n SendVirtualEmailParams,\n SendVirtualSmsParams,\n SmtpSettings,\n TotpDevice,\n TotpOtpResponse,\n} from \"./mailisk.interfaces\";\nimport nodemailer from \"nodemailer\";\n\nexport class MailiskClient {\n constructor({ apiKey, baseUrl, auth }: { apiKey: string; baseUrl?: string; auth?: AxiosBasicCredentials }) {\n this.axiosInstance = axios.create({\n headers: {\n \"X-Api-Key\": apiKey,\n },\n baseURL: baseUrl || \"https://api.mailisk.com/\",\n auth,\n });\n }\n\n private readonly axiosInstance: AxiosInstance;\n\n /**\n * Search SMS messages sent to a phone number.\n *\n * @example\n * Search for SMS messages sent to a phone number\n * ```typescript\n * const { data: smsMessages } = await client.searchSmsMessages(\"1234567890\");\n * ```\n */\n async searchSmsMessages(\n phoneNumber: string,\n params?: SearchSmsMessagesParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchSmsMessagesResponse> {\n let _params: SearchSmsMessagesParams = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_date === undefined || params?.from_date === null) {\n _params.from_date = new Date(Date.now() - 15 * 60 * 1000).toISOString();\n }\n\n // by default wait for sms\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n const requestParams = {\n ..._params,\n from_date: _params.from_date ?? undefined,\n to_date: _params.to_date ?? undefined,\n };\n\n return (\n await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {\n ..._config,\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * List all SMS phone numbers associated with the current account.\n *\n * @example\n * List all SMS phone numbers\n * ```typescript\n * const { data: smsNumbers } = await client.listSmsNumbers();\n * ```\n */\n async listSmsNumbers(): Promise<ListSmsNumbersResponse> {\n return (await this.axiosInstance.get(\"api/sms/numbers\")).data;\n }\n\n async sendVirtualSms(params: SendVirtualSmsParams): Promise<void> {\n return (await this.axiosInstance.post(\"api/sms/virtual\", params)).data;\n }\n\n /**\n * List saved TOTP devices.\n *\n * @example\n * List saved TOTP devices for an issuer and username\n * ```typescript\n * const { items: devices } = await client.listTotpDevices({\n * issuer: \"GitHub\",\n * username: \"qa@example.com\",\n * });\n * ```\n */\n async listTotpDevices(params?: ListTotpDevicesParams): Promise<ListTotpDevicesResponse> {\n const requestParams: ListTotpDevicesParams = {\n ...params,\n username: params?.username?.trim(),\n issuer: params?.issuer?.trim(),\n };\n\n return (\n await this.axiosInstance.get(\"api/devices\", {\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 shared secret using default TOTP settings.\n *\n * @example\n * Create a saved TOTP device from a shared secret\n * ```typescript\n * const device = await client.createTotpDevice({\n * name: \"GitHub staging\",\n * shared_secret: \"JBSWY3DPEHPK3PXP\",\n * });\n * ```\n */\n async createTotpDevice(params: CreateTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices\", params)).data;\n }\n\n /**\n * Create a saved TOTP device with custom settings.\n *\n * @example\n * Create a saved TOTP device with custom settings\n * ```typescript\n * const device = await client.createCustomTotpDevice({\n * name: \"GitHub staging\",\n * secret: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * digits: 6,\n * period: 30,\n * algorithm: \"SHA1\",\n * });\n * ```\n */\n async createCustomTotpDevice(params: CreateCustomTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/custom\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 secret key.\n *\n * @example\n * Create a saved TOTP device from a Base32 secret key\n * ```typescript\n * const device = await client.createTotpDeviceFromBase32SecretKey({\n * base32_secret_key: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromBase32SecretKey(params: CreateBase32SecretKeyTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/base32-secret-key\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from an otpauth://totp URL.\n *\n * @example\n * Create a saved TOTP device from an otpauth URL\n * ```typescript\n * const device = await client.createTotpDeviceFromOtpAuthUrl({\n * otp_auth_url: \"otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromOtpAuthUrl(params: CreateOtpAuthUrlTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/otpauth-url\", params)).data;\n }\n\n /**\n * Generate a TOTP code from a shared secret without saving a device.\n *\n * @example\n * Generate a TOTP code from a shared secret\n * ```typescript\n * const { code } = await client.getTotpOtpBySharedSecret(\"JBSWY3DPEHPK3PXP\", {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpBySharedSecret(sharedSecret: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n return (await this.axiosInstance.post(\"api/devices/otp\", { shared_secret: sharedSecret, ...params })).data;\n }\n\n /**\n * Generate a TOTP code for a saved device.\n *\n * @example\n * Generate a TOTP code for a saved device\n * ```typescript\n * const { code } = await client.getTotpOtpByDeviceId(device.id, {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpByDeviceId(deviceId: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n const url = `api/devices/${deviceId}/otp`;\n\n return params ? (await this.axiosInstance.get(url, { params })).data : (await this.axiosInstance.get(url)).data;\n }\n\n /**\n * Delete a saved TOTP device.\n *\n * @example\n * Delete a saved TOTP device\n * ```typescript\n * await client.deleteTotpDevice(device.id);\n * ```\n */\n async deleteTotpDevice(deviceId: string): Promise<void> {\n await this.axiosInstance.delete(`api/devices/${deviceId}`);\n }\n\n /**\n * List all namespaces that belong to the current account (API key).\n */\n async listNamespaces(): Promise<ListNamespacesResponse> {\n return (await this.axiosInstance.get(\"api/namespaces\")).data;\n }\n\n /**\n * Send an email using the Virtual SMTP.\n *\n * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net\n *\n * @example\n * For example, sending a test email:\n * ```typescript\n * client.sendVirtualEmail(namespace, {\n * from: \"test@example.com\",\n * to: `john@${namespace}.mailisk.net`,\n * subject: \"This is a test\",\n * text: \"Testing\",\n * });\n * ```\n */\n async sendVirtualEmail(namespace: string, params: SendVirtualEmailParams): Promise<void> {\n const smtpSettings = await this.getSmtpSettings(namespace);\n\n const transport = nodemailer.createTransport({\n host: smtpSettings.data.host,\n port: smtpSettings.data.port,\n secure: false,\n auth: {\n user: smtpSettings.data.username,\n pass: smtpSettings.data.password,\n },\n });\n\n const { from, to, subject, text, html, headers, attachments } = params;\n\n await transport.sendMail({\n from,\n to,\n subject,\n text,\n html,\n headers,\n attachments,\n });\n\n transport.close();\n }\n\n /**\n * Search inbox of a namespace.\n *\n * By default, this calls the api using the `wait` flag. This means the call won't timeout until at least one email is received or 5 minutes pass.\n * It also uses a default `from_timestamp` of **current timestamp - 15 minutes**. This means that older emails will be ignored.\n *\n * Both of these settings can be overriden by passing them in the `params` object.\n *\n * @example\n * Get the latest emails\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace);\n * ```\n *\n * @example\n * Get the latest emails for a specific email address\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace, {\n * to_addr_prefix: 'john@mynamespace.mailisk.net'\n * });\n * ```\n *\n * @example\n * Get the last 20 emails in the namespace\n * ```typescript\n * const { data: emails } = await mailisk.searchInbox(namespace, {\n * wait: false,\n * from_timestamp: 0,\n * limit: 20\n * });\n * ```\n */\n async searchInbox(\n namespace: string,\n params?: SearchInboxParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchInboxResponse> {\n let _params = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_timestamp === undefined || params?.from_timestamp === null) {\n _params.from_timestamp = Math.floor(new Date().getTime() / 1000) - 15 * 60;\n }\n\n // by default wait for email\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n return (\n await this.axiosInstance.get(`api/emails/${namespace}/inbox`, {\n ..._config,\n params: _params,\n })\n ).data;\n }\n\n /**\n * Get the SMTP settings for a namespace.\n */\n async getSmtpSettings(namespace: string): Promise<SmtpSettings> {\n const result = await this.axiosInstance.get(`api/smtp/${namespace}`);\n return result.data;\n }\n\n async getAttachment(attachmentId: string): Promise<GetAttachmentResponse> {\n const result = await this.axiosInstance.get(`api/attachments/${attachmentId}`);\n return result.data;\n }\n\n /**\n * Download an attachment from an attachment ID.\n *\n * @example\n * Download an attachment from an email\n * ```typescript\n * const attachment = email.attachments[0];\n * const attachmentBuffer = await client.downloadAttachment(attachment.id);\n *\n * // save to file\n * fs.writeFileSync(attachment.filename, attachmentBuffer);\n * ```\n */\n async downloadAttachment(attachmentId: string): Promise<Buffer> {\n const result = await this.getAttachment(attachmentId);\n\n const response = await axios.get(result.data.download_url, { responseType: \"arraybuffer\" });\n return Buffer.from(response.data);\n }\n}\n"],"mappings":";;;;AAAA,OAAO,WAAyE;AAsBhF,OAAO,gBAAgB;AAEhB,IAAM,gBAAN,MAAoB;AAAA,EAxB3B,OAwB2B;AAAA;AAAA;AAAA,EACzB,YAAY,EAAE,QAAQ,SAAS,KAAK,GAAuE;AACzG,SAAK,gBAAgB,MAAM,OAAO;AAAA,MAChC,SAAS;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA,SAAS,WAAW;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWjB,MAAM,kBACJ,aACA,QACA,QACoC;AACpC,QAAI,UAAmC,EAAE,GAAG,OAAO;AAGnD,QAAI,QAAQ,cAAc,UAAa,QAAQ,cAAc,MAAM;AACjE,cAAQ,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,GAAI,EAAE,YAAY;AAAA,IACxE;AAGA,QAAI,QAAQ,SAAS,OAAO;AAC1B,cAAQ,OAAO;AAAA,IACjB;AAEA,QAAI,UAAU,EAAE,GAAG,OAAO;AAE1B,QAAI,QAAQ,iBAAiB,QAAW;AACtC,cAAQ,eAAe;AAAA,IACzB;AAGA,QAAI,QAAQ,QAAQ,QAAQ,YAAY,QAAW;AACjD,cAAQ,UAAU,MAAO,KAAK;AAAA,IAChC;AAEA,UAAM,gBAAgB;AAAA,MACpB,GAAG;AAAA,MACH,WAAW,QAAQ,aAAa;AAAA,MAChC,SAAS,QAAQ,WAAW;AAAA,IAC9B;AAEA,YACE,MAAM,KAAK,cAAc,IAAI,WAAW,WAAW,aAAa;AAAA,MAC9D,GAAG;AAAA,MACH,QAAQ;AAAA,IACV,CAAC,GACD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,iBAAkD;AACtD,YAAQ,MAAM,KAAK,cAAc,IAAI,iBAAiB,GAAG;AAAA,EAC3D;AAAA,EAEA,MAAM,eAAe,QAA6C;AAChE,YAAQ,MAAM,KAAK,cAAc,KAAK,mBAAmB,MAAM,GAAG;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,gBAAgB,QAAkE;AACtF,UAAM,gBAAuC;AAAA,MAC3C,GAAG;AAAA,MACH,UAAU,QAAQ,UAAU,KAAK;AAAA,MACjC,QAAQ,QAAQ,QAAQ,KAAK;AAAA,IAC/B;AAEA,YACE,MAAM,KAAK,cAAc,IAAI,eAAe;AAAA,MAC1C,QAAQ;AAAA,IACV,CAAC,GACD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,iBAAiB,QAAqD;AAC1E,YAAQ,MAAM,KAAK,cAAc,KAAK,eAAe,MAAM,GAAG;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,uBAAuB,QAA2D;AACtF,YAAQ,MAAM,KAAK,cAAc,KAAK,sBAAsB,MAAM,GAAG;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,oCAAoC,QAAoE;AAC5G,YAAQ,MAAM,KAAK,cAAc,KAAK,iCAAiC,MAAM,GAAG;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,+BAA+B,QAA+D;AAClG,YAAQ,MAAM,KAAK,cAAc,KAAK,2BAA2B,MAAM,GAAG;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,yBAAyB,cAAsB,QAAqD;AACxG,YAAQ,MAAM,KAAK,cAAc,KAAK,mBAAmB,EAAE,eAAe,cAAc,GAAG,OAAO,CAAC,GAAG;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,qBAAqB,UAAkB,QAAqD;AAChG,UAAM,MAAM,eAAe,QAAQ;AAEnC,WAAO,UAAU,MAAM,KAAK,cAAc,IAAI,KAAK,EAAE,OAAO,CAAC,GAAG,QAAQ,MAAM,KAAK,cAAc,IAAI,GAAG,GAAG;AAAA,EAC7G;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,iBAAiB,UAAiC;AACtD,UAAM,KAAK,cAAc,OAAO,eAAe,QAAQ,EAAE;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAkD;AACtD,YAAQ,MAAM,KAAK,cAAc,IAAI,gBAAgB,GAAG;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,iBAAiB,WAAmB,QAA+C;AACvF,UAAM,eAAe,MAAM,KAAK,gBAAgB,SAAS;AAEzD,UAAM,YAAY,WAAW,gBAAgB;AAAA,MAC3C,MAAM,aAAa,KAAK;AAAA,MACxB,MAAM,aAAa,KAAK;AAAA,MACxB,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ,MAAM,aAAa,KAAK;AAAA,QACxB,MAAM,aAAa,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,UAAM,EAAE,MAAM,IAAI,SAAS,MAAM,MAAM,SAAS,YAAY,IAAI;AAEhE,UAAM,UAAU,SAAS;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,cAAU,MAAM;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,MAAM,YACJ,WACA,QACA,QAC8B;AAC9B,QAAI,UAAU,EAAE,GAAG,OAAO;AAG1B,QAAI,QAAQ,mBAAmB,UAAa,QAAQ,mBAAmB,MAAM;AAC3E,cAAQ,iBAAiB,KAAK,OAAM,oBAAI,KAAK,GAAE,QAAQ,IAAI,GAAI,IAAI,KAAK;AAAA,IAC1E;AAGA,QAAI,QAAQ,SAAS,OAAO;AAC1B,cAAQ,OAAO;AAAA,IACjB;AAEA,QAAI,UAAU,EAAE,GAAG,OAAO;AAE1B,QAAI,QAAQ,iBAAiB,QAAW;AACtC,cAAQ,eAAe;AAAA,IACzB;AAGA,QAAI,QAAQ,QAAQ,QAAQ,YAAY,QAAW;AACjD,cAAQ,UAAU,MAAO,KAAK;AAAA,IAChC;AAEA,YACE,MAAM,KAAK,cAAc,IAAI,cAAc,SAAS,UAAU;AAAA,MAC5D,GAAG;AAAA,MACH,QAAQ;AAAA,IACV,CAAC,GACD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,WAA0C;AAC9D,UAAM,SAAS,MAAM,KAAK,cAAc,IAAI,YAAY,SAAS,EAAE;AACnE,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAM,cAAc,cAAsD;AACxE,UAAM,SAAS,MAAM,KAAK,cAAc,IAAI,mBAAmB,YAAY,EAAE;AAC7E,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,mBAAmB,cAAuC;AAC9D,UAAM,SAAS,MAAM,KAAK,cAAc,YAAY;AAEpD,UAAM,WAAW,MAAM,MAAM,IAAI,OAAO,KAAK,cAAc,EAAE,cAAc,cAAc,CAAC;AAC1F,WAAO,OAAO,KAAK,SAAS,IAAI;AAAA,EAClC;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/mailisk.ts"],"sourcesContent":["import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport {\n CreateBase32SecretKeyTotpDeviceParams,\n CreateCustomTotpDeviceParams,\n CreateOtpAuthUrlTotpDeviceParams,\n CreateTotpDeviceParams,\n GetAttachmentResponse,\n GetTotpOtpParams,\n ListNamespacesResponse,\n ListSmsNumbersResponse,\n ListTotpDevicesParams,\n ListTotpDevicesResponse,\n ForwardEmailParams,\n OutboundEmailDetailResponse,\n OutboundEmailResponse,\n ReplyToEmailParams,\n SearchInboxParams,\n SearchInboxResponse,\n SearchSmsMessagesParams,\n SearchSmsMessagesResponse,\n SendEmailParams,\n SendVirtualEmailParams,\n SendVirtualSmsParams,\n SmtpSettings,\n TotpDevice,\n TotpOtpResponse,\n} from \"./mailisk.interfaces\";\nimport nodemailer from \"nodemailer\";\n\nexport class MailiskClient {\n constructor({ apiKey, baseUrl, auth }: { apiKey: string; baseUrl?: string; auth?: AxiosBasicCredentials }) {\n this.axiosInstance = axios.create({\n headers: {\n \"X-Api-Key\": apiKey,\n },\n baseURL: baseUrl || \"https://api.mailisk.com/\",\n auth,\n });\n }\n\n private readonly axiosInstance: AxiosInstance;\n\n /**\n * Search SMS messages sent to a phone number.\n *\n * @example\n * Search for SMS messages sent to a phone number\n * ```typescript\n * const { data: smsMessages } = await client.searchSmsMessages(\"1234567890\");\n * ```\n */\n async searchSmsMessages(\n phoneNumber: string,\n params?: SearchSmsMessagesParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchSmsMessagesResponse> {\n let _params: SearchSmsMessagesParams = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_date === undefined || params?.from_date === null) {\n _params.from_date = new Date(Date.now() - 15 * 60 * 1000).toISOString();\n }\n\n // by default wait for sms\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n const requestParams = {\n ..._params,\n from_date: _params.from_date ?? undefined,\n to_date: _params.to_date ?? undefined,\n };\n\n return (\n await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {\n ..._config,\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * List all SMS phone numbers associated with the current account.\n *\n * @example\n * List all SMS phone numbers\n * ```typescript\n * const { data: smsNumbers } = await client.listSmsNumbers();\n * ```\n */\n async listSmsNumbers(): Promise<ListSmsNumbersResponse> {\n return (await this.axiosInstance.get(\"api/sms/numbers\")).data;\n }\n\n async sendVirtualSms(params: SendVirtualSmsParams): Promise<void> {\n return (await this.axiosInstance.post(\"api/sms/virtual\", params)).data;\n }\n\n /**\n * Create and queue a new outbound email from a namespace.\n *\n * @example\n * Send an outbound email\n * ```typescript\n * const email = await client.sendEmail(\"mynamespace\", {\n * to: [\"verified@example.com\"],\n * subject: \"Hello\",\n * text: \"Hello from Mailisk\",\n * });\n * ```\n */\n async sendEmail(namespace: string, params: SendEmailParams): Promise<OutboundEmailResponse> {\n return (\n await this.axiosInstance.post(\"api/emails/send\", params, {\n params: { namespace },\n })\n ).data;\n }\n\n /**\n * Get current delivery state for an outbound email.\n */\n async getOutboundEmail(outboundEmailId: string): Promise<OutboundEmailDetailResponse> {\n return (await this.axiosInstance.get(`api/emails/outbound/${outboundEmailId}`)).data;\n }\n\n /**\n * Create and queue a reply to an inbound email.\n */\n async replyToEmail(emailId: string, params: ReplyToEmailParams): Promise<OutboundEmailResponse> {\n return (await this.axiosInstance.post(`api/emails/${emailId}/reply`, params)).data;\n }\n\n /**\n * Create and queue a forwarded copy of an inbound email.\n */\n async forwardEmail(emailId: string, params: ForwardEmailParams): Promise<OutboundEmailResponse> {\n return (await this.axiosInstance.post(`api/emails/${emailId}/forward`, params)).data;\n }\n\n /**\n * List saved TOTP devices.\n *\n * @example\n * List saved TOTP devices for an issuer and username\n * ```typescript\n * const { items: devices } = await client.listTotpDevices({\n * issuer: \"GitHub\",\n * username: \"qa@example.com\",\n * });\n * ```\n */\n async listTotpDevices(params?: ListTotpDevicesParams): Promise<ListTotpDevicesResponse> {\n const requestParams: ListTotpDevicesParams = {\n ...params,\n username: params?.username?.trim(),\n issuer: params?.issuer?.trim(),\n };\n\n return (\n await this.axiosInstance.get(\"api/devices\", {\n params: requestParams,\n })\n ).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 shared secret using default TOTP settings.\n *\n * @example\n * Create a saved TOTP device from a shared secret\n * ```typescript\n * const device = await client.createTotpDevice({\n * name: \"GitHub staging\",\n * shared_secret: \"JBSWY3DPEHPK3PXP\",\n * });\n * ```\n */\n async createTotpDevice(params: CreateTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices\", params)).data;\n }\n\n /**\n * Create a saved TOTP device with custom settings.\n *\n * @example\n * Create a saved TOTP device with custom settings\n * ```typescript\n * const device = await client.createCustomTotpDevice({\n * name: \"GitHub staging\",\n * secret: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * digits: 6,\n * period: 30,\n * algorithm: \"SHA1\",\n * });\n * ```\n */\n async createCustomTotpDevice(params: CreateCustomTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/custom\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from a Base32 secret key.\n *\n * @example\n * Create a saved TOTP device from a Base32 secret key\n * ```typescript\n * const device = await client.createTotpDeviceFromBase32SecretKey({\n * base32_secret_key: \"JBSWY3DPEHPK3PXP\",\n * username: \"qa@example.com\",\n * issuer: \"GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromBase32SecretKey(params: CreateBase32SecretKeyTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/base32-secret-key\", params)).data;\n }\n\n /**\n * Create a saved TOTP device from an otpauth://totp URL.\n *\n * @example\n * Create a saved TOTP device from an otpauth URL\n * ```typescript\n * const device = await client.createTotpDeviceFromOtpAuthUrl({\n * otp_auth_url: \"otpauth://totp/GitHub:qa@example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub\",\n * });\n * ```\n */\n async createTotpDeviceFromOtpAuthUrl(params: CreateOtpAuthUrlTotpDeviceParams): Promise<TotpDevice> {\n return (await this.axiosInstance.post(\"api/devices/otpauth-url\", params)).data;\n }\n\n /**\n * Generate a TOTP code from a shared secret without saving a device.\n *\n * @example\n * Generate a TOTP code from a shared secret\n * ```typescript\n * const { code } = await client.getTotpOtpBySharedSecret(\"JBSWY3DPEHPK3PXP\", {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpBySharedSecret(sharedSecret: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n return (await this.axiosInstance.post(\"api/devices/otp\", { shared_secret: sharedSecret, ...params })).data;\n }\n\n /**\n * Generate a TOTP code for a saved device.\n *\n * @example\n * Generate a TOTP code for a saved device\n * ```typescript\n * const { code } = await client.getTotpOtpByDeviceId(device.id, {\n * min_seconds_until_expire: 10,\n * });\n * ```\n */\n async getTotpOtpByDeviceId(deviceId: string, params?: GetTotpOtpParams): Promise<TotpOtpResponse> {\n const url = `api/devices/${deviceId}/otp`;\n\n return params ? (await this.axiosInstance.get(url, { params })).data : (await this.axiosInstance.get(url)).data;\n }\n\n /**\n * Delete a saved TOTP device.\n *\n * @example\n * Delete a saved TOTP device\n * ```typescript\n * await client.deleteTotpDevice(device.id);\n * ```\n */\n async deleteTotpDevice(deviceId: string): Promise<void> {\n await this.axiosInstance.delete(`api/devices/${deviceId}`);\n }\n\n /**\n * List all namespaces that belong to the current account (API key).\n */\n async listNamespaces(): Promise<ListNamespacesResponse> {\n return (await this.axiosInstance.get(\"api/namespaces\")).data;\n }\n\n /**\n * Send an email using the Virtual SMTP.\n *\n * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net\n *\n * @deprecated Use sendEmail(namespace, params) for outbound email. This method remains available for existing Virtual SMTP tests.\n *\n * @example\n * For example, sending a test email:\n * ```typescript\n * client.sendVirtualEmail(namespace, {\n * from: \"test@example.com\",\n * to: `john@${namespace}.mailisk.net`,\n * subject: \"This is a test\",\n * text: \"Testing\",\n * });\n * ```\n */\n async sendVirtualEmail(namespace: string, params: SendVirtualEmailParams): Promise<void> {\n const smtpSettings = await this.getSmtpSettings(namespace);\n\n const transport = nodemailer.createTransport({\n host: smtpSettings.data.host,\n port: smtpSettings.data.port,\n secure: false,\n auth: {\n user: smtpSettings.data.username,\n pass: smtpSettings.data.password,\n },\n });\n\n const { from, to, subject, text, html, headers, attachments } = params;\n\n await transport.sendMail({\n from,\n to,\n subject,\n text,\n html,\n headers,\n attachments,\n });\n\n transport.close();\n }\n\n /**\n * Search inbox of a namespace.\n *\n * By default, this calls the api using the `wait` flag. This means the call won't timeout until at least one email is received or 5 minutes pass.\n * It also uses a default `from_timestamp` of **current timestamp - 15 minutes**. This means that older emails will be ignored.\n *\n * Both of these settings can be overriden by passing them in the `params` object.\n *\n * @example\n * Get the latest emails\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace);\n * ```\n *\n * @example\n * Get the latest emails for a specific email address\n * ```typescript\n * const { data: emails } = await client.searchInbox(namespace, {\n * to_addr_prefix: 'john@mynamespace.mailisk.net'\n * });\n * ```\n *\n * @example\n * Get the last 20 emails in the namespace\n * ```typescript\n * const { data: emails } = await mailisk.searchInbox(namespace, {\n * wait: false,\n * from_timestamp: 0,\n * limit: 20\n * });\n * ```\n */\n async searchInbox(\n namespace: string,\n params?: SearchInboxParams,\n config?: AxiosRequestConfig,\n ): Promise<SearchInboxResponse> {\n let _params = { ...params };\n\n // default from timestamp, 15 minutes before starting this request\n if (params?.from_timestamp === undefined || params?.from_timestamp === null) {\n _params.from_timestamp = Math.floor(new Date().getTime() / 1000) - 15 * 60;\n }\n\n // by default wait for email\n if (params?.wait !== false) {\n _params.wait = true;\n }\n\n let _config = { ...config };\n\n if (config?.maxRedirects === undefined) {\n _config.maxRedirects = 99999;\n }\n\n // by default, wait 5 minutes for emails before timing out\n if (_params.wait && config?.timeout === undefined) {\n _config.timeout = 1000 * 60 * 5;\n }\n\n return (\n await this.axiosInstance.get(`api/emails/${namespace}/inbox`, {\n ..._config,\n params: _params,\n })\n ).data;\n }\n\n /**\n * Get the SMTP settings for a namespace.\n *\n * @deprecated Virtual SMTP is deprecated. Use sendEmail(namespace, params) for outbound email instead.\n */\n async getSmtpSettings(namespace: string): Promise<SmtpSettings> {\n const result = await this.axiosInstance.get(`api/smtp/${namespace}`);\n return result.data;\n }\n\n async getAttachment(attachmentId: string): Promise<GetAttachmentResponse> {\n const result = await this.axiosInstance.get(`api/attachments/${attachmentId}`);\n return result.data;\n }\n\n /**\n * Download an attachment from an attachment ID.\n *\n * @example\n * Download an attachment from an email\n * ```typescript\n * const attachment = email.attachments[0];\n * const attachmentBuffer = await client.downloadAttachment(attachment.id);\n *\n * // save to file\n * fs.writeFileSync(attachment.filename, attachmentBuffer);\n * ```\n */\n async downloadAttachment(attachmentId: string): Promise<Buffer> {\n const result = await this.getAttachment(attachmentId);\n\n const response = await axios.get(result.data.download_url, { responseType: \"arraybuffer\" });\n return Buffer.from(response.data);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailisk",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Mailisk library for NodeJS",
5
5
  "keywords": [
6
6
  "mailisk",
@@ -242,6 +242,227 @@ export interface SendVirtualSmsParams {
242
242
  body: string;
243
243
  }
244
244
 
245
+ export type OutboundEmailType = "new" | "reply" | "forward";
246
+
247
+ export type OutboundEmailStatus = "queued" | "sending" | "sent" | "failed";
248
+
249
+ export type OutboundEmailRecipientType = "to" | "cc" | "bcc";
250
+
251
+ export type OutboundEmailRecipientDeliveryStatus =
252
+ | "pending"
253
+ | "accepted"
254
+ | "queued"
255
+ | "sent"
256
+ | "delayed"
257
+ | "deferred"
258
+ | "delivered"
259
+ | "bounced"
260
+ | "expired"
261
+ | "complained"
262
+ | "unsubscribed"
263
+ | "suppressed"
264
+ | "rejected"
265
+ | "failed"
266
+ | "cancelled";
267
+
268
+ export type OutboundEmailEventType =
269
+ | "accepted"
270
+ | "queued"
271
+ | "sent"
272
+ | "failed"
273
+ | "rejected"
274
+ | "delayed"
275
+ | "deferred"
276
+ | "delivered"
277
+ | "bounced"
278
+ | "expired"
279
+ | "complained"
280
+ | "unsubscribed"
281
+ | "suppressed"
282
+ | "cancelled"
283
+ | "opened"
284
+ | "clicked";
285
+
286
+ export type OutboundEmailAttachmentDisposition = "attachment" | "inline";
287
+
288
+ export interface OutboundEmailAddress {
289
+ /** Email address */
290
+ email: string;
291
+ /** Display name, if one is specified */
292
+ name?: string;
293
+ }
294
+
295
+ export interface OutboundEmailAttachment {
296
+ /** Filename of the attachment */
297
+ filename: string;
298
+ /** MIME content type */
299
+ content_type: string;
300
+ /** Base64 encoded attachment content */
301
+ content_base64: string;
302
+ /** Content-ID for inline attachments */
303
+ content_id?: string;
304
+ /** Attachment disposition */
305
+ disposition?: OutboundEmailAttachmentDisposition;
306
+ }
307
+
308
+ export interface SendEmailParams {
309
+ /** Optional sender override. Must belong to the requested namespace. */
310
+ from?: OutboundEmailAddress;
311
+ /** Optional Reply-To address */
312
+ reply_to?: OutboundEmailAddress;
313
+ /** Primary recipients */
314
+ to?: string[];
315
+ /** Carbon-copied recipients */
316
+ cc?: string[];
317
+ /** Blind carbon-copied recipients */
318
+ bcc?: string[];
319
+ /** Email subject */
320
+ subject: string;
321
+ /** HTML message body */
322
+ html?: string;
323
+ /** Plain text message body */
324
+ text?: string;
325
+ /** Attachments to include */
326
+ attachments?: OutboundEmailAttachment[];
327
+ }
328
+
329
+ export interface ReplyToEmailParams {
330
+ /** Optional sender override. Must belong to the source email namespace. */
331
+ from?: OutboundEmailAddress;
332
+ /** Carbon-copied recipients */
333
+ cc?: string[];
334
+ /** Blind carbon-copied recipients */
335
+ bcc?: string[];
336
+ /** Optional subject. Defaults to Re: original subject. */
337
+ subject?: string;
338
+ /** HTML reply body */
339
+ html?: string;
340
+ /** Plain text reply body */
341
+ text?: string;
342
+ /** Attachments to include */
343
+ attachments?: OutboundEmailAttachment[];
344
+ }
345
+
346
+ export interface ForwardEmailParams {
347
+ /** Optional sender override. Must belong to the source email namespace. */
348
+ from?: OutboundEmailAddress;
349
+ /** Primary recipients */
350
+ to: string[];
351
+ /** Carbon-copied recipients */
352
+ cc?: string[];
353
+ /** Blind carbon-copied recipients */
354
+ bcc?: string[];
355
+ /** Optional subject. Defaults to Fwd: original subject. */
356
+ subject?: string;
357
+ /** Optional HTML body to prepend before the forwarded message */
358
+ html?: string;
359
+ /** Optional plain text body to prepend before the forwarded message */
360
+ text?: string;
361
+ }
362
+
363
+ export interface OutboundEmailResponse {
364
+ id: string;
365
+ organisation_id: string;
366
+ type: OutboundEmailType;
367
+ status: OutboundEmailStatus;
368
+ from: OutboundEmailAddress;
369
+ reply_to?: OutboundEmailAddress;
370
+ subject: string;
371
+ recipient_count: number;
372
+ attachment_count: number;
373
+ message_id: string;
374
+ provider?: string;
375
+ provider_message_id?: string;
376
+ failure_reason?: string;
377
+ queued_at: string;
378
+ sending_at?: string;
379
+ sent_at?: string;
380
+ failed_at?: string;
381
+ created_at: string;
382
+ updated_at: string;
383
+ }
384
+
385
+ export interface OutboundEmailDeliverySummary {
386
+ pending: number;
387
+ accepted: number;
388
+ queued: number;
389
+ sent: number;
390
+ delayed: number;
391
+ deferred: number;
392
+ delivered: number;
393
+ bounced: number;
394
+ expired: number;
395
+ complained: number;
396
+ unsubscribed: number;
397
+ suppressed: number;
398
+ rejected: number;
399
+ failed: number;
400
+ cancelled: number;
401
+ }
402
+
403
+ export interface OutboundEmailRecipient {
404
+ id: string;
405
+ type: OutboundEmailRecipientType;
406
+ email: string;
407
+ name?: string;
408
+ delivery_status: OutboundEmailRecipientDeliveryStatus;
409
+ last_event_type?: string;
410
+ last_event_at?: string;
411
+ accepted_at?: string;
412
+ queued_at?: string;
413
+ sent_at?: string;
414
+ delayed_at?: string;
415
+ deferred_at?: string;
416
+ delivered_at?: string;
417
+ bounced_at?: string;
418
+ expired_at?: string;
419
+ complained_at?: string;
420
+ unsubscribed_at?: string;
421
+ suppressed_at?: string;
422
+ rejected_at?: string;
423
+ failed_at?: string;
424
+ cancelled_at?: string;
425
+ last_smtp_code?: string;
426
+ last_enhanced_status_code?: string;
427
+ last_smtp_response?: string;
428
+ attempt_count: number;
429
+ bounce_type?: string;
430
+ bounce_subtype?: string;
431
+ bounce_classification?: string;
432
+ complaint_feedback_type?: string;
433
+ }
434
+
435
+ export interface OutboundEmailEventRecipient {
436
+ id: string;
437
+ outbound_email_recipient_id?: string;
438
+ email: string;
439
+ smtp_code?: string;
440
+ enhanced_status_code?: string;
441
+ smtp_response?: string;
442
+ diagnostic_code?: string;
443
+ action?: string;
444
+ attempt_count?: number;
445
+ bounce_classification?: string;
446
+ }
447
+
448
+ export interface OutboundEmailEvent {
449
+ id: string;
450
+ provider: string;
451
+ provider_message_id?: string;
452
+ provider_event_id?: string;
453
+ event_type: OutboundEmailEventType;
454
+ event_subtype?: string;
455
+ occurred_at: string;
456
+ recipients: OutboundEmailEventRecipient[];
457
+ created_at: string;
458
+ }
459
+
460
+ export interface OutboundEmailDetailResponse extends OutboundEmailResponse {
461
+ delivery_summary: OutboundEmailDeliverySummary;
462
+ recipients: OutboundEmailRecipient[];
463
+ events: OutboundEmailEvent[];
464
+ }
465
+
245
466
  export type TotpAlgorithm = "SHA1" | "SHA256" | "SHA512";
246
467
 
247
468
  export type KnownTotpDeviceSource = "shared_secret" | "custom" | "base32_secret_key" | "otpauth_url";
package/src/mailisk.ts CHANGED
@@ -10,10 +10,15 @@ import {
10
10
  ListSmsNumbersResponse,
11
11
  ListTotpDevicesParams,
12
12
  ListTotpDevicesResponse,
13
+ ForwardEmailParams,
14
+ OutboundEmailDetailResponse,
15
+ OutboundEmailResponse,
16
+ ReplyToEmailParams,
13
17
  SearchInboxParams,
14
18
  SearchInboxResponse,
15
19
  SearchSmsMessagesParams,
16
20
  SearchSmsMessagesResponse,
21
+ SendEmailParams,
17
22
  SendVirtualEmailParams,
18
23
  SendVirtualSmsParams,
19
24
  SmtpSettings,
@@ -103,6 +108,48 @@ export class MailiskClient {
103
108
  return (await this.axiosInstance.post("api/sms/virtual", params)).data;
104
109
  }
105
110
 
111
+ /**
112
+ * Create and queue a new outbound email from a namespace.
113
+ *
114
+ * @example
115
+ * Send an outbound email
116
+ * ```typescript
117
+ * const email = await client.sendEmail("mynamespace", {
118
+ * to: ["verified@example.com"],
119
+ * subject: "Hello",
120
+ * text: "Hello from Mailisk",
121
+ * });
122
+ * ```
123
+ */
124
+ async sendEmail(namespace: string, params: SendEmailParams): Promise<OutboundEmailResponse> {
125
+ return (
126
+ await this.axiosInstance.post("api/emails/send", params, {
127
+ params: { namespace },
128
+ })
129
+ ).data;
130
+ }
131
+
132
+ /**
133
+ * Get current delivery state for an outbound email.
134
+ */
135
+ async getOutboundEmail(outboundEmailId: string): Promise<OutboundEmailDetailResponse> {
136
+ return (await this.axiosInstance.get(`api/emails/outbound/${outboundEmailId}`)).data;
137
+ }
138
+
139
+ /**
140
+ * Create and queue a reply to an inbound email.
141
+ */
142
+ async replyToEmail(emailId: string, params: ReplyToEmailParams): Promise<OutboundEmailResponse> {
143
+ return (await this.axiosInstance.post(`api/emails/${emailId}/reply`, params)).data;
144
+ }
145
+
146
+ /**
147
+ * Create and queue a forwarded copy of an inbound email.
148
+ */
149
+ async forwardEmail(emailId: string, params: ForwardEmailParams): Promise<OutboundEmailResponse> {
150
+ return (await this.axiosInstance.post(`api/emails/${emailId}/forward`, params)).data;
151
+ }
152
+
106
153
  /**
107
154
  * List saved TOTP devices.
108
155
  *
@@ -255,6 +302,8 @@ export class MailiskClient {
255
302
  *
256
303
  * These emails can only be sent to valid Mailisk namespaces, i.e. emails that end in @mynamespace.mailisk.net
257
304
  *
305
+ * @deprecated Use sendEmail(namespace, params) for outbound email. This method remains available for existing Virtual SMTP tests.
306
+ *
258
307
  * @example
259
308
  * For example, sending a test email:
260
309
  * ```typescript
@@ -364,6 +413,8 @@ export class MailiskClient {
364
413
 
365
414
  /**
366
415
  * Get the SMTP settings for a namespace.
416
+ *
417
+ * @deprecated Virtual SMTP is deprecated. Use sendEmail(namespace, params) for outbound email instead.
367
418
  */
368
419
  async getSmtpSettings(namespace: string): Promise<SmtpSettings> {
369
420
  const result = await this.axiosInstance.get(`api/smtp/${namespace}`);
@@ -107,6 +107,54 @@ export const mockSmsNumbersResponse = {
107
107
  ],
108
108
  };
109
109
 
110
+ export const mockOutboundEmailResponse = {
111
+ id: "2d1d9e75-4bc8-49a4-b618-f9b6af78cc4f",
112
+ organisation_id: "7f0a9c32-66b2-4e25-a4cf-1f77db8f7f3b",
113
+ type: "new",
114
+ status: "queued",
115
+ from: {
116
+ email: "outbound-delivery@test-namespace.mailisk.net",
117
+ },
118
+ subject: "Hello",
119
+ recipient_count: 1,
120
+ attachment_count: 0,
121
+ message_id: "<2d1d9e75-4bc8-49a4-b618-f9b6af78cc4f@test-namespace.mailisk.net>",
122
+ queued_at: "2026-06-01T12:00:00.000Z",
123
+ created_at: "2026-06-01T12:00:00.000Z",
124
+ updated_at: "2026-06-01T12:00:00.000Z",
125
+ };
126
+
127
+ export const mockOutboundEmailDetailResponse = {
128
+ ...mockOutboundEmailResponse,
129
+ delivery_summary: {
130
+ pending: 1,
131
+ accepted: 0,
132
+ queued: 0,
133
+ sent: 0,
134
+ delayed: 0,
135
+ deferred: 0,
136
+ delivered: 0,
137
+ bounced: 0,
138
+ expired: 0,
139
+ complained: 0,
140
+ unsubscribed: 0,
141
+ suppressed: 0,
142
+ rejected: 0,
143
+ failed: 0,
144
+ cancelled: 0,
145
+ },
146
+ recipients: [
147
+ {
148
+ id: "2a30af1d-3348-4232-9958-20bf446ad793",
149
+ type: "to",
150
+ email: "verified@example.com",
151
+ delivery_status: "pending",
152
+ attempt_count: 0,
153
+ },
154
+ ],
155
+ events: [],
156
+ };
157
+
110
158
  export const mockTotpDevice = {
111
159
  id: "9b1f6ec0-b90d-4bd8-8dd0-f6b2d5138273",
112
160
  organisation_id: "7f0a9c32-66b2-4e25-a4cf-1f77db8f7f3b",