Skip to content

Commit 3c89545

Browse files
authored
Merge pull request #77 from internxt/fixture/send-the-correct-email
fix/send the correct recipients when sending drafted email
2 parents bca0e63 + a6644e3 commit 3c89545

2 files changed

Lines changed: 53 additions & 42 deletions

File tree

src/modules/infrastructure/jmap/jmap-mail.provider.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,58 @@ describe('JmapMailProvider', () => {
350350
'Failed to create email for sending',
351351
);
352352
});
353+
354+
test('When sending from an existing draft, then the new email is created with the latest content and the previous draft is removed in the same operation', async () => {
355+
const sentMailbox = newJmapMailbox({ role: 'sent' });
356+
const identity = newJmapIdentity();
357+
358+
jmapService.request.mockResolvedValueOnce(
359+
jmapResponse({ list: [identity] }),
360+
);
361+
jmapService.request.mockResolvedValueOnce(
362+
jmapResponse({ list: [sentMailbox] }),
363+
);
364+
jmapService.request.mockResolvedValueOnce(
365+
jmapMultiResponse(
366+
{ created: { draft: { id: 'sent-email-id' } } },
367+
{ created: { submission: { id: 'sub-id' } } },
368+
),
369+
);
370+
371+
const dto = newSendEmailDto({ draftId: 'old-draft-id' });
372+
const result = await provider.sendEmail('user@test.com', dto);
373+
374+
const lastCall = jmapService.request.mock.calls.at(-1)!;
375+
const [emailSetName, emailSetArgs] = lastCall[1][0]!;
376+
expect(emailSetName).toBe('Email/set');
377+
expect(emailSetArgs['destroy']).toEqual(['old-draft-id']);
378+
expect(emailSetArgs['create']).toBeDefined();
379+
expect(result).toEqual({ id: 'sent-email-id' });
380+
});
381+
382+
test('When sending without a draftId, then the Email/set call does not include any destroy operation', async () => {
383+
const sentMailbox = newJmapMailbox({ role: 'sent' });
384+
const identity = newJmapIdentity();
385+
386+
jmapService.request.mockResolvedValueOnce(
387+
jmapResponse({ list: [identity] }),
388+
);
389+
jmapService.request.mockResolvedValueOnce(
390+
jmapResponse({ list: [sentMailbox] }),
391+
);
392+
jmapService.request.mockResolvedValueOnce(
393+
jmapMultiResponse(
394+
{ created: { draft: { id: 'sent-email-id' } } },
395+
{ created: { submission: { id: 'sub-id' } } },
396+
),
397+
);
398+
399+
await provider.sendEmail('user@test.com', newSendEmailDto());
400+
401+
const lastCall = jmapService.request.mock.calls.at(-1)!;
402+
const [, emailSetArgs] = lastCall[1][0]!;
403+
expect(emailSetArgs['destroy']).toBeUndefined();
404+
});
353405
});
354406

355407
describe('saveDraft', () => {

src/modules/infrastructure/jmap/jmap-mail.provider.ts

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,6 @@ export class JmapMailProvider extends MailProvider {
385385
dto: SendEmailDto,
386386
threading?: ThreadingHeaders,
387387
): Promise<{ id: string }> {
388-
if (dto.draftId) {
389-
return this.submitExistingDraft(userEmail, dto.draftId);
390-
}
391-
392388
const [accountId, identity, sentMailboxId] = await Promise.all([
393389
this.jmap.getPrimaryAccountId(userEmail),
394390
this.resolveIdentity(userEmail),
@@ -408,6 +404,7 @@ export class JmapMailProvider extends MailProvider {
408404
{
409405
accountId,
410406
create: { draft: emailCreate },
407+
...(dto.draftId && { destroy: [dto.draftId] }),
411408
},
412409
'r0',
413410
],
@@ -437,44 +434,6 @@ export class JmapMailProvider extends MailProvider {
437434
return { id: createdId };
438435
}
439436

440-
private async submitExistingDraft(
441-
userEmail: string,
442-
draftId: string,
443-
): Promise<{ id: string }> {
444-
const [accountId, identity, draftsMailboxId, sentMailboxId] =
445-
await Promise.all([
446-
this.jmap.getPrimaryAccountId(userEmail),
447-
this.resolveIdentity(userEmail),
448-
this.resolveMailboxId(userEmail, 'drafts'),
449-
this.resolveMailboxId(userEmail, 'sent'),
450-
]);
451-
452-
await this.jmap.request(userEmail, [
453-
[
454-
'EmailSubmission/set',
455-
{
456-
accountId,
457-
create: {
458-
submission: {
459-
identityId: identity.id,
460-
emailId: draftId,
461-
},
462-
},
463-
onSuccessUpdateEmail: {
464-
'#submission': {
465-
[`mailboxIds/${draftsMailboxId}`]: null,
466-
[`mailboxIds/${sentMailboxId}`]: true,
467-
'keywords/$draft': null,
468-
},
469-
},
470-
},
471-
'r0',
472-
],
473-
]);
474-
475-
return { id: draftId };
476-
}
477-
478437
private async destroyDraft(
479438
userEmail: string,
480439
accountId: string,

0 commit comments

Comments
 (0)