Skip to content

Feature to add "reply_to" option when sending mails. #58

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 18, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
2 changes: 2 additions & 0 deletions examples/sending/everything.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { MailtrapClient } from "mailtrap"
const TOKEN = "<YOUR-TOKEN-HERE>";
const SENDER_EMAIL = "<[email protected]>";
const RECIPIENT_EMAIL = "<[email protected]>";
const REPLY_TO_EMAIL = "<[email protected]>";

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

Expand All @@ -28,6 +29,7 @@ client
from: { name: "Mailtrap Test", email: SENDER_EMAIL },
to: [{ email: RECIPIENT_EMAIL }],
subject: "Hello from Mailtrap!",
reply_to: { email: REPLY_TO_EMAIL },
html: `
<!doctype html>
<html>
Expand Down
8 changes: 7 additions & 1 deletion src/__tests__/adapters/mail.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import adaptMail from "../../adapters/mail";

import config from "../../config";
import { adaptSingleRecipient } from "../../adapters/recipients";
import { adaptSingleRecipient, adaptReplyToRecipient } from "../../adapters/recipients";

const { ERRORS } = config;
const { SUBJECT_REQUIRED, FROM_REQUIRED } = ERRORS;
Expand All @@ -24,6 +24,7 @@ describe("adapters/mail: ", () => {
mockKey: "mock-value",
},
subject: "mock-subject",
replyTo: "mock-reply-to",
};

const expectedResult = {
Expand All @@ -33,6 +34,7 @@ describe("adapters/mail: ", () => {
bcc: [],
headers: data.headers,
subject: data.subject,
reply_to: adaptReplyToRecipient(data.replyTo),
};
const result = adaptMail(data);

Expand All @@ -47,6 +49,7 @@ describe("adapters/mail: ", () => {
mockKey: "mock-value",
},
attachments: [{ filename: "mock-filename", content: "mock-content" }],
replyTo: [],
};

const expectedResult = {
Expand All @@ -57,6 +60,7 @@ describe("adapters/mail: ", () => {
bcc: [],
headers: data.headers,
attachments: data.attachments,
reply_to: adaptReplyToRecipient(data.replyTo),
};
const result = adaptMail(data);

Expand All @@ -74,6 +78,7 @@ describe("adapters/mail: ", () => {
customVariables: {
user_id: "mock-user_id",
},
replyTo: ["mock-reply-to"],
};

const expectedResult = {
Expand All @@ -85,6 +90,7 @@ describe("adapters/mail: ", () => {
headers: data.headers,
attachments: data.attachments,
custom_variables: data.customVariables,
reply_to: adaptReplyToRecipient(data.replyTo),
};
const result = adaptMail(data);

Expand Down
3 changes: 2 additions & 1 deletion src/adapters/mail.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import adaptAttachment from "./attachement";
import adaptContent from "./content";
import adaptHeaders from "./headers";
import adaptRecipients, { adaptSingleRecipient } from "./recipients";
import adaptRecipients, { adaptSingleRecipient, adaptReplyToRecipient } from "./recipients";

import CONFIG from "../config";

Expand All @@ -27,6 +27,7 @@ export default function adaptMail(data: MailtrapMailOptions): Mail | SendError {
to: adaptRecipients(data.to),
cc: adaptRecipients(data.cc),
bcc: adaptRecipients(data.bcc),
reply_to: adaptReplyToRecipient(data.replyTo),
};

if (data.headers) {
Expand Down
24 changes: 24 additions & 0 deletions src/adapters/recipients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,27 @@ export default function adaptRecipients(

return recipients.map(adaptSingleRecipient);
}

/**
* If there is no recipient or empty array is passed, then return undefined since it is an optional field.
* If it's not array, then adapt recipient and returns it.
* Otherwise, if type is array as nodemailer allows, we pick the first recipient
* as Mailtrap doesn't support multiple reply-to recipients.
*/
export function adaptReplyToRecipient(
recipients:
| string
| NodemailerAddress
| Array<string | NodemailerAddress>
| undefined
): Address | undefined {
if(!recipients || (Array.isArray(recipients) && recipients.length === 0)) {
return undefined;
}

if (!Array.isArray(recipients)) {
return adaptSingleRecipient(recipients);
}

return adaptSingleRecipient(recipients[0]);
}
1 change: 1 addition & 0 deletions src/types/mailtrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type CommonMail = {
attachments?: Attachment[];
headers?: MailtrapHeaders;
custom_variables?: CustomVariables;
reply_to?: Address;
};

export type TemplateVariables = Record<string, string | number | boolean>;
Expand Down