diff --git a/apps/web/prisma/migrations/20240515211820_add_reply_to/migration.sql b/apps/web/prisma/migrations/20240515211820_add_reply_to/migration.sql new file mode 100644 index 0000000..e5b0a53 --- /dev/null +++ b/apps/web/prisma/migrations/20240515211820_add_reply_to/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Email" ADD COLUMN "replyTo" TEXT; diff --git a/apps/web/prisma/schema.prisma b/apps/web/prisma/schema.prisma index e8beea2..9dd4616 100644 --- a/apps/web/prisma/schema.prisma +++ b/apps/web/prisma/schema.prisma @@ -157,6 +157,7 @@ model Email { to String from String subject String + replyTo String? text String? html String? latestStatus EmailStatus @default(QUEUED) diff --git a/apps/web/src/server/aws/ses.ts b/apps/web/src/server/aws/ses.ts index 9f76d2a..ba04da7 100644 --- a/apps/web/src/server/aws/ses.ts +++ b/apps/web/src/server/aws/ses.ts @@ -108,6 +108,7 @@ export async function sendEmailThroughSes({ subject, text, html, + replyTo, region = "us-east-1", configurationSetName, }: EmailContent & { @@ -117,6 +118,7 @@ export async function sendEmailThroughSes({ const sesClient = getSesClient(region); const command = new SendEmailCommand({ FromEmailAddress: from, + ReplyToAddresses: replyTo ? [replyTo] : undefined, Destination: { ToAddresses: [to], }, @@ -155,10 +157,12 @@ export async function sendEmailThroughSes({ } } +// Need to improve this. Use some kinda library to do this export async function sendEmailWithAttachments({ to, from, subject, + replyTo, // eslint-disable-next-line no-unused-vars text, html, @@ -174,13 +178,13 @@ export async function sendEmailWithAttachments({ const boundary = "NextPart"; let rawEmail = `From: ${from}\n`; rawEmail += `To: ${to}\n`; + rawEmail += `Reply-To: ${replyTo}\n`; rawEmail += `Subject: ${subject}\n`; rawEmail += `MIME-Version: 1.0\n`; rawEmail += `Content-Type: multipart/mixed; boundary="${boundary}"\n\n`; rawEmail += `--${boundary}\n`; rawEmail += `Content-Type: text/html; charset="UTF-8"\n\n`; rawEmail += `${html}\n\n`; - for (const attachment of attachments) { const content = attachment.content; // Convert buffer to base64 const mimeType = diff --git a/apps/web/src/server/public-api/api/emails/send-email.ts b/apps/web/src/server/public-api/api/emails/send-email.ts index ec3cf93..6ce1484 100644 --- a/apps/web/src/server/public-api/api/emails/send-email.ts +++ b/apps/web/src/server/public-api/api/emails/send-email.ts @@ -15,6 +15,7 @@ const route = createRoute({ to: z.string().email(), from: z.string().email(), subject: z.string(), + replyTo: z.string().optional(), text: z.string().optional(), html: z.string().optional(), attachments: z diff --git a/apps/web/src/server/public-api/hono.ts b/apps/web/src/server/public-api/hono.ts index 134efb8..a23af05 100644 --- a/apps/web/src/server/public-api/hono.ts +++ b/apps/web/src/server/public-api/hono.ts @@ -1,6 +1,7 @@ import { OpenAPIHono } from "@hono/zod-openapi"; import { swaggerUI } from "@hono/swagger-ui"; import { handleError } from "./api-error"; +import { env } from "~/env"; export function getApp() { const app = new OpenAPIHono().basePath("/api"); @@ -14,7 +15,7 @@ export function getApp() { version: "1.0.0", title: "Unsend API", }, - servers: [{ url: `${new URL(c.req.url).origin}/api` }], + servers: [{ url: `${env.APP_URL}/api` }], })); app.openAPIRegistry.registerComponent("securitySchemes", "Bearer", { diff --git a/apps/web/src/server/service/email-service.ts b/apps/web/src/server/service/email-service.ts index 22864f0..2d772ed 100644 --- a/apps/web/src/server/service/email-service.ts +++ b/apps/web/src/server/service/email-service.ts @@ -6,7 +6,8 @@ import { queueEmail } from "./job-service"; export async function sendEmail( emailContent: EmailContent & { teamId: number } ) { - const { to, from, subject, text, html, teamId, attachments } = emailContent; + const { to, from, subject, text, html, teamId, attachments, replyTo } = + emailContent; const fromDomain = from.split("@")[1]; @@ -34,6 +35,7 @@ export async function sendEmail( to, from, subject, + replyTo, text, html, teamId, diff --git a/apps/web/src/server/service/job-service.ts b/apps/web/src/server/service/job-service.ts index a7545c4..7940aab 100644 --- a/apps/web/src/server/service/job-service.ts +++ b/apps/web/src/server/service/job-service.ts @@ -81,6 +81,7 @@ async function executeEmail( to: email.to, from: email.from, subject: email.subject, + replyTo: email.replyTo ?? undefined, text: email.text ?? undefined, html: email.html ?? undefined, region: domain?.region ?? env.AWS_DEFAULT_REGION, diff --git a/apps/web/src/types/index.ts b/apps/web/src/types/index.ts index 7c5c276..361d509 100644 --- a/apps/web/src/types/index.ts +++ b/apps/web/src/types/index.ts @@ -4,6 +4,7 @@ export type EmailContent = { subject: string; text?: string; html?: string; + replyTo?: string; attachments?: Array; };