diff --git a/examples/java/io/mailtrap/examples/contactexports/ContactExportsExample.java b/examples/java/io/mailtrap/examples/contactexports/ContactExportsExample.java new file mode 100644 index 0000000..b1c0872 --- /dev/null +++ b/examples/java/io/mailtrap/examples/contactexports/ContactExportsExample.java @@ -0,0 +1,39 @@ +package io.mailtrap.examples.contactexports; + +import io.mailtrap.config.MailtrapConfig; +import io.mailtrap.factory.MailtrapClientFactory; +import io.mailtrap.model.request.contactexports.ContactExportFilter; +import io.mailtrap.model.request.contactexports.ContactExportFilterOperator; +import io.mailtrap.model.request.contactexports.CreateContactsExportRequest; + +import java.util.List; + +public class ContactExportsExample { + + private static final String TOKEN = ""; + private static final long ACCOUNT_ID = 1L; + private static final long CONTACT_LIST_ID = 1L; + + public static void main(String[] args) { + final var config = new MailtrapConfig.Builder() + .token(TOKEN) + .build(); + + final var client = MailtrapClientFactory.createMailtrapClient(config); + + final var exportFilter = ContactExportFilter.listIds(ContactExportFilterOperator.EQUAL, CONTACT_LIST_ID); + + final var createExportRequest = new CreateContactsExportRequest(List.of(exportFilter)); + + final var createExportResponse = client.contactsApi().contactExports() + .createContactExport(ACCOUNT_ID, createExportRequest); + + System.out.println(createExportResponse); + + var contactExportResponse = client.contactsApi().contactExports() + .getContactExport(ACCOUNT_ID, createExportResponse.getId()); + + System.out.println(contactExportResponse); + } + +} diff --git a/src/main/java/io/mailtrap/api/contactexports/ContactExports.java b/src/main/java/io/mailtrap/api/contactexports/ContactExports.java new file mode 100644 index 0000000..2916dca --- /dev/null +++ b/src/main/java/io/mailtrap/api/contactexports/ContactExports.java @@ -0,0 +1,25 @@ +package io.mailtrap.api.contactexports; + +import io.mailtrap.model.request.contactexports.CreateContactsExportRequest; +import io.mailtrap.model.response.contactexports.ContactExportResponse; + +public interface ContactExports { + + /** + * Create a new Contact Export + * + * @param accountId unique account ID + * @param request payload + * @return created contact export + */ + ContactExportResponse createContactExport(long accountId, CreateContactsExportRequest request); + + /** + * Get Contact Export + * + * @param accountId unique account ID + * @param exportId unique contact export ID + * @return contact export + */ + ContactExportResponse getContactExport(long accountId, long exportId); +} diff --git a/src/main/java/io/mailtrap/api/contactexports/ContactExportsImpl.java b/src/main/java/io/mailtrap/api/contactexports/ContactExportsImpl.java new file mode 100644 index 0000000..fa34b05 --- /dev/null +++ b/src/main/java/io/mailtrap/api/contactexports/ContactExportsImpl.java @@ -0,0 +1,35 @@ +package io.mailtrap.api.contactexports; + +import io.mailtrap.Constants; +import io.mailtrap.api.apiresource.ApiResource; +import io.mailtrap.config.MailtrapConfig; +import io.mailtrap.http.RequestData; +import io.mailtrap.model.request.contactexports.CreateContactsExportRequest; +import io.mailtrap.model.response.contactexports.ContactExportResponse; + +public class ContactExportsImpl extends ApiResource implements ContactExports { + + public ContactExportsImpl(final MailtrapConfig config) { + super(config); + this.apiHost = Constants.GENERAL_HOST; + } + + @Override + public ContactExportResponse createContactExport(final long accountId, final CreateContactsExportRequest request) { + return httpClient.post( + String.format(apiHost + "/api/accounts/%d/contacts/exports", accountId), + request, + new RequestData(), + ContactExportResponse.class + ); + } + + @Override + public ContactExportResponse getContactExport(final long accountId, final long exportId) { + return httpClient.get( + String.format(apiHost + "/api/accounts/%d/contacts/exports/%d", accountId, exportId), + new RequestData(), + ContactExportResponse.class + ); + } +} diff --git a/src/main/java/io/mailtrap/client/api/MailtrapContactsApi.java b/src/main/java/io/mailtrap/client/api/MailtrapContactsApi.java index 8369623..bfb9b16 100644 --- a/src/main/java/io/mailtrap/client/api/MailtrapContactsApi.java +++ b/src/main/java/io/mailtrap/client/api/MailtrapContactsApi.java @@ -1,5 +1,6 @@ package io.mailtrap.client.api; +import io.mailtrap.api.contactexports.ContactExports; import io.mailtrap.api.contactfields.ContactFields; import io.mailtrap.api.contactimports.ContactImports; import io.mailtrap.api.contactlists.ContactLists; @@ -19,4 +20,5 @@ public class MailtrapContactsApi { private final Contacts contacts; private final ContactImports contactImports; private final ContactFields contactFields; + private final ContactExports contactExports; } diff --git a/src/main/java/io/mailtrap/factory/MailtrapClientFactory.java b/src/main/java/io/mailtrap/factory/MailtrapClientFactory.java index dbab8a1..89b5e44 100644 --- a/src/main/java/io/mailtrap/factory/MailtrapClientFactory.java +++ b/src/main/java/io/mailtrap/factory/MailtrapClientFactory.java @@ -6,6 +6,7 @@ import io.mailtrap.api.attachments.AttachmentsImpl; import io.mailtrap.api.billing.BillingImpl; import io.mailtrap.api.bulkemails.BulkEmailsImpl; +import io.mailtrap.api.contactexports.ContactExportsImpl; import io.mailtrap.api.contactfields.ContactFieldsImpl; import io.mailtrap.api.contactimports.ContactImportsImpl; import io.mailtrap.api.contactlists.ContactListsImpl; @@ -74,8 +75,9 @@ private static MailtrapContactsApi createContactsApi(final MailtrapConfig config final var contacts = new ContactsImpl(config); final var contactImports = new ContactImportsImpl(config, VALIDATOR); final var contactFields = new ContactFieldsImpl(config, VALIDATOR); + final var contactExports = new ContactExportsImpl(config); - return new MailtrapContactsApi(contactLists, contacts, contactImports, contactFields); + return new MailtrapContactsApi(contactLists, contacts, contactImports, contactFields, contactExports); } private static MailtrapGeneralApi createGeneralApi(final MailtrapConfig config) { diff --git a/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilter.java b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilter.java new file mode 100644 index 0000000..ba9cc04 --- /dev/null +++ b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilter.java @@ -0,0 +1,28 @@ +package io.mailtrap.model.request.contactexports; + +import lombok.Getter; + +import static io.mailtrap.model.request.contactexports.ContactExportFilterName.list_id; +import static io.mailtrap.model.request.contactexports.ContactExportFilterName.subscription_status; + +@Getter +public class ContactExportFilter { + + private final String name; + private final String operator; + private final Object value; + + private ContactExportFilter(final String name, final String operator, final Object value) { + this.name = name; + this.operator = operator; + this.value = value; + } + + public static ContactExportFilter listIds(final ContactExportFilterOperator operator, final Long... listIds) { + return new ContactExportFilter(list_id.name(), operator.getValue(), listIds); + } + + public static ContactExportFilter subscriptionStatus(final ContactExportFilterOperator operator, final ContactExportFilterSubscriptionStatus status) { + return new ContactExportFilter(subscription_status.name(), operator.getValue(), status.getValue()); + } +} diff --git a/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterName.java b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterName.java new file mode 100644 index 0000000..65ce85f --- /dev/null +++ b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterName.java @@ -0,0 +1,6 @@ +package io.mailtrap.model.request.contactexports; + +public enum ContactExportFilterName { + subscription_status, + list_id +} diff --git a/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterOperator.java b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterOperator.java new file mode 100644 index 0000000..a1c449d --- /dev/null +++ b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterOperator.java @@ -0,0 +1,12 @@ +package io.mailtrap.model.request.contactexports; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ContactExportFilterOperator { + EQUAL("equal"); + + private final String value; +} diff --git a/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterSubscriptionStatus.java b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterSubscriptionStatus.java new file mode 100644 index 0000000..36be901 --- /dev/null +++ b/src/main/java/io/mailtrap/model/request/contactexports/ContactExportFilterSubscriptionStatus.java @@ -0,0 +1,13 @@ +package io.mailtrap.model.request.contactexports; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ContactExportFilterSubscriptionStatus { + SUBSCRIBED("subscribed"), + UNSUBSCRIBED("unsubscribed"); + + private final String value; +} diff --git a/src/main/java/io/mailtrap/model/request/contactexports/CreateContactsExportRequest.java b/src/main/java/io/mailtrap/model/request/contactexports/CreateContactsExportRequest.java new file mode 100644 index 0000000..f8ed034 --- /dev/null +++ b/src/main/java/io/mailtrap/model/request/contactexports/CreateContactsExportRequest.java @@ -0,0 +1,14 @@ +package io.mailtrap.model.request.contactexports; + +import io.mailtrap.model.AbstractModel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class CreateContactsExportRequest extends AbstractModel { + + private List filters; +} diff --git a/src/main/java/io/mailtrap/model/response/contactexports/ContactExportResponse.java b/src/main/java/io/mailtrap/model/response/contactexports/ContactExportResponse.java new file mode 100644 index 0000000..6da3c43 --- /dev/null +++ b/src/main/java/io/mailtrap/model/response/contactexports/ContactExportResponse.java @@ -0,0 +1,21 @@ +package io.mailtrap.model.response.contactexports; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class ContactExportResponse { + + private long id; + + private ContactExportStatus status; + + @JsonProperty("created_at") + private String createdAt; + + @JsonProperty("updated_at") + private String updatedAt; + + private String url; + +} diff --git a/src/main/java/io/mailtrap/model/response/contactexports/ContactExportStatus.java b/src/main/java/io/mailtrap/model/response/contactexports/ContactExportStatus.java new file mode 100644 index 0000000..b3c1c96 --- /dev/null +++ b/src/main/java/io/mailtrap/model/response/contactexports/ContactExportStatus.java @@ -0,0 +1,30 @@ +package io.mailtrap.model.response.contactexports; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ContactExportStatus { + + CREATED("created"), + STARTED("started"), + FINISHED("finished"); + + private final String value; + + @JsonValue + public String getValue() { + return value; + } + + @JsonCreator + public static ContactExportStatus fromValue(final String value) { + for (final ContactExportStatus status : ContactExportStatus.values()) { + if (status.value.equalsIgnoreCase(value)) { + return status; + } + } + throw new IllegalArgumentException("Unknown contact export status value: " + value); + } +} diff --git a/src/test/java/io/mailtrap/api/contactexports/ContactExportsImplTest.java b/src/test/java/io/mailtrap/api/contactexports/ContactExportsImplTest.java new file mode 100644 index 0000000..67ce605 --- /dev/null +++ b/src/test/java/io/mailtrap/api/contactexports/ContactExportsImplTest.java @@ -0,0 +1,65 @@ +package io.mailtrap.api.contactexports; + +import io.mailtrap.Constants; +import io.mailtrap.config.MailtrapConfig; +import io.mailtrap.factory.MailtrapClientFactory; +import io.mailtrap.model.request.contactexports.ContactExportFilter; +import io.mailtrap.model.request.contactexports.ContactExportFilterOperator; +import io.mailtrap.model.request.contactexports.ContactExportFilterSubscriptionStatus; +import io.mailtrap.model.request.contactexports.CreateContactsExportRequest; +import io.mailtrap.model.response.contactexports.ContactExportResponse; +import io.mailtrap.model.response.contactexports.ContactExportStatus; +import io.mailtrap.testutils.BaseTest; +import io.mailtrap.testutils.DataMock; +import io.mailtrap.testutils.TestHttpClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + +public class ContactExportsImplTest extends BaseTest { + + private ContactExports api; + + @BeforeEach + public void init() { + final TestHttpClient httpClient = new TestHttpClient(List.of( + DataMock.build(Constants.GENERAL_HOST + "/api/accounts/" + accountId + "/contacts/exports", + "POST", "api/contactexports/createContactExportRequest.json", "api/contactexports/createContactExportResponse.json"), + + DataMock.build(Constants.GENERAL_HOST + "/api/accounts/" + accountId + "/contacts/exports/" + contactsExportId, + "GET", null, "api/contactexports/getContactExportResponse.json") + )); + + final MailtrapConfig testConfig = new MailtrapConfig.Builder() + .httpClient(httpClient) + .token("dummy_token") + .build(); + + api = MailtrapClientFactory.createMailtrapClient(testConfig).contactsApi().contactExports(); + } + + @Test + void test_createContactExport_ids_filter() { + final var idsFilter = ContactExportFilter.listIds(ContactExportFilterOperator.EQUAL, contactsExportFilterListId); + final var subscriptionStatusFilter = ContactExportFilter.subscriptionStatus(ContactExportFilterOperator.EQUAL, ContactExportFilterSubscriptionStatus.SUBSCRIBED); + + final var request = new CreateContactsExportRequest(List.of(idsFilter, subscriptionStatusFilter)); + + final ContactExportResponse contactExportResponse = api.createContactExport(accountId, request); + + assertEquals(contactsExportId, contactExportResponse.getId()); + assertSame(ContactExportStatus.STARTED, contactExportResponse.getStatus()); + } + + @Test + void test_getContactExport() { + final ContactExportResponse contactExport = api.getContactExport(accountId, contactsExportId); + + assertEquals(contactsExportId, contactExport.getId()); + assertSame(ContactExportStatus.FINISHED, contactExport.getStatus()); + } +} diff --git a/src/test/java/io/mailtrap/testutils/BaseTest.java b/src/test/java/io/mailtrap/testutils/BaseTest.java index f9e2dca..961befe 100644 --- a/src/test/java/io/mailtrap/testutils/BaseTest.java +++ b/src/test/java/io/mailtrap/testutils/BaseTest.java @@ -18,6 +18,8 @@ public class BaseTest { protected final String contactUUID = "018dd5e3-f6d2-7c00-8f9b-e5c3f2d8a132"; protected final String contactUUIDEncoded = URLEncoder.encode(contactUUID, StandardCharsets.UTF_8); protected final Long importId = 1L; + protected final Long contactsExportFilterListId = 101L; + protected final Long contactsExportId = 1L; protected final Long getFieldId = 777L; protected final Long updateFieldId = 999L; protected final Long deleteFieldId = 1111L; diff --git a/src/test/resources/api/contactexports/createContactExportRequest.json b/src/test/resources/api/contactexports/createContactExportRequest.json new file mode 100644 index 0000000..2d75950 --- /dev/null +++ b/src/test/resources/api/contactexports/createContactExportRequest.json @@ -0,0 +1,16 @@ +{ + "filters": [ + { + "name": "list_id", + "operator": "equal", + "value": [ + 101 + ] + }, + { + "name": "subscription_status", + "operator": "equal", + "value": "subscribed" + } + ] +} diff --git a/src/test/resources/api/contactexports/createContactExportResponse.json b/src/test/resources/api/contactexports/createContactExportResponse.json new file mode 100644 index 0000000..cc53a30 --- /dev/null +++ b/src/test/resources/api/contactexports/createContactExportResponse.json @@ -0,0 +1,7 @@ +{ + "id": 1, + "status": "started", + "created_at": "2025-10-06T01:01:01Z", + "updated_at": "2025-10-06T01:01:01Z", + "url": null +} diff --git a/src/test/resources/api/contactexports/getContactExportResponse.json b/src/test/resources/api/contactexports/getContactExportResponse.json new file mode 100644 index 0000000..f4f520a --- /dev/null +++ b/src/test/resources/api/contactexports/getContactExportResponse.json @@ -0,0 +1,7 @@ +{ + "id": 1, + "status": "finished", + "created_at": "2025-10-06T01:01:01Z", + "updated_at": "2025-10-06T01:03:21Z", + "url": null +}