Skip to content

Commit

Permalink
Merge pull request #39 from railsware/bulk-sending-api
Browse files Browse the repository at this point in the history
Bulk sending api
  • Loading branch information
narekhovhannisyan authored Jun 13, 2024
2 parents cf58f3f + 7c607ac commit 2bb26f7
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 12 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [3.4.0] - 2024-06-10
- Add support for Bulk product API.
- Refer to the [`examples/bulk`](examples/bulk) folder for code examples.
- Restructure examples folder.

## [3.3.0] - 2024-01-31
- Add support for Testing product API.
- All public routes from API V2 are now available in SDK.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ Refer to the [`examples`](examples) folder for the source code of this and other
- [Projects](examples/testing/projects.ts)
- [Send mail using template](examples/testing/template.ts)

### Bulk sending API

- [Send mail](examples/bulk/send-mail.ts)

### Nodemailer Transport

> NOTE: [Nodemailer](https://www.npmjs.com/package/nodemailer) is needed as a dependency.
Expand Down
24 changes: 24 additions & 0 deletions examples/bulk/send-mail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MailtrapClient } from "mailtrap"

/**
* For this example, you need to have ready-to-use sending domain or,
* a Demo domain that allows sending emails to your own account email.
* @see https://help.mailtrap.io/article/69-sending-domain-setup
*/

", @see https://help.mailtrap.io/article/69-sending-domain-setup#Demo-Domain--oYOU5"

const TOKEN = "<YOUR-TOKEN-HERE>";
const SENDER_EMAIL = "<[email protected]>";
const RECIPIENT_EMAIL = "<[email protected]>";

const client = new MailtrapClient({ token: TOKEN });

client.bulk.send({
from: { name: "Mailtrap Test", email: SENDER_EMAIL },
to: [{ email: RECIPIENT_EMAIL }],
subject: "Hello from Mailtrap!",
text: "Welcome to Mailtrap Sending!",
})
.then(console.log)
.catch(console.error);
4 changes: 2 additions & 2 deletions examples/sending/everything.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import path from "node:path"
import { MailtrapClient } from "mailtrap"

/**
* For this example to work, you need to set up a sending domain,
* and obtain a token that is authorized to send from the domain.
* For this example, you need to have ready-to-use sending domain or,
* a Demo domain that allows sending emails to your own account email.
* @see https://help.mailtrap.io/article/69-sending-domain-setup
*/

Expand Down
4 changes: 2 additions & 2 deletions examples/sending/minimal.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MailtrapClient } from "mailtrap"

/**
* For this example to work, you need to set up a sending domain,
* and obtain a token that is authorized to send from the domain.
* For this example, you need to have ready-to-use sending domain or,
* a Demo domain that allows sending emails to your own account email.
* @see https://help.mailtrap.io/article/69-sending-domain-setup
*/

Expand Down
4 changes: 2 additions & 2 deletions examples/sending/template.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MailtrapClient } from "mailtrap"

/**
* For this example to work, you need to set up a sending domain,
* and obtain a token that is authorized to send from the domain.
* For this example, you need to have ready-to-use sending domain or,
* a Demo domain that allows sending emails to your own account email.
* @see https://help.mailtrap.io/article/69-sending-domain-setup
*/

Expand Down
4 changes: 2 additions & 2 deletions examples/sending/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Nodemailer from "nodemailer";
import { MailtrapTransport } from "mailtrap"

/**
* For this example to work, you need to set up a sending domain,
* and obtain a token that is authorized to send from the domain.
* For this example, you need to have ready-to-use sending domain or,
* a Demo domain that allows sending emails to your own account email.
* @see https://help.mailtrap.io/article/69-sending-domain-setup
*/

Expand Down
146 changes: 146 additions & 0 deletions src/__tests__/lib/api/Bulk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import axios from "axios";
import AxiosMockAdapter from "axios-mock-adapter";

import BulkAPI from "../../../lib/api/Bulk";
import handleSendingError from "../../../lib/axios-logger";
import MailtrapError from "../../../lib/MailtrapError";

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

const { CLIENT_SETTINGS } = CONFIG;
const { BULK_ENDPOINT } = CLIENT_SETTINGS;

describe("lib/api/Bulk: ", () => {
let mock: AxiosMockAdapter;
const bulkAPI = new BulkAPI(axios);

describe("class Testing(): ", () => {
describe("init: ", () => {
it("initalizes with all necessary params.", () => {
expect(bulkAPI).toHaveProperty("send");
});
});

beforeAll(() => {
/**
* Init Axios interceptors for handling response.data, errors.
*/
axios.interceptors.response.use(
(response) => response.data,
handleSendingError
);
mock = new AxiosMockAdapter(axios);
});

afterEach(() => {
mock.reset();
});

describe("send(): ", () => {
it("successfully sends email.", async () => {
const endpoint = `${BULK_ENDPOINT}/api/send`;
const expectedResponseData = {
success: true,
message_ids: ["0c7fd939-02cf-11ed-88c2-0a58a9feac02"],
};
mock.onPost(endpoint).reply(200, expectedResponseData);

const emailData = {
from: {
email: "[email protected]",
name: "sender",
},
to: [
{
email: "[email protected]",
name: "recipient",
},
],
subject: "mock-subject",
text: "Mock text",
html: "<div>Mock text</div>",
};

const result = await bulkAPI.send(emailData);

expect(mock.history.post[0].url).toEqual(endpoint);
expect(mock.history.post[0].data).toEqual(JSON.stringify(emailData));
expect(result).toEqual(expectedResponseData);
});

it("handles an API error.", async () => {
const responseData = {
success: false,
errors: ["mock-error-1", "mock-error-2"],
};

const endpoint = `${BULK_ENDPOINT}/api/send`;

mock.onPost(endpoint).reply(400, responseData);

const emailData = {
from: {
email: "[email protected]",
name: "sender",
},
to: [
{
email: "[email protected]",
name: "recipient",
},
],
subject: "mock-subject",
text: "Mock text",
html: "<div>Mock text</div>",
};

const expectedErrorMessage = responseData.errors.join(",");

expect.assertions(3);

try {
await bulkAPI.send(emailData);
} catch (error) {
expect(mock.history.post[0].url).toEqual(endpoint);
expect(mock.history.post[0].data).toEqual(JSON.stringify(emailData));

if (error instanceof Error) {
expect(error.message).toEqual(expectedErrorMessage);
}
}
});

it("handles an HTTP transport error.", async () => {
const emailData = {
from: {
email: "[email protected]",
name: "sender",
},
to: [
{
email: "[email protected]",
name: "recipient",
},
],
subject: "mock-subject",
text: "Mock text",
html: "<div>Mock text</div>",
};

const expectedErrorMessage = "Request failed with status code 404";

expect.assertions(2);

try {
await bulkAPI.send(emailData);
} catch (error) {
expect(error).toBeInstanceOf(MailtrapError);

if (error instanceof MailtrapError) {
expect(error.message).toEqual(expectedErrorMessage);
}
}
});
});
});
});
4 changes: 2 additions & 2 deletions src/__tests__/lib/api/Testing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe("lib/api/Testing: ", () => {
expect(result).toEqual(expectedResponseData);
});

it("rejects with api error.", async () => {
it("handles an API error.", async () => {
const responseData = {
success: false,
errors: ["mock-error-1", "mock-error-2"],
Expand Down Expand Up @@ -115,7 +115,7 @@ describe("lib/api/Testing: ", () => {
}
});

it("rejects with axios error.", async () => {
it("handles an HTTP transport error.", async () => {
const emailData = {
from: {
email: "[email protected]",
Expand Down
1 change: 1 addition & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default {
},
CLIENT_SETTINGS: {
SENDING_ENDPOINT: "https://send.api.mailtrap.io",
BULK_ENDPOINT: "https://bulk.api.mailtrap.io",
TESTING_ENDPOINT: "https://sandbox.api.mailtrap.io",
GENERAL_ENDPOINT: "https://mailtrap.io",
USER_AGENT:
Expand Down
8 changes: 6 additions & 2 deletions src/lib/MailtrapClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import axios, { AxiosInstance } from "axios";

import encodeMailBuffers from "./mail-buffer-encoder";
import handleSendingError from "./axios-logger";

import GeneralAPI from "./api/General";
import TestingAPI from "./api/Testing";
import BulkAPI from "./api/Bulk";

import CONFIG from "../config";

Expand All @@ -31,6 +33,8 @@ export default class MailtrapClient {

public general: GeneralAPI;

public bulk: BulkAPI;

/**
* Initalizes axios instance with Mailtrap params.
*/
Expand Down Expand Up @@ -58,15 +62,15 @@ export default class MailtrapClient {
this.accountId = accountId;

/**
* Initialize testing API.
* Initialize APIs.
*/
this.testingAPI = new TestingAPI(
this.axios,
this.testInboxId,
this.accountId
);

this.general = new GeneralAPI(this.axios, this.accountId);
this.bulk = new BulkAPI(this.axios);
}

/**
Expand Down
25 changes: 25 additions & 0 deletions src/lib/api/Bulk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AxiosInstance } from "axios";

import encodeMailBuffers from "../mail-buffer-encoder";

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

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

const { CLIENT_SETTINGS } = CONFIG;
const { BULK_ENDPOINT } = CLIENT_SETTINGS;

export default class BulkAPI {
private client: AxiosInstance;

constructor(client: AxiosInstance) {
this.client = client;
}

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

return this.client.post<SendResponse, SendResponse>(url, preparedMail);
}
}

0 comments on commit 2bb26f7

Please sign in to comment.