import { createFileRoute } from "@tanstack/react-router"; import { useEffect, useState } from "react"; import { supabase } from "@/integrations/supabase/client"; import { useAuth } from "@/lib/auth"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Switch } from "@/components/ui/switch"; import { Loader2, Mail, Send, KeyRound } from "lucide-react"; import { toast } from "sonner"; export const Route = createFileRoute("/settings/smtp")({ component: SmtpSettingsPage, }); const EMPTY = { host: "", port: "587", secure: false, username: "", from_email: "", from_name: "", reply_to: "", enabled: true, notes: "", }; function SmtpSettingsPage() { const { user, isAdmin } = useAuth(); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [testing, setTesting] = useState(false); const [recordId, setRecordId] = useState(null); const [form, setForm] = useState({ ...EMPTY }); const [testTo, setTestTo] = useState(""); const load = async () => { setLoading(true); const { data } = await supabase .from("smtp_settings") .select("*") .order("updated_at", { ascending: false }) .limit(1) .maybeSingle(); if (data) { setRecordId(data.id); setForm({ host: data.host ?? "", port: String(data.port ?? 587), secure: !!data.secure, username: data.username ?? "", from_email: data.from_email ?? "", from_name: data.from_name ?? "", reply_to: data.reply_to ?? "", enabled: data.enabled ?? true, notes: data.notes ?? "", }); } setLoading(false); }; useEffect(() => { if (isAdmin) load(); else setLoading(false); }, [isAdmin]); const update = (k: keyof typeof EMPTY, v: string | boolean) => setForm((f) => ({ ...f, [k]: v })); const save = async () => { if (!form.host || !form.from_email) { toast.error("Host and From email are required"); return; } setSaving(true); const payload = { host: form.host.trim(), port: parseInt(form.port, 10) || 587, secure: form.secure, username: form.username || null, from_email: form.from_email.trim(), from_name: form.from_name || null, reply_to: form.reply_to || null, enabled: form.enabled, notes: form.notes || null, updated_by: user?.id, }; const { error } = recordId ? await supabase.from("smtp_settings").update(payload).eq("id", recordId) : await supabase.from("smtp_settings").insert(payload); setSaving(false); if (error) { toast.error("Could not save", { description: error.message }); return; } toast.success("SMTP settings saved"); load(); }; const sendTest = async () => { if (!testTo) { toast.error("Enter a test recipient email"); return; } setTesting(true); const { data, error } = await supabase.functions.invoke("send-smtp-email", { body: { to: testTo, subject: "SMTP test from your firm CRM", html: `

This is a test email sent from ${form.from_email} via ${form.host}:${form.port}.

If you received this, your SMTP settings are working.

`, text: `Test email from ${form.from_email} via ${form.host}:${form.port}.`, }, }); setTesting(false); if (error || (data as any)?.error) { toast.error("Send failed", { description: (error as any)?.message || (data as any)?.error, }); return; } toast.success(`Test email sent to ${testTo}`); }; if (!isAdmin) { return (
Only administrators can manage SMTP settings.
); } if (loading) { return (
); } return (
SMTP server update("host", e.target.value)} placeholder="smtp.gmail.com" /> update("port", e.target.value)} placeholder="587" /> update("username", e.target.value)} placeholder="user@yourdomain.com" />
Stored securely as the SMTP_PASSWORD secret.
Use TLS / SSL
Enable for port 465 (implicit TLS). Leave off for 587 (STARTTLS).
update("secure", v)} />
Sender identity update("from_email", e.target.value)} placeholder="notifications@yourfirm.com" /> update("from_name", e.target.value)} placeholder="Your Firm" /> update("reply_to", e.target.value)} />