-
Notifications
You must be signed in to change notification settings - Fork 1
feat: update send and batch email method to also support templates #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| package com.resend.services.emails.model; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * Represents a template configuration for sending emails. | ||
| */ | ||
| public class Template { | ||
|
|
||
| @JsonProperty("id") | ||
| private final String id; | ||
|
|
||
| @JsonProperty("variables") | ||
| private final Map<String, Object> variables; | ||
|
|
||
| /** | ||
| * Constructs a Template using the provided builder. | ||
| * | ||
| * @param builder The builder to construct the Template. | ||
| */ | ||
| private Template(Builder builder) { | ||
| this.id = builder.id; | ||
| this.variables = builder.variables; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the template ID. | ||
| * | ||
| * @return The template ID. | ||
| */ | ||
| public String getId() { | ||
| return id; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the template variables. | ||
| * | ||
| * @return The template variables. | ||
| */ | ||
| public Map<String, Object> getVariables() { | ||
| return variables; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new builder instance for constructing Template objects. | ||
| * | ||
| * @return A new builder instance. | ||
| */ | ||
| public static Builder builder() { | ||
| return new Builder(); | ||
| } | ||
|
|
||
| /** | ||
| * Helper method to create a Variable for use with varargs methods. | ||
| * | ||
| * @param key The variable key. | ||
| * @param value The variable value. | ||
| * @return A new Variable instance. | ||
| */ | ||
| public static Variable variable(String key, Object value) { | ||
| return new Variable(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Represents a template variable with a key and value. | ||
| */ | ||
| public static class Variable { | ||
| private final String key; | ||
| private final Object value; | ||
|
|
||
| /** | ||
| * Constructs a Variable with the specified key and value. | ||
| * | ||
| * @param key The variable key. | ||
| * @param value The variable value. | ||
| */ | ||
| public Variable(String key, Object value) { | ||
| this.key = key; | ||
| this.value = value; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the variable key. | ||
| * | ||
| * @return The variable key. | ||
| */ | ||
| public String getKey() { | ||
| return key; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the variable value. | ||
| * | ||
| * @return The variable value. | ||
| */ | ||
| public Object getValue() { | ||
| return value; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Builder class for constructing Template objects. | ||
| */ | ||
| public static class Builder { | ||
| private String id; | ||
| private Map<String, Object> variables; | ||
|
|
||
| /** | ||
| * Set the template ID. | ||
| * | ||
| * @param id The template ID (must be a published template). | ||
| * @return The builder instance. | ||
| */ | ||
| public Builder id(String id) { | ||
| this.id = id; | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Set the template variables. | ||
| * | ||
| * @param variables The template variables as key/value pairs. | ||
| * @return The builder instance. | ||
| */ | ||
| public Builder variables(Map<String, Object> variables) { | ||
| this.variables = variables; | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Add multiple template variables using varargs. | ||
| * | ||
| * @param variables The variables to add. | ||
| * @return The builder instance. | ||
| */ | ||
| public Builder variables(Variable... variables) { | ||
| if (this.variables == null) { | ||
| this.variables = new HashMap<>(); | ||
| } | ||
| for (Variable variable : variables) { | ||
| this.variables.put(variable.getKey(), variable.getValue()); | ||
| } | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Add a single template variable. | ||
| * | ||
| * @param key The variable key. | ||
| * @param value The variable value. | ||
| * @return The builder instance. | ||
| */ | ||
| public Builder addVariable(String key, Object value) { | ||
| if (this.variables == null) { | ||
| this.variables = new HashMap<>(); | ||
| } | ||
| this.variables.put(key, value); | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Build a new Template object. | ||
| * | ||
| * @return A new Template object. | ||
| */ | ||
| public Template build() { | ||
| return new Template(this); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -218,4 +218,71 @@ public void testListAttachmentsWithPagination_Success() throws ResendException { | |
| assertEquals(expectedResponse.hasMore(), response.hasMore()); | ||
| verify(emails, times(1)).listAttachments(emailId, params); | ||
| } | ||
|
|
||
| @Test | ||
| public void testSendEmail_WithTemplate_Success() throws ResendException { | ||
| Template template = Template.builder() | ||
| .id("template_123") | ||
| .addVariable("firstName", "John") | ||
| .addVariable("lastName", "Doe") | ||
| .addVariable("company", "Acme Corp") | ||
| .build(); | ||
|
|
||
| CreateEmailOptions emailWithTemplate = CreateEmailOptions.builder() | ||
| .from("Acme <[email protected]>") | ||
| .to("[email protected]") | ||
| .subject("Welcome John!") | ||
| .template(template) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rule violated: API Key Permission Check SDK Methods This new template-based send path exercises additional Resend SDK capabilities, but nothing here confirms the production API keys cover the template permissions required by the API. Please verify those credentials so template sends don’t start failing after release. Prompt for AI agents |
||
| .build(); | ||
|
|
||
| CreateEmailResponse expectedResponse = EmailsUtil.createSendEmailResponse(); | ||
|
|
||
| when(emails.send(emailWithTemplate)).thenReturn(expectedResponse); | ||
|
|
||
| CreateEmailResponse response = emails.send(emailWithTemplate); | ||
|
|
||
| assertNotNull(response); | ||
| assertEquals(expectedResponse.getId(), response.getId()); | ||
| verify(emails, times(1)).send(emailWithTemplate); | ||
| } | ||
|
|
||
| @Test | ||
| public void testSendBatchEmails_WithTemplate_Success() throws ResendException { | ||
| Template template1 = Template.builder() | ||
| .id("template_123") | ||
| .addVariable("firstName", "John") | ||
| .addVariable("company", "Tech Corp") | ||
| .build(); | ||
|
|
||
| Template template2 = Template.builder() | ||
| .id("template_123") | ||
| .addVariable("firstName", "Jane") | ||
| .addVariable("company", "Design Studios") | ||
| .build(); | ||
|
|
||
| CreateEmailOptions email1 = CreateEmailOptions.builder() | ||
| .from("Acme <[email protected]>") | ||
| .to("[email protected]") | ||
| .subject("Welcome John!") | ||
| .template(template1) | ||
| .build(); | ||
|
|
||
| CreateEmailOptions email2 = CreateEmailOptions.builder() | ||
| .from("Acme <[email protected]>") | ||
| .to("[email protected]") | ||
| .subject("Welcome Jane!") | ||
| .template(template2) | ||
| .build(); | ||
|
|
||
| List<CreateEmailOptions> batchEmails = java.util.Arrays.asList(email1, email2); | ||
| CreateBatchEmailsResponse expectedResponse = EmailsUtil.createBatchEmailsResponse(); | ||
|
|
||
| when(batch.send(batchEmails)).thenReturn(expectedResponse); | ||
|
|
||
| CreateBatchEmailsResponse response = batch.send(batchEmails); | ||
|
|
||
| assertNotNull(response); | ||
| assertEquals(expectedResponse.getData().size(), response.getData().size()); | ||
| verify(batch, times(1)).send(batchEmails); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,35 @@ public static Tag createTag() { | |
| .build(); | ||
| } | ||
|
|
||
| public static Template createTemplate() { | ||
| Map<String, Object> variables = new HashMap<>(); | ||
| variables.put("name", "John"); | ||
| variables.put("company", "Acme Corp"); | ||
|
|
||
| return Template.builder() | ||
| .id("template_123") | ||
| .variables(variables) | ||
| .build(); | ||
| } | ||
|
|
||
| public static Template createTemplateWithAddVariable() { | ||
| return Template.builder() | ||
| .id("template_123") | ||
| .addVariable("name", "John") | ||
| .addVariable("company", "Acme Corp") | ||
| .build(); | ||
| } | ||
|
|
||
| public static Template createTemplateWithVarargs() { | ||
| return Template.builder() | ||
| .id("template_123") | ||
| .variables( | ||
| Template.variable("name", "John"), | ||
| Template.variable("company", "Acme Corp") | ||
| ) | ||
| .build(); | ||
| } | ||
|
|
||
| public static CreateEmailOptions createEmailOptions() { | ||
| return CreateEmailOptions.builder() | ||
| .from("Acme <[email protected]>") | ||
|
|
@@ -42,6 +71,15 @@ public static CreateEmailOptions createEmailOptions() { | |
| .build(); | ||
| } | ||
|
|
||
| public static CreateEmailOptions createEmailOptionsWithTemplate() { | ||
| return CreateEmailOptions.builder() | ||
| .from("Acme <[email protected]>") | ||
| .to(Arrays.asList("[email protected]")) | ||
| .subject("Welcome to Acme") | ||
| .template(createTemplate()) | ||
| .build(); | ||
| } | ||
|
|
||
| public static RequestOptions createRequestOptions() { | ||
| return RequestOptions.builder() | ||
| .setIdempotencyKey("welcome-user/123456789").build(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Template constructor stores the builder's mutable variables map by reference, so reusing the builder mutates previously built Template instances. Make a defensive copy when assigning.
Prompt for AI agents