diff --git a/.env.development.local.example b/.env.development.local.example index 1f44d28d7..a246a5252 100644 --- a/.env.development.local.example +++ b/.env.development.local.example @@ -1,5 +1,3 @@ -# Email provider: 'customerio' (default) or 'mailgun' -# EMAIL_PROVIDER=customerio # MAILGUN_API_KEY=key-... # MAILGUN_DOMAIN=app.kilocode.ai # NEVERBOUNCE_API_KEY=... diff --git a/.env.test b/.env.test index 42cb5bd5e..2d8f83f64 100644 --- a/.env.test +++ b/.env.test @@ -3,7 +3,6 @@ NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=test-only-non-secret XAI_API_KEY=invalid-mock-grok-key MISTRAL_API_KEY=invalid-mock-mistral-key -CUSTOMERIO_EMAIL_API_KEY=invalid-mock-customerio-key STRIPE_SECRET_KEY=invalid-mock-stripe-key POSTGRES_URL="postgres://postgres:postgres@localhost:5432/postgres" POSTGRES_CONNECT_TIMEOUT=10000 @@ -84,4 +83,3 @@ STRIPE_KILOCLAW_STANDARD_FIRST_MONTH_COUPON_ID=coupon_test_kiloclaw_standard_fir NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_invalid_mock_key CREDIT_CATEGORIES_ENCRYPTION_KEY= -EMAIL_PROVIDER=customerio diff --git a/package.json b/package.json index ba14e7e9e..930782b7d 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,6 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "customerio-node": "^4.3.0", "date-fns": "^4.1.0", "dayjs": "^1.11.20", "discord-api-types": "^0.38.42", diff --git a/packages/trpc/dist/index.d.ts b/packages/trpc/dist/index.d.ts index 1c3621ea3..463d6f6a3 100644 --- a/packages/trpc/dist/index.d.ts +++ b/packages/trpc/dist/index.d.ts @@ -10547,46 +10547,26 @@ declare const rootRouter: _trpc_server.TRPCBuiltRouter<{ input: void; output: { name: "orgSubscription" | "orgRenewed" | "orgCancelled" | "orgSSOUserJoined" | "orgInvitation" | "magicLink" | "balanceAlert" | "autoTopUpFailed" | "ossInviteNewUser" | "ossInviteExistingUser" | "ossExistingOrgProvisioned" | "deployFailed" | "clawTrialEndingSoon" | "clawTrialExpiresTomorrow" | "clawSuspendedTrial" | "clawSuspendedSubscription" | "clawSuspendedPayment" | "clawDestructionWarning" | "clawInstanceDestroyed" | "clawEarlybirdEndingSoon" | "clawEarlybirdExpiresTomorrow"; - subject: string; + subject: "Welcome to Kilo for Teams!" | "Kilo: Your Teams Subscription Renewal" | "Kilo: Your Teams Subscription is Cancelled" | "Kilo: New SSO User Joined Your Organization" | "Kilo: Teams Invitation" | "Sign in to Kilo Code" | "Kilo: Low Balance Alert" | "Kilo: Auto Top-Up Failed" | "Kilo: OSS Sponsorship Offer" | "Kilo: Your Deployment Failed" | "Your KiloClaw Trial Ends in 2 Days" | "Your KiloClaw Trial Expires Tomorrow" | "Your KiloClaw Trial Has Ended" | "Your KiloClaw Subscription Has Ended" | "Action Required: KiloClaw Payment Overdue" | "Your KiloClaw Instance Will Be Deleted in 2 Days" | "Your KiloClaw Instance Has Been Deleted" | "Your KiloClaw Earlybird Access Ends Soon" | "Your KiloClaw Earlybird Access Expires Tomorrow"; }[]; meta: object; }>; - getProviders: _trpc_server.TRPCQueryProcedure<{ - input: void; - output: ("customerio" | "mailgun")[]; - meta: object; - }>; getPreview: _trpc_server.TRPCQueryProcedure<{ input: { template: "orgSubscription" | "orgRenewed" | "orgCancelled" | "orgSSOUserJoined" | "orgInvitation" | "magicLink" | "balanceAlert" | "autoTopUpFailed" | "ossInviteNewUser" | "ossInviteExistingUser" | "ossExistingOrgProvisioned" | "deployFailed" | "clawTrialEndingSoon" | "clawTrialExpiresTomorrow" | "clawSuspendedTrial" | "clawSuspendedSubscription" | "clawSuspendedPayment" | "clawDestructionWarning" | "clawInstanceDestroyed" | "clawEarlybirdEndingSoon" | "clawEarlybirdExpiresTomorrow"; - provider: "customerio" | "mailgun"; }; output: { - type: "mailgun"; - subject: string; + subject: "Welcome to Kilo for Teams!" | "Kilo: Your Teams Subscription Renewal" | "Kilo: Your Teams Subscription is Cancelled" | "Kilo: New SSO User Joined Your Organization" | "Kilo: Teams Invitation" | "Sign in to Kilo Code" | "Kilo: Low Balance Alert" | "Kilo: Auto Top-Up Failed" | "Kilo: OSS Sponsorship Offer" | "Kilo: Your Deployment Failed" | "Your KiloClaw Trial Ends in 2 Days" | "Your KiloClaw Trial Expires Tomorrow" | "Your KiloClaw Trial Has Ended" | "Your KiloClaw Subscription Has Ended" | "Action Required: KiloClaw Payment Overdue" | "Your KiloClaw Instance Will Be Deleted in 2 Days" | "Your KiloClaw Instance Has Been Deleted" | "Your KiloClaw Earlybird Access Ends Soon" | "Your KiloClaw Earlybird Access Expires Tomorrow"; html: string; - transactional_message_id?: undefined; - message_data?: undefined; - } | { - type: "customerio"; - transactional_message_id: "6" | "10" | "11" | "12" | "13" | "14" | "16" | "17" | "18" | "19" | "20" | "21" | "22" | "23" | "24" | "25" | "26" | "27" | "28" | "29" | "30"; - subject: string; - message_data: Record; - html?: undefined; }; meta: object; }>; sendTest: _trpc_server.TRPCMutationProcedure<{ input: { template: "orgSubscription" | "orgRenewed" | "orgCancelled" | "orgSSOUserJoined" | "orgInvitation" | "magicLink" | "balanceAlert" | "autoTopUpFailed" | "ossInviteNewUser" | "ossInviteExistingUser" | "ossExistingOrgProvisioned" | "deployFailed" | "clawTrialEndingSoon" | "clawTrialExpiresTomorrow" | "clawSuspendedTrial" | "clawSuspendedSubscription" | "clawSuspendedPayment" | "clawDestructionWarning" | "clawInstanceDestroyed" | "clawEarlybirdEndingSoon" | "clawEarlybirdExpiresTomorrow"; - provider: "customerio" | "mailgun"; recipient: string; }; output: { - provider: "customerio"; - recipient: string; - } | { - provider: "mailgun"; recipient: string; }; meta: object; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25bc2032e..b4b0f8384 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -308,9 +308,6 @@ importers: cmdk: specifier: ^1.1.1 version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - customerio-node: - specifier: ^4.3.0 - version: 4.3.0 date-fns: specifier: ^4.1.0 version: 4.1.0 @@ -8610,9 +8607,6 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - customerio-node@4.3.0: - resolution: {integrity: sha512-umNxZzBNmyT+OQRQE1M7IgARgrgvnoY8bw+XGAuazB9QMfPTktkPnXImmyR8WAQHhnyfnsi8pqc1PzzToZmB5g==} - cwd@0.10.0: resolution: {integrity: sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==} engines: {node: '>=0.8'} @@ -22906,8 +22900,6 @@ snapshots: csstype@3.2.3: {} - customerio-node@4.3.0: {} - cwd@0.10.0: dependencies: find-pkg: 0.1.2 diff --git a/src/app/admin/email-testing/page.tsx b/src/app/admin/email-testing/page.tsx index 616edc03b..3c6c64936 100644 --- a/src/app/admin/email-testing/page.tsx +++ b/src/app/admin/email-testing/page.tsx @@ -34,11 +34,9 @@ export default function EmailTestingPage() { const { data: session } = useSession(); const [selectedTemplate, setSelectedTemplate] = useState(null); - const [selectedProvider, setSelectedProvider] = useState(null); const [recipient, setRecipient] = useState(''); const { data: templates } = useQuery(trpc.admin.emailTesting.getTemplates.queryOptions()); - const { data: providers } = useQuery(trpc.admin.emailTesting.getProviders.queryOptions()); // Pre-fill recipient with logged-in admin's email useEffect(() => { @@ -47,44 +45,36 @@ export default function EmailTestingPage() { } }, [session?.user?.email, recipient]); - // Auto-select first template and provider on load + // Auto-select first template on load useEffect(() => { if (templates && templates.length > 0 && !selectedTemplate) { setSelectedTemplate(templates[0].name); } }, [templates, selectedTemplate]); - useEffect(() => { - if (providers && providers.length > 0 && !selectedProvider) { - setSelectedProvider(providers[0]); - } - }, [providers, selectedProvider]); - const previewQuery = useQuery( trpc.admin.emailTesting.getPreview.queryOptions( { - // Values come directly from the server's getTemplates/getProviders responses, + // Values come directly from the server's getTemplates response, // so the cast is safe — tRPC zod will reject anything invalid at runtime anyway. template: (selectedTemplate ?? 'orgSubscription') as TemplateName, - provider: (selectedProvider ?? 'customerio') as 'customerio' | 'mailgun', }, - { enabled: selectedTemplate !== null && selectedProvider !== null } + { enabled: selectedTemplate !== null } ) ); const sendTestMutation = useMutation(trpc.admin.emailTesting.sendTest.mutationOptions()); const handleSend = () => { - if (!selectedTemplate || !selectedProvider || !recipient) return; + if (!selectedTemplate || !recipient) return; sendTestMutation.mutate( { template: selectedTemplate as TemplateName, - provider: selectedProvider as 'customerio' | 'mailgun', recipient, }, { onSuccess: result => { - toast.success(`Test email sent via ${result?.provider} to ${result?.recipient}`); + toast.success(`Test email sent to ${result?.recipient}`); }, onError: error => { toast.error(error.message || 'Failed to send test email'); @@ -111,11 +101,11 @@ export default function EmailTestingPage() { Test Email Controls - Select a template and provider, then send a test email to any address. + Select a template, then send a test email to any address. -
+
-
- - -
-
{sendTestMutation.isPending ? 'Sending...' : 'Send Test Email'} @@ -173,7 +145,7 @@ export default function EmailTestingPage() { {/* Preview Pane */} - {selectedTemplate && selectedProvider && ( + {selectedTemplate && ( @@ -185,49 +157,13 @@ export default function EmailTestingPage() { )} - - {selectedProvider === 'customerio' - ? 'Variables that will be sent to the Customer.io API' - : 'Rendered HTML email'} - + Rendered HTML email {previewQuery.isPending && (

Loading preview...

)} - {previewQuery.data?.type === 'customerio' && ( -
-

- Template ID:{' '} - {previewQuery.data.transactional_message_id} -

-
- - - - - - - - - {Object.entries(previewQuery.data.message_data).map(([key, value]) => ( - - - - - ))} - -
- Variable - - Value -
{key} - {String(value)} -
-
-
- )} - {previewQuery.data?.type === 'mailgun' && ( + {previewQuery.data && (