Skip to content

Commit 0a3339f

Browse files
committed
Fix email tags, settings, and batch idempotency
1 parent 9739b5b commit 0a3339f

4 files changed

Lines changed: 55 additions & 12 deletions

File tree

src/main/java/co/lettermint/client/LettermintClient.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ public <T> T post(String path, Object payload, Class<T> responseClass, Map<Strin
9292
}
9393

9494
public <T> T post(String path, Object payload, TypeReference<T> responseType) {
95-
return request("POST", url(path, null), payload, null, responseType, null);
95+
return post(path, payload, responseType, null);
96+
}
97+
98+
public <T> T post(String path, Object payload, TypeReference<T> responseType, Map<String, String> headers) {
99+
return request("POST", url(path, null), payload, null, responseType, headers);
96100
}
97101

98102
public <T> T get(String path, Class<T> responseClass) {

src/main/java/co/lettermint/endpoints/EmailEndpoint.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public class EmailEndpoint extends Endpoint {
2626
private List<Attachment> attachments;
2727
private String route;
2828
private Map<String, Object> metadata;
29-
private List<String> tags;
29+
private String tag;
30+
private Map<String, Object> settings;
3031
private String idempotencyKey;
3132

3233
public EmailEndpoint(LettermintClient client) {
@@ -50,7 +51,8 @@ private void reset() {
5051
this.attachments = new ArrayList<>();
5152
this.route = null;
5253
this.metadata = new LinkedHashMap<>();
53-
this.tags = new ArrayList<>();
54+
this.tag = null;
55+
this.settings = null;
5456
this.idempotencyKey = null;
5557
}
5658

@@ -196,10 +198,18 @@ public EmailEndpoint metadata(String key, Object value) {
196198
}
197199

198200
/**
199-
* Add tags to the email.
201+
* Set the email tag.
200202
*/
201-
public EmailEndpoint tag(String... tags) {
202-
this.tags.addAll(Arrays.asList(tags));
203+
public EmailEndpoint tag(String tag) {
204+
this.tag = tag;
205+
return this;
206+
}
207+
208+
/**
209+
* Set per-email settings that override the selected route.
210+
*/
211+
public EmailEndpoint settings(Map<String, Object> settings) {
212+
this.settings = new LinkedHashMap<>(settings);
203213
return this;
204214
}
205215

@@ -231,7 +241,17 @@ public SendEmailResponse send() {
231241
}
232242

233243
public List<SendMailResponse> sendBatch(List<SendMailRequest> payloads) {
234-
return client.post("/send/batch", payloads, new TypeReference<List<SendMailResponse>>() {});
244+
Map<String, String> requestHeaders = null;
245+
246+
if (idempotencyKey != null && !idempotencyKey.isEmpty()) {
247+
requestHeaders = Collections.singletonMap("Idempotency-Key", idempotencyKey);
248+
}
249+
250+
try {
251+
return client.post("/send/batch", payloads, new TypeReference<List<SendMailResponse>>() {}, requestHeaders);
252+
} finally {
253+
reset();
254+
}
235255
}
236256

237257
public String ping() {
@@ -289,8 +309,12 @@ private Map<String, Object> buildPayload() {
289309
payload.put("metadata", metadata);
290310
}
291311

292-
if (!tags.isEmpty()) {
293-
payload.put("tags", tags);
312+
if (tag != null) {
313+
payload.put("tag", tag);
314+
}
315+
316+
if (settings != null) {
317+
payload.put("settings", settings);
294318
}
295319

296320
return payload;

src/test/java/co/lettermint/ApiClientTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@ void sendsBatchEmailsWithTypedPayloads() throws Exception {
8484

8585
List<SendMailResponse> response = Lettermint
8686
.email("sending-token", server.url("/v1").toString())
87+
.idempotencyKey("batch-key")
8788
.sendBatch(Collections.singletonList(payload));
8889

8990
RecordedRequest request = server.takeRequest();
9091
assertEquals("/v1/send/batch", request.getPath());
9192
assertEquals("sending-token", request.getHeader("x-lettermint-token"));
93+
assertEquals("batch-key", request.getHeader("Idempotency-Key"));
9294
assertEquals("msg_123", response.get(0).messageId);
9395
}
9496
}

src/test/java/co/lettermint/EmailEndpointTest.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,18 @@ void testEmailWithAllOptions() throws Exception {
6363
.setHeader("Content-Type", "application/json"));
6464

6565
Map<String, String> headers = new HashMap<>();
66-
headers.put("X-Custom-Header", "custom-value");
66+
headers.put("Message-ID", "<ticket-123@example.com>");
67+
headers.put("X-LM-Preserve-Message-ID", "true");
6768

6869
Map<String, Object> metadata = new HashMap<>();
6970
metadata.put("userId", "user_123");
7071
metadata.put("campaign", "welcome");
7172

73+
Map<String, Object> settings = new HashMap<>();
74+
settings.put("track_opens", false);
75+
settings.put("track_clicks", true);
76+
settings.put("tls", "enforced");
77+
7278
SendEmailResponse response = lettermint.email()
7379
.from("John Doe <sender@example.com>")
7480
.to("recipient1@example.com", "recipient2@example.com")
@@ -84,7 +90,8 @@ void testEmailWithAllOptions() throws Exception {
8490
.attach("invite.ics", "base64icalFile", null, "text/calendar; method=REQUEST")
8591
.route("route-slug-123")
8692
.metadata(metadata)
87-
.tag("welcome", "onboarding")
93+
.tag("welcome")
94+
.settings(settings)
8895
.idempotencyKey("unique-key-123")
8996
.send();
9097

@@ -103,7 +110,13 @@ void testEmailWithAllOptions() throws Exception {
103110
assertTrue(body.contains("\"html\":\"<p>Hello <b>World</b></p>\""));
104111
assertTrue(body.contains("\"text\":\"Hello World\""));
105112
assertTrue(body.contains("\"route\":\"route-slug-123\""));
106-
assertTrue(body.contains("\"tags\":[\"welcome\",\"onboarding\"]"));
113+
assertTrue(body.contains("\"tag\":\"welcome\""));
114+
assertTrue(body.contains("\"settings\":"));
115+
assertTrue(body.contains("\"track_opens\":false"));
116+
assertTrue(body.contains("\"track_clicks\":true"));
117+
assertTrue(body.contains("\"tls\":\"enforced\""));
118+
assertTrue(body.contains("\"Message-ID\":\"<ticket-123@example.com>\""));
119+
assertTrue(body.contains("\"X-LM-Preserve-Message-ID\":\"true\""));
107120
assertTrue(body.contains("{\"filename\":\"document.pdf\",\"content\":\"base64content\"}"));
108121
assertTrue(body.contains("{\"filename\":\"logo.png\",\"content\":\"base64logo\",\"content_id\":\"logo-cid\"}"));
109122
assertTrue(body.contains("{\"filename\":\"invite.ics\",\"content\":\"base64icalFile\",\"content_type\":\"text/calendar; method=REQUEST\"}"));

0 commit comments

Comments
 (0)