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