mailisk 2.1.1 → 2.2.2
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/README.md +63 -11
- package/dist/index.d.ts +122 -9
- package/dist/index.js +33 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/mailisk.interfaces.ts +91 -6
- package/src/mailisk.ts +89 -7
- package/tests/mocks/axios-mocks.ts +85 -26
- package/tests/unit/mailisk.test.ts +138 -2
package/README.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Mailisk Node Client
|
|
2
2
|
|
|
3
|
-
Mailisk is an end-to-end email testing platform. It allows you to receive emails with code
|
|
3
|
+
Mailisk is an end-to-end email and SMS testing platform. It allows you to receive emails and SMS messages with code to automate tests.
|
|
4
4
|
|
|
5
5
|
- Get a unique subdomain and unlimited email addresses for free.
|
|
6
6
|
- Easily automate E2E password reset and account verification by catching emails.
|
|
7
|
-
-
|
|
7
|
+
- Receive SMS messages and automate SMS tests.
|
|
8
|
+
- Virtual SMTP and SMS support to test without 3rd party clients.
|
|
8
9
|
|
|
9
10
|
## Get started
|
|
10
11
|
|
|
@@ -52,9 +53,9 @@ console.log(result);
|
|
|
52
53
|
|
|
53
54
|
This library wraps the REST API endpoints. Find out more in the [API Reference](https://docs.mailisk.com/api-reference/).
|
|
54
55
|
|
|
55
|
-
## Client functions
|
|
56
|
+
## Client functions (Email)
|
|
56
57
|
|
|
57
|
-
### `searchInbox(namespace, params?)`
|
|
58
|
+
### `searchInbox(namespace, params?, requestOptions?)`
|
|
58
59
|
|
|
59
60
|
Use `searchInbox` to fetch messages that arrived in a given namespace, optionally waiting until the first new mail shows up.
|
|
60
61
|
|
|
@@ -70,13 +71,13 @@ Default behaviour:
|
|
|
70
71
|
|
|
71
72
|
```js
|
|
72
73
|
// wait up to the default 5 min for *any* new mail
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
await mailisk.searchInbox(namespace);
|
|
75
75
|
// custom 60-second timeout
|
|
76
76
|
await mailisk.searchInbox(namespace, {}, { timeout: 1000 * 60 });
|
|
77
|
-
|
|
78
77
|
// polling pattern — return immediately, even if inbox is empty
|
|
79
78
|
await mailisk.searchInbox(namespace, { wait: false });
|
|
79
|
+
// returns the last 20 emails in the namespace immediately
|
|
80
|
+
await mailisk.searchInbox(namespace, { wait: false, from_timestamp: 0, limit: 20 });
|
|
80
81
|
```
|
|
81
82
|
|
|
82
83
|
#### Filter by destination address
|
|
@@ -105,17 +106,15 @@ await mailisk.sendVirtualEmail(namespace, {
|
|
|
105
106
|
});
|
|
106
107
|
```
|
|
107
108
|
|
|
108
|
-
This does not call an API endpoint but rather uses nodemailer to send an email using SMTP.
|
|
109
|
-
|
|
110
109
|
### `listNamespaces()`
|
|
111
110
|
|
|
112
111
|
List all namespaces associated with the current API Key.
|
|
113
112
|
|
|
114
113
|
```js
|
|
115
|
-
const
|
|
114
|
+
const { data: namespaces } = await mailisk.listNamespaces();
|
|
116
115
|
|
|
117
116
|
// will be ['namespace1', 'namespace2']
|
|
118
|
-
const
|
|
117
|
+
const namespacesList = namespaces.map((nr) => nr.namespace);
|
|
119
118
|
```
|
|
120
119
|
|
|
121
120
|
### `getAttachment(attachmentId)`
|
|
@@ -158,3 +157,56 @@ const res = await fetch(meta.download_url);
|
|
|
158
157
|
const fileStream = fs.createWriteStream(filename);
|
|
159
158
|
await new Promise((ok, err) => res.body.pipe(fileStream).on("finish", ok).on("error", err));
|
|
160
159
|
```
|
|
160
|
+
|
|
161
|
+
## Client functions (SMS)
|
|
162
|
+
|
|
163
|
+
### `searchSmsMessages(phoneNumber, params?, requestOptions?)`
|
|
164
|
+
|
|
165
|
+
Fetch recent SMS messages that were delivered to one of your Mailisk phone numbers.
|
|
166
|
+
For the full parameter list see the [Search SMS reference](https://docs.mailisk.com/api-reference/search-sms-messages.html#request).
|
|
167
|
+
|
|
168
|
+
Default behaviour:
|
|
169
|
+
|
|
170
|
+
- Waits until at least one SMS matches the filters (override with `wait: false`).
|
|
171
|
+
- Times out after 5 minutes if nothing shows up (adjust via `requestOptions.timeout`).
|
|
172
|
+
- Ignores messages older than 15 minutes (change via `from_date`).
|
|
173
|
+
|
|
174
|
+
#### Quick examples
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
// get or wait for SMS messages sent to ths number
|
|
178
|
+
const { data: sms } = await mailisk.searchSmsMessages(phoneNumber);
|
|
179
|
+
|
|
180
|
+
// look for a verification code coming from a known sender
|
|
181
|
+
await mailisk.searchSmsMessages(phoneNumber, {
|
|
182
|
+
from_number: "+1800555",
|
|
183
|
+
body: "Your code",
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// polling pattern — return immediately even if nothing matched
|
|
187
|
+
await mailisk.searchSmsMessages(
|
|
188
|
+
phoneNumber,
|
|
189
|
+
{ wait: false, limit: 10, from_date: new Date(Date.now() - 1000 * 60 * 5).toISOString() },
|
|
190
|
+
{ timeout: 10_000 }
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### `listSmsNumbers()`
|
|
195
|
+
|
|
196
|
+
List all SMS phone numbers associated with the current account.
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
const { data: phoneNumbers } = await mailisk.listSmsNumbers();
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### `sendVirtualSms(params)`
|
|
203
|
+
|
|
204
|
+
Send a virtual SMS message to a phone number you have access to.
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
await mailisk.sendVirtualSms({
|
|
208
|
+
from_number: "15551234567",
|
|
209
|
+
to_number: "15557654321",
|
|
210
|
+
body: "Test message",
|
|
211
|
+
});
|
|
212
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,40 @@ interface Email {
|
|
|
47
47
|
/** The attachments of the email */
|
|
48
48
|
attachments?: EmailAttachment[];
|
|
49
49
|
}
|
|
50
|
+
interface SmsMessage {
|
|
51
|
+
/** Unique identifier for the message */
|
|
52
|
+
id: string;
|
|
53
|
+
/** Unique identifier for the SMS phone number */
|
|
54
|
+
sms_phone_number_id: string;
|
|
55
|
+
/** Body of the message */
|
|
56
|
+
body: string;
|
|
57
|
+
/** From number of the message */
|
|
58
|
+
from_number: string;
|
|
59
|
+
/** To number of the message */
|
|
60
|
+
to_number: string;
|
|
61
|
+
/** Provider message ID */
|
|
62
|
+
provider_message_id?: string;
|
|
63
|
+
/** Date and time the message was created */
|
|
64
|
+
created_at: string;
|
|
65
|
+
/** Direction of the message */
|
|
66
|
+
direction: "inbound" | "outbound";
|
|
67
|
+
}
|
|
68
|
+
interface SmsNumber {
|
|
69
|
+
/** Unique identifier for the SMS number */
|
|
70
|
+
id: string;
|
|
71
|
+
/** Unique identifier for the organisation */
|
|
72
|
+
organisation_id: string;
|
|
73
|
+
/** Status of the SMS number */
|
|
74
|
+
status: "requested" | "active" | "disabled";
|
|
75
|
+
/** Country of the SMS number */
|
|
76
|
+
country: string;
|
|
77
|
+
/** SMS Phone number */
|
|
78
|
+
phone_number?: string;
|
|
79
|
+
/** Date and time the SMS number was created */
|
|
80
|
+
created_at: string;
|
|
81
|
+
/** Date and time the SMS number was updated */
|
|
82
|
+
updated_at: string;
|
|
83
|
+
}
|
|
50
84
|
interface SearchInboxParams {
|
|
51
85
|
/**
|
|
52
86
|
* The maximum number of emails that can be returned in this request, used alongside `offset` for pagination.
|
|
@@ -122,12 +156,11 @@ interface GetAttachmentResponse {
|
|
|
122
156
|
};
|
|
123
157
|
}
|
|
124
158
|
interface ListNamespacesResponse {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
];
|
|
159
|
+
total_count: number;
|
|
160
|
+
data: {
|
|
161
|
+
id: string;
|
|
162
|
+
namespace: string;
|
|
163
|
+
}[];
|
|
131
164
|
}
|
|
132
165
|
interface SendVirtualEmailParams {
|
|
133
166
|
/** Sender of email */
|
|
@@ -149,6 +182,55 @@ interface SendVirtualEmailParams {
|
|
|
149
182
|
/** Attachments to the email */
|
|
150
183
|
attachments?: Attachment[];
|
|
151
184
|
}
|
|
185
|
+
interface SearchSmsMessagesParams {
|
|
186
|
+
/**
|
|
187
|
+
* The maximum number of SMS messages returned (1-100), used alongside `offset` for pagination.
|
|
188
|
+
*/
|
|
189
|
+
limit?: number;
|
|
190
|
+
/**
|
|
191
|
+
* The number of SMS messages to skip/ignore, used alongside `limit` for pagination.
|
|
192
|
+
*/
|
|
193
|
+
offset?: number;
|
|
194
|
+
/**
|
|
195
|
+
* Filter messages by body contents (case insensitive).
|
|
196
|
+
*/
|
|
197
|
+
body?: string;
|
|
198
|
+
/**
|
|
199
|
+
* Filter messages by sender phone number prefix.
|
|
200
|
+
*/
|
|
201
|
+
from_number?: string;
|
|
202
|
+
/**
|
|
203
|
+
* Filter messages created on or after this date.
|
|
204
|
+
* Provide an ISO 8601 timestamp string.
|
|
205
|
+
*/
|
|
206
|
+
from_date?: string;
|
|
207
|
+
/**
|
|
208
|
+
* Filter messages created on or before this date.
|
|
209
|
+
* Provide an ISO 8601 timestamp string.
|
|
210
|
+
*/
|
|
211
|
+
to_date?: string;
|
|
212
|
+
/**
|
|
213
|
+
* When true, keep the request open until at least one SMS is returned.
|
|
214
|
+
*/
|
|
215
|
+
wait?: boolean;
|
|
216
|
+
}
|
|
217
|
+
interface SearchSmsMessagesResponse {
|
|
218
|
+
total_count: number;
|
|
219
|
+
options: SearchSmsMessagesParams;
|
|
220
|
+
data: SmsMessage[];
|
|
221
|
+
}
|
|
222
|
+
interface ListSmsNumbersResponse {
|
|
223
|
+
total_count: number;
|
|
224
|
+
data: SmsNumber[];
|
|
225
|
+
}
|
|
226
|
+
interface SendVirtualSmsParams {
|
|
227
|
+
/** The phone number to send the SMS from */
|
|
228
|
+
from_number: string;
|
|
229
|
+
/** The phone number to send the SMS to */
|
|
230
|
+
to_number: string;
|
|
231
|
+
/** The body of the SMS message */
|
|
232
|
+
body: string;
|
|
233
|
+
}
|
|
152
234
|
|
|
153
235
|
declare class MailiskClient {
|
|
154
236
|
constructor({ apiKey, baseUrl, auth }: {
|
|
@@ -157,6 +239,27 @@ declare class MailiskClient {
|
|
|
157
239
|
auth?: AxiosBasicCredentials;
|
|
158
240
|
});
|
|
159
241
|
private readonly axiosInstance;
|
|
242
|
+
/**
|
|
243
|
+
* Search SMS messages sent to a phone number.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* Search for SMS messages sent to a phone number
|
|
247
|
+
* ```typescript
|
|
248
|
+
* const { data: smsMessages } = await client.searchSmsMessages("1234567890");
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
searchSmsMessages(phoneNumber: string, params?: SearchSmsMessagesParams, config?: AxiosRequestConfig): Promise<SearchSmsMessagesResponse>;
|
|
252
|
+
/**
|
|
253
|
+
* List all SMS phone numbers associated with the current account.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* List all SMS phone numbers
|
|
257
|
+
* ```typescript
|
|
258
|
+
* const { data: smsNumbers } = await client.listSmsNumbers();
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
listSmsNumbers(): Promise<ListSmsNumbersResponse>;
|
|
262
|
+
sendVirtualSms(params: SendVirtualSmsParams): Promise<void>;
|
|
160
263
|
/**
|
|
161
264
|
* List all namespaces that belong to the current account (API key).
|
|
162
265
|
*/
|
|
@@ -182,12 +285,12 @@ declare class MailiskClient {
|
|
|
182
285
|
* Search inbox of a namespace.
|
|
183
286
|
*
|
|
184
287
|
* 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.
|
|
185
|
-
* It also uses a default `from_timestamp` of **current timestamp -
|
|
288
|
+
* It also uses a default `from_timestamp` of **current timestamp - 15 minutes**. This means that older emails will be ignored.
|
|
186
289
|
*
|
|
187
290
|
* Both of these settings can be overriden by passing them in the `params` object.
|
|
188
291
|
*
|
|
189
292
|
* @example
|
|
190
|
-
* Get the latest emails
|
|
293
|
+
* Get the latest emails
|
|
191
294
|
* ```typescript
|
|
192
295
|
* const { data: emails } = await client.searchInbox(namespace);
|
|
193
296
|
* ```
|
|
@@ -196,7 +299,17 @@ declare class MailiskClient {
|
|
|
196
299
|
* Get the latest emails for a specific email address
|
|
197
300
|
* ```typescript
|
|
198
301
|
* const { data: emails } = await client.searchInbox(namespace, {
|
|
199
|
-
*
|
|
302
|
+
* to_addr_prefix: 'john@mynamespace.mailisk.net'
|
|
303
|
+
* });
|
|
304
|
+
* ```
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* Get the last 20 emails in the namespace
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const { data: emails } = await mailisk.searchInbox(namespace, {
|
|
310
|
+
* wait: false,
|
|
311
|
+
* from_timestamp: 0,
|
|
312
|
+
* limit: 20
|
|
200
313
|
* });
|
|
201
314
|
* ```
|
|
202
315
|
*/
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,37 @@ var MailiskClient = class {
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
axiosInstance;
|
|
48
|
+
async searchSmsMessages(phoneNumber, params, config) {
|
|
49
|
+
let _params = { ...params };
|
|
50
|
+
if (params?.from_date === void 0 || params?.from_date === null) {
|
|
51
|
+
_params.from_date = new Date(Date.now() - 15 * 60 * 1e3).toISOString();
|
|
52
|
+
}
|
|
53
|
+
if (params?.wait !== false) {
|
|
54
|
+
_params.wait = true;
|
|
55
|
+
}
|
|
56
|
+
let _config = { ...config };
|
|
57
|
+
if (config?.maxRedirects === void 0) {
|
|
58
|
+
_config.maxRedirects = 99999;
|
|
59
|
+
}
|
|
60
|
+
if (_params.wait && config?.timeout === void 0) {
|
|
61
|
+
_config.timeout = 1e3 * 60 * 5;
|
|
62
|
+
}
|
|
63
|
+
const requestParams = {
|
|
64
|
+
..._params,
|
|
65
|
+
from_date: _params.from_date ?? void 0,
|
|
66
|
+
to_date: _params.to_date ?? void 0
|
|
67
|
+
};
|
|
68
|
+
return (await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {
|
|
69
|
+
..._config,
|
|
70
|
+
params: requestParams
|
|
71
|
+
})).data;
|
|
72
|
+
}
|
|
73
|
+
async listSmsNumbers() {
|
|
74
|
+
return (await this.axiosInstance.get("api/sms/numbers")).data;
|
|
75
|
+
}
|
|
76
|
+
async sendVirtualSms(params) {
|
|
77
|
+
return (await this.axiosInstance.post("api/sms/virtual", params)).data;
|
|
78
|
+
}
|
|
48
79
|
async listNamespaces() {
|
|
49
80
|
return (await this.axiosInstance.get("api/namespaces")).data;
|
|
50
81
|
}
|
|
@@ -80,10 +111,10 @@ var MailiskClient = class {
|
|
|
80
111
|
_params.wait = true;
|
|
81
112
|
}
|
|
82
113
|
let _config = { ...config };
|
|
83
|
-
if (
|
|
114
|
+
if (config?.maxRedirects === void 0) {
|
|
84
115
|
_config.maxRedirects = 99999;
|
|
85
116
|
}
|
|
86
|
-
if (_params.wait &&
|
|
117
|
+
if (_params.wait && config?.timeout === void 0) {
|
|
87
118
|
_config.timeout = 1e3 * 60 * 5;
|
|
88
119
|
}
|
|
89
120
|
return (await this.axiosInstance.get(`api/emails/${namespace}/inbox`, {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/mailisk.ts"],"sourcesContent":["export * from \"./mailisk\";\n","import axios, { AxiosBasicCredentials, AxiosRequestConfig } from \"axios\";\nimport {\n GetAttachmentResponse,\n ListNamespacesResponse,\n SearchInboxParams,\n SearchInboxResponse,\n SendVirtualEmailParams,\n SmtpSettings,\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;\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 -
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/mailisk.ts"],"sourcesContent":["export * from \"./mailisk\";\n","import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport {\n GetAttachmentResponse,\n ListNamespacesResponse,\n ListSmsNumbersResponse,\n SearchInboxParams,\n SearchInboxResponse,\n SearchSmsMessagesParams,\n SearchSmsMessagesResponse,\n SendVirtualEmailParams,\n SendVirtualSmsParams,\n SmtpSettings,\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 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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -15,6 +15,37 @@ var MailiskClient = class {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
axiosInstance;
|
|
18
|
+
async searchSmsMessages(phoneNumber, params, config) {
|
|
19
|
+
let _params = { ...params };
|
|
20
|
+
if (params?.from_date === void 0 || params?.from_date === null) {
|
|
21
|
+
_params.from_date = new Date(Date.now() - 15 * 60 * 1e3).toISOString();
|
|
22
|
+
}
|
|
23
|
+
if (params?.wait !== false) {
|
|
24
|
+
_params.wait = true;
|
|
25
|
+
}
|
|
26
|
+
let _config = { ...config };
|
|
27
|
+
if (config?.maxRedirects === void 0) {
|
|
28
|
+
_config.maxRedirects = 99999;
|
|
29
|
+
}
|
|
30
|
+
if (_params.wait && config?.timeout === void 0) {
|
|
31
|
+
_config.timeout = 1e3 * 60 * 5;
|
|
32
|
+
}
|
|
33
|
+
const requestParams = {
|
|
34
|
+
..._params,
|
|
35
|
+
from_date: _params.from_date ?? void 0,
|
|
36
|
+
to_date: _params.to_date ?? void 0
|
|
37
|
+
};
|
|
38
|
+
return (await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {
|
|
39
|
+
..._config,
|
|
40
|
+
params: requestParams
|
|
41
|
+
})).data;
|
|
42
|
+
}
|
|
43
|
+
async listSmsNumbers() {
|
|
44
|
+
return (await this.axiosInstance.get("api/sms/numbers")).data;
|
|
45
|
+
}
|
|
46
|
+
async sendVirtualSms(params) {
|
|
47
|
+
return (await this.axiosInstance.post("api/sms/virtual", params)).data;
|
|
48
|
+
}
|
|
18
49
|
async listNamespaces() {
|
|
19
50
|
return (await this.axiosInstance.get("api/namespaces")).data;
|
|
20
51
|
}
|
|
@@ -50,10 +81,10 @@ var MailiskClient = class {
|
|
|
50
81
|
_params.wait = true;
|
|
51
82
|
}
|
|
52
83
|
let _config = { ...config };
|
|
53
|
-
if (
|
|
84
|
+
if (config?.maxRedirects === void 0) {
|
|
54
85
|
_config.maxRedirects = 99999;
|
|
55
86
|
}
|
|
56
|
-
if (_params.wait &&
|
|
87
|
+
if (_params.wait && config?.timeout === void 0) {
|
|
57
88
|
_config.timeout = 1e3 * 60 * 5;
|
|
58
89
|
}
|
|
59
90
|
return (await this.axiosInstance.get(`api/emails/${namespace}/inbox`, {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mailisk.ts"],"sourcesContent":["import axios, { AxiosBasicCredentials, AxiosRequestConfig } from \"axios\";\nimport {\n GetAttachmentResponse,\n ListNamespacesResponse,\n SearchInboxParams,\n SearchInboxResponse,\n SendVirtualEmailParams,\n SmtpSettings,\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;\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 -
|
|
1
|
+
{"version":3,"sources":["../src/mailisk.ts"],"sourcesContent":["import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport {\n GetAttachmentResponse,\n ListNamespacesResponse,\n ListSmsNumbersResponse,\n SearchInboxParams,\n SearchInboxResponse,\n SearchSmsMessagesParams,\n SearchSmsMessagesResponse,\n SendVirtualEmailParams,\n SendVirtualSmsParams,\n SmtpSettings,\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 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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailisk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Mailisk library for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mailisk",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"jest-mock-axios": "^4.8.0",
|
|
27
27
|
"ts-jest": "^29.2.6",
|
|
28
28
|
"tsup": "^6.2.3",
|
|
29
|
-
"typescript": "^4.
|
|
29
|
+
"typescript": "^4.9.5"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"axios": "^1.1.2",
|
|
@@ -49,6 +49,42 @@ export interface Email {
|
|
|
49
49
|
attachments?: EmailAttachment[];
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
export interface SmsMessage {
|
|
53
|
+
/** Unique identifier for the message */
|
|
54
|
+
id: string;
|
|
55
|
+
/** Unique identifier for the SMS phone number */
|
|
56
|
+
sms_phone_number_id: string;
|
|
57
|
+
/** Body of the message */
|
|
58
|
+
body: string;
|
|
59
|
+
/** From number of the message */
|
|
60
|
+
from_number: string;
|
|
61
|
+
/** To number of the message */
|
|
62
|
+
to_number: string;
|
|
63
|
+
/** Provider message ID */
|
|
64
|
+
provider_message_id?: string;
|
|
65
|
+
/** Date and time the message was created */
|
|
66
|
+
created_at: string;
|
|
67
|
+
/** Direction of the message */
|
|
68
|
+
direction: "inbound" | "outbound";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface SmsNumber {
|
|
72
|
+
/** Unique identifier for the SMS number */
|
|
73
|
+
id: string;
|
|
74
|
+
/** Unique identifier for the organisation */
|
|
75
|
+
organisation_id: string;
|
|
76
|
+
/** Status of the SMS number */
|
|
77
|
+
status: "requested" | "active" | "disabled";
|
|
78
|
+
/** Country of the SMS number */
|
|
79
|
+
country: string;
|
|
80
|
+
/** SMS Phone number */
|
|
81
|
+
phone_number?: string;
|
|
82
|
+
/** Date and time the SMS number was created */
|
|
83
|
+
created_at: string;
|
|
84
|
+
/** Date and time the SMS number was updated */
|
|
85
|
+
updated_at: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
52
88
|
export interface SearchInboxParams {
|
|
53
89
|
/**
|
|
54
90
|
* The maximum number of emails that can be returned in this request, used alongside `offset` for pagination.
|
|
@@ -128,12 +164,8 @@ export interface GetAttachmentResponse {
|
|
|
128
164
|
}
|
|
129
165
|
|
|
130
166
|
export interface ListNamespacesResponse {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
id: string;
|
|
134
|
-
namespace: string;
|
|
135
|
-
}
|
|
136
|
-
];
|
|
167
|
+
total_count: number;
|
|
168
|
+
data: { id: string; namespace: string }[];
|
|
137
169
|
}
|
|
138
170
|
|
|
139
171
|
export interface SendVirtualEmailParams {
|
|
@@ -156,3 +188,56 @@ export interface SendVirtualEmailParams {
|
|
|
156
188
|
/** Attachments to the email */
|
|
157
189
|
attachments?: Attachment[];
|
|
158
190
|
}
|
|
191
|
+
|
|
192
|
+
export interface SearchSmsMessagesParams {
|
|
193
|
+
/**
|
|
194
|
+
* The maximum number of SMS messages returned (1-100), used alongside `offset` for pagination.
|
|
195
|
+
*/
|
|
196
|
+
limit?: number;
|
|
197
|
+
/**
|
|
198
|
+
* The number of SMS messages to skip/ignore, used alongside `limit` for pagination.
|
|
199
|
+
*/
|
|
200
|
+
offset?: number;
|
|
201
|
+
/**
|
|
202
|
+
* Filter messages by body contents (case insensitive).
|
|
203
|
+
*/
|
|
204
|
+
body?: string;
|
|
205
|
+
/**
|
|
206
|
+
* Filter messages by sender phone number prefix.
|
|
207
|
+
*/
|
|
208
|
+
from_number?: string;
|
|
209
|
+
/**
|
|
210
|
+
* Filter messages created on or after this date.
|
|
211
|
+
* Provide an ISO 8601 timestamp string.
|
|
212
|
+
*/
|
|
213
|
+
from_date?: string;
|
|
214
|
+
/**
|
|
215
|
+
* Filter messages created on or before this date.
|
|
216
|
+
* Provide an ISO 8601 timestamp string.
|
|
217
|
+
*/
|
|
218
|
+
to_date?: string;
|
|
219
|
+
/**
|
|
220
|
+
* When true, keep the request open until at least one SMS is returned.
|
|
221
|
+
*/
|
|
222
|
+
wait?: boolean;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface SearchSmsMessagesResponse {
|
|
226
|
+
total_count: number;
|
|
227
|
+
options: SearchSmsMessagesParams;
|
|
228
|
+
data: SmsMessage[];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface ListSmsNumbersResponse {
|
|
232
|
+
total_count: number;
|
|
233
|
+
data: SmsNumber[];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface SendVirtualSmsParams {
|
|
237
|
+
/** The phone number to send the SMS from */
|
|
238
|
+
from_number: string;
|
|
239
|
+
/** The phone number to send the SMS to */
|
|
240
|
+
to_number: string;
|
|
241
|
+
/** The body of the SMS message */
|
|
242
|
+
body: string;
|
|
243
|
+
}
|
package/src/mailisk.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import axios, { AxiosBasicCredentials, AxiosRequestConfig } from "axios";
|
|
1
|
+
import axios, { AxiosBasicCredentials, AxiosInstance, AxiosRequestConfig } from "axios";
|
|
2
2
|
import {
|
|
3
3
|
GetAttachmentResponse,
|
|
4
4
|
ListNamespacesResponse,
|
|
5
|
+
ListSmsNumbersResponse,
|
|
5
6
|
SearchInboxParams,
|
|
6
7
|
SearchInboxResponse,
|
|
8
|
+
SearchSmsMessagesParams,
|
|
9
|
+
SearchSmsMessagesResponse,
|
|
7
10
|
SendVirtualEmailParams,
|
|
11
|
+
SendVirtualSmsParams,
|
|
8
12
|
SmtpSettings,
|
|
9
13
|
} from "./mailisk.interfaces";
|
|
10
14
|
import nodemailer from "nodemailer";
|
|
@@ -20,7 +24,75 @@ export class MailiskClient {
|
|
|
20
24
|
});
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
private readonly axiosInstance;
|
|
27
|
+
private readonly axiosInstance: AxiosInstance;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Search SMS messages sent to a phone number.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* Search for SMS messages sent to a phone number
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const { data: smsMessages } = await client.searchSmsMessages("1234567890");
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
async searchSmsMessages(
|
|
39
|
+
phoneNumber: string,
|
|
40
|
+
params?: SearchSmsMessagesParams,
|
|
41
|
+
config?: AxiosRequestConfig
|
|
42
|
+
): Promise<SearchSmsMessagesResponse> {
|
|
43
|
+
let _params: SearchSmsMessagesParams = { ...params };
|
|
44
|
+
|
|
45
|
+
// default from timestamp, 15 minutes before starting this request
|
|
46
|
+
if (params?.from_date === undefined || params?.from_date === null) {
|
|
47
|
+
_params.from_date = new Date(Date.now() - 15 * 60 * 1000).toISOString();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// by default wait for sms
|
|
51
|
+
if (params?.wait !== false) {
|
|
52
|
+
_params.wait = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let _config = { ...config };
|
|
56
|
+
|
|
57
|
+
if (config?.maxRedirects === undefined) {
|
|
58
|
+
_config.maxRedirects = 99999;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// by default, wait 5 minutes for emails before timing out
|
|
62
|
+
if (_params.wait && config?.timeout === undefined) {
|
|
63
|
+
_config.timeout = 1000 * 60 * 5;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const requestParams = {
|
|
67
|
+
..._params,
|
|
68
|
+
from_date: _params.from_date ?? undefined,
|
|
69
|
+
to_date: _params.to_date ?? undefined,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
await this.axiosInstance.get(`api/sms/${phoneNumber}/messages`, {
|
|
74
|
+
..._config,
|
|
75
|
+
params: requestParams,
|
|
76
|
+
})
|
|
77
|
+
).data;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* List all SMS phone numbers associated with the current account.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* List all SMS phone numbers
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const { data: smsNumbers } = await client.listSmsNumbers();
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
async listSmsNumbers(): Promise<ListSmsNumbersResponse> {
|
|
90
|
+
return (await this.axiosInstance.get("api/sms/numbers")).data;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async sendVirtualSms(params: SendVirtualSmsParams): Promise<void> {
|
|
94
|
+
return (await this.axiosInstance.post("api/sms/virtual", params)).data;
|
|
95
|
+
}
|
|
24
96
|
|
|
25
97
|
/**
|
|
26
98
|
* List all namespaces that belong to the current account (API key).
|
|
@@ -77,12 +149,12 @@ export class MailiskClient {
|
|
|
77
149
|
* Search inbox of a namespace.
|
|
78
150
|
*
|
|
79
151
|
* 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.
|
|
80
|
-
* It also uses a default `from_timestamp` of **current timestamp -
|
|
152
|
+
* It also uses a default `from_timestamp` of **current timestamp - 15 minutes**. This means that older emails will be ignored.
|
|
81
153
|
*
|
|
82
154
|
* Both of these settings can be overriden by passing them in the `params` object.
|
|
83
155
|
*
|
|
84
156
|
* @example
|
|
85
|
-
* Get the latest emails
|
|
157
|
+
* Get the latest emails
|
|
86
158
|
* ```typescript
|
|
87
159
|
* const { data: emails } = await client.searchInbox(namespace);
|
|
88
160
|
* ```
|
|
@@ -91,7 +163,17 @@ export class MailiskClient {
|
|
|
91
163
|
* Get the latest emails for a specific email address
|
|
92
164
|
* ```typescript
|
|
93
165
|
* const { data: emails } = await client.searchInbox(namespace, {
|
|
94
|
-
*
|
|
166
|
+
* to_addr_prefix: 'john@mynamespace.mailisk.net'
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* Get the last 20 emails in the namespace
|
|
172
|
+
* ```typescript
|
|
173
|
+
* const { data: emails } = await mailisk.searchInbox(namespace, {
|
|
174
|
+
* wait: false,
|
|
175
|
+
* from_timestamp: 0,
|
|
176
|
+
* limit: 20
|
|
95
177
|
* });
|
|
96
178
|
* ```
|
|
97
179
|
*/
|
|
@@ -114,12 +196,12 @@ export class MailiskClient {
|
|
|
114
196
|
|
|
115
197
|
let _config = { ...config };
|
|
116
198
|
|
|
117
|
-
if (
|
|
199
|
+
if (config?.maxRedirects === undefined) {
|
|
118
200
|
_config.maxRedirects = 99999;
|
|
119
201
|
}
|
|
120
202
|
|
|
121
203
|
// by default, wait 5 minutes for emails before timing out
|
|
122
|
-
if (_params.wait &&
|
|
204
|
+
if (_params.wait && config?.timeout === undefined) {
|
|
123
205
|
_config.timeout = 1000 * 60 * 5;
|
|
124
206
|
}
|
|
125
207
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Mock namespace response data
|
|
2
2
|
export const mockNamespacesResponse = {
|
|
3
|
-
|
|
3
|
+
total_count: 1,
|
|
4
|
+
data: [
|
|
4
5
|
{
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
id: "0fde5afa-a8a8-41a4-9ca4-21d83efc37d8",
|
|
7
|
+
namespace: "test-namespace",
|
|
7
8
|
expires_at: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
|
|
8
9
|
},
|
|
9
10
|
],
|
|
@@ -11,39 +12,97 @@ export const mockNamespacesResponse = {
|
|
|
11
12
|
|
|
12
13
|
// Mock email response data
|
|
13
14
|
export const mockEmailsResponse = {
|
|
14
|
-
|
|
15
|
+
total_count: 1,
|
|
16
|
+
options: {
|
|
17
|
+
wait: true,
|
|
18
|
+
},
|
|
19
|
+
data: [
|
|
15
20
|
{
|
|
16
|
-
id: "
|
|
17
|
-
from: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
id: "1763808382384-m-m-dEmYI7ic5",
|
|
22
|
+
from: {
|
|
23
|
+
address: "sender@example.com",
|
|
24
|
+
name: "Sender",
|
|
25
|
+
},
|
|
26
|
+
to: [
|
|
27
|
+
{
|
|
28
|
+
address: "recipient@test-namespace.mailisk.net",
|
|
29
|
+
name: "Recipient",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
subject: "test",
|
|
33
|
+
html: "false",
|
|
34
|
+
text: "test",
|
|
35
|
+
received_date: "2025-11-22T10:46:22.000Z",
|
|
36
|
+
received_timestamp: 1763808382,
|
|
37
|
+
expires_timestamp: 1764672382,
|
|
38
|
+
spam_score: null,
|
|
25
39
|
},
|
|
26
40
|
],
|
|
27
|
-
count: 1,
|
|
28
41
|
};
|
|
29
42
|
|
|
30
43
|
// Mock attachment response data
|
|
31
44
|
export const mockAttachmentResponse = {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
data: {
|
|
46
|
+
id: "b04730be-9c13-4f23-a2b7-a4a9a943cd31",
|
|
47
|
+
filename: "Sample.png",
|
|
48
|
+
content_type: "image/png",
|
|
49
|
+
size: 140551,
|
|
50
|
+
expires_at: "2025-09-09T10:03:33.000Z",
|
|
51
|
+
download_url: "url",
|
|
52
|
+
},
|
|
38
53
|
};
|
|
39
54
|
|
|
40
55
|
// Mock SMTP settings response
|
|
41
56
|
export const mockSmtpSettingsResponse = {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
data: {
|
|
58
|
+
host: "smtp.mailisk.net",
|
|
59
|
+
port: 587,
|
|
60
|
+
username: "test-namespace",
|
|
61
|
+
password: "mock-password",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Mock SMS messages response data
|
|
66
|
+
export const mockSmsMessagesResponse = {
|
|
67
|
+
total_count: 1,
|
|
68
|
+
options: {
|
|
69
|
+
limit: 20,
|
|
70
|
+
offset: 0,
|
|
48
71
|
},
|
|
72
|
+
data: [
|
|
73
|
+
{
|
|
74
|
+
id: "37a2bc57-c2c7-4c08-a9dc-d143bc17643f",
|
|
75
|
+
sms_phone_number_id: "ba548be2-bff9-4e3f-a54b-e034c415e906",
|
|
76
|
+
body: "test newline \\n\\n test2",
|
|
77
|
+
from_number: "+18777804236",
|
|
78
|
+
to_number: "+19285639871",
|
|
79
|
+
provider_message_id: "SMf72eb72b6281a02e60a0114f38e34e36",
|
|
80
|
+
created_at: "2020-11-24T16:48:22.170Z",
|
|
81
|
+
direction: "inbound",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Mock SMS numbers response data
|
|
87
|
+
export const mockSmsNumbersResponse = {
|
|
88
|
+
total_count: 2,
|
|
89
|
+
data: [
|
|
90
|
+
{
|
|
91
|
+
id: "13c4551e-a5be-4959-9ea5-82931dcfc74d",
|
|
92
|
+
organisation_id: "c02bdb84-22df-4c18-85ba-2defdd04eccb",
|
|
93
|
+
status: "requested",
|
|
94
|
+
country: "US",
|
|
95
|
+
created_at: "2020-11-22T16:59:25.462Z",
|
|
96
|
+
updated_at: "2020-11-22T16:59:25.462Z",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "6bf073d6-d333-45c9-b009-c77f0cac7657",
|
|
100
|
+
organisation_id: "ddec2c7b-b087-45b6-a81d-b195f25d457f",
|
|
101
|
+
status: "active",
|
|
102
|
+
country: "US",
|
|
103
|
+
phone_number: "+19285639871",
|
|
104
|
+
created_at: "2020-11-22T16:41:40.329Z",
|
|
105
|
+
updated_at: "2020-11-22T16:41:40.329Z",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
49
108
|
};
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
mockEmailsResponse,
|
|
10
10
|
mockSmtpSettingsResponse,
|
|
11
11
|
mockAttachmentResponse,
|
|
12
|
+
mockSmsMessagesResponse,
|
|
13
|
+
mockSmsNumbersResponse,
|
|
12
14
|
} from "../mocks/axios-mocks";
|
|
13
15
|
|
|
14
16
|
const setupMockAxios = () => {
|
|
@@ -132,7 +134,7 @@ describe("MailiskClient", () => {
|
|
|
132
134
|
describe("downloadAttachment", () => {
|
|
133
135
|
it("should download and return attachment data", async () => {
|
|
134
136
|
const getAttachmentSpy = jest.spyOn(MailiskClient.prototype, "getAttachment");
|
|
135
|
-
getAttachmentSpy.mockResolvedValueOnce(
|
|
137
|
+
getAttachmentSpy.mockResolvedValueOnce(mockAttachmentResponse);
|
|
136
138
|
|
|
137
139
|
const mockBuffer = Buffer.from("test content");
|
|
138
140
|
(axios.get as jest.Mock).mockResolvedValueOnce({ data: mockBuffer });
|
|
@@ -140,11 +142,145 @@ describe("MailiskClient", () => {
|
|
|
140
142
|
const client = new MailiskClient({ apiKey: "test-key" });
|
|
141
143
|
const result = await client.downloadAttachment("attachment-123");
|
|
142
144
|
|
|
143
|
-
expect(axios.get).toHaveBeenCalledWith(mockAttachmentResponse.download_url, { responseType: "arraybuffer" });
|
|
145
|
+
expect(axios.get).toHaveBeenCalledWith(mockAttachmentResponse.data.download_url, { responseType: "arraybuffer" });
|
|
144
146
|
expect(result).toEqual(mockBuffer);
|
|
145
147
|
});
|
|
146
148
|
});
|
|
147
149
|
|
|
150
|
+
describe("searchSmsMessages", () => {
|
|
151
|
+
it("should fetch and return SMS messages with default parameters", async () => {
|
|
152
|
+
const { mockGet } = setupMockAxios();
|
|
153
|
+
mockGet.mockResolvedValueOnce({ data: mockSmsMessagesResponse });
|
|
154
|
+
|
|
155
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
156
|
+
const result = await client.searchSmsMessages("1234567890");
|
|
157
|
+
|
|
158
|
+
expect(mockGet).toHaveBeenCalledWith("api/sms/1234567890/messages", {
|
|
159
|
+
maxRedirects: 99999,
|
|
160
|
+
timeout: 1000 * 60 * 5,
|
|
161
|
+
params: {
|
|
162
|
+
from_date: expect.any(String),
|
|
163
|
+
wait: true,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(result).toEqual(mockSmsMessagesResponse);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("should use custom parameters if provided", async () => {
|
|
171
|
+
const { mockGet } = setupMockAxios();
|
|
172
|
+
mockGet.mockResolvedValueOnce({ data: mockSmsMessagesResponse });
|
|
173
|
+
|
|
174
|
+
const customParams = {
|
|
175
|
+
limit: 5,
|
|
176
|
+
offset: 2,
|
|
177
|
+
body: "verification",
|
|
178
|
+
from_number: "+18005550123",
|
|
179
|
+
from_date: "2023-01-01T00:00:00.000Z",
|
|
180
|
+
to_date: "2023-02-01T00:00:00.000Z",
|
|
181
|
+
wait: false,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
185
|
+
const result = await client.searchSmsMessages("+1234567890", customParams);
|
|
186
|
+
|
|
187
|
+
const expectedParams = { ...customParams };
|
|
188
|
+
|
|
189
|
+
expect(mockGet).toHaveBeenCalledWith("api/sms/+1234567890/messages", {
|
|
190
|
+
maxRedirects: 99999,
|
|
191
|
+
params: expectedParams,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(result).toEqual(mockSmsMessagesResponse);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("should use custom axios config if provided", async () => {
|
|
198
|
+
const { mockGet } = setupMockAxios();
|
|
199
|
+
mockGet.mockResolvedValueOnce({ data: mockSmsMessagesResponse });
|
|
200
|
+
|
|
201
|
+
const customConfig = {
|
|
202
|
+
timeout: 10000,
|
|
203
|
+
maxRedirects: 5,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
207
|
+
const result = await client.searchSmsMessages("+1234567890", undefined, customConfig);
|
|
208
|
+
|
|
209
|
+
expect(mockGet).toHaveBeenCalledWith("api/sms/+1234567890/messages", {
|
|
210
|
+
...customConfig,
|
|
211
|
+
params: {
|
|
212
|
+
from_date: expect.any(String),
|
|
213
|
+
wait: true,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
expect(result).toEqual(mockSmsMessagesResponse);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("should handle errors correctly", async () => {
|
|
221
|
+
const { mockGet } = setupMockAxios();
|
|
222
|
+
const error = new Error("Search SMS Error");
|
|
223
|
+
mockGet.mockRejectedValueOnce(error);
|
|
224
|
+
|
|
225
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
226
|
+
|
|
227
|
+
await expect(client.searchSmsMessages("+1234567890")).rejects.toThrow("Search SMS Error");
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe("listSmsNumbers", () => {
|
|
232
|
+
it("should fetch and return SMS numbers", async () => {
|
|
233
|
+
const { mockGet } = setupMockAxios();
|
|
234
|
+
mockGet.mockResolvedValueOnce({ data: mockSmsNumbersResponse });
|
|
235
|
+
|
|
236
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
237
|
+
const result = await client.listSmsNumbers();
|
|
238
|
+
|
|
239
|
+
expect(mockGet).toHaveBeenCalledWith("api/sms/numbers");
|
|
240
|
+
expect(result).toEqual(mockSmsNumbersResponse);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("should handle errors correctly", async () => {
|
|
244
|
+
const { mockGet } = setupMockAxios();
|
|
245
|
+
const error = new Error("List SMS Numbers Error");
|
|
246
|
+
mockGet.mockRejectedValueOnce(error);
|
|
247
|
+
|
|
248
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
249
|
+
|
|
250
|
+
await expect(client.listSmsNumbers()).rejects.toThrow("List SMS Numbers Error");
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
describe("sendVirtualSms", () => {
|
|
255
|
+
it("should send an SMS through the API", async () => {
|
|
256
|
+
const { mockPost } = setupMockAxios();
|
|
257
|
+
mockPost.mockResolvedValueOnce({ data: {} });
|
|
258
|
+
|
|
259
|
+
const smsParams = {
|
|
260
|
+
from_number: "15551234567",
|
|
261
|
+
to_number: "15557654321",
|
|
262
|
+
body: "Test message",
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
266
|
+
await client.sendVirtualSms(smsParams);
|
|
267
|
+
|
|
268
|
+
expect(mockPost).toHaveBeenCalledWith("api/sms/virtual", smsParams);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it("should handle errors when sending SMS", async () => {
|
|
272
|
+
const { mockPost } = setupMockAxios();
|
|
273
|
+
const error = new Error("Send SMS Error");
|
|
274
|
+
mockPost.mockRejectedValueOnce(error);
|
|
275
|
+
|
|
276
|
+
const client = new MailiskClient({ apiKey: "test-key" });
|
|
277
|
+
|
|
278
|
+
await expect(
|
|
279
|
+
client.sendVirtualSms({ from_number: "+15551234567", to_number: "+15557654321", body: "Test message" })
|
|
280
|
+
).rejects.toThrow("Send SMS Error");
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
148
284
|
describe("searchInbox", () => {
|
|
149
285
|
it("should fetch and return emails with default parameters", async () => {
|
|
150
286
|
const { mockGet } = setupMockAxios();
|