Skip to content

Commit 63dddcb

Browse files
rajat1saxenaRajat
andauthored
Removed setting email_from's email in order to be compatible with AWS SES policies (#741)
Co-authored-by: Rajat <hi@rajatsaxena.dev>
1 parent 17795cc commit 63dddcb

File tree

9 files changed

+30
-30
lines changed

9 files changed

+30
-30
lines changed

apps/queue/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ PORT=4000
22
EMAIL_USER=email_user
33
EMAIL_PASS=email_pass
44
EMAIL_HOST=email_host
5+
EMAIL_FROM=no-reply@example.com
56
DB_CONNECTION_STRING=mongodb://db.string
67
REDIS_HOST=localhost
78
REDIS_PORT=6379

apps/queue/src/domain/__tests__/process-ongoing-sequences.test.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import EmailDelivery from "../model/email-delivery";
1515
import * as queries from "../queries";
1616
import * as mail from "../../mail";
1717
import { AdminSequence, InternalUser } from "@courselit/common-logic";
18-
import { jwtUtils } from "@courselit/utils";
18+
import { getEmailFrom, jwtUtils } from "@courselit/utils";
1919
import { getUnsubLink } from "../../utils/get-unsub-link";
2020
import { getSiteUrl } from "../../utils/get-site-url";
2121
import { sequenceBounceLimit } from "../../constants";
@@ -77,6 +77,9 @@ jest.mock("liquidjs", () => {
7777
const mockedSendMail = mail.sendMail as jest.MockedFunction<
7878
typeof mail.sendMail
7979
>;
80+
const mockedGetEmailFrom = getEmailFrom as jest.MockedFunction<
81+
typeof getEmailFrom
82+
>;
8083
const mockedJwtUtils = jwtUtils as jest.Mocked<typeof jwtUtils>;
8184
const mockedGetUnsubLink = getUnsubLink as jest.MockedFunction<
8285
typeof getUnsubLink
@@ -100,6 +103,7 @@ describe("processOngoingSequence", () => {
100103
process.env.PROTOCOL = "https";
101104
process.env.DOMAIN = "test.com";
102105
process.env.NODE_ENV = "test";
106+
process.env.EMAIL_FROM = "verified-sender@example.com";
103107

104108
// Create test domain
105109
testDomain = await (DomainModel.create as any)({
@@ -265,6 +269,9 @@ describe("processOngoingSequence", () => {
265269
mockedGetUnsubLink.mockReturnValue(
266270
"https://test.com/api/unsubscribe/unsub-token-123",
267271
);
272+
mockedGetEmailFrom.mockImplementation(
273+
({ name, email }) => `${name} <${email}>`,
274+
);
268275
mockedJwtUtils.generateToken = jest.fn().mockReturnValue("test-token");
269276
// renderEmailToHtml is not mocked - we test the real email formatting
270277
mockedSendMail.mockResolvedValue(undefined);
@@ -466,7 +473,9 @@ describe("processOngoingSequence", () => {
466473
// Verify email was sent
467474
expect(mockedSendMail).toHaveBeenCalledWith(
468475
expect.objectContaining({
469-
from: expect.stringContaining("queue-creator@example.com"),
476+
from: expect.stringContaining(
477+
"verified-sender@example.com",
478+
),
470479
to: "queue-user@example.com",
471480
subject: "First Email",
472481
html: expect.any(String),

apps/queue/src/domain/process-drip.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Liquid } from "liquidjs";
55
import { getDomain, getMemberships } from "./queries";
66
import { Constants } from "@courselit/common-models";
77
import { InternalCourse, InternalUser } from "@courselit/common-logic";
8+
import { getEmailFrom } from "@courselit/utils";
89
import { FilterQuery, UpdateQuery } from "mongoose";
910
import { renderEmailToHtml } from "@courselit/email-editor";
1011
import { getSiteUrl } from "../utils/get-site-url";
@@ -146,9 +147,10 @@ export async function processDrip() {
146147
firstGroupWithDripEmailSet.drip.email
147148
.subject,
148149
body: content,
149-
from: `${creator?.name || creator?.email} <${
150-
creator?.email
151-
}>`,
150+
from: getEmailFrom({
151+
name: creator?.name || creator?.email || "",
152+
email: process.env.EMAIL_FROM || "",
153+
}),
152154
});
153155
}
154156
}

apps/queue/src/domain/process-ongoing-sequences/process-ongoing-sequence.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { AdminSequence, InternalUser } from "@courselit/common-logic";
1919
import { Email as EmailType, renderEmailToHtml } from "@courselit/email-editor";
2020
import { getUnsubLink } from "@/utils/get-unsub-link";
2121
import { getSiteUrl } from "@/utils/get-site-url";
22-
import { jwtUtils } from "@courselit/utils";
22+
import { getEmailFrom, jwtUtils } from "@courselit/utils";
2323
import { JSDOM } from "jsdom";
2424
import { DomainDocument } from "@/domain/model/domain";
2525
import { Liquid } from "liquidjs";
@@ -150,9 +150,10 @@ async function attemptMailSending({
150150
email: Email;
151151
domain: DomainDocument;
152152
}) {
153-
const from = sequence.from
154-
? `${sequence.from.name} <${creator.email}>`
155-
: `${creator.email} <${creator.email}>`;
153+
const from = getEmailFrom({
154+
name: sequence.from?.name || creator.name || creator.email,
155+
email: process.env.EMAIL_FROM || "",
156+
});
156157
const to = user.email;
157158
const subject = email.subject;
158159
const unsubscribeLink = getUnsubLink(domain, user.unsubscribeToken);

apps/queue/src/notifications/services/channels/email.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class EmailChannel implements NotificationChannel {
4444
to: [payload.recipient.email],
4545
from: getEmailFrom({
4646
name: payload.domain.settings?.title || payload.domain.name,
47-
email: process.env.EMAIL_FROM || payload.domain.email,
47+
email: process.env.EMAIL_FROM || "",
4848
}),
4949
subject: notificationDetails.message,
5050
body: `

apps/web/auth.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { APIError, betterAuth } from "better-auth";
22
import { customSession, emailOTP } from "better-auth/plugins";
33
import { MongoClient } from "mongodb";
44
import DomainModel, { Domain } from "@models/Domain";
5+
import { getEmailFrom } from "@courselit/utils";
56
import { addMailJob } from "@/services/queue";
67
import pug from "pug";
78
import MagicCodeEmailTemplate from "@/templates/magic-code-email";
8-
import { generateEmailFrom } from "@/lib/utils";
99
import { responses } from "@/config/strings";
1010
import { mongodbAdapter } from "@/ba-multitenant-adapter";
1111
import { updateUserAfterCreationViaAuth } from "./graphql/users/logic";
@@ -52,15 +52,12 @@ const config: any = {
5252
to: [email],
5353
subject: `${responses.sign_in_mail_prefix} ${ctx!.headers?.get("host")}`,
5454
body: emailBody,
55-
from: generateEmailFrom({
55+
from: getEmailFrom({
5656
name:
5757
ctx!.headers?.get("domaintitle") ||
5858
ctx!.headers?.get("domain") ||
5959
"",
60-
email:
61-
process.env.EMAIL_FROM ||
62-
ctx!.headers?.get("domainemail") ||
63-
"",
60+
email: process.env.EMAIL_FROM || "",
6461
}),
6562
});
6663
},

apps/web/graphql/mails/helpers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import RuleModel from "@models/Rule";
22
import { Email, Rule, Sequence, User } from "@courselit/common-models";
3+
import { getEmailFrom } from "@courselit/utils";
34
import GQLContext from "@models/GQLContext";
45
import mongoose from "mongoose";
56
import SearchData from "./models/search-data";
67
import DownloadLinkModel from "@models/DownloadLink";
78
import pug from "pug";
89
import digitalDownloadTemplate from "../../templates/download-link";
910
import { responses } from "@config/strings";
10-
import { generateEmailFrom } from "@/lib/utils";
1111
import { addMailJob } from "@/services/queue";
1212
import { EmailBlock } from "@courselit/email-editor";
1313
import UserModel from "@models/User";
@@ -103,9 +103,9 @@ export async function createTemplateAndSendMail({
103103
to: [user.email],
104104
subject: `Thank you for signing up for ${course.title}`,
105105
body: emailBody,
106-
from: generateEmailFrom({
106+
from: getEmailFrom({
107107
name: ctx.subdomain?.settings?.title || ctx.subdomain.name,
108-
email: process.env.EMAIL_FROM || ctx.subdomain.email,
108+
email: process.env.EMAIL_FROM || "",
109109
}),
110110
});
111111
}

apps/web/graphql/users/logic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export const inviteCustomer = async (
238238
body: emailBody,
239239
from: getEmailFrom({
240240
name: ctx.subdomain?.settings?.title || ctx.subdomain.name,
241-
email: process.env.EMAIL_FROM || ctx.subdomain.email,
241+
email: process.env.EMAIL_FROM || "",
242242
}),
243243
});
244244
} catch (error) {

apps/web/lib/utils.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,6 @@ export const getProtocol = (protocol: string | string[] = "http") => {
3737
return protocol.includes("https") ? "https" : "http";
3838
};
3939

40-
export const generateEmailFrom = ({
41-
name,
42-
email,
43-
}: {
44-
name: string;
45-
email: string;
46-
}) => {
47-
return `${name} <${email}>`;
48-
};
49-
5040
export const hasPermissionToAccessSetupChecklist = (
5141
userPermissions: string[],
5242
) => {

0 commit comments

Comments
 (0)