Skip to content

Commit

Permalink
merge: pull request #24 from email-testing.
Browse files Browse the repository at this point in the history
  • Loading branch information
narekhovhannisyan authored Nov 10, 2023
2 parents 97f4ab4 + 74146d1 commit 3af12a3
Show file tree
Hide file tree
Showing 16 changed files with 775 additions and 31 deletions.
35 changes: 35 additions & 0 deletions examples/testing/inboxes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { MailtrapClient } from "../../src"

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

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

const projectsClient = client.testing.projects
const inboxesClient = client.testing.inboxes

projectsClient.getList()
.then(async (projects) => {
if (projects && projects.length > 0) {
const firstProjectId = projects[0].id

await inboxesClient.create(firstProjectId, 'test-inbox')

const inboxes = await inboxesClient.getList()

if (inboxes && inboxes.length > 0) {
const firstInboxId = inboxes[0].id

const inboxAttributes = await inboxesClient.getInboxAttributes(firstInboxId)
await inboxesClient.updateInbox(firstInboxId, {name: 'mock-name', emailUsername: 'mocker'})
await inboxesClient.cleanInbox(firstInboxId)
await inboxesClient.markAsRead(firstInboxId)
await inboxesClient.resetCredentials(firstInboxId)
await inboxesClient.enableEmailAddress(firstInboxId)
const response = await inboxesClient.resetEmailAddress(firstInboxId)

console.log(response)
}
}
})
41 changes: 41 additions & 0 deletions examples/testing/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { MailtrapClient } from "../../src"

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

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

const inboxesClient = client.testing.inboxes
const messagesClient = client.testing.messages

inboxesClient.getList()
.then(async (inboxes) => {
if (inboxes && inboxes.length > 0) {
const firstInboxId = inboxes[0].id

const messages = await messagesClient.get(firstInboxId)

if (messages && messages.length > 0) {
const firstMessageId = messages[0].id

await messagesClient.get(firstInboxId)
await messagesClient.getHtmlAnalysis(firstInboxId, firstMessageId)
await messagesClient.getHtmlMessage(firstInboxId, firstMessageId)
await messagesClient.getTextMessage(firstInboxId, firstMessageId)
await messagesClient.getMailHeaders(firstInboxId, firstMessageId)
await messagesClient.getMessageAsEml(firstInboxId, firstMessageId)
await messagesClient.getMessageHtmlSource(firstInboxId, firstMessageId)
await messagesClient.getRawMessage(firstInboxId, firstMessageId)
await messagesClient.getSpamScore(firstInboxId, firstMessageId)
await messagesClient.showEmailMessage(firstInboxId, firstMessageId)
await messagesClient.updateMessage(firstInboxId, firstMessageId, {
isRead: false
})
await messagesClient.forward(firstInboxId, firstMessageId, '[email protected]')
const response = await messagesClient.deleteMessage(firstInboxId, firstMessageId)

console.log(response)
}
}
})
22 changes: 22 additions & 0 deletions examples/testing/projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { MailtrapClient } from "mailtrap"

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

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

const projectsClient = client.testing.projects

projectsClient.getList()
.then(async (projects) => {
if (projects) {
const firstProject = projects[0].id // Grab the first project.

const updatedProject =
await projectsClient.update(firstProject, 'test-project') // Update the name of the project.

await projectsClient.delete()
}
})
.catch(console.error)
12 changes: 5 additions & 7 deletions src/__tests__/lib/mailtrap-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ describe("lib/mailtrap-client: ", () => {
const client = new MailtrapClient({ token: "MY_API_TOKEN" });
const result = await client.send(goodMail);

expect(mock.history.post[0].baseURL).toEqual(
"https://send.api.mailtrap.io"
expect(mock.history.post[0].url).toEqual(
"https://send.api.mailtrap.io/api/send"
);
expect(mock.history.post[0].url).toEqual("/api/send");
expect(mock.history.post[0].headers).toEqual({
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
Expand Down Expand Up @@ -94,10 +93,9 @@ describe("lib/mailtrap-client: ", () => {
},
});

expect(mock.history.post[0].baseURL).toEqual(
"https://send.api.mailtrap.io"
expect(mock.history.post[0].url).toEqual(
"https://send.api.mailtrap.io/api/send"
);
expect(mock.history.post[0].url).toEqual("/api/send");
expect(mock.history.post[0].headers).toEqual({
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
Expand Down Expand Up @@ -130,7 +128,7 @@ describe("lib/mailtrap-client: ", () => {
} catch (err) {
expect(err).toBeInstanceOf(MailtrapError);
if (err instanceof MailtrapError) {
expect(err.message).toEqual("subject is missing, message is missing");
expect(err.message).toEqual("subject is missing,message is missing");
// @ts-expect-error ES5 types don't know about cause property
expect(err.cause).toBeInstanceOf(AxiosError);
}
Expand Down
7 changes: 6 additions & 1 deletion src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ export default {
FROM_REQUIRED: "From is required.",
SENDING_FAILED: "Sending failed.",
NO_DATA_ERROR: "No Data.",
TEST_INBOX_ID_MISSING: "testInboxId is missing, testing API will not work.",
ACCOUNT_ID_MISSING:
"accountId is missing, some features of testing API may not work properly.",
},
CLIENT_SETTINGS: {
MAILTRAP_ENDPOINT: "https://send.api.mailtrap.io",
SENDING_ENDPOINT: "https://send.api.mailtrap.io",
TESTING_ENDPOINT: "https://sandbox.api.mailtrap.io",
GENERAL_ENDPOINT: "https://mailtrap.io",
USER_AGENT:
"mailtrap-nodejs (https://github.com/railsware/mailtrap-nodejs)",
MAX_REDIRECTS: 0,
Expand Down
57 changes: 57 additions & 0 deletions src/lib/api/Testing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import axios, { AxiosInstance } from "axios";

import ProjectsApi from "./resources/Projects";
import InboxesApi from "./resources/Inboxes";
import MessagesApi from "./resources/Messages";
import encodeMailBuffers from "../mail-buffer-encoder";
import handleSendingError from "../axios-logger";

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

import { Mail, SendResponse } from "../../types/mailtrap";

const { CLIENT_SETTINGS } = CONFIG;
const { TESTING_ENDPOINT } = CLIENT_SETTINGS;

export default class TestingAPI {
private client: AxiosInstance;

private testInboxId?: number;

private accountId?: number;

public projects: ProjectsApi;

public inboxes: InboxesApi;

public messages: MessagesApi;

constructor(client: AxiosInstance, testInboxId?: number, accountId?: number) {
this.client = client;
this.accountId = accountId;
this.testInboxId = testInboxId;
this.projects = new ProjectsApi(this.client, this.accountId);
this.inboxes = new InboxesApi(this.client, this.accountId);
this.messages = new MessagesApi(this.client, this.accountId);
}

public async send(mail: Mail): Promise<SendResponse> {
const url = `${TESTING_ENDPOINT}/api/send/${this.testInboxId}`;
const preparedMail = encodeMailBuffers(mail);

try {
const axiosResponse = await this.client.post<SendResponse>(
url,
preparedMail
);

return axiosResponse.data;
} catch (error) {
if (axios.isAxiosError(error)) {
handleSendingError(error);
}

throw error; // should not happen, but otherwise rethrow error as is
}
}
}
128 changes: 128 additions & 0 deletions src/lib/api/resources/Inboxes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { AxiosInstance } from "axios";

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

import { Inbox, UpdateInboxParams } from "../../../types/api/inboxes";

const { CLIENT_SETTINGS } = CONFIG;
const { GENERAL_ENDPOINT } = CLIENT_SETTINGS;

export default class InboxesApi {
private client: AxiosInstance;

private accountId?: number;

private inboxesURL: string;

constructor(client: AxiosInstance, accountId?: number) {
this.client = client;
this.accountId = accountId;
this.inboxesURL = `${GENERAL_ENDPOINT}/api/accounts/${this.accountId}/inboxes`;
}

/**
* Creates an inbox in a project.
*/
public async create(projectId: number, inboxName: string) {
const url = `${GENERAL_ENDPOINT}/api/accounts/${this.accountId}/projects/${projectId}/inboxes`;
const data = { inbox: { name: inboxName } };
const apiResponse = await this.client.post<Inbox>(url, data);

return apiResponse.data;
}

/**
* Gets inbox attributes by inbox id.
*/
public async getInboxAttributes(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}`;
const apiResponse = await this.client.get<Inbox>(url);

return apiResponse.data;
}

/**
* Deletes an inbox with all its emails.
*/
public async delete(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}`;
const apiResponse = await this.client.delete<Inbox>(url);

return apiResponse.data;
}

/**
* Updates inbox name, inbox email username.
*/
public async updateInbox(inboxId: number, params: UpdateInboxParams) {
const url = `${this.inboxesURL}/${inboxId}`;
const data = {
inbox: {
name: params.name,
email_username: params.emailUsername,
},
};
const apiRespone = await this.client.patch<Inbox>(url, data);

return apiRespone.data;
}

/**
* Deletes all messages (emails) from inbox.
*/
public async cleanInbox(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}/clean`;
const apiRespone = await this.client.patch<Inbox>(url);

return apiRespone.data;
}

/**
* Marks all messages in the inbox as read.
*/
public async markAsRead(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}/all_read`;
const apiRespone = await this.client.patch<Inbox>(url);

return apiRespone.data;
}

/**
* Resets SMTP credentials of the inbox.
*/
public async resetCredentials(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}/reset_credentials`;
const apiRespone = await this.client.patch<Inbox>(url);

return apiRespone.data;
}

/**
* Turns the email address of the inbox on/off.
*/
public async enableEmailAddress(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}/toggle_email_username`;
const apiRespone = await this.client.patch<Inbox>(url);

return apiRespone.data;
}

/**
* Resets username of email address per inbox.
*/
public async resetEmailAddress(inboxId: number) {
const url = `${this.inboxesURL}/${inboxId}/reset_email_username`;
const apiRespone = await this.client.patch<Inbox>(url);

return apiRespone.data;
}

/**
* Gets a list of inboxes.
*/
public async getList() {
const apiRespone = await this.client.get<Inbox[]>(this.inboxesURL);

return apiRespone.data;
}
}
Loading

0 comments on commit 3af12a3

Please sign in to comment.