Skip to content

Commit 2f964ac

Browse files
feat: update send and batch email method to also support templates (#71)
1 parent d18d450 commit 2f964ac

File tree

4 files changed

+306
-0
lines changed

4 files changed

+306
-0
lines changed

src/main/java/com/resend/services/emails/model/CreateEmailOptions.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ public class CreateEmailOptions {
4444
@JsonProperty("scheduled_at")
4545
private final String scheduledAt;
4646

47+
@JsonProperty("template")
48+
private final Template template;
49+
4750
private CreateEmailOptions(Builder builder) {
4851
this.from = builder.from;
4952
this.to = builder.to;
@@ -57,6 +60,7 @@ private CreateEmailOptions(Builder builder) {
5760
this.html = builder.html;
5861
this.headers = builder.headers;
5962
this.scheduledAt = builder.scheduledAt;
63+
this.template = builder.template;
6064
}
6165

6266
/**
@@ -167,6 +171,15 @@ public String getScheduledAt() {
167171
return scheduledAt;
168172
}
169173

174+
/**
175+
* Retrieves the template configuration of the email.
176+
*
177+
* @return The template configuration of the email.
178+
*/
179+
public Template getTemplate() {
180+
return template;
181+
}
182+
170183
/**
171184
* Creates a new builder instance to construct CreateEmailOptions.
172185
*
@@ -192,6 +205,7 @@ public static class Builder {
192205
private List<Tag> tags;
193206
private Map<String, String> headers;
194207
private String scheduledAt;
208+
private Template template;
195209

196210
/**
197211
* Set the 'from' email address.
@@ -528,6 +542,21 @@ public Builder scheduledAt(String scheduledAt) {
528542
return this;
529543
}
530544

545+
/**
546+
* Set the template configuration for the email.
547+
* <p>
548+
* Note: If a template is provided, you cannot send html, text, or react in the payload.
549+
* When sending a template, the payload for from, subject, and reply_to take precedence
550+
* over the template's defaults for these fields.
551+
*
552+
* @param template The template configuration.
553+
* @return This builder instance for method chaining.
554+
*/
555+
public Builder template(Template template) {
556+
this.template = template;
557+
return this;
558+
}
559+
531560
/**
532561
* Builds and returns a {@code CreateEmailOptions} based on the configured properties.
533562
*
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package com.resend.services.emails.model;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
/**
8+
* Represents a template configuration for sending emails.
9+
*/
10+
public class Template {
11+
12+
@JsonProperty("id")
13+
private final String id;
14+
15+
@JsonProperty("variables")
16+
private final Map<String, Object> variables;
17+
18+
/**
19+
* Constructs a Template using the provided builder.
20+
*
21+
* @param builder The builder to construct the Template.
22+
*/
23+
private Template(Builder builder) {
24+
this.id = builder.id;
25+
this.variables = builder.variables;
26+
}
27+
28+
/**
29+
* Gets the template ID.
30+
*
31+
* @return The template ID.
32+
*/
33+
public String getId() {
34+
return id;
35+
}
36+
37+
/**
38+
* Gets the template variables.
39+
*
40+
* @return The template variables.
41+
*/
42+
public Map<String, Object> getVariables() {
43+
return variables;
44+
}
45+
46+
/**
47+
* Creates a new builder instance for constructing Template objects.
48+
*
49+
* @return A new builder instance.
50+
*/
51+
public static Builder builder() {
52+
return new Builder();
53+
}
54+
55+
/**
56+
* Helper method to create a Variable for use with varargs methods.
57+
*
58+
* @param key The variable key.
59+
* @param value The variable value.
60+
* @return A new Variable instance.
61+
*/
62+
public static Variable variable(String key, Object value) {
63+
return new Variable(key, value);
64+
}
65+
66+
/**
67+
* Represents a template variable with a key and value.
68+
*/
69+
public static class Variable {
70+
private final String key;
71+
private final Object value;
72+
73+
/**
74+
* Constructs a Variable with the specified key and value.
75+
*
76+
* @param key The variable key.
77+
* @param value The variable value.
78+
*/
79+
public Variable(String key, Object value) {
80+
this.key = key;
81+
this.value = value;
82+
}
83+
84+
/**
85+
* Gets the variable key.
86+
*
87+
* @return The variable key.
88+
*/
89+
public String getKey() {
90+
return key;
91+
}
92+
93+
/**
94+
* Gets the variable value.
95+
*
96+
* @return The variable value.
97+
*/
98+
public Object getValue() {
99+
return value;
100+
}
101+
}
102+
103+
/**
104+
* Builder class for constructing Template objects.
105+
*/
106+
public static class Builder {
107+
private String id;
108+
private Map<String, Object> variables;
109+
110+
/**
111+
* Set the template ID.
112+
*
113+
* @param id The template ID (must be a published template).
114+
* @return The builder instance.
115+
*/
116+
public Builder id(String id) {
117+
this.id = id;
118+
return this;
119+
}
120+
121+
/**
122+
* Set the template variables.
123+
*
124+
* @param variables The template variables as key/value pairs.
125+
* @return The builder instance.
126+
*/
127+
public Builder variables(Map<String, Object> variables) {
128+
this.variables = variables;
129+
return this;
130+
}
131+
132+
/**
133+
* Add multiple template variables using varargs.
134+
*
135+
* @param variables The variables to add.
136+
* @return The builder instance.
137+
*/
138+
public Builder variables(Variable... variables) {
139+
if (this.variables == null) {
140+
this.variables = new HashMap<>();
141+
}
142+
for (Variable variable : variables) {
143+
this.variables.put(variable.getKey(), variable.getValue());
144+
}
145+
return this;
146+
}
147+
148+
/**
149+
* Add a single template variable.
150+
*
151+
* @param key The variable key.
152+
* @param value The variable value.
153+
* @return The builder instance.
154+
*/
155+
public Builder addVariable(String key, Object value) {
156+
if (this.variables == null) {
157+
this.variables = new HashMap<>();
158+
}
159+
this.variables.put(key, value);
160+
return this;
161+
}
162+
163+
/**
164+
* Build a new Template object.
165+
*
166+
* @return A new Template object.
167+
*/
168+
public Template build() {
169+
return new Template(this);
170+
}
171+
}
172+
}

src/test/java/com/resend/services/emails/EmailsTest.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,71 @@ public void testListAttachmentsWithPagination_Success() throws ResendException {
218218
assertEquals(expectedResponse.hasMore(), response.hasMore());
219219
verify(emails, times(1)).listAttachments(emailId, params);
220220
}
221+
222+
@Test
223+
public void testSendEmail_WithTemplate_Success() throws ResendException {
224+
Template template = Template.builder()
225+
.id("template_123")
226+
.addVariable("firstName", "John")
227+
.addVariable("lastName", "Doe")
228+
.addVariable("company", "Acme Corp")
229+
.build();
230+
231+
CreateEmailOptions emailWithTemplate = CreateEmailOptions.builder()
232+
.from("Acme <[email protected]>")
233+
234+
.subject("Welcome John!")
235+
.template(template)
236+
.build();
237+
238+
CreateEmailResponse expectedResponse = EmailsUtil.createSendEmailResponse();
239+
240+
when(emails.send(emailWithTemplate)).thenReturn(expectedResponse);
241+
242+
CreateEmailResponse response = emails.send(emailWithTemplate);
243+
244+
assertNotNull(response);
245+
assertEquals(expectedResponse.getId(), response.getId());
246+
verify(emails, times(1)).send(emailWithTemplate);
247+
}
248+
249+
@Test
250+
public void testSendBatchEmails_WithTemplate_Success() throws ResendException {
251+
Template template1 = Template.builder()
252+
.id("template_123")
253+
.addVariable("firstName", "John")
254+
.addVariable("company", "Tech Corp")
255+
.build();
256+
257+
Template template2 = Template.builder()
258+
.id("template_123")
259+
.addVariable("firstName", "Jane")
260+
.addVariable("company", "Design Studios")
261+
.build();
262+
263+
CreateEmailOptions email1 = CreateEmailOptions.builder()
264+
.from("Acme <[email protected]>")
265+
266+
.subject("Welcome John!")
267+
.template(template1)
268+
.build();
269+
270+
CreateEmailOptions email2 = CreateEmailOptions.builder()
271+
.from("Acme <[email protected]>")
272+
273+
.subject("Welcome Jane!")
274+
.template(template2)
275+
.build();
276+
277+
List<CreateEmailOptions> batchEmails = java.util.Arrays.asList(email1, email2);
278+
CreateBatchEmailsResponse expectedResponse = EmailsUtil.createBatchEmailsResponse();
279+
280+
when(batch.send(batchEmails)).thenReturn(expectedResponse);
281+
282+
CreateBatchEmailsResponse response = batch.send(batchEmails);
283+
284+
assertNotNull(response);
285+
assertEquals(expectedResponse.getData().size(), response.getData().size());
286+
verify(batch, times(1)).send(batchEmails);
287+
}
221288
}

src/test/java/com/resend/services/util/EmailsUtil.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@ public static Tag createTag() {
2727
.build();
2828
}
2929

30+
public static Template createTemplate() {
31+
Map<String, Object> variables = new HashMap<>();
32+
variables.put("name", "John");
33+
variables.put("company", "Acme Corp");
34+
35+
return Template.builder()
36+
.id("template_123")
37+
.variables(variables)
38+
.build();
39+
}
40+
41+
public static Template createTemplateWithAddVariable() {
42+
return Template.builder()
43+
.id("template_123")
44+
.addVariable("name", "John")
45+
.addVariable("company", "Acme Corp")
46+
.build();
47+
}
48+
49+
public static Template createTemplateWithVarargs() {
50+
return Template.builder()
51+
.id("template_123")
52+
.variables(
53+
Template.variable("name", "John"),
54+
Template.variable("company", "Acme Corp")
55+
)
56+
.build();
57+
}
58+
3059
public static CreateEmailOptions createEmailOptions() {
3160
return CreateEmailOptions.builder()
3261
.from("Acme <[email protected]>")
@@ -42,6 +71,15 @@ public static CreateEmailOptions createEmailOptions() {
4271
.build();
4372
}
4473

74+
public static CreateEmailOptions createEmailOptionsWithTemplate() {
75+
return CreateEmailOptions.builder()
76+
.from("Acme <[email protected]>")
77+
.to(Arrays.asList("[email protected]"))
78+
.subject("Welcome to Acme")
79+
.template(createTemplate())
80+
.build();
81+
}
82+
4583
public static RequestOptions createRequestOptions() {
4684
return RequestOptions.builder()
4785
.setIdempotencyKey("welcome-user/123456789").build();

0 commit comments

Comments
 (0)