Skip to content

Commit 594de69

Browse files
authored
fix: correct email batch api call with reply_to (#460)
1 parent 1d43eb3 commit 594de69

6 files changed

+93
-16
lines changed

src/batch/batch.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import type * as React from 'react';
2+
import type { EmailApiOptions } from '../common/interfaces/email-api-options.interface';
3+
import { parseEmailToApiOptions } from '../common/utils/parse-email-to-api-options';
24
import type { Resend } from '../resend';
35
import type {
46
CreateBatchOptions,
@@ -22,6 +24,8 @@ export class Batch {
2224
payload: CreateBatchOptions,
2325
options: CreateBatchRequestOptions = {},
2426
): Promise<CreateBatchResponse> {
27+
const emails: EmailApiOptions[] = [];
28+
2529
for (const email of payload) {
2630
if (email.react) {
2731
if (!this.renderAsync) {
@@ -38,11 +42,13 @@ export class Batch {
3842
email.html = await this.renderAsync(email.react as React.ReactElement);
3943
email.react = undefined;
4044
}
45+
46+
emails.push(parseEmailToApiOptions(email));
4147
}
4248

4349
const data = await this.resend.post<CreateBatchSuccessResponse>(
4450
'/emails/batch',
45-
payload,
51+
emails,
4652
options,
4753
);
4854

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { Attachment } from '../../emails/interfaces/create-email-options.interface';
2+
import type { Tag } from '../../interfaces';
3+
4+
export interface EmailApiOptions {
5+
from: string;
6+
to: string | string[];
7+
subject: string;
8+
region?: string;
9+
headers?: Record<string, string>;
10+
html?: string;
11+
text?: string;
12+
bcc?: string | string[];
13+
cc?: string | string[];
14+
reply_to?: string | string[];
15+
scheduled_at?: string;
16+
tags?: Tag[];
17+
attachments?: Attachment[];
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import type { CreateEmailOptions } from '../../emails/interfaces/create-email-options.interface';
2+
import { parseEmailToApiOptions } from './parse-email-to-api-options';
3+
4+
describe('parseEmailToApiOptions', () => {
5+
it('should handle minimal email with only required fields', () => {
6+
const emailPayload: CreateEmailOptions = {
7+
8+
9+
subject: 'Hey, there!',
10+
html: '<h1>Hey, there!</h1>',
11+
};
12+
13+
const apiOptions = parseEmailToApiOptions(emailPayload);
14+
15+
expect(apiOptions).toEqual({
16+
17+
18+
subject: 'Hey, there!',
19+
html: '<h1>Hey, there!</h1>',
20+
});
21+
});
22+
23+
it('should properly parse camel case to snake case', () => {
24+
const emailPayload: CreateEmailOptions = {
25+
26+
27+
subject: 'Hey, there!',
28+
html: '<h1>Hey, there!</h1>',
29+
replyTo: '[email protected]',
30+
scheduledAt: 'in 1 min',
31+
};
32+
33+
const apiOptions = parseEmailToApiOptions(emailPayload);
34+
35+
expect(apiOptions).toEqual({
36+
37+
38+
subject: 'Hey, there!',
39+
html: '<h1>Hey, there!</h1>',
40+
reply_to: '[email protected]',
41+
scheduled_at: 'in 1 min',
42+
});
43+
});
44+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { CreateEmailOptions } from '../../emails/interfaces/create-email-options.interface';
2+
import type { EmailApiOptions } from '../interfaces/email-api-options.interface';
3+
4+
export function parseEmailToApiOptions(
5+
email: CreateEmailOptions,
6+
): EmailApiOptions {
7+
return {
8+
attachments: email.attachments,
9+
bcc: email.bcc,
10+
cc: email.cc,
11+
from: email.from,
12+
headers: email.headers,
13+
html: email.html,
14+
reply_to: email.replyTo,
15+
scheduled_at: email.scheduledAt,
16+
subject: email.subject,
17+
tags: email.tags,
18+
text: email.text,
19+
to: email.to,
20+
};
21+
}

src/emails/emails.ts

+2-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type * as React from 'react';
2+
import { parseEmailToApiOptions } from '../common/utils/parse-email-to-api-options';
23
import type { Resend } from '../resend';
34
import type {
45
CancelEmailResponse,
@@ -54,20 +55,7 @@ export class Emails {
5455

5556
const data = await this.resend.post<CreateEmailResponseSuccess>(
5657
'/emails',
57-
{
58-
attachments: payload.attachments,
59-
bcc: payload.bcc,
60-
cc: payload.cc,
61-
from: payload.from,
62-
headers: payload.headers,
63-
html: payload.html,
64-
reply_to: payload.replyTo,
65-
scheduled_at: payload.scheduledAt,
66-
subject: payload.subject,
67-
tags: payload.tags,
68-
text: payload.text,
69-
to: payload.to,
70-
},
58+
parseEmailToApiOptions(payload),
7159
options,
7260
);
7361

src/emails/interfaces/create-email-options.interface.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export interface CreateEmailResponse {
103103
error: ErrorResponse | null;
104104
}
105105

106-
interface Attachment {
106+
export interface Attachment {
107107
/** Content of an attached file. */
108108
content?: string | Buffer;
109109
/** Name of attached file. */

0 commit comments

Comments
 (0)