Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
cc608b9
examples: add example script for sending domains API usage
narekhovhannisyan Oct 9, 2025
c2d72be
test: add unit tests for sending domains API in MailtrapClient
narekhovhannisyan Oct 9, 2025
f9b0760
test: implement unit tests for SendingDomains API methods including g…
narekhovhannisyan Oct 9, 2025
b6449f8
lib: add getter for SendingDomainsBaseAPI in MailtrapClient
narekhovhannisyan Oct 9, 2025
51a77c7
api: implement SendingDomainsBaseAPI class for managing sending domains
narekhovhannisyan Oct 9, 2025
808d825
resources: add SendingDomainsApi class for managing sending domains w…
narekhovhannisyan Oct 9, 2025
f5e1be1
types: add TypeScript interfaces for sending domains and DNS records
narekhovhannisyan Oct 9, 2025
c6a2957
Merge branch 'main' of github.com:railsware/mailtrap-nodejs into crea…
narekhovhannisyan Oct 10, 2025
04166b4
types: add documentation for ContactFields and ContactField interface…
narekhovhannisyan Oct 10, 2025
7764c04
types: add SendingDomainsResponse interface to define the structure o…
narekhovhannisyan Oct 10, 2025
c641885
refactor: update getList method in SendingDomainsApi to return Sendin…
narekhovhannisyan Oct 10, 2025
a944630
test: update SendingDomains test to match new response structure with…
narekhovhannisyan Oct 10, 2025
8c9a923
refactor: update sending domains example to improve flow and structure
narekhovhannisyan Oct 10, 2025
643dcf4
types: update SendingDomain interface to allow null values for dns_ve…
narekhovhannisyan Oct 13, 2025
a0aa0cb
refactor: simplify getList method and update create method to use cor…
narekhovhannisyan Oct 13, 2025
64b885e
test: adjust SendingDomains test to validate updated response structu…
narekhovhannisyan Oct 13, 2025
89f5a27
types: remove SetupInstructionsResponse interface as it is no longer …
narekhovhannisyan Oct 13, 2025
977a9d9
refactor: rename setup instructions endpoint and simplify post reques…
narekhovhannisyan Oct 13, 2025
20f7294
test: update SendingDomains test to reflect changes in setup instruct…
narekhovhannisyan Oct 13, 2025
cae8810
refactor: enhance sending domains example with improved error handlin…
narekhovhannisyan Oct 13, 2025
eedec50
test: remove unused SetupInstructionsResponse import from SendingDoma…
narekhovhannisyan Oct 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions examples/sending-domains/everything.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { MailtrapClient } from "../../src/index";

const TOKEN = "<YOUR-TOKEN-HERE>";
const ACCOUNT_ID = "<YOUR-ACCOUNT-ID-HERE>";

const client = new MailtrapClient({
token: TOKEN,
accountId: Number(ACCOUNT_ID),
});

async function sendingDomainsFlow() {
try {
// Get all sending domains
const all = await client.sendingDomains.getList();
console.log("All sending domains:", JSON.stringify(all, null, 2));

if (!all.data || all.data.length === 0) {
console.log("No sending domains found for this account.");
return;
}

// Get a specific sending domain
const one = await client.sendingDomains.get(all.data[0].id);
console.log("One sending domain:", JSON.stringify(one, null, 2));

// Send setup instructions
const setupResponse = await client.sendingDomains.sendSetupInstructions(
all.data[0].id,
"admin@example.com"
);
console.log("Setup instructions sent");

// Create a new sending domain
const created = await client.sendingDomains.create({
domain_name: "test-domain-" + Date.now() + ".com",
});
console.log("Created sending domain:", JSON.stringify(created, null, 2));

// Delete the created domain
await client.sendingDomains.delete(created.id);
console.log("Sending domain deleted");

} catch (error) {
console.error("Error in sendingDomainsFlow:", error instanceof Error ? error.message : String(error));
}
}

sendingDomainsFlow();
233 changes: 233 additions & 0 deletions src/__tests__/lib/api/resources/SendingDomains.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import axios, { AxiosInstance } from "axios";
import MockAdapter from "axios-mock-adapter";

import SendingDomainsBaseAPI from "../../../../lib/api/SendingDomains";
import {
SendingDomain,
DnsRecord,
SendingDomainPermissions,
} from "../../../../types/api/sending-domains";

describe("lib/api/SendingDomains: ", () => {
const axiosInstance: AxiosInstance = axios.create();
const mock = new MockAdapter(axiosInstance);

// Add the response interceptor that returns response.data
axiosInstance.interceptors.response.use((response) => response.data);

const testAccountId = 100;
const sendingDomainsAPI = new SendingDomainsBaseAPI(
axiosInstance,
testAccountId
);

describe("class SendingDomainsBaseAPI(): ", () => {
describe("init: ", () => {
it("initializes with all necessary params.", () => {
expect(sendingDomainsAPI).toHaveProperty("get");
expect(sendingDomainsAPI).toHaveProperty("getList");
expect(sendingDomainsAPI).toHaveProperty("create");
expect(sendingDomainsAPI).toHaveProperty("delete");
expect(sendingDomainsAPI).toHaveProperty("sendSetupInstructions");
});
});

describe("sendingDomains.getList(): ", () => {
it("should get sending domains list.", async () => {
const mockDnsRecords: DnsRecord[] = [
{
key: "verification",
domain: "ve6wza2rbpe60x7z.example.com",
type: "CNAME",
value: "smtp.mailtrap.live",
status: "pass",
name: "ve6wza2rbpe60x7z",
},
{
key: "spf",
domain: "example.com",
type: "TXT",
value: "v=spf1 include:_spf.smtp.mailtrap.live ~all",
status: "pass",
name: "",
},
];

const mockPermissions: SendingDomainPermissions = {
can_read: true,
can_update: true,
can_destroy: true,
};

const mockSendingDomains: SendingDomain[] = [
{
id: 435,
domain_name: "example.com",
demo: false,
compliance_status: "compliant",
dns_verified: true,
dns_verified_at: "2024-12-26T09:40:44.161Z",
dns_records: mockDnsRecords,
open_tracking_enabled: true,
click_tracking_enabled: true,
auto_unsubscribe_link_enabled: true,
custom_domain_tracking_enabled: true,
health_alerts_enabled: true,
critical_alerts_enabled: true,
alert_recipient_email: "john.doe@example.com",
permissions: mockPermissions,
},
];

mock
.onGet(
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains`
)
.reply(200, { data: mockSendingDomains });

const result = await sendingDomainsAPI.getList();

expect(result).toEqual({ data: mockSendingDomains });
});
});

describe("sendingDomains.get(): ", () => {
it("should get a single sending domain by id.", async () => {
const mockDnsRecords: DnsRecord[] = [
{
key: "verification",
domain: "ve6wza2rbpe60x7z.example.com",
type: "CNAME",
value: "smtp.mailtrap.live",
status: "pass",
name: "ve6wza2rbpe60x7z",
},
];

const mockPermissions: SendingDomainPermissions = {
can_read: true,
can_update: true,
can_destroy: true,
};

const mockSendingDomain: SendingDomain = {
id: 999,
domain_name: "example.com",
demo: false,
compliance_status: "compliant",
dns_verified: true,
dns_verified_at: "2024-12-26T09:40:44.161Z",
dns_records: mockDnsRecords,
open_tracking_enabled: true,
click_tracking_enabled: true,
auto_unsubscribe_link_enabled: true,
custom_domain_tracking_enabled: true,
health_alerts_enabled: true,
critical_alerts_enabled: true,
alert_recipient_email: "john.doe@example.com",
permissions: mockPermissions,
};

mock
.onGet(
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains/${mockSendingDomain.id}`
)
.reply(200, mockSendingDomain);

const result = await sendingDomainsAPI.get(mockSendingDomain.id);

expect(result).toEqual(mockSendingDomain);
});
});

describe("sendingDomains.create(): ", () => {
it("should create a new sending domain.", async () => {
const mockDnsRecords: DnsRecord[] = [
{
key: "verification",
domain: "ve6wza2rbpe60x7z.newdomain.com",
type: "CNAME",
value: "smtp.mailtrap.live",
status: "pass",
name: "ve6wza2rbpe60x7z",
},
];

const mockPermissions: SendingDomainPermissions = {
can_read: true,
can_update: true,
can_destroy: true,
};

const mockSendingDomain: SendingDomain = {
id: 436,
domain_name: "newdomain.com",
demo: false,
compliance_status: "pending",
dns_verified: false,
dns_verified_at: "",
dns_records: mockDnsRecords,
open_tracking_enabled: true,
click_tracking_enabled: true,
auto_unsubscribe_link_enabled: true,
custom_domain_tracking_enabled: true,
health_alerts_enabled: true,
critical_alerts_enabled: true,
alert_recipient_email: "admin@newdomain.com",
permissions: mockPermissions,
};

const createParams = {
domain_name: "newdomain.com",
};

mock
.onPost(
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains`,
{ sending_domain: createParams }
)
.reply(201, mockSendingDomain);

const result = await sendingDomainsAPI.create(createParams);

expect(result).toEqual(mockSendingDomain);
});
});

describe("sendingDomains.delete(): ", () => {
it("should delete a sending domain by id.", async () => {
const sendingDomainId = 999;

mock
.onDelete(
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains/${sendingDomainId}`
)
.reply(204);

const result = await sendingDomainsAPI.delete(sendingDomainId);

expect(result).toBeUndefined();
});
});

describe("sendingDomains.sendSetupInstructions(): ", () => {
it("should send setup instructions for a sending domain.", async () => {
const sendingDomainId = 999;
const email = "admin@example.com";

mock
.onPost(
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains/${sendingDomainId}/send_setup_instructions`
)
.reply(204);

const result = await sendingDomainsAPI.sendSetupInstructions(
sendingDomainId,
email
);

expect(result).toBeUndefined();
});
});
});
});
27 changes: 27 additions & 0 deletions src/__tests__/lib/mailtrap-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ContactLists from "../../lib/api/ContactLists";
import Contacts from "../../lib/api/Contacts";
import TemplatesBaseAPI from "../../lib/api/Templates";
import SuppressionsBaseAPI from "../../lib/api/Suppressions";
import SendingDomainsBaseAPI from "../../lib/api/SendingDomains";

const { ERRORS, CLIENT_SETTINGS } = CONFIG;
const { TESTING_ENDPOINT, BULK_ENDPOINT, SENDING_ENDPOINT } = CLIENT_SETTINGS;
Expand Down Expand Up @@ -873,5 +874,31 @@ describe("lib/mailtrap-client: ", () => {
expect(suppressionsClient).toBeInstanceOf(SuppressionsBaseAPI);
});
});

describe("get sendingDomains(): ", () => {
it("rejects with Mailtrap error, when `accountId` is missing.", () => {
expect.assertions(1);

const client = new MailtrapClient({
token: "test-token",
});

expect(() => client.sendingDomains).toThrow(
"accountId is missing, some features of testing API may not work properly."
);
});

it("returns sending domains API object when accountId is provided.", () => {
expect.assertions(1);

const client = new MailtrapClient({
token: "test-token",
accountId: 123,
});

const sendingDomainsClient = client.sendingDomains;
expect(sendingDomainsClient).toBeInstanceOf(SendingDomainsBaseAPI);
});
});
});
});
10 changes: 10 additions & 0 deletions src/lib/MailtrapClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ContactListsBaseAPI from "./api/ContactLists";
import ContactFieldsBaseAPI from "./api/ContactFields";
import TemplatesBaseAPI from "./api/Templates";
import SuppressionsBaseAPI from "./api/Suppressions";
import SendingDomainsBaseAPI from "./api/SendingDomains";

import CONFIG from "../config";

Expand Down Expand Up @@ -161,6 +162,15 @@ export default class MailtrapClient {
return new SuppressionsBaseAPI(this.axios, accountId);
}

/**
* Getter for Sending Domains API.
*/
get sendingDomains() {
this.validateAccountIdPresence();

return new SendingDomainsBaseAPI(this.axios, this.accountId!);
}

/**
* Returns configured host. Checks if `bulk` and `sandbox` modes are activated simultaneously,
* then reject with Mailtrap Error.
Expand Down
28 changes: 28 additions & 0 deletions src/lib/api/SendingDomains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AxiosInstance } from "axios";

import SendingDomainsApi from "./resources/SendingDomains";

export default class SendingDomainsBaseAPI {
private client: AxiosInstance;

public get: SendingDomainsApi["get"];

public getList: SendingDomainsApi["getList"];

public create: SendingDomainsApi["create"];

public delete: SendingDomainsApi["delete"];

public sendSetupInstructions: SendingDomainsApi["sendSetupInstructions"];

constructor(client: AxiosInstance, accountId: number) {
this.client = client;
const sendingDomains = new SendingDomainsApi(this.client, accountId);
this.get = sendingDomains.get.bind(sendingDomains);
this.getList = sendingDomains.getList.bind(sendingDomains);
this.create = sendingDomains.create.bind(sendingDomains);
this.delete = sendingDomains.delete.bind(sendingDomains);
this.sendSetupInstructions =
sendingDomains.sendSetupInstructions.bind(sendingDomains);
}
}
Loading