Skip to content

Commit 55433a7

Browse files
committed
set up resend for email
1 parent fdeb965 commit 55433a7

File tree

4 files changed

+92
-40
lines changed

4 files changed

+92
-40
lines changed

packages/core/deno.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"pg": "npm:pg@^8.16.0",
1818
"pg-pool": "npm:pg-pool@^3.10.0",
1919
"djwt": "https://deno.land/x/djwt@v3.0.2/mod.ts",
20+
"resend": "npm:resend@^4.5.2",
2021
"stripe": "npm:stripe@^18.2.1",
2122
"zod": "npm:zod@^3.24.4"
2223
}

packages/core/src/email/console/index.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/core/src/email/index.ts

Lines changed: 86 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,70 @@ import type {
22
StripeBillingCycle,
33
StripeProduct,
44
} from "../db/models/workspace.ts";
5-
import { ConsoleEmailService } from "./console/index.ts";
6-
7-
export function getEmailService() {
8-
return new ConsoleEmailService();
5+
import { Resend } from "resend";
6+
import settings from "../settings.ts";
7+
8+
export type SendEmail = (options: {
9+
to: string[];
10+
cc?: string[];
11+
bcc?: string[];
12+
subject: string;
13+
text: string;
14+
html?: string;
15+
}) => Promise<void>;
16+
17+
const resend = new Resend(settings.EMAIL.RESEND_API_KEY);
18+
19+
const sendEmailWithResend: SendEmail = async (options: {
20+
to: string[];
21+
cc?: string[];
22+
bcc?: string[];
23+
subject: string;
24+
text: string;
25+
html?: string;
26+
}) => {
27+
const response = await resend.emails.send({
28+
from: `${settings.EMAIL.FROM_EMAIL} <${settings.EMAIL.FROM_EMAIL}>`,
29+
to: options.to,
30+
cc: options.cc,
31+
bcc: options.bcc,
32+
subject: options.subject,
33+
text: options.text,
34+
html: options.html,
35+
});
36+
37+
if (response.error) {
38+
throw new Error(`Failed to send email: ${response.error.message}`);
39+
}
40+
};
41+
42+
// deno-lint-ignore require-await
43+
const sendEmailWithConsole: SendEmail = async (options: {
44+
to: string[];
45+
cc?: string[];
46+
bcc?: string[];
47+
subject: string;
48+
text: string;
49+
html?: string;
50+
}) => {
51+
console.info(`Sending email to ${options.to}: ${options.subject}`);
52+
console.info(options.text);
53+
};
54+
55+
function getSendEmail() {
56+
if (settings.EMAIL.USE_CONSOLE) {
57+
return sendEmailWithConsole;
58+
}
59+
60+
return sendEmailWithResend;
961
}
1062

1163
export function sendOtpEmail(email: string, otp: string) {
12-
const emailService = getEmailService();
13-
emailService.sendEmail(
14-
email,
15-
"Your One-Time Password (OTP)",
16-
`Hi there,
64+
const sendEmail = getSendEmail();
65+
sendEmail({
66+
to: [email],
67+
subject: "Your One-Time Password (OTP)",
68+
text: `Hi there,
1769
1870
You've requested a one-time password to access your account. Please use the code below to complete your authentication:
1971
@@ -25,15 +77,15 @@ If you didn't request this code, please ignore this email or contact our support
2577
2678
Best regards,
2779
The Team`,
28-
);
80+
});
2981
}
3082

3183
export function sendWelcomeEmail(email: string) {
32-
const emailService = getEmailService();
33-
emailService.sendEmail(
34-
email,
35-
"Welcome to our platform!",
36-
`Hi there,
84+
const sendEmail = getSendEmail();
85+
sendEmail({
86+
to: [email],
87+
subject: "Welcome to our platform!",
88+
text: `Hi there,
3789
3890
Welcome to our platform! We're thrilled to have you join our community.
3991
@@ -50,7 +102,7 @@ We're excited to see what you'll accomplish with our platform.
50102
51103
Best regards,
52104
The Team`,
53-
);
105+
});
54106
}
55107

56108
export function sendInvitationEmail(
@@ -59,17 +111,17 @@ export function sendInvitationEmail(
59111
invitationUuid: string,
60112
returnUrl: string,
61113
) {
62-
const emailService = getEmailService();
114+
const sendEmail = getSendEmail();
63115

64116
const searchParams = new URLSearchParams();
65117
searchParams.set("invitationUuid", invitationUuid);
66118

67119
const invitationLink = `${returnUrl}?${searchParams.toString()}`;
68120

69-
emailService.sendEmail(
70-
email,
71-
`Invitation to join ${workspaceName}`,
72-
`Hi there,
121+
sendEmail({
122+
to: [email],
123+
subject: `Invitation to join ${workspaceName}`,
124+
text: `Hi there,
73125
74126
You've been invited to join "${workspaceName}"!
75127
@@ -83,7 +135,7 @@ We look forward to collaborating with you!
83135
84136
Best regards,
85137
The Team`,
86-
);
138+
});
87139
}
88140

89141
export function sendSubscriptionUpgradedEmail(
@@ -100,11 +152,11 @@ export function sendSubscriptionUpgradedEmail(
100152
};
101153
},
102154
) {
103-
const emailService = getEmailService();
104-
emailService.sendEmail(
105-
payload.email,
106-
"Subscription upgraded",
107-
`Hi there,
155+
const sendEmail = getSendEmail();
156+
sendEmail({
157+
to: [payload.email],
158+
subject: "Subscription upgraded",
159+
text: `Hi there,
108160
109161
Your subscription for workspace "${payload.workspaceName}" has been successfully upgraded!
110162
@@ -121,7 +173,7 @@ If you have any questions about your upgraded subscription, please don't hesitat
121173
122174
Best regards,
123175
The Team`,
124-
);
176+
});
125177
}
126178

127179
export function sendSubscriptionDowngradedEmail(
@@ -139,11 +191,11 @@ export function sendSubscriptionDowngradedEmail(
139191
newSubscriptionDate: string;
140192
},
141193
) {
142-
const emailService = getEmailService();
143-
emailService.sendEmail(
144-
payload.email,
145-
"Subscription downgraded",
146-
`Hi there,
194+
const sendEmail = getSendEmail();
195+
sendEmail({
196+
to: [payload.email],
197+
subject: "Subscription downgraded",
198+
text: `Hi there,
147199
148200
Your subscription for workspace "${payload.workspaceName}" has been scheduled for downgrade.
149201
@@ -161,5 +213,5 @@ If you have any questions, please don't hesitate to contact our support team.
161213
162214
Best regards,
163215
The Team`,
164-
);
216+
});
165217
}

packages/core/src/settings.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,9 @@ export default {
8888
PASSWORD: getEnv("DATABASE_PASSWORD", "password"),
8989
DATABASE: getEnv("DATABASE_NAME", "core"),
9090
},
91+
EMAIL: {
92+
RESEND_API_KEY: getEnv("RESEND_API_KEY", "resend_api_key"),
93+
FROM_EMAIL: getEnv("RESEND_FROM_EMAIL", "noreply@nanoapi.io"),
94+
USE_CONSOLE: getEnv("EMAIL_USE_CONSOLE", "true") === "true",
95+
},
9196
};

0 commit comments

Comments
 (0)