diff --git a/examples/testing/inboxes.ts b/examples/testing/inboxes.ts new file mode 100644 index 0000000..7e147cb --- /dev/null +++ b/examples/testing/inboxes.ts @@ -0,0 +1,35 @@ +import { MailtrapClient } from "../../src" + +const TOKEN = ""; +const TEST_INBOX_ID = "" +const ACCOUNT_ID = "" + +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) + } + } + }) diff --git a/examples/testing/messages.ts b/examples/testing/messages.ts new file mode 100644 index 0000000..8a6c5b2 --- /dev/null +++ b/examples/testing/messages.ts @@ -0,0 +1,41 @@ +import { MailtrapClient } from "../../src" + +const TOKEN = ""; +const TEST_INBOX_ID = "" +const ACCOUNT_ID = "" + +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, 'mock@mail.com') + const response = await messagesClient.deleteMessage(firstInboxId, firstMessageId) + + console.log(response) + } + } + }) diff --git a/examples/testing/projects.ts b/examples/testing/projects.ts new file mode 100644 index 0000000..b7f8520 --- /dev/null +++ b/examples/testing/projects.ts @@ -0,0 +1,22 @@ +import { MailtrapClient } from "mailtrap" + +const TOKEN = ""; +const TEST_INBOX_ID = "" +const ACCOUNT_ID = "" + +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) diff --git a/src/__tests__/lib/mailtrap-client.test.ts b/src/__tests__/lib/mailtrap-client.test.ts index 17c0f75..983e4b3 100644 --- a/src/__tests__/lib/mailtrap-client.test.ts +++ b/src/__tests__/lib/mailtrap-client.test.ts @@ -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", @@ -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", @@ -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); } diff --git a/src/config/index.ts b/src/config/index.ts index 27eda94..446884d 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -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, diff --git a/src/lib/api/Testing.ts b/src/lib/api/Testing.ts new file mode 100644 index 0000000..6759c3b --- /dev/null +++ b/src/lib/api/Testing.ts @@ -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 { + const url = `${TESTING_ENDPOINT}/api/send/${this.testInboxId}`; + const preparedMail = encodeMailBuffers(mail); + + try { + const axiosResponse = await this.client.post( + url, + preparedMail + ); + + return axiosResponse.data; + } catch (error) { + if (axios.isAxiosError(error)) { + handleSendingError(error); + } + + throw error; // should not happen, but otherwise rethrow error as is + } + } +} diff --git a/src/lib/api/resources/Inboxes.ts b/src/lib/api/resources/Inboxes.ts new file mode 100644 index 0000000..813b19e --- /dev/null +++ b/src/lib/api/resources/Inboxes.ts @@ -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(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(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(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(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(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(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(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(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(url); + + return apiRespone.data; + } + + /** + * Gets a list of inboxes. + */ + public async getList() { + const apiRespone = await this.client.get(this.inboxesURL); + + return apiRespone.data; + } +} diff --git a/src/lib/api/resources/Messages.ts b/src/lib/api/resources/Messages.ts new file mode 100644 index 0000000..a8f80a8 --- /dev/null +++ b/src/lib/api/resources/Messages.ts @@ -0,0 +1,165 @@ +import { AxiosInstance } from "axios"; + +import CONFIG from "../../../config"; + +import { + EmailHeaders, + Message, + MessageUpdateParams, + Report, + SpamReport, +} from "../../../types/api/messages"; + +const { CLIENT_SETTINGS } = CONFIG; +const { GENERAL_ENDPOINT } = CLIENT_SETTINGS; + +export default class MessagesApi { + private client: AxiosInstance; + + private messagesURL: string; + + constructor(client: AxiosInstance, accountId?: number) { + this.client = client; + this.messagesURL = `${GENERAL_ENDPOINT}/api/accounts/${accountId}/inboxes`; + } + + /** + * Gets email message by given `messageId`. + */ + public async showEmailMessage(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Updates message attributes (right now only the is_read attribute is available for modification). + */ + public async updateMessage( + inboxId: number, + messageId: number, + params: MessageUpdateParams + ) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}`; + const data = { message: { is_read: params.isRead } }; + const apiResponse = await this.client.patch(url, data); + + return apiResponse.data; + } + + /** + * Deletes message from inbox. + */ + public async deleteMessage(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}`; + const apiResponse = await this.client.delete(url); + + return apiResponse.data; + } + + /** + * Gets all messages in inboxes. + */ + public async get(inboxId: number) { + const url = `${this.messagesURL}/${inboxId}/messages`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Forwards message to an email address. The email address must be confirmed by the recipient in advance. + */ + public async forward( + inboxId: number, + messageId: number, + emailToForward: string + ) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/forward`; + const data = { email: emailToForward }; + const apiResponse = await this.client.post(url, data); + + return apiResponse.data; + } + + /** + * Gets a brief spam report by given `messageId`. + */ + public async getSpamScore(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/spam_report`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets a brief HTML report by message ID. + */ + public async getHtmlAnalysis(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/analyze`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets text email body, if it exists. + */ + public async getTextMessage(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/body.txt`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets raw email body. + */ + public async getRawMessage(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/body.raw`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets HTML source of email. + */ + public async getMessageHtmlSource(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/body.htmlsource`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets formatted HTML email body. Not applicable for plain text emails. + */ + public async getHtmlMessage(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/body.html`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets email message in .eml format. + */ + public async getMessageAsEml(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/body.eml`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Gets mail headers of a message. + */ + public async getMailHeaders(inboxId: number, messageId: number) { + const url = `${this.messagesURL}/${inboxId}/messages/${messageId}/mail_headers`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } +} diff --git a/src/lib/api/resources/Projects.ts b/src/lib/api/resources/Projects.ts new file mode 100644 index 0000000..cc4c204 --- /dev/null +++ b/src/lib/api/resources/Projects.ts @@ -0,0 +1,72 @@ +import { AxiosInstance } from "axios"; + +import CONFIG from "../../../config"; + +import { Project } from "../../../types/api/projects"; + +const { CLIENT_SETTINGS } = CONFIG; +const { GENERAL_ENDPOINT } = CLIENT_SETTINGS; + +export default class ProjectsApi { + private client: AxiosInstance; + + private accountId?: number; + + private projectsURL: string; + + constructor(client: AxiosInstance, accountId?: number) { + this.client = client; + this.accountId = accountId; + this.projectsURL = `${GENERAL_ENDPOINT}/api/accounts/${this.accountId}/projects`; + } + + /** + * Creates new project. + */ + public async create(projectName: string) { + const data = { project: { name: projectName } }; + const apiResponse = await this.client.post(this.projectsURL, data); + + return apiResponse.data; + } + + /** + * Lists projects and their inboxes to which the API token has access. + */ + public async getList() { + const apiResponse = await this.client.get(this.projectsURL); + + return apiResponse.data; + } + + /** + * Gets the project and it's inboxes. + */ + public async getById(projectId: number) { + const url = `${this.projectsURL}/${projectId}`; + const apiResponse = await this.client.get(url); + + return apiResponse.data; + } + + /** + * Updates project name. The project name is min 2 characters and max 100 characters long. + */ + public async update(projectId: number, updatedName: string) { + const url = `${this.projectsURL}/${projectId}`; + const data = { project: { name: updatedName } }; + const apiResponse = await this.client.patch(url, data); + + return apiResponse.data; + } + + /** + * Deletes a project by its ID. + */ + public async delete(projectId: number) { + const url = `${this.projectsURL}/${projectId}`; + const apiResponse = await this.client.delete(url); + + return apiResponse.data; + } +} diff --git a/src/lib/axios-logger.ts b/src/lib/axios-logger.ts new file mode 100644 index 0000000..478f048 --- /dev/null +++ b/src/lib/axios-logger.ts @@ -0,0 +1,69 @@ +import axios, { AxiosError } from "axios"; + +import MailtrapError from "./MailtrapError"; + +import { AxiosErrorObject } from "../types/axios"; + +/** + * Axios error names guard. + */ +const hasErrorProperty = ( + obj: unknown, + propertyName: T +): obj is AxiosErrorObject => { + return (obj as AxiosErrorObject)?.[propertyName] !== undefined; +}; + +/** + * Error handler for axios response. + */ +export default function handleSendingError(error: AxiosError | unknown) { + if (axios.isAxiosError(error)) { + /** + * Handles case where error is in `data.errors`. + */ + const serverErrorsObject = + error.response?.data && + typeof error.response.data === "object" && + "errors" in error.response.data && + error.response.data.errors; + + /** + * Handles case where error is in `data.error`. + */ + const serverErrorObject = + error.response?.data && + typeof error.response.data === "object" && + "error" in error.response.data && + error.response.data.error; + + /** + * Joins error messages contained in `name` property. + */ + const errorNames = + hasErrorProperty(serverErrorsObject, "name") && + serverErrorsObject.name.join(", "); + + /** + * Joins error messages contained in `base` property. + */ + const errorBase = + hasErrorProperty(serverErrorsObject, "base") && + serverErrorsObject.base.join(", "); + + /** + * Selects available error. + */ + const message = + errorNames || + errorBase || + serverErrorsObject || + serverErrorObject || + error.message; + + // @ts-expect-error weird typing around Error class, but it's tested to work + throw new MailtrapError(message, { cause: error }); + } + + throw error; // should not happen, but otherwise rethrow error as is +} diff --git a/src/lib/mailtrap-client.ts b/src/lib/mailtrap-client.ts index 2d62508..03b78c9 100644 --- a/src/lib/mailtrap-client.ts +++ b/src/lib/mailtrap-client.ts @@ -4,15 +4,17 @@ import * as https from "https"; import axios, { AxiosInstance } from "axios"; import encodeMailBuffers from "./mail-buffer-encoder"; -import MailtrapError from "./MailtrapError"; +import handleSendingError from "./axios-logger"; +import TestingAPI from "./api/Testing"; import CONFIG from "../config"; import { Mail, SendResponse, MailtrapClientConfig } from "../types/mailtrap"; -const { CLIENT_SETTINGS } = CONFIG; -const { MAILTRAP_ENDPOINT, MAX_REDIRECTS, USER_AGENT, TIMEOUT } = +const { CLIENT_SETTINGS, ERRORS } = CONFIG; +const { SENDING_ENDPOINT, MAX_REDIRECTS, USER_AGENT, TIMEOUT } = CLIENT_SETTINGS; +const { TEST_INBOX_ID_MISSING, ACCOUNT_ID_MISSING } = ERRORS; /** * Mailtrap client class. Initializes instance with available methods. @@ -20,14 +22,19 @@ const { MAILTRAP_ENDPOINT, MAX_REDIRECTS, USER_AGENT, TIMEOUT } = export default class MailtrapClient { private axios: AxiosInstance; + private testInboxId?: number; + + private accountId?: number; + + private testingAPI: TestingAPI; + /** * Initalizes axios instance with Mailtrap params. */ - constructor({ endpoint = MAILTRAP_ENDPOINT, token }: MailtrapClientConfig) { + constructor({ token, testInboxId, accountId }: MailtrapClientConfig) { this.axios = axios.create({ httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), - baseURL: endpoint, headers: { Authorization: `Bearer ${token}`, Connection: "keep-alive", @@ -36,39 +43,57 @@ export default class MailtrapClient { maxRedirects: MAX_REDIRECTS, timeout: TIMEOUT, }); + this.axios.interceptors.response.use( + (response) => response, + handleSendingError + ); + this.testInboxId = testInboxId; + this.accountId = accountId; + + this.testingAPI = new TestingAPI( + this.axios, + this.testInboxId, + this.accountId + ); + } + + /** + * Getter for testing API. Warns if some of the required keys are missing. + */ + get testing() { + if (!this.testInboxId) { + // eslint-disable-next-line no-console + console.warn(TEST_INBOX_ID_MISSING); + } + + if (!this.accountId) { + // eslint-disable-next-line no-console + console.warn(ACCOUNT_ID_MISSING); + } + + return this.testingAPI; } /** * Sends mail with given `mail` params. If there is error, rejects with `MailtrapError`. */ public async send(mail: Mail): Promise { + const url = `${SENDING_ENDPOINT}/api/send`; const preparedMail = encodeMailBuffers(mail); try { const axiosResponse = await this.axios.post( - "/api/send", + url, preparedMail ); return axiosResponse.data; - } catch (err) { - if (axios.isAxiosError(err)) { - const serverErrors = - err.response?.data && - typeof err.response.data === "object" && - "errors" in err.response.data && - err.response.data.errors instanceof Array - ? err.response.data.errors - : undefined; - - const message = serverErrors ? serverErrors.join(", ") : err.message; - - // @ts-expect-error weird typing around Error class, but it's tested to work - throw new MailtrapError(message, { cause: err }); + } catch (error) { + if (axios.isAxiosError(error)) { + handleSendingError(error); } - // should not happen, but otherwise rethrow error as is - throw err; + throw error; // should not happen, but otherwise rethrow error as is } } } diff --git a/src/types/api/inboxes.ts b/src/types/api/inboxes.ts new file mode 100644 index 0000000..f6a3378 --- /dev/null +++ b/src/types/api/inboxes.ts @@ -0,0 +1,37 @@ +export type UpdateInboxParams = { + name: string; + emailUsername: string; +}; + +type Permissions = { + can_read: boolean; + can_update: boolean; + can_destroy: boolean; + can_leave: boolean; +}; + +export type Inbox = { + id: number; + name: string; + username: string; + password: string; + max_size: number; + status: string; + email_username: string; + email_username_enabled: boolean; + sent_messages_count: number; + forwarded_messages_count: number; + used: boolean; + forward_from_email_address: string; + project_id: number; + domain: string; + pop3_domain: string; + email_domain: string; + smtp_ports: number[]; + pop3_ports: number[]; + emails_count: number; + emails_unread_count: number; + last_message_sent_at: string | null; + max_message_size: number; + permissions: Permissions; +}; diff --git a/src/types/api/messages.ts b/src/types/api/messages.ts new file mode 100644 index 0000000..e7f3cba --- /dev/null +++ b/src/types/api/messages.ts @@ -0,0 +1,71 @@ +export type Message = { + id: number; + inbox_id: number; + subject: string; + sent_at: string; + from_email: string; + from_name: string; + to_email: string; + to_name: string; + email_size: number; + is_read: boolean; + created_at: string; + updated_at: string; + html_body_size: number; + text_body_size: number; + human_size: string; + html_path: string; + txt_path: string; + raw_path: string; + download_path: string; + html_source_path: string; + blacklists_report_info: boolean; + smtp_information: { + ok: boolean; + }; +}; + +type ReportError = { + status: "error"; + msg: string; +}; + +type ReportSuccess = { + status: "success"; + errors: string[]; +}; + +export type Report = ReportError | ReportSuccess; + +export type EmailHeaders = { + headers: { + date: string; + from: string; + to: string; + subject: string; + mime_version: string; + content_type: string; + content_transfer_encoding: string; + bcc?: string; + }; +}; + +type SpamReportDetail = { + Pts: string; + RuleName: string; + Description: string; +}; + +export type SpamReport = { + ResponseCode: number; + ResponseMessage: string; + ResponseVersion: string; + Score: number; + Spam: boolean; + Threshold: number; + Details: SpamReportDetail[]; +}; + +export type MessageUpdateParams = { + isRead: boolean; +}; diff --git a/src/types/api/projects.ts b/src/types/api/projects.ts new file mode 100644 index 0000000..843a26c --- /dev/null +++ b/src/types/api/projects.ts @@ -0,0 +1,14 @@ +import { Inbox } from "./inboxes"; + +type ShareLinks = { + admin: string; + viewer: string; +}; + +export type Project = { + id: number; + name: string; + share_links: ShareLinks; + inboxes: Inbox[]; + permissions: Permissions; +}; diff --git a/src/types/axios.ts b/src/types/axios.ts new file mode 100644 index 0000000..16aefee --- /dev/null +++ b/src/types/axios.ts @@ -0,0 +1,4 @@ +export type AxiosErrorObject = { + name: string[]; + base: string[]; +}; diff --git a/src/types/mailtrap.ts b/src/types/mailtrap.ts index 4d48129..59a46b6 100644 --- a/src/types/mailtrap.ts +++ b/src/types/mailtrap.ts @@ -61,6 +61,7 @@ export type SendError = { }; export type MailtrapClientConfig = { - endpoint?: string; token: string; + testInboxId?: number; + accountId?: number; };