mailpit-api 1.1.0 → 1.2.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/src/index.ts CHANGED
@@ -4,238 +4,444 @@ import axios, {
4
4
  isAxiosError,
5
5
  } from "axios";
6
6
 
7
- // Common types
8
- interface Address {
7
+ // COMMON TYPES
8
+ /** Represents a name and email address for a request. */
9
+ export interface MailpitEmailAddressRequest {
10
+ /** Email address */
11
+ Email: string;
12
+ /** Optional name associated with the email address */
13
+ Name?: string;
14
+ }
15
+
16
+ /** Represents a name and email address from a response. */
17
+ export interface MailpitEmailAddressResponse {
18
+ /** Email address */
9
19
  Address: string;
20
+ /** Name associated with the email address */
10
21
  Name: string;
11
22
  }
12
23
 
13
- interface Email {
14
- Email: string;
15
- Name: string;
24
+ /** Represents an attachment for a request. */
25
+ export interface MailpitAttachmentRequest {
26
+ /** Base64-encoded string for the file content */
27
+ Content: string;
28
+ /** Optional Content-ID (cid) for attachment. If this field is set then the file is attached inline. */
29
+ ContentID?: string;
30
+ /** Optional Content Type for the the attachment. If this field is not set (or empty) then the content type is automatically detected. */
31
+ ContentType?: string;
32
+ /** Filename for the attachement */
33
+ Filename: string;
16
34
  }
17
35
 
18
- interface Attachment {
36
+ /** Represents an attachment from a response. */
37
+ export interface MailpitAttachmentResponse {
38
+ /** Content ID */
19
39
  ContentID: string;
40
+ /** Content type */
20
41
  ContentType: string;
42
+ /** File name */
21
43
  FileName: string;
44
+ /** Attachment part ID */
22
45
  PartID: string;
46
+ /** Size in bytes */
23
47
  Size: number;
24
48
  }
25
49
 
26
- interface ChaosTrigger {
50
+ /** Represents information about a Chaos trigger */
51
+ export interface MailpitChaosTrigger {
52
+ /** SMTP error code to return. The value must range from 400 to 599. */
27
53
  ErrorCode: number;
54
+ /** Probability (chance) of triggering the error. The value must range from 0 to 100. */
28
55
  Probability: number;
29
56
  }
30
57
 
31
- // Responses and Requests
58
+ /** Common request parameters for APIs with a search query */
59
+ export interface MailpitSearchRequest {
60
+ /** {@link https://mailpit.axllent.org/docs/usage/search-filters/ | Search query} */
61
+ query: string;
62
+ /** {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones | Timezone identifier} used only for `before:` & `after:` searches (eg: "Pacific/Auckland"). */
63
+ tz?: string;
64
+ }
65
+
66
+ /** Common request parameters for APIs requiring a list of message database IDs */
67
+ export interface MailpitDatabaseIDsRequest {
68
+ /** Array of message database IDs */
69
+ IDs?: string[];
70
+ }
71
+
72
+ // API RESPONSES AND REQUESTS
73
+ /** Response for the {@link MailpitClient.getInfo | getInfo()} API containing information about the Mailpit instance. */
32
74
  export interface MailpitInfoResponse {
75
+ /** Database path */
33
76
  Database: string;
77
+ /** Datacase size in bytes */
34
78
  DatabaseSize: number;
79
+ /** Latest Mailpit version */
35
80
  LatestVersion: string;
81
+ /** Total number of messages in the database */
36
82
  Messages: number;
83
+ /** Runtime statistics */
37
84
  RuntimeStats: {
85
+ /** Current memory usage in bytes */
38
86
  Memory: number;
87
+ /** Database runtime messages deleted */
39
88
  MessagesDeleted: number;
89
+ /** Accepted runtime SMTP messages */
40
90
  SMTPAccepted: number;
91
+ /** Total runtime accepted messages size in bytes */
41
92
  SMTPAcceptedSize: number;
93
+ /** Ignored runtime SMTP messages (when using --ignore-duplicate-ids) */
42
94
  SMTPIgnored: number;
95
+ /** Rejected runtime SMTP messages */
43
96
  SMTPRejected: number;
97
+ /** Mailpit server uptime in seconds */
44
98
  Uptime: number;
45
99
  };
100
+ /** Tag information */
46
101
  Tags: {
102
+ /** Tag names and the total messages per tag */
47
103
  [key: string]: number;
48
104
  };
105
+ /** Total number of messages in the database */
49
106
  Unread: number;
107
+ /** Current Mailpit version */
50
108
  Version: string;
51
109
  }
52
110
 
111
+ /** Response for the {@link MailpitClient.getConfiguration| getConfiguraton()} API containing configuration for the Mailpit web UI. */
53
112
  export interface MailpitConfigurationResponse {
113
+ /** Whether Chaos support is enabled at runtime */
114
+ ChaosEnabled: boolean;
115
+ /** Whether messages with duplicate IDs are ignored */
54
116
  DuplicatesIgnored: boolean;
117
+ /** Label to identify this Mailpit instance */
55
118
  Label: string;
56
- SpamAssassin: boolean;
57
119
  MessageRelay: {
120
+ /** Only allow relaying to these recipients (regex) */
58
121
  AllowedRecipients: string;
122
+ /** Block relaying to these recipients (regex) */
123
+ BlockedRecipients: string;
124
+ /** Whether message relaying (release) is enabled */
59
125
  Enabled: boolean;
126
+ /** Overrides the "From" address for all relayed messages */
127
+ OverrideFrom: string;
128
+ /** Enforced Return-Path (if set) for relay bounces */
60
129
  ReturnPath: string;
130
+ /** The configured SMTP server address */
61
131
  SMTPServer: string;
62
132
  };
133
+ /** Whether SpamAssassin is enabled */
134
+ SpamAssassin: boolean;
63
135
  }
64
136
 
137
+ /** Response for the {@link MailpitClient.getMessageSummary| getMessageSummary()} API containing the summary of a message */
65
138
  export interface MailpitMessageSummaryResponse {
66
- Attachments: Attachment[];
67
- Bcc: Address[];
68
- Cc: Address[];
139
+ /** Message Attachmets */
140
+ Attachments: MailpitAttachmentResponse[];
141
+ /** BCC addresses */
142
+ Bcc: MailpitEmailAddressResponse[];
143
+ /** CC addresses */
144
+ Cc: MailpitEmailAddressResponse[];
145
+ /** Message date if set, else date received. In ISO format: 1970-01-01T00:00:00.000Z */
69
146
  Date: string;
70
- From: Address;
147
+ /** sender address */
148
+ From: MailpitEmailAddressResponse;
149
+ /** Message body HTML */
71
150
  HTML: string;
151
+ /** Database ID */
72
152
  ID: string;
73
- Inline: Attachment[];
153
+ /** Inline message attachements */
154
+ Inline: MailpitEmailAddressResponse[];
155
+ /** Message ID */
74
156
  MessageID: string;
75
- ReplyTo: Address[];
157
+ /** ReplyTo addresses */
158
+ ReplyTo: MailpitEmailAddressResponse[];
159
+ /** Return-Path */
76
160
  ReturnPath: string;
161
+ /** Message size in bytes */
77
162
  Size: number;
163
+ /** Message subject */
78
164
  Subject: string;
165
+ /** Messages tags */
79
166
  Tags: string[];
167
+ /** Message body text */
80
168
  Text: string;
81
- To: Address[];
169
+ /** To addresses */
170
+ To: MailpitEmailAddressResponse[];
82
171
  }
83
172
 
173
+ /** Response for the {@link MailpitClient.listMessages| listMessages()} API containing the summary of multiple messages. */
84
174
  export interface MailpitMessagesSummaryResponse {
175
+ /** Messages */
85
176
  messages: {
177
+ /** The number of attachments */
86
178
  Attachments: number;
179
+ /** BCC addresses */
180
+ Bcc: MailpitEmailAddressResponse[];
181
+ /** CC addresses */
182
+ Cc: MailpitEmailAddressResponse[];
183
+ /** Created time in ISO format: 1970-01-01T00:00:00.000Z */
184
+ Created: string;
185
+ /** Sender address */
186
+ From: MailpitEmailAddressResponse;
187
+ /** Database ID */
188
+ ID: string;
189
+ /** Message ID */
190
+ MessageID: string;
191
+ /** Read status */
192
+ Read: boolean;
193
+ /** Reply-To addresses */
194
+ ReplyTo: MailpitEmailAddressResponse[];
195
+ /** Message size in bytes (total) */
87
196
  Size: number;
197
+ /** Message snippet includes up to 250 characters */
88
198
  Snippet: string;
199
+ /** Email subject */
89
200
  Subject: string;
201
+ /** Message tags */
90
202
  Tags: string[];
91
- ID: string;
92
- MessageID: string;
93
- Read: boolean;
94
- Bcc: Address[];
95
- Cc: Address[];
96
- From: Address;
97
- ReplyTo: Address[];
98
- To: Address[];
203
+ /** To addresses */
204
+ To: MailpitEmailAddressResponse[];
99
205
  }[];
206
+ /** Total number of messages matching the current query */
100
207
  messages_count: number;
208
+ /** Pagination offset */
101
209
  start: number;
210
+ /** All current tags */
102
211
  tags: string[];
212
+ /** Total number of messages in mailbox */
103
213
  total: number;
214
+ /** Total number of unread messages in mailbox */
104
215
  unread: number;
105
216
  }
106
217
 
218
+ /** Response for the {@link MailpitClient.getMessageHeaders | getMessageHeaders()} API containing message headers */
107
219
  export interface MailpitMessageHeadersResponse {
108
- [key: string]: string;
220
+ /** Message headers */
221
+ [key: string]: [string];
109
222
  }
110
223
 
224
+ /** Request parameters for the {@link MailpitClient.sendMessage | sendMessage()} API. */
111
225
  export interface MailpitSendRequest {
112
- Attachments: {
113
- Content: string;
114
- Filename: string;
115
- }[];
116
- Bcc: string[];
117
- Cc: Email[];
118
- From: Email;
119
- HTML: string;
120
- Headers: {
226
+ /** Attachments */
227
+ Attachments?: MailpitAttachmentRequest[];
228
+ /** Bcc recipients email addresses only */
229
+ Bcc?: string[];
230
+ /** CC recipients */
231
+ Cc?: MailpitEmailAddressRequest[];
232
+ /** Sender address */
233
+ From: MailpitEmailAddressRequest;
234
+ /** Message body (HTML) */
235
+ HTML?: string;
236
+ /** Optional message headers */
237
+ Headers?: {
238
+ /** Header in key value */
121
239
  [key: string]: string;
122
240
  };
123
- ReplyTo: Email[];
124
- Subject: string;
125
- Tags: string[];
126
- Text: string;
127
- To: Email[];
241
+ /** Optional Reply-To recipients */
242
+ ReplyTo?: MailpitEmailAddressRequest[];
243
+ /** Email message subject */
244
+ Subject?: string;
245
+ /** Mailpit tags */
246
+ Tags?: string[];
247
+ /** Message body (text) */
248
+ Text?: string;
249
+ /** To recipients */
250
+ To: MailpitEmailAddressRequest[];
128
251
  }
129
252
 
253
+ /** Response for the {@link MailpitClient.sendMessage | sendMessage()} API containing confirmation identifier. */
130
254
  export interface MailpitSendMessageConfirmationResponse {
255
+ /** Confirmation message ID */
131
256
  ID: string;
132
257
  }
133
258
 
259
+ /** Response from the {@link MailpitClient.htmlCheck | htmlCheck()} API containing HTML check results. */
134
260
  export interface MailpitHTMLCheckResponse {
261
+ /** All platforms tested, mainly for the web UI */
135
262
  Platforms: {
136
263
  [key: string]: [string];
137
264
  };
265
+ /** Total weighted result for all scores */
138
266
  Total: {
267
+ /** Total number of HTML nodes detected in message */
139
268
  Nodes: number;
269
+ /** Overall percentage partially supported */
140
270
  Partial: number;
271
+ /** Overall percentage supported */
141
272
  Supported: number;
273
+ /** Total number of tests done */
142
274
  Tests: number;
275
+ /** Overall percentage unsupported */
143
276
  Unsupported: number;
144
277
  };
278
+ /** List of warnings from tests */
145
279
  Warnings: {
280
+ /** Category */
146
281
  Category: "css" | "html";
282
+ /** Description */
147
283
  Description: string;
284
+ /** Keywords */
148
285
  Keywords: string;
286
+ /** Notes based on results */
149
287
  NotesByNumber: {
288
+ /** Note in key value */
150
289
  [key: string]: string;
151
290
  };
291
+ /** Test results */
152
292
  Results: {
293
+ /** Family eg: Outlook, Mozilla Thunderbird */
153
294
  Family: string;
295
+ /** Friendly name of result, combining family, platform & version */
154
296
  Name: string;
297
+ /** Note number for partially supported if applicable */
155
298
  NoteNumber: string;
299
+ /** Platform eg: ios, android, windows */
156
300
  Platform: string;
301
+ /** Support */
157
302
  Support: "yes" | "no" | "partial";
303
+ /** Family version eg: 4.7.1, 2019-10, 10.3 */
158
304
  Version: string;
159
305
  }[];
306
+ /** Score object */
160
307
  Score: {
308
+ /** Number of matches in the document */
161
309
  Found: number;
310
+ /** Total percentage partially supported */
162
311
  Partial: number;
312
+ /** Total percentage supported */
163
313
  Supported: number;
314
+ /** Total percentage unsupported */
164
315
  Unsupported: number;
165
316
  };
317
+ /** Slug identifier */
166
318
  Slug: string;
319
+ /** Tags */
167
320
  Tags: string[];
321
+ /** Friendly title */
168
322
  Title: string;
323
+ /** URL to caniemail.com */
169
324
  URL: string;
170
325
  }[];
171
326
  }
172
327
 
328
+ /** Response from the {@link MailpitClient.linkCheck | linkCheck()} API containing link check results. */
173
329
  export interface MailpitLinkCheckResponse {
330
+ /** Total number of errors */
174
331
  Errors: number;
332
+ /** Tested links */
175
333
  Links: {
334
+ /** HTTP status definition */
176
335
  Status: string;
336
+ /** HTTP status code */
177
337
  StatusCode: number;
338
+ /** Link URL */
178
339
  URL: string;
179
340
  }[];
180
341
  }
181
342
 
343
+ /** Response from the {@link MailpitClient.spamAssassinCheck | spamAssassinCheck()} API containing containing SpamAssassin check results. */
182
344
  export interface MailpitSpamAssassinResponse {
345
+ /** If populated will return an error string */
183
346
  Errors: number;
347
+ /** Whether the message is spam or not */
184
348
  IsSpam: boolean;
349
+ /** Spam rules triggered */
185
350
  Rules: {
351
+ /** SpamAssassin rule description */
186
352
  Description: string;
353
+ /** SpamAssassin rule name */
187
354
  Name: string;
355
+ /** Spam rule score */
188
356
  Score: number;
189
357
  }[];
358
+ /** Total spam score based on triggered rules */
190
359
  Score: number;
191
360
  }
192
361
 
193
- export interface MailpitReadStatusRequest {
194
- IDs: string[];
195
- Read: boolean;
362
+ /** Request parameters for the {@link MailpitClient.setReadStatus | setReadStatus()} API. */
363
+ export interface MailpitReadStatusRequest extends MailpitDatabaseIDsRequest {
364
+ /**
365
+ * Read status
366
+ * @defaultValue false
367
+ */
368
+ Read?: boolean;
196
369
  }
197
370
 
198
- export interface MailpitDeleteRequest {
199
- IDs: string[];
200
- }
201
-
202
- export interface MailpitSearchRequest {
203
- query: string;
371
+ /** Request parameters for the {@link MailpitClient.searchMessages | searchMessages()} API. */
372
+ export interface MailpitSearchMessagesRequest extends MailpitSearchRequest {
373
+ /** Pagination offset */
204
374
  start?: number;
375
+ /** Limit results */
205
376
  limit?: number;
206
- tz?: string;
207
- }
208
-
209
- export interface MailpitSearchDeleteRequest {
210
- query: string;
211
- tz?: string;
212
377
  }
213
378
 
379
+ /** Request parameters for the {@link MailpitClient.setTags | setTags()} API. */
214
380
  export interface MailpitSetTagsRequest {
381
+ /** Array of message database IDs */
215
382
  IDs: string[];
216
- Tags: string[];
383
+ /** Array of tag names to set */
384
+ Tags?: string[];
217
385
  }
218
386
 
219
- export interface ChaosTriggersRequest {
220
- Authentication?: ChaosTrigger;
221
- Recipient?: ChaosTrigger;
222
- Sender?: ChaosTrigger;
387
+ /** Request parameters for the {@link MailpitClient.setChaosTriggers | setChaosTriggers()} API. */
388
+ export interface MailpitChaosTriggersRequest {
389
+ /** Optional Authentication trigger for Chaos */
390
+ Authentication?: MailpitChaosTrigger;
391
+ /** Optional Recipient trigger for Chaos */
392
+ Recipient?: MailpitChaosTrigger;
393
+ /** Optional Sender trigger for Chaos */
394
+ Sender?: MailpitChaosTrigger;
223
395
  }
224
396
 
225
- export interface ChaosTriggersResponse {
226
- Authentication: ChaosTrigger;
227
- Recipient?: ChaosTrigger;
228
- Sender?: ChaosTrigger;
397
+ /** Response for the {@link MailpitClient.setChaosTriggers | setChaosTriggers()} and {@link MailpitClient.getChaosTriggers | getChaosTriggers()} APIs containing the current chaos triggers. */
398
+ export interface MailpitChaosTriggersResponse {
399
+ /** Authentication trigger for Chaos */
400
+ Authentication: MailpitChaosTrigger;
401
+ /** Recipient trigger for Chaos */
402
+ Recipient: MailpitChaosTrigger;
403
+ /** Sender trigger for Chaos */
404
+ Sender: MailpitChaosTrigger;
229
405
  }
230
406
 
231
- interface AttachmentResponse {
407
+ /** Response for the {@link MailpitClient.getMessageAttachment |getMessageAttachment()} and {@link MailpitClient.getAttachmentThumbnail | getAttachmentThumbnail()} APIs containing attachment data */
408
+ export interface MailpitAttachmentDataResponse {
409
+ /** The attachment binary data */
232
410
  data: ArrayBuffer;
411
+ /** The attachment MIME type */
233
412
  contentType: string;
234
413
  }
235
414
 
415
+ /**
416
+ * Client for interacting with the {@link https://mailpit.axllent.org/docs/api-v1/ | Mailpit API}.
417
+ * @example
418
+ * ```typescript
419
+ * import { MailpitClient } from "mailpit-api";
420
+ * const mailpit = new MailpitClient("http://localhost:8025");
421
+ * console.log(await mailpit.getInfo());
422
+ * ```
423
+ */
236
424
  export class MailpitClient {
237
425
  private axiosInstance: AxiosInstance;
238
426
 
427
+ /**
428
+ * Creates an instance of {@link MailpitClient}.
429
+ * @param baseURL - The base URL of the Mailpit API.
430
+ * @param auth - Optional authentication credentials.
431
+ * @param auth.username - The username for basic authentication.
432
+ * @param auth.password - The password for basic authentication.
433
+ * @example No Auth
434
+ * ```typescript
435
+ * const mailpit = new MailpitClient("http://localhost:8025");
436
+ * ```
437
+ * @example Basic Auth
438
+ * ```typescript
439
+ * const mailpit = new MailpitClient("http://localhost:8025", {
440
+ * username: "admin",
441
+ * password: "supersecret",
442
+ * });
443
+ * ```
444
+ */
239
445
  constructor(baseURL: string, auth?: { username: string; password: string }) {
240
446
  this.axiosInstance = axios.create({
241
447
  baseURL,
@@ -246,6 +452,13 @@ export class MailpitClient {
246
452
  });
247
453
  }
248
454
 
455
+ /**
456
+ * @internal
457
+ * Handles API requests and errors.
458
+ * @param request - The request function to be executed.
459
+ * @param options - Optional options for the request.
460
+ * @returns A promise that resolves to the response data or the full response object.
461
+ */
249
462
  private async handleRequest<T>(
250
463
  request: () => Promise<AxiosResponse<T>>,
251
464
  options: { fullResponse: true },
@@ -287,20 +500,45 @@ export class MailpitClient {
287
500
  }
288
501
  }
289
502
 
290
- // Application
503
+ /**
504
+ * Retrieves information about the Mailpit instance.
505
+ *
506
+ * @returns Basic runtime information, message totals and latest release version.
507
+ * @example
508
+ * ```typescript
509
+ * const info = await mailpit.getInfo();
510
+ * ```
511
+ */
291
512
  public async getInfo(): Promise<MailpitInfoResponse> {
292
513
  return await this.handleRequest(() =>
293
514
  this.axiosInstance.get<MailpitInfoResponse>("/api/v1/info"),
294
515
  );
295
516
  }
296
517
 
518
+ /**
519
+ * Retrieves the configuration of the Mailpit web UI.
520
+ * @remarks Intended for web UI only!
521
+ * @returns Configuration settings
522
+ * @example
523
+ * ```typescript
524
+ * const config = await mailpit.getConfiguration();
525
+ * ```
526
+ */
297
527
  public async getConfiguration(): Promise<MailpitConfigurationResponse> {
298
528
  return await this.handleRequest(() =>
299
529
  this.axiosInstance.get<MailpitConfigurationResponse>("/api/v1/webui"),
300
530
  );
301
531
  }
302
532
 
303
- // Message
533
+ /**
534
+ * Retrieves a summary of a specific message and marks it as read.
535
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
536
+ * @returns Message summary
537
+ * @example
538
+ * ```typescript
539
+ * const message = await mailpit.getMessageSummary();
540
+ * ```
541
+ */
304
542
  public async getMessageSummary(
305
543
  id: string = "latest",
306
544
  ): Promise<MailpitMessageSummaryResponse> {
@@ -311,6 +549,16 @@ export class MailpitClient {
311
549
  );
312
550
  }
313
551
 
552
+ /**
553
+ * Retrieves the headers of a specific message.
554
+ * @remarks Header keys are returned alphabetically.
555
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
556
+ * @returns Message headers
557
+ * @example
558
+ * ```typescript
559
+ * const headers = await mailpit.getMessageHeaders();
560
+ * ```
561
+ */
314
562
  public async getMessageHeaders(
315
563
  id: string = "latest",
316
564
  ): Promise<MailpitMessageHeadersResponse> {
@@ -321,10 +569,24 @@ export class MailpitClient {
321
569
  );
322
570
  }
323
571
 
572
+ /**
573
+ * Retrieves a specific attachment from a message.
574
+ * @param id - Message database ID or "latest"
575
+ * @param partID - The attachment part ID
576
+ * @returns Attachment as binary data and the content type
577
+ * @example
578
+ * ```typescript
579
+ * const message = await mailpit.getMessageSummary();
580
+ * if (message.Attachments.length) {
581
+ * const attachment = await mailpit.getMessageAttachment(message.ID, message.Attachments[0].PartID);
582
+ * // Do something with the attachment data
583
+ * }
584
+ * ```
585
+ */
324
586
  public async getMessageAttachment(
325
587
  id: string,
326
588
  partID: string,
327
- ): Promise<AttachmentResponse> {
589
+ ): Promise<MailpitAttachmentDataResponse> {
328
590
  const response = await this.handleRequest(
329
591
  () =>
330
592
  this.axiosInstance.get<ArrayBuffer>(
@@ -339,16 +601,28 @@ export class MailpitClient {
339
601
  };
340
602
  }
341
603
 
342
- public async getMessageSource(id: string = "latest"): Promise<string> {
343
- return await this.handleRequest(() =>
344
- this.axiosInstance.get<string>(`/api/v1/message/${id}/raw`),
345
- );
346
- }
347
-
604
+ /**
605
+ * Generates a cropped 180x120 JPEG thumbnail of an image attachment from a message.
606
+ * Only image attachments are supported.
607
+ * @remarks
608
+ * If the image is smaller than 180x120 then the image is padded.
609
+ * If the attachment is not an image then a blank image is returned.
610
+ * @param id - Message database ID or "latest"
611
+ * @param partID - The attachment part ID
612
+ * @returns Image attachment thumbnail as binary data and the content type
613
+ * @example
614
+ * ```typescript
615
+ * const message = await mailpit.getMessageSummary();
616
+ * if (message.Attachments.length) {
617
+ * const thumbnail = await mailpit.getAttachmentThumbnail(message.ID, message.Attachments[0].PartID);
618
+ * // Do something with the thumbnail data
619
+ * }
620
+ * ```
621
+ */
348
622
  public async getAttachmentThumbnail(
349
623
  id: string,
350
624
  partID: string,
351
- ): Promise<AttachmentResponse> {
625
+ ): Promise<MailpitAttachmentDataResponse> {
352
626
  const response = await this.handleRequest(
353
627
  () =>
354
628
  this.axiosInstance.get<ArrayBuffer>(
@@ -365,18 +639,54 @@ export class MailpitClient {
365
639
  };
366
640
  }
367
641
 
642
+ /**
643
+ * Retrieves the full email message source as plain text.
644
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
645
+ * @returns Plain text message source
646
+ * @example
647
+ * ```typescript
648
+ * const messageSource = await mailpit.getMessageSource();
649
+ * ```
650
+ */
651
+ public async getMessageSource(id: string = "latest"): Promise<string> {
652
+ return await this.handleRequest(() =>
653
+ this.axiosInstance.get<string>(`/api/v1/message/${id}/raw`),
654
+ );
655
+ }
656
+
657
+ /**
658
+ * Release a message via a pre-configured external SMTP server.
659
+ * @remarks This is only enabled if message relaying has been configured.
660
+ * @param id - The message database ID. Use `latest` to return the latest message.
661
+ * @param relayTo - Array of email addresses to relay the message to
662
+ * @returns Plain text "ok" response
663
+ * @example
664
+ * ```typescript
665
+ * const message = await mailpit.releaseMessage("latest", ["user1@example.test", "user2@example.test"]);
666
+ * ```
667
+ */
368
668
  public async releaseMessage(
369
669
  id: string,
370
- releaseRequest: { To: string[] },
670
+ relayTo: { To: string[] },
371
671
  ): Promise<string> {
372
672
  return await this.handleRequest(() =>
373
- this.axiosInstance.post<string>(
374
- `/api/v1/message/${id}/release`,
375
- releaseRequest,
376
- ),
673
+ this.axiosInstance.post<string>(`/api/v1/message/${id}/release`, relayTo),
377
674
  );
378
675
  }
379
676
 
677
+ /**
678
+ * Sends a message
679
+ * @param sendReqest - The request containing the message details.
680
+ * @returns Response containing database messsage ID
681
+ * @example
682
+ * ```typescript
683
+ * await mailpit.sendMessage(
684
+ * From: { Email: "user@example.test", Name: "First LastName" },
685
+ * To: [{ Email: "rec@example.test", Name: "Recipient Name"}, {Email: "another@example.test"}],
686
+ * Subject: "Test Email",
687
+ * );
688
+ * ```
689
+ */
380
690
  public async sendMessage(
381
691
  sendReqest: MailpitSendRequest,
382
692
  ): Promise<MailpitSendMessageConfirmationResponse> {
@@ -388,40 +698,18 @@ export class MailpitClient {
388
698
  );
389
699
  }
390
700
 
391
- // Other
392
- public async htmlCheck(
393
- id: string = "latest",
394
- ): Promise<MailpitHTMLCheckResponse> {
395
- return await this.handleRequest(() =>
396
- this.axiosInstance.get<MailpitHTMLCheckResponse>(
397
- `/api/v1/message/${id}/html-check`,
398
- ),
399
- );
400
- }
401
-
402
- public async linkCheck(
403
- id: string = "latest",
404
- follow: "true" | "false" = "false",
405
- ): Promise<MailpitLinkCheckResponse> {
406
- return await this.handleRequest(() =>
407
- this.axiosInstance.get<MailpitLinkCheckResponse>(
408
- `/api/v1/message/${id}/link-check`,
409
- { params: { follow } },
410
- ),
411
- );
412
- }
413
-
414
- public async spamAssassinCheck(
415
- id: string = "latest",
416
- ): Promise<MailpitSpamAssassinResponse> {
417
- return await this.handleRequest(() =>
418
- this.axiosInstance.get<MailpitSpamAssassinResponse>(
419
- `/api/v1/message/${id}/sa-check`,
420
- ),
421
- );
422
- }
423
-
424
- // Messages
701
+ /**
702
+ * Retrieves a list of message summaries ordered from newest to oldest.
703
+ * @remarks Only contains the number of attachments and a snippet of the message body.
704
+ * @see {@link MailpitClient.getMessageSummary | getMessageSummary()} for more attachment and body details for a specific message.
705
+ * @param start - The pagination offset. Defaults to `0`.
706
+ * @param limit - The number of messages to retrieve. Defaults to `50`.
707
+ * @returns A list of message summaries
708
+ * @example
709
+ * ```typescript
710
+ * const messages = await.listMessages();
711
+ * ```
712
+ */
425
713
  public async listMessages(
426
714
  start: number = 0,
427
715
  limit: number = 50,
@@ -434,6 +722,24 @@ export class MailpitClient {
434
722
  );
435
723
  }
436
724
 
725
+ /**
726
+ * Set the read status of messages.
727
+ * @param readStatus - The request containing the message database IDs and read status.
728
+ * @param readStatus.Read - The read status to set. Defaults to `false`.
729
+ * @param readStatus.IDs - The IDs of the messages to update. If not set then all messages are updated.
730
+ * @returns Plain text "ok" response
731
+ * @example
732
+ * ```typescript
733
+ * // Set all messages as unread
734
+ * await mailpit.setReadStatus();
735
+ *
736
+ * // Set all messages as read
737
+ * await mailpit.setReadStatus({ Read: true });
738
+ *
739
+ * // Set specific messages as read
740
+ * await mailpit.setReadStatus({ IDs: ["1", "2", "3"], Read: true });
741
+ * ```
742
+ */
437
743
  public async setReadStatus(
438
744
  readStatus: MailpitReadStatusRequest,
439
745
  ): Promise<string> {
@@ -442,8 +748,22 @@ export class MailpitClient {
442
748
  );
443
749
  }
444
750
 
751
+ /**
752
+ * Delete individual or all messages.
753
+ * @remarks If no `IDs` are provided then all messages are deleted.
754
+ * @param deleteRequest - The request containing the message database IDs to delete.
755
+ * @returns Plain text "ok" response
756
+ * @example
757
+ * ```typescript
758
+ * // Delete all messages
759
+ * await mailpit.deleteMessages();
760
+ *
761
+ * // Delete specific messages
762
+ * await mailpit.deleteMessages({ IDs: ["1", "2", "3"] });
763
+ * ```
764
+ */
445
765
  public async deleteMessages(
446
- deleteRequest?: MailpitDeleteRequest,
766
+ deleteRequest?: MailpitDatabaseIDsRequest,
447
767
  ): Promise<string> {
448
768
  return await this.handleRequest(() =>
449
769
  this.axiosInstance.delete<string>(`/api/v1/messages`, {
@@ -452,9 +772,21 @@ export class MailpitClient {
452
772
  );
453
773
  }
454
774
 
455
- // See https://mailpit.axllent.org/docs/usage/search-filters/
775
+ /**
776
+ * Retrieve messages matching a search, sorted by received date (descending).
777
+ * @see {@link https://mailpit.axllent.org/docs/usage/search-filters/ | Search filters}
778
+ * @remarks Only contains the number of attachments and a snippet of the message body.
779
+ * @see {@link MailpitClient.getMessageSummary | getMessageSummary()} for more attachment and body details for a specific message.
780
+ * @param search - The search request containing the query and optional parameters.
781
+ * @returns A list of message summaries matching the search criteria.
782
+ * @example
783
+ * ```typescript
784
+ * // Search for messages from a the domain example.test
785
+ * const messages = await mailpit.searchMessages({query: "from:example.test"});
786
+ * ```
787
+ */
456
788
  public async searchMessages(
457
- search: MailpitSearchRequest,
789
+ search: MailpitSearchMessagesRequest,
458
790
  ): Promise<MailpitMessagesSummaryResponse> {
459
791
  return await this.handleRequest(() =>
460
792
  this.axiosInstance.get<MailpitMessagesSummaryResponse>(`/api/v1/search`, {
@@ -463,30 +795,135 @@ export class MailpitClient {
463
795
  );
464
796
  }
465
797
 
466
- // See https://mailpit.axllent.org/docs/usage/search-filters/
798
+ /**
799
+ * Delete all messages matching a search.
800
+ * @see {@link https://mailpit.axllent.org/docs/usage/search-filters/ | Search filters}
801
+ * @param search - The search request containing the query.
802
+ * @returns Plain text "ok" response
803
+ * @example
804
+ * ```typescript
805
+ * // Delete all messages from the domain example.test
806
+ * await mailpit.deleteMessagesBySearch({query: "from:example.test"});
807
+ * ```
808
+ */
467
809
  public async deleteMessagesBySearch(
468
- search: MailpitSearchDeleteRequest,
810
+ search: MailpitSearchRequest,
469
811
  ): Promise<string> {
470
812
  return await this.handleRequest(() =>
471
813
  this.axiosInstance.delete<string>(`/api/v1/search`, { params: search }),
472
814
  );
473
815
  }
474
816
 
475
- // Tags
817
+ /**
818
+ * Performs an HTML check on a specific message.
819
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
820
+ * @returns The summary of the message HTML checker
821
+ * @example
822
+ * ```typescript
823
+ * const htmlCheck = await mailpit.htmlCheck();
824
+ * ```
825
+ */
826
+ public async htmlCheck(
827
+ id: string = "latest",
828
+ ): Promise<MailpitHTMLCheckResponse> {
829
+ return await this.handleRequest(() =>
830
+ this.axiosInstance.get<MailpitHTMLCheckResponse>(
831
+ `/api/v1/message/${id}/html-check`,
832
+ ),
833
+ );
834
+ }
835
+
836
+ /**
837
+ * Performs a link check on a specific message.
838
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
839
+ * @param follow - Whether to follow links. Defaults to `false`.
840
+ * @returns The summary of the message Link checker.
841
+ * @example
842
+ * ```typescript
843
+ * const linkCheck = await mailpit.linkCheck();
844
+ * ```
845
+ */
846
+ public async linkCheck(
847
+ id: string = "latest",
848
+ follow: "true" | "false" = "false",
849
+ ): Promise<MailpitLinkCheckResponse> {
850
+ return await this.handleRequest(() =>
851
+ this.axiosInstance.get<MailpitLinkCheckResponse>(
852
+ `/api/v1/message/${id}/link-check`,
853
+ { params: { follow } },
854
+ ),
855
+ );
856
+ }
857
+
858
+ /**
859
+ * Performs a SpamAssassin check (if enabled) on a specific message.
860
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
861
+ * @returns The SpamAssassin summary (if enabled)
862
+ * @example
863
+ * ```typescript
864
+ * const spamAssassinCheck = await mailpit.spamAssassinCheck();
865
+ * ```
866
+ */
867
+ public async spamAssassinCheck(
868
+ id: string = "latest",
869
+ ): Promise<MailpitSpamAssassinResponse> {
870
+ return await this.handleRequest(() =>
871
+ this.axiosInstance.get<MailpitSpamAssassinResponse>(
872
+ `/api/v1/message/${id}/sa-check`,
873
+ ),
874
+ );
875
+ }
876
+
877
+ /**
878
+ * Retrieves a list of all the unique tags.
879
+ * @returns All unique message tags
880
+ * @example
881
+ * ```typescript
882
+ * const tags = await mailpit.getTags();
883
+ * ```
884
+ */
476
885
  public async getTags(): Promise<string[]> {
477
886
  return await this.handleRequest(() =>
478
887
  this.axiosInstance.get<string[]>(`/api/v1/tags`),
479
888
  );
480
889
  }
481
890
 
891
+ /**
892
+ * Sets and removes tag(s) on message(s). This will overwrite any existing tags for selected message database IDs.
893
+ * @param request - The request containing the message IDs and tags. To remove all tags from a message, pass an empty `Tags` array or exclude `Tags` entirely.
894
+ * @remarks
895
+ * Tags are limited to the following characters: `a-z`, `A-Z`, `0-9`, `-`, `.`, `spaces`, and `_`, and must be a minimum of 1 character.
896
+ * Other characters are silently stripped from the tag.
897
+ * @returns Plain text "ok" response
898
+ * @example
899
+ * ```typescript
900
+ * // Set tags on message(s)
901
+ * await mailpit.setTags({ IDs: ["1", "2", "3"], Tags: ["tag1", "tag2"] });
902
+ * // Remove tags from message(s)
903
+ * await mailpit.setTags({ IDs: ["1", "2", "3"]});
904
+ * ```
905
+ */
482
906
  public async setTags(request: MailpitSetTagsRequest): Promise<string> {
483
907
  return await this.handleRequest(() =>
484
908
  this.axiosInstance.put<string>(`/api/v1/tags`, request),
485
909
  );
486
910
  }
487
911
 
912
+ /**
913
+ * Renames an existing tag.
914
+ * @param tag - The current name of the tag.
915
+ * @param newTagName - A new name for the tag.
916
+ * @remarks
917
+ * Tags are limited to the following characters: `a-z`, `A-Z`, `0-9`, `-`, `.`, `spaces`, and `_`, and must be a minimum of 1 character.
918
+ * Other characters are silently stripped from the tag.
919
+ * @returns Plain text "ok" response
920
+ * @example
921
+ * ```typescript
922
+ * await mailpit.renameTag("Old Tag Name", "New Tag Name");
923
+ * ```
924
+ */
488
925
  public async renameTag(tag: string, newTagName: string): Promise<string> {
489
- const encodedTag = encodeURI(tag);
926
+ const encodedTag = encodeURIComponent(tag);
490
927
  return await this.handleRequest(() =>
491
928
  this.axiosInstance.put<string>(`/api/v1/tags/${encodedTag}`, {
492
929
  Name: newTagName,
@@ -494,40 +931,100 @@ export class MailpitClient {
494
931
  );
495
932
  }
496
933
 
934
+ /**
935
+ * Deletes a tag from all messages.
936
+ * @param tag - The name of the tag to delete.
937
+ * @remarks This does NOT delete any messages
938
+ * @returns Plain text "ok" response
939
+ * ```typescript
940
+ * await mailpit.deleteTag("Tag 1");
941
+ * ```
942
+ */
497
943
  public async deleteTag(tag: string): Promise<string> {
498
- const encodedTag = encodeURI(tag);
944
+ const encodedTag = encodeURIComponent(tag);
499
945
  return await this.handleRequest(() =>
500
946
  this.axiosInstance.delete<string>(`/api/v1/tags/${encodedTag}`),
501
947
  );
502
948
  }
503
949
 
504
- // Testing
505
- public async renderMessageHTML(
506
- id: string = "latest",
507
- embed?: 1,
508
- ): Promise<string> {
950
+ /**
951
+ * Retrieves the current Chaos triggers configuration (if enabled).
952
+ * @remarks This will return an error if Chaos is not enabled at runtime.
953
+ * @returns The Chaos triggers configuration
954
+ * @example
955
+ * ```typescript
956
+ * const triggers = await mailpit.getChaosTriggers();
957
+ * ```
958
+ */
959
+ public async getChaosTriggers(): Promise<MailpitChaosTriggersResponse> {
509
960
  return await this.handleRequest(() =>
510
- this.axiosInstance.get<string>(`/view/${id}.html`, { params: { embed } }),
961
+ this.axiosInstance.get<MailpitChaosTriggersResponse>("/api/v1/chaos"),
511
962
  );
512
963
  }
513
964
 
514
- public async renderMessageText(id: string = "latest"): Promise<string> {
965
+ /**
966
+ * Sets and/or resets the Chaos triggers configuration (if enabled).
967
+ * @param triggers - The request containing the chaos triggers. Omitted triggers will reset to the default `0%` probabibility.
968
+ * @remarks This will return an error if Chaos is not enabled at runtime.
969
+ * @returns The updated Chaos triggers configuration
970
+ * @example
971
+ * ```typescript
972
+ * // Reset all triggers to `0%` probability
973
+ * const triggers = await mailpit.setChaosTriggers();
974
+ * // Set `Sender` and reset `Authentication` and `Recipient` triggers
975
+ * const triggers = await mailpit.setChaosTriggers({ Sender: { ErrorCode: 451, Probability: 5 } });
976
+ * ```
977
+ */
978
+ public async setChaosTriggers(
979
+ triggers: MailpitChaosTriggersRequest = {},
980
+ ): Promise<MailpitChaosTriggersResponse> {
515
981
  return await this.handleRequest(() =>
516
- this.axiosInstance.get<string>(`/view/${id}.txt`),
982
+ this.axiosInstance.put<MailpitChaosTriggersResponse>(
983
+ "/api/v1/chaos",
984
+ triggers,
985
+ ),
517
986
  );
518
987
  }
519
988
 
520
- public async getChaosTriggers(): Promise<ChaosTriggersResponse> {
989
+ /**
990
+ * Renders the HTML part of a specific message which can be used for UI integration testing.
991
+ * @remarks
992
+ * Attached inline images are modified to link to the API provided they exist.
993
+ * If the message does not contain an HTML part then a 404 error is returned.
994
+ *
995
+ *
996
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
997
+ * @param embed - Whether this route is to be embedded in an iframe. Defaults to `undefined`. Set to `1` to embed.
998
+ * The `embed` parameter will add `target="_blank"` and `rel="noreferrer noopener"` to all links.
999
+ * In addition, a small script will be added to the end of the document to post (postMessage()) the height of the document back to the parent window for optional iframe height resizing.
1000
+ * Note that this will also transform the message into a full HTML document (if it isn't already), so this option is useful for viewing but not programmatic testing.
1001
+ * @returns Rendered HTML
1002
+ * @example
1003
+ * ```typescript
1004
+ * const html = await mailpit.renderMessageHTML();
1005
+ * ```
1006
+ */
1007
+ public async renderMessageHTML(
1008
+ id: string = "latest",
1009
+ embed?: 1,
1010
+ ): Promise<string> {
521
1011
  return await this.handleRequest(() =>
522
- this.axiosInstance.get<ChaosTriggersResponse>("/api/v1/chaos"),
1012
+ this.axiosInstance.get<string>(`/view/${id}.html`, { params: { embed } }),
523
1013
  );
524
1014
  }
525
1015
 
526
- public async setChaosTriggers(
527
- triggers: ChaosTriggersRequest = {},
528
- ): Promise<ChaosTriggersResponse> {
1016
+ /**
1017
+ * Renders just the message's text part which can be used for UI integration testing.
1018
+ * @param id - The message database ID. Defaults to `latest` to return the latest message.
1019
+ * @returns Plain text
1020
+ * @example
1021
+ * ```typescript
1022
+ * const html = await mailpit.renderMessageText();
1023
+ * ```
1024
+ */
1025
+ public async renderMessageText(id: string = "latest"): Promise<string> {
529
1026
  return await this.handleRequest(() =>
530
- this.axiosInstance.put<ChaosTriggersResponse>("/api/v1/chaos", triggers),
1027
+ this.axiosInstance.get<string>(`/view/${id}.txt`),
531
1028
  );
532
1029
  }
533
1030
  }