Skip to content

Commit 70796f4

Browse files
Merge pull request #93 from railsware/create-sending-domain
Sending domains API
2 parents 0da12ca + eedec50 commit 70796f4

File tree

9 files changed

+470
-0
lines changed

9 files changed

+470
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { MailtrapClient } from "../../src/index";
2+
3+
const TOKEN = "<YOUR-TOKEN-HERE>";
4+
const ACCOUNT_ID = "<YOUR-ACCOUNT-ID-HERE>";
5+
6+
const client = new MailtrapClient({
7+
token: TOKEN,
8+
accountId: Number(ACCOUNT_ID),
9+
});
10+
11+
async function sendingDomainsFlow() {
12+
try {
13+
// Get all sending domains
14+
const all = await client.sendingDomains.getList();
15+
console.log("All sending domains:", JSON.stringify(all, null, 2));
16+
17+
if (!all.data || all.data.length === 0) {
18+
console.log("No sending domains found for this account.");
19+
return;
20+
}
21+
22+
// Get a specific sending domain
23+
const one = await client.sendingDomains.get(all.data[0].id);
24+
console.log("One sending domain:", JSON.stringify(one, null, 2));
25+
26+
// Send setup instructions
27+
const setupResponse = await client.sendingDomains.sendSetupInstructions(
28+
all.data[0].id,
29+
30+
);
31+
console.log("Setup instructions sent");
32+
33+
// Create a new sending domain
34+
const created = await client.sendingDomains.create({
35+
domain_name: "test-domain-" + Date.now() + ".com",
36+
});
37+
console.log("Created sending domain:", JSON.stringify(created, null, 2));
38+
39+
// Delete the created domain
40+
await client.sendingDomains.delete(created.id);
41+
console.log("Sending domain deleted");
42+
43+
} catch (error) {
44+
console.error("Error in sendingDomainsFlow:", error instanceof Error ? error.message : String(error));
45+
}
46+
}
47+
48+
sendingDomainsFlow();
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import axios, { AxiosInstance } from "axios";
2+
import MockAdapter from "axios-mock-adapter";
3+
4+
import SendingDomainsBaseAPI from "../../../../lib/api/SendingDomains";
5+
import {
6+
SendingDomain,
7+
DnsRecord,
8+
SendingDomainPermissions,
9+
} from "../../../../types/api/sending-domains";
10+
11+
describe("lib/api/SendingDomains: ", () => {
12+
const axiosInstance: AxiosInstance = axios.create();
13+
const mock = new MockAdapter(axiosInstance);
14+
15+
// Add the response interceptor that returns response.data
16+
axiosInstance.interceptors.response.use((response) => response.data);
17+
18+
const testAccountId = 100;
19+
const sendingDomainsAPI = new SendingDomainsBaseAPI(
20+
axiosInstance,
21+
testAccountId
22+
);
23+
24+
describe("class SendingDomainsBaseAPI(): ", () => {
25+
describe("init: ", () => {
26+
it("initializes with all necessary params.", () => {
27+
expect(sendingDomainsAPI).toHaveProperty("get");
28+
expect(sendingDomainsAPI).toHaveProperty("getList");
29+
expect(sendingDomainsAPI).toHaveProperty("create");
30+
expect(sendingDomainsAPI).toHaveProperty("delete");
31+
expect(sendingDomainsAPI).toHaveProperty("sendSetupInstructions");
32+
});
33+
});
34+
35+
describe("sendingDomains.getList(): ", () => {
36+
it("should get sending domains list.", async () => {
37+
const mockDnsRecords: DnsRecord[] = [
38+
{
39+
key: "verification",
40+
domain: "ve6wza2rbpe60x7z.example.com",
41+
type: "CNAME",
42+
value: "smtp.mailtrap.live",
43+
status: "pass",
44+
name: "ve6wza2rbpe60x7z",
45+
},
46+
{
47+
key: "spf",
48+
domain: "example.com",
49+
type: "TXT",
50+
value: "v=spf1 include:_spf.smtp.mailtrap.live ~all",
51+
status: "pass",
52+
name: "",
53+
},
54+
];
55+
56+
const mockPermissions: SendingDomainPermissions = {
57+
can_read: true,
58+
can_update: true,
59+
can_destroy: true,
60+
};
61+
62+
const mockSendingDomains: SendingDomain[] = [
63+
{
64+
id: 435,
65+
domain_name: "example.com",
66+
demo: false,
67+
compliance_status: "compliant",
68+
dns_verified: true,
69+
dns_verified_at: "2024-12-26T09:40:44.161Z",
70+
dns_records: mockDnsRecords,
71+
open_tracking_enabled: true,
72+
click_tracking_enabled: true,
73+
auto_unsubscribe_link_enabled: true,
74+
custom_domain_tracking_enabled: true,
75+
health_alerts_enabled: true,
76+
critical_alerts_enabled: true,
77+
alert_recipient_email: "[email protected]",
78+
permissions: mockPermissions,
79+
},
80+
];
81+
82+
mock
83+
.onGet(
84+
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains`
85+
)
86+
.reply(200, { data: mockSendingDomains });
87+
88+
const result = await sendingDomainsAPI.getList();
89+
90+
expect(result).toEqual({ data: mockSendingDomains });
91+
});
92+
});
93+
94+
describe("sendingDomains.get(): ", () => {
95+
it("should get a single sending domain by id.", async () => {
96+
const mockDnsRecords: DnsRecord[] = [
97+
{
98+
key: "verification",
99+
domain: "ve6wza2rbpe60x7z.example.com",
100+
type: "CNAME",
101+
value: "smtp.mailtrap.live",
102+
status: "pass",
103+
name: "ve6wza2rbpe60x7z",
104+
},
105+
];
106+
107+
const mockPermissions: SendingDomainPermissions = {
108+
can_read: true,
109+
can_update: true,
110+
can_destroy: true,
111+
};
112+
113+
const mockSendingDomain: SendingDomain = {
114+
id: 999,
115+
domain_name: "example.com",
116+
demo: false,
117+
compliance_status: "compliant",
118+
dns_verified: true,
119+
dns_verified_at: "2024-12-26T09:40:44.161Z",
120+
dns_records: mockDnsRecords,
121+
open_tracking_enabled: true,
122+
click_tracking_enabled: true,
123+
auto_unsubscribe_link_enabled: true,
124+
custom_domain_tracking_enabled: true,
125+
health_alerts_enabled: true,
126+
critical_alerts_enabled: true,
127+
alert_recipient_email: "[email protected]",
128+
permissions: mockPermissions,
129+
};
130+
131+
mock
132+
.onGet(
133+
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains/${mockSendingDomain.id}`
134+
)
135+
.reply(200, mockSendingDomain);
136+
137+
const result = await sendingDomainsAPI.get(mockSendingDomain.id);
138+
139+
expect(result).toEqual(mockSendingDomain);
140+
});
141+
});
142+
143+
describe("sendingDomains.create(): ", () => {
144+
it("should create a new sending domain.", async () => {
145+
const mockDnsRecords: DnsRecord[] = [
146+
{
147+
key: "verification",
148+
domain: "ve6wza2rbpe60x7z.newdomain.com",
149+
type: "CNAME",
150+
value: "smtp.mailtrap.live",
151+
status: "pass",
152+
name: "ve6wza2rbpe60x7z",
153+
},
154+
];
155+
156+
const mockPermissions: SendingDomainPermissions = {
157+
can_read: true,
158+
can_update: true,
159+
can_destroy: true,
160+
};
161+
162+
const mockSendingDomain: SendingDomain = {
163+
id: 436,
164+
domain_name: "newdomain.com",
165+
demo: false,
166+
compliance_status: "pending",
167+
dns_verified: false,
168+
dns_verified_at: "",
169+
dns_records: mockDnsRecords,
170+
open_tracking_enabled: true,
171+
click_tracking_enabled: true,
172+
auto_unsubscribe_link_enabled: true,
173+
custom_domain_tracking_enabled: true,
174+
health_alerts_enabled: true,
175+
critical_alerts_enabled: true,
176+
alert_recipient_email: "[email protected]",
177+
permissions: mockPermissions,
178+
};
179+
180+
const createParams = {
181+
domain_name: "newdomain.com",
182+
};
183+
184+
mock
185+
.onPost(
186+
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains`,
187+
{ sending_domain: createParams }
188+
)
189+
.reply(201, mockSendingDomain);
190+
191+
const result = await sendingDomainsAPI.create(createParams);
192+
193+
expect(result).toEqual(mockSendingDomain);
194+
});
195+
});
196+
197+
describe("sendingDomains.delete(): ", () => {
198+
it("should delete a sending domain by id.", async () => {
199+
const sendingDomainId = 999;
200+
201+
mock
202+
.onDelete(
203+
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains/${sendingDomainId}`
204+
)
205+
.reply(204);
206+
207+
const result = await sendingDomainsAPI.delete(sendingDomainId);
208+
209+
expect(result).toBeUndefined();
210+
});
211+
});
212+
213+
describe("sendingDomains.sendSetupInstructions(): ", () => {
214+
it("should send setup instructions for a sending domain.", async () => {
215+
const sendingDomainId = 999;
216+
const email = "[email protected]";
217+
218+
mock
219+
.onPost(
220+
`https://mailtrap.io/api/accounts/${testAccountId}/sending_domains/${sendingDomainId}/send_setup_instructions`
221+
)
222+
.reply(204);
223+
224+
const result = await sendingDomainsAPI.sendSetupInstructions(
225+
sendingDomainId,
226+
email
227+
);
228+
229+
expect(result).toBeUndefined();
230+
});
231+
});
232+
});
233+
});

src/__tests__/lib/mailtrap-client.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ContactLists from "../../lib/api/ContactLists";
1313
import Contacts from "../../lib/api/Contacts";
1414
import TemplatesBaseAPI from "../../lib/api/Templates";
1515
import SuppressionsBaseAPI from "../../lib/api/Suppressions";
16+
import SendingDomainsBaseAPI from "../../lib/api/SendingDomains";
1617

1718
const { ERRORS, CLIENT_SETTINGS } = CONFIG;
1819
const { TESTING_ENDPOINT, BULK_ENDPOINT, SENDING_ENDPOINT } = CLIENT_SETTINGS;
@@ -873,5 +874,31 @@ describe("lib/mailtrap-client: ", () => {
873874
expect(suppressionsClient).toBeInstanceOf(SuppressionsBaseAPI);
874875
});
875876
});
877+
878+
describe("get sendingDomains(): ", () => {
879+
it("rejects with Mailtrap error, when `accountId` is missing.", () => {
880+
expect.assertions(1);
881+
882+
const client = new MailtrapClient({
883+
token: "test-token",
884+
});
885+
886+
expect(() => client.sendingDomains).toThrow(
887+
"accountId is missing, some features of testing API may not work properly."
888+
);
889+
});
890+
891+
it("returns sending domains API object when accountId is provided.", () => {
892+
expect.assertions(1);
893+
894+
const client = new MailtrapClient({
895+
token: "test-token",
896+
accountId: 123,
897+
});
898+
899+
const sendingDomainsClient = client.sendingDomains;
900+
expect(sendingDomainsClient).toBeInstanceOf(SendingDomainsBaseAPI);
901+
});
902+
});
876903
});
877904
});

src/lib/MailtrapClient.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import ContactListsBaseAPI from "./api/ContactLists";
1414
import ContactFieldsBaseAPI from "./api/ContactFields";
1515
import TemplatesBaseAPI from "./api/Templates";
1616
import SuppressionsBaseAPI from "./api/Suppressions";
17+
import SendingDomainsBaseAPI from "./api/SendingDomains";
1718

1819
import CONFIG from "../config";
1920

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

165+
/**
166+
* Getter for Sending Domains API.
167+
*/
168+
get sendingDomains() {
169+
this.validateAccountIdPresence();
170+
171+
return new SendingDomainsBaseAPI(this.axios, this.accountId!);
172+
}
173+
164174
/**
165175
* Returns configured host. Checks if `bulk` and `sandbox` modes are activated simultaneously,
166176
* then reject with Mailtrap Error.

src/lib/api/SendingDomains.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { AxiosInstance } from "axios";
2+
3+
import SendingDomainsApi from "./resources/SendingDomains";
4+
5+
export default class SendingDomainsBaseAPI {
6+
private client: AxiosInstance;
7+
8+
public get: SendingDomainsApi["get"];
9+
10+
public getList: SendingDomainsApi["getList"];
11+
12+
public create: SendingDomainsApi["create"];
13+
14+
public delete: SendingDomainsApi["delete"];
15+
16+
public sendSetupInstructions: SendingDomainsApi["sendSetupInstructions"];
17+
18+
constructor(client: AxiosInstance, accountId: number) {
19+
this.client = client;
20+
const sendingDomains = new SendingDomainsApi(this.client, accountId);
21+
this.get = sendingDomains.get.bind(sendingDomains);
22+
this.getList = sendingDomains.getList.bind(sendingDomains);
23+
this.create = sendingDomains.create.bind(sendingDomains);
24+
this.delete = sendingDomains.delete.bind(sendingDomains);
25+
this.sendSetupInstructions =
26+
sendingDomains.sendSetupInstructions.bind(sendingDomains);
27+
}
28+
}

0 commit comments

Comments
 (0)