diff --git a/app/api/emails/route.ts b/app/api/emails/route.ts index df3555ae..412379ea 100644 --- a/app/api/emails/route.ts +++ b/app/api/emails/route.ts @@ -18,7 +18,7 @@ export async function OPTIONS() { * POST /api/emails * * Sends an email to one or more explicit recipients via Resend. Emails are sent - * from `Agent by Recoup `. Account-scoped — requires + * from `Agent by Recoup `. Account-scoped — requires * authentication via x-api-key header or Authorization Bearer token. * * Body parameters: diff --git a/lib/composio/toolRouter/getSharedAccountConnections.ts b/lib/composio/toolRouter/getSharedAccountConnections.ts index 56e63c34..3facaa75 100644 --- a/lib/composio/toolRouter/getSharedAccountConnections.ts +++ b/lib/composio/toolRouter/getSharedAccountConnections.ts @@ -15,7 +15,7 @@ const SHARED_ACCOUNT_ID = "recoup-shared-767f498e-e1e9-43c6-a152-a96ae3bd8d07"; * Get Google Drive/Sheets/Docs connections from the shared Recoupable account. * * When a customer doesn't want to grant full Google Drive access, - * they can share specific files with shared@recoupable.com instead. + * they can share specific files with shared@recoupable.dev instead. * This function fetches the shared account's connections so they * can be used as a fallback in tool router sessions. * diff --git a/lib/const.ts b/lib/const.ts index 47dc64d8..5b178dd0 100644 --- a/lib/const.ts +++ b/lib/const.ts @@ -15,11 +15,11 @@ export const PRIVY_PROJECT_SECRET = process.env.PRIVY_PROJECT_SECRET; /** Base URL for the public API documentation site */ export const DOCS_BASE_URL = "https://docs.recoupable.dev"; -/** Domain for receiving inbound emails (e.g., support@mail.recoupable.com) */ -export const INBOUND_EMAIL_DOMAIN = "@mail.recoupable.com"; +/** Domain for receiving inbound emails (e.g., support@recoupable.dev) */ +export const INBOUND_EMAIL_DOMAIN = "@recoupable.dev"; -/** Domain for sending outbound emails (e.g., support@recoupable.com) */ -export const OUTBOUND_EMAIL_DOMAIN = "@recoupable.com"; +/** Domain for sending outbound emails (e.g., support@recoupable.dev) */ +export const OUTBOUND_EMAIL_DOMAIN = "@recoupable.dev"; /** Default from address for outbound emails */ export const RECOUP_FROM_EMAIL = `Agent by Recoup `; diff --git a/lib/emails/__tests__/processAndSendEmail.test.ts b/lib/emails/__tests__/processAndSendEmail.test.ts index 4a6b14d2..f4940b13 100644 --- a/lib/emails/__tests__/processAndSendEmail.test.ts +++ b/lib/emails/__tests__/processAndSendEmail.test.ts @@ -34,7 +34,7 @@ describe("processAndSendEmail", () => { } expect(mockSendEmailWithResend).toHaveBeenCalledWith( expect.objectContaining({ - from: "Agent by Recoup ", + from: "Agent by Recoup ", to: ["user@example.com"], subject: "Test", html: expect.stringContaining("Hello world"), diff --git a/lib/emails/inbound/__tests__/getFromWithName.test.ts b/lib/emails/inbound/__tests__/getFromWithName.test.ts index 3b0c867d..7dfaa6e4 100644 --- a/lib/emails/inbound/__tests__/getFromWithName.test.ts +++ b/lib/emails/inbound/__tests__/getFromWithName.test.ts @@ -3,81 +3,78 @@ import { getFromWithName } from "../getFromWithName"; describe("getFromWithName", () => { describe("outbound domain conversion", () => { - it("converts inbound @mail.recoupable.com to outbound @recoupable.com", () => { - const result = getFromWithName(["support@mail.recoupable.com"]); + it("converts inbound @recoupable.dev to outbound @recoupable.dev", () => { + const result = getFromWithName(["support@recoupable.dev"]); - expect(result).toBe("Support by Recoup "); + expect(result).toBe("Support by Recoup "); }); it("preserves the email name when converting domains", () => { - const result = getFromWithName(["agent@mail.recoupable.com"]); + const result = getFromWithName(["agent@recoupable.dev"]); - expect(result).toBe("Agent by Recoup "); + expect(result).toBe("Agent by Recoup "); }); }); describe("finding inbound email", () => { it("finds recoup email in to array", () => { - const result = getFromWithName(["hello@mail.recoupable.com"]); + const result = getFromWithName(["hello@recoupable.dev"]); - expect(result).toBe("Hello by Recoup "); + expect(result).toBe("Hello by Recoup "); }); it("finds recoup email among multiple to addresses", () => { const result = getFromWithName([ "other@example.com", - "support@mail.recoupable.com", + "support@recoupable.dev", "another@example.com", ]); - expect(result).toBe("Support by Recoup "); + expect(result).toBe("Support by Recoup "); }); it("falls back to cc array when not in to array", () => { - const result = getFromWithName(["other@example.com"], ["support@mail.recoupable.com"]); + const result = getFromWithName(["other@example.com"], ["support@recoupable.dev"]); - expect(result).toBe("Support by Recoup "); + expect(result).toBe("Support by Recoup "); }); it("prefers to array over cc array", () => { - const result = getFromWithName( - ["to-agent@mail.recoupable.com"], - ["cc-agent@mail.recoupable.com"], - ); + const result = getFromWithName(["to-agent@recoupable.dev"], ["cc-agent@recoupable.dev"]); - expect(result).toBe("To-agent by Recoup "); + expect(result).toBe("To-agent by Recoup "); }); it("handles case-insensitive domain matching", () => { - const result = getFromWithName(["Support@MAIL.RECOUPABLE.COM"]); + const result = getFromWithName(["Support@RECOUPABLE.DEV"]); - expect(result).toBe("Support by Recoup "); + expect(result).toBe("Support by Recoup "); }); }); describe("error handling", () => { it("throws error when no recoup email found in to or cc", () => { expect(() => getFromWithName(["other@example.com"])).toThrow( - "No email found ending with @mail.recoupable.com", + "No email found ending with @recoupable.dev", ); }); it("throws error when arrays are empty", () => { - expect(() => getFromWithName([])).toThrow("No email found ending with @mail.recoupable.com"); + expect(() => getFromWithName([])).toThrow("No email found ending with @recoupable.dev"); }); }); describe("name formatting", () => { it("capitalizes first letter of name", () => { - const result = getFromWithName(["lowercase@mail.recoupable.com"]); + const result = getFromWithName(["lowercase@recoupable.dev"]); - expect(result).toBe("Lowercase by Recoup "); + expect(result).toBe("Lowercase by Recoup "); }); it("preserves rest of name casing", () => { - const result = getFromWithName(["myAgent@mail.recoupable.com"]); + const result = getFromWithName(["myAgent@recoupable.dev"]); - expect(result).toBe("MyAgent by Recoup "); + expect(result).toBe("MyAgent by Recoup "); }); }); }); diff --git a/lib/emails/inbound/getFromWithName.ts b/lib/emails/inbound/getFromWithName.ts index cac86361..53a8e8f6 100644 --- a/lib/emails/inbound/getFromWithName.ts +++ b/lib/emails/inbound/getFromWithName.ts @@ -6,7 +6,7 @@ import { OUTBOUND_EMAIL_DOMAIN, INBOUND_EMAIL_DOMAIN } from "@/lib/const"; * * @param toEmails - Array of email addresses from the 'to' field * @param ccEmails - Optional array of email addresses from the 'cc' field (fallback) - * @returns Formatted email address with display name (e.g., "Support by Recoup ") + * @returns Formatted email address with display name (e.g., "Support by Recoup ") * @throws Error if no email ending with the inbound domain is found in either array */ export function getFromWithName(toEmails: string[], ccEmails: string[] = []): string { diff --git a/lib/emails/isTestEmail.ts b/lib/emails/isTestEmail.ts index 8a05a352..1bf2cecd 100644 --- a/lib/emails/isTestEmail.ts +++ b/lib/emails/isTestEmail.ts @@ -1,4 +1,4 @@ // Returns true if the email is a test email export const isTestEmail = (email: string): boolean => { - return email === "sweetmantech@gmail.com" || email === "sidney@recoupable.com"; + return email === "sweetmantech@gmail.com" || email === "sidney@recoupable.dev"; }; diff --git a/lib/emails/sendEmailHandler.ts b/lib/emails/sendEmailHandler.ts index 006bd002..8eac17e5 100644 --- a/lib/emails/sendEmailHandler.ts +++ b/lib/emails/sendEmailHandler.ts @@ -7,7 +7,7 @@ import { processAndSendEmail } from "@/lib/emails/processAndSendEmail"; * Handler for POST /api/emails. * * Sends an email to the explicit recipients in the request body via Resend - * (from `Agent by Recoup `), reusing the same + * (from `Agent by Recoup `), reusing the same * `processAndSendEmail` domain function as the `send_email` MCP tool. * Account-scoped: requires authentication via x-api-key or Authorization Bearer. * Body validation, auth, and the recipient restriction all live in diff --git a/lib/sandbox/__tests__/resolveGitUser.test.ts b/lib/sandbox/__tests__/resolveGitUser.test.ts index 04aef07f..5b52c05f 100644 --- a/lib/sandbox/__tests__/resolveGitUser.test.ts +++ b/lib/sandbox/__tests__/resolveGitUser.test.ts @@ -53,7 +53,7 @@ describe("resolveGitUser", () => { const gitUser = await resolveGitUser(ACCOUNT_ID); expect(gitUser.name).toBe("Ada Lovelace"); - expect(gitUser.email).toBe(`${ACCOUNT_ID}@users.noreply.recoupable.com`); + expect(gitUser.email).toBe(`${ACCOUNT_ID}@users.noreply.recoupable.dev`); }); it("falls back on both fields when nothing is on file", async () => { @@ -64,7 +64,7 @@ describe("resolveGitUser", () => { expect(gitUser).toEqual({ name: `recoupable-${ACCOUNT_ID.slice(0, 8)}`, - email: `${ACCOUNT_ID}@users.noreply.recoupable.com`, + email: `${ACCOUNT_ID}@users.noreply.recoupable.dev`, }); }); @@ -78,6 +78,6 @@ describe("resolveGitUser", () => { const gitUser = await resolveGitUser(ACCOUNT_ID); - expect(gitUser.email).toBe(`${ACCOUNT_ID}@users.noreply.recoupable.com`); + expect(gitUser.email).toBe(`${ACCOUNT_ID}@users.noreply.recoupable.dev`); }); }); diff --git a/lib/sandbox/resolveGitUser.ts b/lib/sandbox/resolveGitUser.ts index 12d3d027..7e7efc47 100644 --- a/lib/sandbox/resolveGitUser.ts +++ b/lib/sandbox/resolveGitUser.ts @@ -33,7 +33,7 @@ export async function resolveGitUser(accountId: string): Promise { const emailRow = emails.find(row => typeof row.email === "string" && row.email.length > 0); const name = account?.name?.trim() || `recoupable-${accountId.slice(0, 8)}`; - const email = emailRow?.email ?? `${accountId}@users.noreply.recoupable.com`; + const email = emailRow?.email ?? `${accountId}@users.noreply.recoupable.dev`; return { name, email }; }