@unboundcx/sdk 2.7.7 → 2.8.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.
@@ -0,0 +1,690 @@
1
+ import { EmailTemplatesService } from './EmailTemplatesService.js';
2
+ import { EmailDomainsService } from './EmailDomainsService.js';
3
+ import { EmailAddressesService } from './EmailAddressesService.js';
4
+ import { EmailMailboxesService } from './EmailMailboxesService.js';
5
+ import { EmailAnalyticsService } from './EmailAnalyticsService.js';
6
+ import { EmailQueueService } from './EmailQueueService.js';
7
+ import { EmailSuppressionService } from './EmailSuppressionService.js';
8
+
9
+ export class EmailService {
10
+ constructor(sdk) {
11
+ this.sdk = sdk;
12
+ this.templates = new EmailTemplatesService(sdk);
13
+ this.domains = new EmailDomainsService(sdk);
14
+ this.addresses = new EmailAddressesService(sdk);
15
+ this.mailboxes = new EmailMailboxesService(sdk);
16
+ this.analytics = new EmailAnalyticsService(sdk);
17
+ this.queue = new EmailQueueService(sdk);
18
+ this.suppression = new EmailSuppressionService(sdk);
19
+ }
20
+
21
+ /**
22
+ * Send an email message
23
+ * @param {Object} params - Email parameters
24
+ * @param {string} [params.from] - Sender email address (required unless using draftId)
25
+ * @param {string|Array<string>} [params.to] - Recipient email address(es) (required unless using draftId)
26
+ * @param {string} [params.subject] - Email subject (required unless using draftId)
27
+ * @param {string|Array<string>} [params.cc] - CC recipients
28
+ * @param {string|Array<string>} [params.bcc] - BCC recipients
29
+ * @param {string} [params.html] - HTML email body
30
+ * @param {string} [params.text] - Plain text email body
31
+ * @param {string} [params.templateId] - Email template ID to use
32
+ * @param {Object} [params.variables] - Template variables for substitution
33
+ * @param {Array} [params.storageId] - Array of storage IDs for attachments
34
+ * @param {string} [params.replyTo] - Reply-to email address
35
+ * @param {string} [params.replyToEmailId] - ID of email this is replying to
36
+ * @param {string} [params.relatedId] - Related record ID
37
+ * @param {string} [params.emailType='marketing'] - Email type: 'marketing' or 'transactional'
38
+ * @param {boolean} [params.tracking=true] - Enable email tracking (opens, clicks)
39
+ * @param {string} [params.mailboxId] - Specific mailbox to send from
40
+ * @param {string} [params.draftId] - Convert existing draft to sent email
41
+ * @returns {Promise<Object>} Email send result with ID and threading info
42
+ */
43
+ async send({
44
+ from,
45
+ to,
46
+ cc,
47
+ bcc,
48
+ subject,
49
+ html,
50
+ text,
51
+ templateId,
52
+ variables,
53
+ storageId,
54
+ replyTo,
55
+ replyToEmailId,
56
+ relatedId,
57
+ emailType,
58
+ tracking,
59
+ mailboxId,
60
+ draftId,
61
+ engagementSessionId,
62
+ }) {
63
+ // Validate required params (relaxed when using draftId)
64
+ if (!draftId) {
65
+ this.sdk.validateParams(
66
+ { from, to, subject },
67
+ {
68
+ from: { type: 'string', required: true },
69
+ subject: { type: 'string', required: true },
70
+ },
71
+ );
72
+ }
73
+
74
+ // Validate optional params
75
+ this.sdk.validateParams(
76
+ {
77
+ cc,
78
+ bcc,
79
+ html,
80
+ text,
81
+ templateId,
82
+ variables,
83
+ storageId,
84
+ replyTo,
85
+ replyToEmailId,
86
+ relatedId,
87
+ emailType,
88
+ tracking,
89
+ mailboxId,
90
+ draftId,
91
+ engagementSessionId,
92
+ },
93
+ {
94
+ html: { type: 'string', required: false },
95
+ text: { type: 'string', required: false },
96
+ templateId: { type: 'string', required: false },
97
+ variables: { type: 'object', required: false },
98
+ storageId: { type: 'array', required: false },
99
+ replyTo: { type: 'string', required: false },
100
+ replyToEmailId: { type: 'string', required: false },
101
+ relatedId: { type: 'string', required: false },
102
+ emailType: { type: 'string', required: false },
103
+ tracking: { type: 'boolean', required: false },
104
+ mailboxId: { type: 'string', required: false },
105
+ draftId: { type: 'string', required: false },
106
+ engagementSessionId: { type: 'string', required: false },
107
+ },
108
+ );
109
+
110
+ const emailData = {};
111
+
112
+ if (from !== undefined) emailData.from = from;
113
+ if (to !== undefined) emailData.to = to;
114
+ if (subject !== undefined) emailData.subject = subject;
115
+ if (cc) emailData.cc = cc;
116
+ if (bcc) emailData.bcc = bcc;
117
+ if (html) emailData.html = html;
118
+ if (text) emailData.text = text;
119
+ if (templateId) emailData.templateId = templateId;
120
+ if (variables) emailData.variables = variables;
121
+ if (storageId) emailData.storageId = storageId;
122
+ if (replyTo) emailData.replyTo = replyTo;
123
+ if (replyToEmailId) emailData.replyToEmailId = replyToEmailId;
124
+ if (relatedId) emailData.relatedId = relatedId;
125
+ if (emailType) emailData.emailType = emailType;
126
+ if (tracking !== undefined) emailData.tracking = tracking;
127
+ if (mailboxId) emailData.mailboxId = mailboxId;
128
+ if (draftId) emailData.draftId = draftId;
129
+ if (engagementSessionId)
130
+ emailData.engagementSessionId = engagementSessionId;
131
+
132
+ const options = {
133
+ body: emailData,
134
+ };
135
+
136
+ const result = await this.sdk._fetch('/messaging/email', 'POST', options);
137
+ return result;
138
+ }
139
+
140
+ /**
141
+ * Get email message by ID
142
+ * @param {string} id - Email message ID (required)
143
+ * @returns {Promise<Object>} Email message details with related emails (deduplicated from same person/company)
144
+ * @example
145
+ * const email = await sdk.messaging.email.get('email_123');
146
+ * // Returns:
147
+ * {
148
+ * id: "email_123",
149
+ * subject: "Project Discussion",
150
+ * html: "<p>Email content...</p>",
151
+ * plainText: "Email content...",
152
+ * from: "john@company.com",
153
+ * to: ["jane@mycompany.com"],
154
+ * peopleId: "person_456",
155
+ * companyId: "company_789",
156
+ * relatedEmails: [
157
+ * { id: "email_124", subject: "Previous email from John", dateTime: "2023-12-01T10:00:00Z", ... },
158
+ * { id: "email_125", subject: "Other email from Company", dateTime: "2023-11-30T15:00:00Z", ... }
159
+ * ]
160
+ * }
161
+ */
162
+ async get(id) {
163
+ this.sdk.validateParams(
164
+ { id },
165
+ {
166
+ id: { type: 'string', required: true },
167
+ },
168
+ );
169
+
170
+ const result = await this.sdk._fetch(
171
+ `/messaging/email/message/${id}`,
172
+ 'GET',
173
+ );
174
+ return result;
175
+ }
176
+
177
+ /**
178
+ * Update domain email settings
179
+ * @param {string} id - Domain ID (required)
180
+ * @param {Object} params - Update parameters
181
+ * @param {boolean} [params.dkimEnabled] - Enable DKIM signing
182
+ * @param {Object} [params.customDkim] - Custom DKIM configuration
183
+ * @returns {Promise<Object>} Updated domain details
184
+ */
185
+ async updateDomain(id, { dkimEnabled, customDkim }) {
186
+ this.sdk.validateParams(
187
+ { id },
188
+ {
189
+ id: { type: 'string', required: true },
190
+ dkimEnabled: { type: 'boolean', required: false },
191
+ customDkim: { type: 'object', required: false },
192
+ },
193
+ );
194
+
195
+ const updateData = {};
196
+ if (dkimEnabled !== undefined) updateData.dkimEnabled = dkimEnabled;
197
+ if (customDkim) updateData.customDkim = customDkim;
198
+
199
+ const options = {
200
+ body: updateData,
201
+ };
202
+
203
+ const result = await this.sdk._fetch(
204
+ `/messaging/email/${id}`,
205
+ 'PUT',
206
+ options,
207
+ );
208
+ return result;
209
+ }
210
+
211
+ /*
212
+ * EMAIL DRAFTS
213
+ */
214
+
215
+ /**
216
+ * Create an email draft
217
+ * @param {Object} params - Draft parameters
218
+ * @param {string} [params.from] - Sender email address (auto-selected from mailbox if not provided)
219
+ * @param {string|Array<string>} [params.to] - Recipient email address(es)
220
+ * @param {string|Array<string>} [params.cc] - CC recipients
221
+ * @param {string|Array<string>} [params.bcc] - BCC recipients
222
+ * @param {string} [params.subject] - Email subject
223
+ * @param {string} [params.html] - HTML email body
224
+ * @param {string} [params.text] - Plain text email body
225
+ * @param {string} [params.templateId] - Email template ID to use
226
+ * @param {Object} [params.variables] - Template variables for substitution
227
+ * @param {Array} [params.storageId] - Array of storage IDs for attachments
228
+ * @param {string} [params.replyTo] - Reply-to email address
229
+ * @param {string} [params.replyToEmailId] - ID of email this is replying to
230
+ * @param {string} [params.relatedId] - Related record ID
231
+ * @param {string} [params.emailType='marketing'] - Email type: 'marketing' or 'transactional'
232
+ * @param {boolean} [params.tracking=true] - Enable email tracking (opens, clicks)
233
+ * @param {string} [params.mailboxId] - Specific mailbox for the draft
234
+ * @param {string} [params.replyType] - Reply type: 'reply', 'replyAll', or 'forward' (auto-formats content)
235
+ * @param {string} [params.engagementSessionId] - Engagement session ID to link to the draft
236
+ * @returns {Promise<Object>} Created draft details
237
+ */
238
+ async createDraft({
239
+ from,
240
+ to,
241
+ cc,
242
+ bcc,
243
+ subject,
244
+ html,
245
+ text,
246
+ templateId,
247
+ variables,
248
+ storageId,
249
+ replyTo,
250
+ replyToEmailId,
251
+ relatedId,
252
+ emailType,
253
+ tracking,
254
+ mailboxId,
255
+ replyType,
256
+ engagementSessionId,
257
+ }) {
258
+ this.sdk.validateParams(
259
+ {
260
+ from,
261
+ to,
262
+ cc,
263
+ bcc,
264
+ subject,
265
+ html,
266
+ text,
267
+ templateId,
268
+ variables,
269
+ storageId,
270
+ replyTo,
271
+ replyToEmailId,
272
+ relatedId,
273
+ emailType,
274
+ tracking,
275
+ mailboxId,
276
+ replyType,
277
+ engagementSessionId,
278
+ },
279
+ {
280
+ from: { type: 'string', required: false },
281
+ subject: { type: 'string', required: false },
282
+ html: { type: 'string', required: false },
283
+ text: { type: 'string', required: false },
284
+ templateId: { type: 'string', required: false },
285
+ variables: { type: 'object', required: false },
286
+ storageId: { type: 'array', required: false },
287
+ replyTo: { type: 'string', required: false },
288
+ replyToEmailId: { type: 'string', required: false },
289
+ relatedId: { type: 'string', required: false },
290
+ emailType: { type: 'string', required: false },
291
+ tracking: { type: 'boolean', required: false },
292
+ mailboxId: { type: 'string', required: false },
293
+ replyType: { type: 'string', required: false },
294
+ engagementSessionId: { type: 'string', required: false },
295
+ },
296
+ );
297
+
298
+ const draftData = {};
299
+
300
+ if (from) draftData.from = from;
301
+ if (to) draftData.to = to;
302
+ if (cc) draftData.cc = cc;
303
+ if (bcc) draftData.bcc = bcc;
304
+ if (subject) draftData.subject = subject;
305
+ if (html) draftData.html = html;
306
+ if (text) draftData.text = text;
307
+ if (templateId) draftData.templateId = templateId;
308
+ if (variables) draftData.variables = variables;
309
+ if (storageId) draftData.storageId = storageId;
310
+ if (replyTo) draftData.replyTo = replyTo;
311
+ if (replyToEmailId) draftData.replyToEmailId = replyToEmailId;
312
+ if (relatedId) draftData.relatedId = relatedId;
313
+ if (emailType) draftData.emailType = emailType;
314
+ if (tracking !== undefined) draftData.tracking = tracking;
315
+ if (mailboxId) draftData.mailboxId = mailboxId;
316
+ if (replyType) draftData.replyType = replyType;
317
+ if (engagementSessionId)
318
+ draftData.engagementSessionId = engagementSessionId;
319
+
320
+ const params = {
321
+ body: draftData,
322
+ };
323
+
324
+ const result = await this.sdk._fetch(
325
+ '/messaging/email/drafts',
326
+ 'POST',
327
+ params,
328
+ );
329
+ return result;
330
+ }
331
+
332
+ /**
333
+ * Update an existing email draft
334
+ * @param {string} id - Draft ID (required)
335
+ * @param {Object} params - Fields to update
336
+ * @param {string} [params.from] - Sender email address
337
+ * @param {string|Array<string>} [params.to] - Recipient email address(es)
338
+ * @param {string|Array<string>} [params.cc] - CC recipients
339
+ * @param {string|Array<string>} [params.bcc] - BCC recipients
340
+ * @param {string} [params.subject] - Email subject
341
+ * @param {string} [params.html] - HTML email body
342
+ * @param {string} [params.text] - Plain text email body
343
+ * @param {string} [params.templateId] - Email template ID to use
344
+ * @param {Object} [params.variables] - Template variables for substitution
345
+ * @param {Array} [params.storageId] - Array of storage IDs for attachments
346
+ * @param {string} [params.replyTo] - Reply-to email address
347
+ * @param {string} [params.emailType] - Email type: 'marketing' or 'transactional'
348
+ * @param {boolean} [params.tracking] - Enable email tracking (opens, clicks)
349
+ * @param {string} [params.mailboxId] - Specific mailbox for the draft
350
+ * @param {string} [params.engagementSessionId] - Engagement session ID to link to the draft
351
+ * @returns {Promise<Object>} Updated draft details
352
+ */
353
+ async updateDraft(
354
+ id,
355
+ {
356
+ from,
357
+ to,
358
+ cc,
359
+ bcc,
360
+ subject,
361
+ html,
362
+ text,
363
+ templateId,
364
+ variables,
365
+ storageId,
366
+ replyTo,
367
+ emailType,
368
+ tracking,
369
+ mailboxId,
370
+ engagementSessionId,
371
+ },
372
+ ) {
373
+ this.sdk.validateParams(
374
+ {
375
+ id,
376
+ from,
377
+ to,
378
+ cc,
379
+ bcc,
380
+ subject,
381
+ html,
382
+ text,
383
+ templateId,
384
+ variables,
385
+ storageId,
386
+ replyTo,
387
+ emailType,
388
+ tracking,
389
+ mailboxId,
390
+ engagementSessionId,
391
+ },
392
+ {
393
+ id: { type: 'string', required: true },
394
+ from: { type: 'string', required: false },
395
+ subject: { type: 'string', required: false },
396
+ html: { type: 'string', required: false },
397
+ text: { type: 'string', required: false },
398
+ templateId: { type: 'string', required: false },
399
+ variables: { type: 'object', required: false },
400
+ storageId: { type: 'array', required: false },
401
+ replyTo: { type: 'string', required: false },
402
+ emailType: { type: 'string', required: false },
403
+ tracking: { type: 'boolean', required: false },
404
+ mailboxId: { type: 'string', required: false },
405
+ engagementSessionId: { type: 'string', required: false },
406
+ },
407
+ );
408
+
409
+ const updateData = {};
410
+
411
+ if (from !== undefined) updateData.from = from;
412
+ if (to !== undefined) updateData.to = to;
413
+ if (cc !== undefined) updateData.cc = cc;
414
+ if (bcc !== undefined) updateData.bcc = bcc;
415
+ if (subject !== undefined) updateData.subject = subject;
416
+ if (html !== undefined) updateData.html = html;
417
+ if (text !== undefined) updateData.text = text;
418
+ if (templateId !== undefined) updateData.templateId = templateId;
419
+ if (variables !== undefined) updateData.variables = variables;
420
+ if (storageId !== undefined) updateData.storageId = storageId;
421
+ if (replyTo !== undefined) updateData.replyTo = replyTo;
422
+ if (emailType !== undefined) updateData.emailType = emailType;
423
+ if (tracking !== undefined) updateData.tracking = tracking;
424
+ if (mailboxId !== undefined) updateData.mailboxId = mailboxId;
425
+ if (engagementSessionId)
426
+ updateData.engagementSessionId = engagementSessionId;
427
+
428
+ const params = {
429
+ body: updateData,
430
+ };
431
+
432
+ const result = await this.sdk._fetch(
433
+ `/messaging/email/drafts/${id}`,
434
+ 'PUT',
435
+ params,
436
+ );
437
+ return result;
438
+ }
439
+
440
+ /**
441
+ * Get draft by ID
442
+ * @param {string} id - Draft ID (required)
443
+ * @returns {Promise<Object>} Draft details
444
+ */
445
+ async getDraft(id) {
446
+ this.sdk.validateParams(
447
+ { id },
448
+ {
449
+ id: { type: 'string', required: true },
450
+ },
451
+ );
452
+
453
+ const result = await this.sdk._fetch(
454
+ `/messaging/email/drafts/${id}`,
455
+ 'GET',
456
+ );
457
+ return result;
458
+ }
459
+
460
+ /**
461
+ * Delete draft by ID
462
+ * @param {string} id - Draft ID (required)
463
+ * @returns {Promise<Object>} Deletion result
464
+ */
465
+ async deleteDraft(id) {
466
+ this.sdk.validateParams(
467
+ { id },
468
+ {
469
+ id: { type: 'string', required: true },
470
+ },
471
+ );
472
+
473
+ const result = await this.sdk._fetch(
474
+ `/messaging/email/drafts/${id}`,
475
+ 'DELETE',
476
+ );
477
+ return result;
478
+ }
479
+
480
+ /**
481
+ * List email drafts
482
+ * @param {Object} [filters] - Filter options
483
+ * @param {string} [filters.mailboxId] - Filter by mailbox ID
484
+ * @param {string} [filters.subject] - Search in subject
485
+ * @param {string} [filters.threadId] - Filter by thread ID
486
+ * @param {number} [filters.limit=50] - Number of results per page (max 200)
487
+ * @param {number} [filters.offset=0] - Offset for pagination
488
+ * @returns {Promise<Object>} Paginated list of drafts
489
+ */
490
+ async listDrafts({
491
+ mailboxId,
492
+ subject,
493
+ threadId,
494
+ limit = 50,
495
+ offset = 0,
496
+ } = {}) {
497
+ this.sdk.validateParams(
498
+ { mailboxId, subject, threadId, limit, offset },
499
+ {
500
+ mailboxId: { type: 'string', required: false },
501
+ subject: { type: 'string', required: false },
502
+ threadId: { type: 'string', required: false },
503
+ limit: { type: 'number', required: false },
504
+ offset: { type: 'number', required: false },
505
+ },
506
+ );
507
+ const params = {
508
+ query: {
509
+ limit,
510
+ offset,
511
+ mailboxId,
512
+ subject,
513
+ threadId,
514
+ },
515
+ };
516
+
517
+ const result = await this.sdk._fetch(
518
+ '/messaging/email/drafts',
519
+ 'GET',
520
+ params,
521
+ );
522
+ return result;
523
+ }
524
+
525
+ /*
526
+ * MAILBOX EMAILS
527
+ */
528
+
529
+ /**
530
+ * Get emails from a specific mailbox (Gmail-like view with messages and their threads)
531
+ * @param {string} mailboxId - Mailbox ID (required)
532
+ * @param {Object} [filters] - Filter options
533
+ * @param {string} [filters.folder='open'] - Email folder: 'open' or 'closed'
534
+ * @param {boolean} [filters.includeDrafts=false] - Include draft emails
535
+ * @param {string} [filters.search] - Search in subject, from, or recipients
536
+ * @param {string} [filters.sortBy='dateTime'] - Sort field: 'dateTime', 'createdAt', 'subject', 'from'
537
+ * @param {string} [filters.sortOrder='desc'] - Sort order: 'asc', 'desc'
538
+ * @param {number} [filters.limit=25] - Number of results per page (max 200)
539
+ * @param {number} [filters.offset=0] - Offset for pagination
540
+ * @returns {Promise<Object>} List of email messages with their threads
541
+ * @example
542
+ * // Returns messages with nested threads for Gmail-like UI:
543
+ * {
544
+ * messages: [
545
+ * {
546
+ * id: "email_123",
547
+ * subject: "Project Discussion",
548
+ * to: ["john@example.com"],
549
+ * cc: [],
550
+ * from: "jane@example.com",
551
+ * isDraft: false,
552
+ * hasAttachments: false,
553
+ * isUnread: true,
554
+ * direction: "inbound",
555
+ * dateTime: "2023-12-01T15:30:00Z",
556
+ * snippet: "Thanks for the update...",
557
+ * threads: [
558
+ * {
559
+ * id: "email_124",
560
+ * subject: "Re: Project Discussion",
561
+ * // ... same structure as main message
562
+ * }
563
+ * ]
564
+ * }
565
+ * ],
566
+ * pagination: { total: 50, limit: 25, hasMore: true }
567
+ * }
568
+ */
569
+ async getMailboxEmails(
570
+ mailboxId,
571
+ {
572
+ folder = 'open',
573
+ includeDrafts = false,
574
+ search,
575
+ sortBy = 'dateTime',
576
+ sortOrder = 'desc',
577
+ limit = 25,
578
+ offset = 0,
579
+ } = {},
580
+ ) {
581
+ this.sdk.validateParams(
582
+ {
583
+ mailboxId,
584
+ folder,
585
+ includeDrafts,
586
+ search,
587
+ sortBy,
588
+ sortOrder,
589
+ limit,
590
+ offset,
591
+ },
592
+ {
593
+ mailboxId: { type: 'string', required: true },
594
+ folder: { type: 'string', required: false },
595
+ includeDrafts: { type: 'boolean', required: false },
596
+ search: { type: 'string', required: false },
597
+ sortBy: { type: 'string', required: false },
598
+ sortOrder: { type: 'string', required: false },
599
+ limit: { type: 'number', required: false },
600
+ offset: { type: 'number', required: false },
601
+ },
602
+ );
603
+
604
+ const query = { folder, includeDrafts, sortBy, sortOrder, limit, offset };
605
+ if (search) query.search = search;
606
+
607
+ const params = {
608
+ query,
609
+ };
610
+
611
+ const result = await this.sdk._fetch(
612
+ `/messaging/email/mailbox/${mailboxId}/emails`,
613
+ 'GET',
614
+ params,
615
+ );
616
+ return result;
617
+ }
618
+
619
+ /**
620
+ * Update an email message (e.g., move between folders, mark as read/unread)
621
+ * @param {string} emailId - Email ID to update
622
+ * @param {Object} updates - Object containing fields to update
623
+ * @param {string} [updates.folder] - Folder to move email to (open, completed, trash, spam)
624
+ * @param {boolean} [updates.isRead] - Mark email as read (true) or unread (false). Automatically sets/clears isReadBy field.
625
+ * @returns {Promise<Object>} Update result
626
+ * @example
627
+ * // Move email to completed folder
628
+ * await sdk.messaging.email.update('emailId123', {folder: 'completed'});
629
+ *
630
+ * // Mark email as read (sets isReadBy to current user)
631
+ * await sdk.messaging.email.update('emailId123', {isRead: true});
632
+ *
633
+ * // Mark email as unread (clears isReadBy field)
634
+ * await sdk.messaging.email.update('emailId123', {isRead: false});
635
+ *
636
+ * // Mark as unread and move to open
637
+ * await sdk.messaging.email.update('emailId123', {folder: 'open', isRead: false});
638
+ */
639
+ async update(emailId, updates = {}) {
640
+ const updateData = { ...updates };
641
+
642
+ this.sdk.validateParams(
643
+ { emailId, ...updateData },
644
+ {
645
+ emailId: { type: 'string', required: true },
646
+ folder: { type: 'string', required: false },
647
+ isRead: { type: 'boolean', required: false },
648
+ },
649
+ );
650
+
651
+ const result = await this.sdk._fetch(
652
+ `/messaging/email/message/${emailId}`,
653
+ 'PUT',
654
+ {
655
+ body: updateData,
656
+ },
657
+ );
658
+ return result;
659
+ }
660
+
661
+ /**
662
+ * Delete an email message (two-stage deletion)
663
+ * - First delete: Move to trash folder (recoverable)
664
+ * - Second delete: Permanently delete if already in trash
665
+ * @param {string} emailId - Email ID to delete
666
+ * @returns {Promise<Object>} Deletion result with action type
667
+ * @example
668
+ * // First delete: Move to trash
669
+ * const result1 = await sdk.messaging.email.delete('emailId123');
670
+ * // Returns: { action: 'trash', message: 'Email moved to trash' }
671
+ *
672
+ * // Second delete: Permanent deletion
673
+ * const result2 = await sdk.messaging.email.delete('emailId123');
674
+ * // Returns: { action: 'permanent', message: 'Email permanently deleted' }
675
+ */
676
+ async delete(emailId) {
677
+ this.sdk.validateParams(
678
+ { emailId },
679
+ {
680
+ emailId: { type: 'string', required: true },
681
+ },
682
+ );
683
+
684
+ const result = await this.sdk._fetch(
685
+ `/messaging/email/message/${emailId}`,
686
+ 'DELETE',
687
+ );
688
+ return result;
689
+ }
690
+ }