diff --git a/src/main/java/com/resend/Resend.java b/src/main/java/com/resend/Resend.java index 327890a..c3d21d1 100644 --- a/src/main/java/com/resend/Resend.java +++ b/src/main/java/com/resend/Resend.java @@ -10,6 +10,7 @@ import com.resend.services.domains.Domains; import com.resend.services.emails.Emails; import com.resend.services.segments.Segments; +import com.resend.services.suppressions.Suppressions; import com.resend.services.webhooks.Webhooks; import com.resend.services.receiving.Receiving; import com.resend.services.topics.Topics; @@ -183,6 +184,15 @@ public Automations automations() { return new Automations(apiKey); } + /** + * Returns a Suppressions object that can be used to interact with the Suppressions service. + * + * @return A Suppressions object. + */ + public Suppressions suppressions() { + return new Suppressions(apiKey); + } + /** * Returns an OAuthGrants object that can be used to interact with the OAuthGrants service. * diff --git a/src/main/java/com/resend/services/suppressions/Suppressions.java b/src/main/java/com/resend/services/suppressions/Suppressions.java new file mode 100644 index 0000000..8c541f1 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/Suppressions.java @@ -0,0 +1,133 @@ +package com.resend.services.suppressions; + +import com.resend.core.exception.ResendException; +import com.resend.core.net.AbstractHttpResponse; +import com.resend.core.net.HttpMethod; +import com.resend.core.net.IHttpClient; +import com.resend.core.service.BaseService; +import com.resend.services.suppressions.model.*; +import okhttp3.MediaType; + +/** + * Represents the Resend Suppressions module. + */ +public class Suppressions extends BaseService { + + /** + * Constructs an instance of the {@code Suppressions} class. + * + * @param apiKey The apiKey used for authentication. + */ + public Suppressions(final String apiKey) { + super(apiKey); + } + + Suppressions(final String apiKey, final IHttpClient httpClient) { + super(apiKey, httpClient); + } + + /** + * Returns a SuppressionsBatch object that can be used to add or remove suppressions in batch. + * + * @return A SuppressionsBatch object. + */ + public SuppressionsBatch batch() { + return new SuppressionsBatch(super.apiKey, super.httpClient); + } + + /** + * Adds an email address to the suppression list. + * + * @param addSuppressionOptions The suppression details. + * @return The details of the added suppression. + * @throws ResendException If an error occurs during the suppression creation process. + */ + public AddSuppressionResponseSuccess add(AddSuppressionOptions addSuppressionOptions) throws ResendException { + String payload = super.resendMapper.writeValue(addSuppressionOptions); + AbstractHttpResponse response = httpClient.perform("/suppressions", super.apiKey, HttpMethod.POST, payload, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, AddSuppressionResponseSuccess.class); + } + + /** + * Removes a suppression by its unique identifier or by the suppressed email address. + * + * @param suppressionIdOrEmail The unique identifier or the suppressed email address. + * @return The RemoveSuppressionResponseSuccess with the details of the removed suppression. + * @throws ResendException If an error occurs during the suppression removal process. + */ + public RemoveSuppressionResponseSuccess remove(String suppressionIdOrEmail) throws ResendException { + AbstractHttpResponse response = httpClient.perform("/suppressions/" + suppressionIdOrEmail, super.apiKey, HttpMethod.DELETE, null, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, RemoveSuppressionResponseSuccess.class); + } + + /** + * Retrieves a suppression by its unique identifier or by the suppressed email address. + * + * @param suppressionIdOrEmail The unique identifier or the suppressed email address. + * @return The retrieved suppression details. + * @throws ResendException If an error occurs while retrieving the suppression. + */ + public GetSuppressionResponseSuccess get(String suppressionIdOrEmail) throws ResendException { + AbstractHttpResponse response = this.httpClient.perform("/suppressions/" + suppressionIdOrEmail, super.apiKey, HttpMethod.GET, null, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, GetSuppressionResponseSuccess.class); + } + + /** + * Retrieves a list of suppressions. + * + * @return A ListSuppressionsResponseSuccess containing the list of suppressions. + * @throws ResendException If an error occurs during the suppressions list retrieval process. + */ + public ListSuppressionsResponseSuccess list() throws ResendException { + AbstractHttpResponse response = this.httpClient.perform("/suppressions", super.apiKey, HttpMethod.GET, null, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, ListSuppressionsResponseSuccess.class); + } + + /** + * Retrieves a paginated list of suppressions with optional filtering by origin. + * + * @param params The params used to customize the list. + * @return A ListSuppressionsResponseSuccess containing the paginated list of suppressions. + * @throws ResendException If an error occurs during the suppressions list retrieval process. + */ + public ListSuppressionsResponseSuccess list(ListSuppressionsParams params) throws ResendException { + String pathWithQuery = "/suppressions" + (params != null ? params.toQueryString() : ""); + AbstractHttpResponse response = this.httpClient.perform(pathWithQuery, super.apiKey, HttpMethod.GET, null, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, ListSuppressionsResponseSuccess.class); + } +} diff --git a/src/main/java/com/resend/services/suppressions/SuppressionsBatch.java b/src/main/java/com/resend/services/suppressions/SuppressionsBatch.java new file mode 100644 index 0000000..8f26c30 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/SuppressionsBatch.java @@ -0,0 +1,69 @@ +package com.resend.services.suppressions; + +import com.resend.core.exception.ResendException; +import com.resend.core.net.AbstractHttpResponse; +import com.resend.core.net.HttpMethod; +import com.resend.core.net.IHttpClient; +import com.resend.core.service.BaseService; +import com.resend.services.suppressions.model.*; +import okhttp3.MediaType; + +/** + * Represents the Resend Suppressions Batch module. + */ +public class SuppressionsBatch extends BaseService { + + /** + * Constructs an instance of the {@code SuppressionsBatch} class. + * + * @param apiKey The apiKey used for authentication. + */ + public SuppressionsBatch(final String apiKey) { + super(apiKey); + } + + SuppressionsBatch(final String apiKey, final IHttpClient httpClient) { + super(apiKey, httpClient); + } + + /** + * Adds up to 100 email addresses to the suppression list at once. + * + * @param addSuppressionsOptions The email addresses to suppress. + * @return The AddSuppressionsResponseSuccess with the details of the added suppressions. + * @throws ResendException If an error occurs during the suppressions creation process. + */ + public AddSuppressionsResponseSuccess add(AddSuppressionsOptions addSuppressionsOptions) throws ResendException { + String payload = super.resendMapper.writeValue(addSuppressionsOptions); + AbstractHttpResponse response = httpClient.perform("/suppressions/batch/add", super.apiKey, HttpMethod.POST, payload, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, AddSuppressionsResponseSuccess.class); + } + + /** + * Removes up to 100 suppressions from the suppression list at once. + * Provide either emails or ids, but not both. + * + * @param removeSuppressionsOptions The suppressions to remove. + * @return The RemoveSuppressionsResponseSuccess with the details of the removed suppressions. + * @throws ResendException If an error occurs during the suppressions removal process. + */ + public RemoveSuppressionsResponseSuccess remove(RemoveSuppressionsOptions removeSuppressionsOptions) throws ResendException { + String payload = super.resendMapper.writeValue(removeSuppressionsOptions); + AbstractHttpResponse response = httpClient.perform("/suppressions/batch/remove", super.apiKey, HttpMethod.POST, payload, MediaType.get("application/json")); + + if (!response.isSuccessful()) { + throw new ResendException(response.getCode(), response.getBody()); + } + + String responseBody = response.getBody(); + + return resendMapper.readValue(responseBody, RemoveSuppressionsResponseSuccess.class); + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/AddSuppressionOptions.java b/src/main/java/com/resend/services/suppressions/model/AddSuppressionOptions.java new file mode 100644 index 0000000..54ff1f2 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/AddSuppressionOptions.java @@ -0,0 +1,72 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a request to add an email address to the suppression list. + */ +public class AddSuppressionOptions { + + @JsonProperty("email") + private final String email; + + /** + * Constructs an Add Suppression Options object using the provided builder. + * + * @param builder The builder to construct the Add Suppression Options. + */ + public AddSuppressionOptions(Builder builder) { + this.email = builder.email; + } + + /** + * Get the email address to suppress. + * + * @return The email address to suppress. + */ + public String getEmail() { + return email; + } + + /** + * Create a new builder instance for constructing AddSuppressionOptions objects. + * + * @return A new builder instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for constructing AddSuppressionOptions objects. + */ + public static class Builder { + /** + * Creates a new Builder instance. + */ + public Builder() { + } + + private String email; + + /** + * Set the email address to suppress. + * + * @param email The email address to suppress. + * @return The builder instance. + */ + public Builder email(String email) { + this.email = email; + return this; + } + + /** + * Build a new AddSuppressionOptions object. + * + * @return A new AddSuppressionOptions object. + */ + public AddSuppressionOptions build() { + return new AddSuppressionOptions(this); + } + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/AddSuppressionResponseSuccess.java b/src/main/java/com/resend/services/suppressions/model/AddSuppressionResponseSuccess.java new file mode 100644 index 0000000..1ba8d59 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/AddSuppressionResponseSuccess.java @@ -0,0 +1,25 @@ +package com.resend.services.suppressions.model; + +/** + * Represents a successful response for adding an email address to the suppression list. + * Extends the AddedSuppression class. + */ +public class AddSuppressionResponseSuccess extends AddedSuppression { + + /** + * Default constructor + */ + public AddSuppressionResponseSuccess() { + + } + + /** + * Constructs a successful response for adding a suppression. + * + * @param object The object type of the suppression. + * @param id The ID of the suppression. + */ + public AddSuppressionResponseSuccess(String object, String id) { + super(object, id); + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/AddSuppressionsOptions.java b/src/main/java/com/resend/services/suppressions/model/AddSuppressionsOptions.java new file mode 100644 index 0000000..78a4a0b --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/AddSuppressionsOptions.java @@ -0,0 +1,97 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a request to add email addresses to the suppression list. + * Must contain between 1 and 100 email addresses. + */ +public class AddSuppressionsOptions { + + @JsonProperty("emails") + private final List emails; + + /** + * Constructs an Add Suppressions Options object using the provided builder. + * + * @param builder The builder to construct the Add Suppressions Options. + */ + public AddSuppressionsOptions(Builder builder) { + this.emails = builder.emails; + } + + /** + * Get the email addresses to suppress. + * + * @return The email addresses to suppress. + */ + public List getEmails() { + return emails; + } + + /** + * Create a new builder instance for constructing AddSuppressionsOptions objects. + * + * @return A new builder instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for constructing AddSuppressionsOptions objects. + */ + public static class Builder { + /** + * Creates a new Builder instance. + */ + public Builder() { + } + + private List emails; + + /** + * Set the email addresses to suppress. + * + * @param emails The email addresses to suppress. + * @return The builder instance. + */ + public Builder emails(List emails) { + this.emails = emails; + return this; + } + + /** + * Add an email address to suppress. + * + * @param email The email address to suppress. + * @return The builder instance. + */ + public Builder email(String email) { + if (this.emails == null) { + this.emails = new ArrayList<>(); + } + this.emails.add(email); + return this; + } + + /** + * Build a new AddSuppressionsOptions object. + * + * @return A new AddSuppressionsOptions object. + * @throws IllegalArgumentException If emails is empty or contains more than 100 email addresses. + */ + public AddSuppressionsOptions build() { + if (emails == null || emails.isEmpty()) { + throw new IllegalArgumentException("At least one email address must be provided"); + } + if (emails.size() > 100) { + throw new IllegalArgumentException("A maximum of 100 email addresses can be provided"); + } + return new AddSuppressionsOptions(this); + } + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/AddSuppressionsResponseSuccess.java b/src/main/java/com/resend/services/suppressions/model/AddSuppressionsResponseSuccess.java new file mode 100644 index 0000000..d842407 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/AddSuppressionsResponseSuccess.java @@ -0,0 +1,39 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Represents a successful response for adding email addresses to the suppression list. + */ +public class AddSuppressionsResponseSuccess { + + @JsonProperty("data") + private List data; + + /** + * Default constructor + */ + public AddSuppressionsResponseSuccess() { + + } + + /** + * Constructs a successful response for adding suppressions. + * + * @param data The list of added suppressions. + */ + public AddSuppressionsResponseSuccess(List data) { + this.data = data; + } + + /** + * Get the list of added suppressions. + * + * @return The list of added suppressions. + */ + public List getData() { + return data; + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/AddedSuppression.java b/src/main/java/com/resend/services/suppressions/model/AddedSuppression.java new file mode 100644 index 0000000..2a38580 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/AddedSuppression.java @@ -0,0 +1,51 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a suppression added to the suppression list. + */ +public class AddedSuppression { + + @JsonProperty("object") + private String object; + + @JsonProperty("id") + private String id; + + /** + * Default constructor + */ + public AddedSuppression() { + + } + + /** + * Constructs an added suppression. + * + * @param object The object type of the suppression. + * @param id The ID of the suppression. + */ + public AddedSuppression(String object, String id) { + this.object = object; + this.id = id; + } + + /** + * Get the object type. + * + * @return The object type of the suppression. + */ + public String getObject() { + return object; + } + + /** + * Get the ID of the suppression. + * + * @return The ID of the suppression. + */ + public String getId() { + return id; + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/GetSuppressionResponseSuccess.java b/src/main/java/com/resend/services/suppressions/model/GetSuppressionResponseSuccess.java new file mode 100644 index 0000000..fb5ce23 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/GetSuppressionResponseSuccess.java @@ -0,0 +1,29 @@ +package com.resend.services.suppressions.model; + +/** + * Represents a successful response for retrieving a suppression. + * Extends the Suppression class. + */ +public class GetSuppressionResponseSuccess extends Suppression { + + /** + * Default constructor + */ + public GetSuppressionResponseSuccess() { + + } + + /** + * Constructs a successful response for retrieving a suppression. + * + * @param object The object type of the suppression. + * @param id The ID of the suppression. + * @param email The suppressed email address. + * @param origin The origin of the suppression. + * @param sourceId The ID of the email that triggered the suppression. + * @param createdAt The creation timestamp of the suppression. + */ + public GetSuppressionResponseSuccess(String object, String id, String email, String origin, String sourceId, String createdAt) { + super(object, id, email, origin, sourceId, createdAt); + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/ListSuppressionsParams.java b/src/main/java/com/resend/services/suppressions/model/ListSuppressionsParams.java new file mode 100644 index 0000000..829791f --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/ListSuppressionsParams.java @@ -0,0 +1,163 @@ +package com.resend.services.suppressions.model; + +import com.resend.core.helper.URLHelper; +import com.resend.core.net.ListParams; + +import java.util.Collections; +import java.util.Map; + +/** + * Represents parameters for listing suppressions with filtering and pagination. + */ +public class ListSuppressionsParams { + + private final Integer limit; + private final String after; + private final String before; + private final SuppressionOrigin origin; + + /** + * Constructs ListSuppressionsParams using the provided builder. + * + * @param builder The builder to construct the params. + */ + public ListSuppressionsParams(Builder builder) { + this.limit = builder.limit; + this.after = builder.after; + this.before = builder.before; + this.origin = builder.origin; + } + + /** + * Retrieves the maximum number of results. + * + * @return The limit. + */ + public Integer getLimit() { + return limit; + } + + /** + * Retrieves the cursor for pagination (after). + * + * @return The after cursor. + */ + public String getAfter() { + return after; + } + + /** + * Retrieves the cursor for pagination (before). + * + * @return The before cursor. + */ + public String getBefore() { + return before; + } + + /** + * Retrieves the origin filter. + * + * @return The suppression origin filter. + */ + public SuppressionOrigin getOrigin() { + return origin; + } + + /** + * Converts the parameters to a query string. + * + * @return A query string starting with "?" if parameters exist, or an empty string otherwise. + */ + public String toQueryString() { + ListParams base = ListParams.builder() + .limit(limit) + .after(after) + .before(before) + .build(); + + Map extras = origin == null + ? Collections.emptyMap() + : Collections.singletonMap("origin", origin.getValue()); + + return URLHelper.parse(base, extras); + } + + /** + * Creates a new builder instance for ListSuppressionsParams. + * + * @return A new Builder instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for constructing ListSuppressionsParams objects. + */ + public static class Builder { + /** + * Creates a new Builder instance. + */ + public Builder() { + } + + private Integer limit; + private String after; + private String before; + private SuppressionOrigin origin; + + /** + * Sets the maximum number of results. + * + * @param limit The limit. + * @return The builder instance. + */ + public Builder limit(Integer limit) { + this.limit = limit; + return this; + } + + /** + * Sets the after cursor for pagination. + * + * @param after The after cursor. + * @return The builder instance. + */ + public Builder after(String after) { + this.after = after; + return this; + } + + /** + * Sets the before cursor for pagination. + * + * @param before The before cursor. + * @return The builder instance. + */ + public Builder before(String before) { + this.before = before; + return this; + } + + /** + * Sets the origin filter. + * + * @param origin The suppression origin. + * @return The builder instance. + */ + public Builder origin(SuppressionOrigin origin) { + this.origin = origin; + return this; + } + + /** + * Builds a new ListSuppressionsParams instance. + * + * @return A new ListSuppressionsParams. + */ + public ListSuppressionsParams build() { + return new ListSuppressionsParams(this); + } + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/ListSuppressionsResponseSuccess.java b/src/main/java/com/resend/services/suppressions/model/ListSuppressionsResponseSuccess.java new file mode 100644 index 0000000..e13cdcd --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/ListSuppressionsResponseSuccess.java @@ -0,0 +1,67 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Represents a successful response for listing suppressions. + */ +public class ListSuppressionsResponseSuccess { + + @JsonProperty("object") + private String object; + + @JsonProperty("has_more") + private Boolean hasMore; + + @JsonProperty("data") + private List data; + + /** + * Default constructor + */ + public ListSuppressionsResponseSuccess() { + + } + + /** + * Constructs a successful response for listing suppressions. + * + * @param object The object type of the list. + * @param hasMore Whether there are more suppressions available for pagination. + * @param data The list of suppressions. + */ + public ListSuppressionsResponseSuccess(String object, Boolean hasMore, List data) { + this.object = object; + this.hasMore = hasMore; + this.data = data; + } + + /** + * Get the object type. + * + * @return The object type of the list. + */ + public String getObject() { + return object; + } + + /** + * Get the indicator whether there are more suppressions available for pagination. + * + * @return Whether there are more suppressions available for pagination. + */ + public Boolean hasMore() { + return hasMore; + } + + /** + * Get the list of suppressions. + * + * @return The list of suppressions. + */ + public List getData() { + return data; + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionResponseSuccess.java b/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionResponseSuccess.java new file mode 100644 index 0000000..00e9ad9 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionResponseSuccess.java @@ -0,0 +1,26 @@ +package com.resend.services.suppressions.model; + +/** + * Represents a successful response for removing a suppression from the suppression list. + * Extends the RemovedSuppression class. + */ +public class RemoveSuppressionResponseSuccess extends RemovedSuppression { + + /** + * Default constructor + */ + public RemoveSuppressionResponseSuccess() { + + } + + /** + * Constructs a successful response for removing a suppression. + * + * @param object The object type of the suppression. + * @param id The ID of the suppression. + * @param deleted Whether the suppression was deleted. + */ + public RemoveSuppressionResponseSuccess(String object, String id, Boolean deleted) { + super(object, id, deleted); + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionsOptions.java b/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionsOptions.java new file mode 100644 index 0000000..a84b402 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionsOptions.java @@ -0,0 +1,137 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a request to remove suppressions from the suppression list. + * Provide either emails or ids, but not both. + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RemoveSuppressionsOptions { + + @JsonProperty("emails") + private final List emails; + + @JsonProperty("ids") + private final List ids; + + /** + * Constructs a Remove Suppressions Options object using the provided builder. + * + * @param builder The builder to construct the Remove Suppressions Options. + */ + public RemoveSuppressionsOptions(Builder builder) { + this.emails = builder.emails; + this.ids = builder.ids; + } + + /** + * Get the email addresses to remove from the suppression list. + * + * @return The email addresses to remove from the suppression list. + */ + public List getEmails() { + return emails; + } + + /** + * Get the suppression IDs to remove from the suppression list. + * + * @return The suppression IDs to remove from the suppression list. + */ + public List getIds() { + return ids; + } + + /** + * Create a new builder instance for constructing RemoveSuppressionsOptions objects. + * + * @return A new builder instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for constructing RemoveSuppressionsOptions objects. + */ + public static class Builder { + /** + * Creates a new Builder instance. + */ + public Builder() { + } + + private List emails; + private List ids; + + /** + * Set the email addresses to remove from the suppression list. + * + * @param emails The email addresses to remove from the suppression list. + * @return The builder instance. + */ + public Builder emails(List emails) { + this.emails = emails; + return this; + } + + /** + * Add an email address to remove from the suppression list. + * + * @param email The email address to remove from the suppression list. + * @return The builder instance. + */ + public Builder email(String email) { + if (this.emails == null) { + this.emails = new ArrayList<>(); + } + this.emails.add(email); + return this; + } + + /** + * Set the suppression IDs to remove from the suppression list. + * + * @param ids The suppression IDs to remove from the suppression list. + * @return The builder instance. + */ + public Builder ids(List ids) { + this.ids = ids; + return this; + } + + /** + * Add a suppression ID to remove from the suppression list. + * + * @param id The suppression ID to remove from the suppression list. + * @return The builder instance. + */ + public Builder id(String id) { + if (this.ids == null) { + this.ids = new ArrayList<>(); + } + this.ids.add(id); + return this; + } + + /** + * Build a new RemoveSuppressionsOptions object. + * + * @return A new RemoveSuppressionsOptions object. + * @throws IllegalArgumentException If neither or both of emails and ids are provided. + */ + public RemoveSuppressionsOptions build() { + boolean hasEmails = emails != null && !emails.isEmpty(); + boolean hasIds = ids != null && !ids.isEmpty(); + if (hasEmails == hasIds) { + throw new IllegalArgumentException("Either 'emails' or 'ids' must be provided, but not both."); + } + return new RemoveSuppressionsOptions(this); + } + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionsResponseSuccess.java b/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionsResponseSuccess.java new file mode 100644 index 0000000..f1c04aa --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/RemoveSuppressionsResponseSuccess.java @@ -0,0 +1,39 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Represents a successful response for removing suppressions from the suppression list. + */ +public class RemoveSuppressionsResponseSuccess { + + @JsonProperty("data") + private List data; + + /** + * Default constructor + */ + public RemoveSuppressionsResponseSuccess() { + + } + + /** + * Constructs a successful response for removing suppressions. + * + * @param data The list of removed suppressions. + */ + public RemoveSuppressionsResponseSuccess(List data) { + this.data = data; + } + + /** + * Get the list of removed suppressions. + * + * @return The list of removed suppressions. + */ + public List getData() { + return data; + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/RemovedSuppression.java b/src/main/java/com/resend/services/suppressions/model/RemovedSuppression.java new file mode 100644 index 0000000..46ff023 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/RemovedSuppression.java @@ -0,0 +1,65 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a suppression removed from the suppression list. + */ +public class RemovedSuppression { + + @JsonProperty("object") + private String object; + + @JsonProperty("id") + private String id; + + @JsonProperty("deleted") + private Boolean deleted; + + /** + * Default constructor + */ + public RemovedSuppression() { + + } + + /** + * Constructs a removed suppression. + * + * @param object The object type of the suppression. + * @param id The ID of the suppression. + * @param deleted Whether the suppression was deleted. + */ + public RemovedSuppression(String object, String id, Boolean deleted) { + this.object = object; + this.id = id; + this.deleted = deleted; + } + + /** + * Get the object type. + * + * @return The object type of the suppression. + */ + public String getObject() { + return object; + } + + /** + * Get the ID of the suppression. + * + * @return The ID of the suppression. + */ + public String getId() { + return id; + } + + /** + * Get whether the suppression was deleted. + * + * @return Whether the suppression was deleted. + */ + public Boolean getDeleted() { + return deleted; + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/Suppression.java b/src/main/java/com/resend/services/suppressions/model/Suppression.java new file mode 100644 index 0000000..5d87322 --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/Suppression.java @@ -0,0 +1,108 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents a suppression from the suppression list. + */ +public class Suppression { + + @JsonProperty("object") + private String object; + + @JsonProperty("id") + private String id; + + @JsonProperty("email") + private String email; + + @JsonProperty("origin") + private String origin; + + @JsonProperty("source_id") + private String sourceId; + + @JsonProperty("created_at") + private String createdAt; + + /** + * Default constructor + */ + public Suppression() { + + } + + /** + * Constructs a suppression. + * + * @param object The object type of the suppression. + * @param id The ID of the suppression. + * @param email The suppressed email address. + * @param origin The origin of the suppression. + * @param sourceId The ID of the email that triggered the suppression. + * @param createdAt The creation timestamp of the suppression. + */ + public Suppression(String object, String id, String email, String origin, String sourceId, String createdAt) { + this.object = object; + this.id = id; + this.email = email; + this.origin = origin; + this.sourceId = sourceId; + this.createdAt = createdAt; + } + + /** + * Get the object type. + * + * @return The object type of the suppression. + */ + public String getObject() { + return object; + } + + /** + * Get the ID of the suppression. + * + * @return The ID of the suppression. + */ + public String getId() { + return id; + } + + /** + * Get the suppressed email address. + * + * @return The suppressed email address. + */ + public String getEmail() { + return email; + } + + /** + * Get the origin of the suppression. + * + * @return The origin of the suppression. + */ + public String getOrigin() { + return origin; + } + + /** + * Get the ID of the email that triggered the suppression. + * For suppressions with a manual origin, the source ID is null. + * + * @return The ID of the email that triggered the suppression. + */ + public String getSourceId() { + return sourceId; + } + + /** + * Get the creation timestamp of the suppression. + * + * @return The creation timestamp of the suppression. + */ + public String getCreatedAt() { + return createdAt; + } +} diff --git a/src/main/java/com/resend/services/suppressions/model/SuppressionOrigin.java b/src/main/java/com/resend/services/suppressions/model/SuppressionOrigin.java new file mode 100644 index 0000000..c44c73f --- /dev/null +++ b/src/main/java/com/resend/services/suppressions/model/SuppressionOrigin.java @@ -0,0 +1,49 @@ +package com.resend.services.suppressions.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Represents the origin of a suppression. + */ +public enum SuppressionOrigin { + /** Emails suppressed automatically after a bounce. */ + BOUNCE("bounce"), + /** Emails suppressed due to a user complaint. */ + COMPLAINT("complaint"), + /** Emails suppressed by your team manually. */ + MANUAL("manual"); + + private final String value; + + SuppressionOrigin(String value) { + this.value = value; + } + + /** + * Returns the string value of the origin. + * + * @return The origin value. + */ + @JsonValue + public String getValue() { + return value; + } + + /** + * Creates a SuppressionOrigin from a string value. + * + * @param value The string value. + * @return The corresponding SuppressionOrigin. + * @throws IllegalArgumentException If the value is unknown. + */ + @JsonCreator + public static SuppressionOrigin fromValue(String value) { + for (SuppressionOrigin origin : SuppressionOrigin.values()) { + if (origin.value.equals(value)) { + return origin; + } + } + throw new IllegalArgumentException("Unknown origin: " + value); + } +} diff --git a/src/test/java/com/resend/services/suppressions/SuppressionsTest.java b/src/test/java/com/resend/services/suppressions/SuppressionsTest.java new file mode 100644 index 0000000..56ce3f0 --- /dev/null +++ b/src/test/java/com/resend/services/suppressions/SuppressionsTest.java @@ -0,0 +1,351 @@ +package com.resend.services.suppressions; + +import com.resend.core.exception.ResendException; +import com.resend.core.net.AbstractHttpResponse; +import com.resend.core.net.HttpMethod; +import com.resend.core.net.IHttpClient; +import com.resend.services.suppressions.model.AddSuppressionOptions; +import com.resend.services.suppressions.model.AddSuppressionResponseSuccess; +import com.resend.services.suppressions.model.AddSuppressionsOptions; +import com.resend.services.suppressions.model.AddSuppressionsResponseSuccess; +import com.resend.services.suppressions.model.GetSuppressionResponseSuccess; +import com.resend.services.suppressions.model.ListSuppressionsParams; +import com.resend.services.suppressions.model.ListSuppressionsResponseSuccess; +import com.resend.services.suppressions.model.RemoveSuppressionResponseSuccess; +import com.resend.services.suppressions.model.RemoveSuppressionsOptions; +import com.resend.services.suppressions.model.RemoveSuppressionsResponseSuccess; +import com.resend.services.suppressions.model.SuppressionOrigin; +import com.resend.services.util.SuppressionsUtil; +import okhttp3.MediaType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; + +@SuppressWarnings("unchecked") +public class SuppressionsTest { + + private static final String ADD_SINGLE_RESPONSE_JSON = + "{\"object\":\"suppression\",\"id\":\"e169aa45-1ecf-4183-9955-b1499d5701d3\"}"; + + private static final String REMOVE_SINGLE_RESPONSE_JSON = + "{\"object\":\"suppression\",\"id\":\"e169aa45-1ecf-4183-9955-b1499d5701d3\",\"deleted\":true}"; + + private static final String ADD_RESPONSE_JSON = "{\"data\":[" + + "{\"object\":\"suppression\",\"id\":\"e169aa45-1ecf-4183-9955-b1499d5701d3\"}," + + "{\"object\":\"suppression\",\"id\":\"520784e2-887d-4c25-b53c-4ad46ad38100\"}" + + "]}"; + + private static final String GET_RESPONSE_JSON = + "{\"object\":\"suppression\",\"id\":\"e169aa45-1ecf-4183-9955-b1499d5701d3\"," + + "\"email\":\"steve.wozniak@example.com\",\"origin\":\"bounce\"," + + "\"source_id\":\"4ef9a417-02e9-4d39-ad75-9611e0fcc33c\"," + + "\"created_at\":\"2026-10-06T23:47:56.678Z\"}"; + + private static final String LIST_RESPONSE_JSON = "{\"object\":\"list\",\"has_more\":false,\"data\":[" + + "{\"object\":\"suppression\",\"id\":\"e169aa45-1ecf-4183-9955-b1499d5701d3\"," + + "\"email\":\"steve.wozniak@example.com\",\"origin\":\"manual\",\"source_id\":null," + + "\"created_at\":\"2026-10-06T23:47:56.678Z\"}," + + "{\"object\":\"suppression\",\"id\":\"520784e2-887d-4c25-b53c-4ad46ad38100\"," + + "\"email\":\"susan.kare@example.com\",\"origin\":\"bounce\"," + + "\"source_id\":\"4ef9a417-02e9-4d39-ad75-9611e0fcc33c\"," + + "\"created_at\":\"2026-10-07T08:12:03.412Z\"}" + + "]}"; + + private static final String REMOVE_RESPONSE_JSON = "{\"data\":[" + + "{\"object\":\"suppression\",\"id\":\"e169aa45-1ecf-4183-9955-b1499d5701d3\",\"deleted\":true}" + + "]}"; + + @Mock + private IHttpClient httpClient; + + private Suppressions suppressions; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + suppressions = new Suppressions("test-api-key", httpClient); + } + + @Test + public void testAddSuppression_Success() throws ResendException { + AddSuppressionOptions request = SuppressionsUtil.addSuppressionRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, ADD_SINGLE_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + AddSuppressionResponseSuccess response = suppressions.add(request); + + assertNotNull(response); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getId()); + assertEquals("suppression", response.getObject()); + } + + @Test + public void testAddSuppression_ApiError_ThrowsResendException() throws ResendException { + AddSuppressionOptions request = SuppressionsUtil.addSuppressionRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(422, + "{\"name\":\"validation_error\",\"message\":\"Invalid request\"}", false); + + when(httpClient.perform(eq("/suppressions"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + ResendException ex = assertThrows(ResendException.class, () -> suppressions.add(request)); + assertEquals(422, (int) ex.getStatusCode()); + } + + @Test + public void testRemoveSuppressionById_Success() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, REMOVE_SINGLE_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/e169aa45-1ecf-4183-9955-b1499d5701d3"), anyString(), eq(HttpMethod.DELETE), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + RemoveSuppressionResponseSuccess response = suppressions.remove("e169aa45-1ecf-4183-9955-b1499d5701d3"); + + assertNotNull(response); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getId()); + assertEquals("suppression", response.getObject()); + assertTrue(response.getDeleted()); + } + + @Test + public void testRemoveSuppressionByEmail_Success() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, REMOVE_SINGLE_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/steve.wozniak@example.com"), anyString(), eq(HttpMethod.DELETE), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + RemoveSuppressionResponseSuccess response = suppressions.remove("steve.wozniak@example.com"); + + assertNotNull(response); + assertTrue(response.getDeleted()); + } + + @Test + public void testRemoveSuppression_ApiError_ThrowsResendException() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(404, + "{\"name\":\"not_found\",\"message\":\"Suppression not found\"}", false); + + when(httpClient.perform(eq("/suppressions/123"), anyString(), eq(HttpMethod.DELETE), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + assertThrows(ResendException.class, () -> suppressions.remove("123")); + } + + @Test + public void testAddSuppressions_Success() throws ResendException { + AddSuppressionsOptions request = SuppressionsUtil.addSuppressionsRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, ADD_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/batch/add"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + AddSuppressionsResponseSuccess response = suppressions.batch().add(request); + + assertNotNull(response); + assertEquals(2, response.getData().size()); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getData().get(0).getId()); + assertEquals("suppression", response.getData().get(0).getObject()); + assertEquals("520784e2-887d-4c25-b53c-4ad46ad38100", response.getData().get(1).getId()); + } + + @Test + public void testAddSuppressions_ApiError_ThrowsResendException() throws ResendException { + AddSuppressionsOptions request = SuppressionsUtil.addSuppressionsRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(422, + "{\"name\":\"validation_error\",\"message\":\"Invalid request\"}", false); + + when(httpClient.perform(eq("/suppressions/batch/add"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + ResendException ex = assertThrows(ResendException.class, () -> suppressions.batch().add(request)); + assertEquals(422, (int) ex.getStatusCode()); + } + + @Test + public void testGetSuppressionById_Success() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, GET_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/e169aa45-1ecf-4183-9955-b1499d5701d3"), anyString(), eq(HttpMethod.GET), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + GetSuppressionResponseSuccess response = suppressions.get("e169aa45-1ecf-4183-9955-b1499d5701d3"); + + assertNotNull(response); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getId()); + assertEquals("steve.wozniak@example.com", response.getEmail()); + assertEquals("bounce", response.getOrigin()); + assertEquals("4ef9a417-02e9-4d39-ad75-9611e0fcc33c", response.getSourceId()); + assertEquals("2026-10-06T23:47:56.678Z", response.getCreatedAt()); + assertEquals("suppression", response.getObject()); + } + + @Test + public void testGetSuppressionByEmail_Success() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, GET_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/steve.wozniak@example.com"), anyString(), eq(HttpMethod.GET), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + GetSuppressionResponseSuccess response = suppressions.get("steve.wozniak@example.com"); + + assertNotNull(response); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getId()); + assertEquals("steve.wozniak@example.com", response.getEmail()); + } + + @Test + public void testGetSuppression_ApiError_ThrowsResendException() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(404, + "{\"name\":\"not_found\",\"message\":\"Suppression not found\"}", false); + + when(httpClient.perform(eq("/suppressions/123"), anyString(), eq(HttpMethod.GET), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + assertThrows(ResendException.class, () -> suppressions.get("123")); + } + + @Test + public void testListSuppressions_Success() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, LIST_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions"), anyString(), eq(HttpMethod.GET), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + ListSuppressionsResponseSuccess response = suppressions.list(); + + assertNotNull(response); + assertEquals("list", response.getObject()); + assertFalse(response.hasMore()); + assertEquals(2, response.getData().size()); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getData().get(0).getId()); + assertEquals("steve.wozniak@example.com", response.getData().get(0).getEmail()); + assertEquals("manual", response.getData().get(0).getOrigin()); + assertNull(response.getData().get(0).getSourceId()); + assertEquals("bounce", response.getData().get(1).getOrigin()); + assertEquals("4ef9a417-02e9-4d39-ad75-9611e0fcc33c", response.getData().get(1).getSourceId()); + } + + @Test + public void testListSuppressionsWithParams_Success() throws ResendException { + ListSuppressionsParams params = SuppressionsUtil.listSuppressionsParams(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, LIST_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions?limit=20&origin=bounce"), anyString(), eq(HttpMethod.GET), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + ListSuppressionsResponseSuccess response = suppressions.list(params); + + assertNotNull(response); + assertEquals(2, response.getData().size()); + } + + @Test + public void testListSuppressionsParams_ToQueryString() { + ListSuppressionsParams params = ListSuppressionsParams.builder() + .limit(50) + .after("cursor_abc") + .origin(SuppressionOrigin.MANUAL) + .build(); + + assertEquals("?limit=50&after=cursor_abc&origin=manual", params.toQueryString()); + } + + @Test + public void testListSuppressions_ApiError_ThrowsResendException() throws ResendException { + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(401, + "{\"name\":\"missing_api_key\",\"message\":\"Missing API key\"}", false); + + when(httpClient.perform(eq("/suppressions"), anyString(), eq(HttpMethod.GET), isNull(), any(MediaType.class))) + .thenReturn(httpResponse); + + assertThrows(ResendException.class, () -> suppressions.list()); + } + + @Test + public void testRemoveSuppressionsByEmails_Success() throws ResendException { + RemoveSuppressionsOptions request = SuppressionsUtil.removeSuppressionsByEmailsRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, REMOVE_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/batch/remove"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + RemoveSuppressionsResponseSuccess response = suppressions.batch().remove(request); + + assertNotNull(response); + assertEquals(1, response.getData().size()); + assertEquals("e169aa45-1ecf-4183-9955-b1499d5701d3", response.getData().get(0).getId()); + assertEquals("suppression", response.getData().get(0).getObject()); + assertTrue(response.getData().get(0).getDeleted()); + } + + @Test + public void testRemoveSuppressionsByIds_Success() throws ResendException { + RemoveSuppressionsOptions request = SuppressionsUtil.removeSuppressionsByIdsRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(200, REMOVE_RESPONSE_JSON, true); + + when(httpClient.perform(eq("/suppressions/batch/remove"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + RemoveSuppressionsResponseSuccess response = suppressions.batch().remove(request); + + assertNotNull(response); + assertEquals(1, response.getData().size()); + assertTrue(response.getData().get(0).getDeleted()); + } + + @Test + public void testAddSuppressionsOptions_EmptyEmails_ThrowsIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> AddSuppressionsOptions.builder().build()); + } + + @Test + public void testAddSuppressionsOptions_MoreThan100Emails_ThrowsIllegalArgumentException() { + AddSuppressionsOptions.Builder builder = AddSuppressionsOptions.builder(); + for (int i = 0; i <= 100; i++) { + builder.email("user" + i + "@example.com"); + } + assertThrows(IllegalArgumentException.class, builder::build); + } + + @Test + public void testRemoveSuppressionsOptions_NeitherEmailsNorIds_ThrowsIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> RemoveSuppressionsOptions.builder().build()); + } + + @Test + public void testRemoveSuppressionsOptions_BothEmailsAndIds_ThrowsIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> RemoveSuppressionsOptions.builder() + .email("steve.wozniak@example.com") + .id("e169aa45-1ecf-4183-9955-b1499d5701d3") + .build()); + } + + @Test + public void testListSuppressionsParams_ToQueryString_EncodesValues() { + ListSuppressionsParams params = ListSuppressionsParams.builder() + .after("cursor&abc=def") + .build(); + + assertEquals("?after=cursor%26abc%3Ddef", params.toQueryString()); + } + + @Test + public void testRemoveSuppressions_ApiError_ThrowsResendException() throws ResendException { + RemoveSuppressionsOptions request = SuppressionsUtil.removeSuppressionsByIdsRequest(); + AbstractHttpResponse httpResponse = new AbstractHttpResponse<>(422, + "{\"name\":\"validation_error\",\"message\":\"Invalid request\"}", false); + + when(httpClient.perform(eq("/suppressions/batch/remove"), anyString(), eq(HttpMethod.POST), anyString(), any(MediaType.class))) + .thenReturn(httpResponse); + + ResendException ex = assertThrows(ResendException.class, () -> suppressions.batch().remove(request)); + assertEquals(422, (int) ex.getStatusCode()); + } +} diff --git a/src/test/java/com/resend/services/util/SuppressionsUtil.java b/src/test/java/com/resend/services/util/SuppressionsUtil.java new file mode 100644 index 0000000..7edc5c0 --- /dev/null +++ b/src/test/java/com/resend/services/util/SuppressionsUtil.java @@ -0,0 +1,39 @@ +package com.resend.services.util; + +import com.resend.services.suppressions.model.*; + +public class SuppressionsUtil { + + public static AddSuppressionOptions addSuppressionRequest() { + return AddSuppressionOptions.builder() + .email("steve.wozniak@example.com") + .build(); + } + + public static AddSuppressionsOptions addSuppressionsRequest() { + return AddSuppressionsOptions.builder() + .email("steve.wozniak@example.com") + .email("susan.kare@example.com") + .build(); + } + + public static ListSuppressionsParams listSuppressionsParams() { + return ListSuppressionsParams.builder() + .limit(20) + .origin(SuppressionOrigin.BOUNCE) + .build(); + } + + public static RemoveSuppressionsOptions removeSuppressionsByEmailsRequest() { + return RemoveSuppressionsOptions.builder() + .email("steve.wozniak@example.com") + .email("susan.kare@example.com") + .build(); + } + + public static RemoveSuppressionsOptions removeSuppressionsByIdsRequest() { + return RemoveSuppressionsOptions.builder() + .id("e169aa45-1ecf-4183-9955-b1499d5701d3") + .build(); + } +}