Spring Boot
A RestClient bean and a service, configured the way Spring expects.
The key
# src/main/resources/application.properties
# The value comes from the EMAILSSH_API_KEY environment variable, so the key
# itself is never in the repository. Get one at
# https://emails.sh/dashboard/api-keys.
emailssh.api-key=${EMAILSSH_API_KEY}
emailssh.from=Acme <hello@acme.com>The client bean
// src/main/java/com/acme/EmailConfig.java
package com.acme;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
@Configuration
public class EmailConfig {
@Bean
public RestClient emailsshClient(@Value("${emailssh.api-key}") String apiKey) {
return RestClient.builder()
.baseUrl("https://emails.sh")
.defaultHeader("Authorization", "Bearer " + apiKey)
.build();
}
}The service
// src/main/java/com/acme/EmailService.java
package com.acme;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClientResponseException;
@Service
public class EmailService {
private final RestClient client;
private final String from;
public EmailService(RestClient emailsshClient, @Value("${emailssh.from}") String from) {
this.client = emailsshClient;
this.from = from;
}
public record Queued(String id, String status) {}
@Async
public void sendWelcome(String to) {
try {
Queued queued = client.post()
.uri("/v1/emails")
.contentType(MediaType.APPLICATION_JSON)
.body(Map.of(
"from", from,
"to", List.of(to),
"subject", "Welcome to Acme",
"html", "<p>Confirm your address to finish signing up.</p>",
"idempotency_key", "signup-" + to))
.retrieve()
.body(Queued.class);
System.out.println("queued " + queued.id());
} catch (RestClientResponseException e) {
// The body carries {"error", "message"}; the message says what to do.
System.err.println("emails.sh refused the send: " + e.getResponseBodyAsString());
}
}
}