mirror of
https://github.com/beilunyang/moemail.git
synced 2026-07-09 22:51:23 +08:00
feat: implement email sending functionality via Resend service
This commit is contained in:
@@ -5,41 +5,72 @@ import { Loader2 } from "lucide-react"
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { useTheme } from "next-themes"
|
||||
import { useToast } from "@/components/ui/use-toast"
|
||||
|
||||
interface Message {
|
||||
id: string
|
||||
from_address: string
|
||||
from_address?: string
|
||||
to_address?: string
|
||||
subject: string
|
||||
content: string
|
||||
html: string | null
|
||||
received_at: number
|
||||
html?: string
|
||||
received_at?: number
|
||||
sent_at?: number
|
||||
}
|
||||
|
||||
interface MessageViewProps {
|
||||
emailId: string
|
||||
messageId: string
|
||||
messageType?: 'received' | 'sent'
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
type ViewMode = "html" | "text"
|
||||
|
||||
export function MessageView({ emailId, messageId }: MessageViewProps) {
|
||||
export function MessageView({ emailId, messageId, messageType = 'received' }: MessageViewProps) {
|
||||
const [message, setMessage] = useState<Message | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [viewMode, setViewMode] = useState<ViewMode>("html")
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null)
|
||||
const { theme } = useTheme()
|
||||
const { toast } = useToast()
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMessage = async () => {
|
||||
try {
|
||||
const response = await fetch(`/api/emails/${emailId}/${messageId}`)
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
const url = `/api/emails/${emailId}/${messageId}${messageType === 'sent' ? '?type=sent' : ''}`;
|
||||
|
||||
const response = await fetch(url)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
const errorMessage = (errorData as { error?: string }).error || '获取邮件详情失败'
|
||||
setError(errorMessage)
|
||||
toast({
|
||||
title: "错误",
|
||||
description: errorMessage,
|
||||
variant: "destructive"
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const data = await response.json() as { message: Message }
|
||||
setMessage(data.message)
|
||||
if (!data.message.html) {
|
||||
setViewMode("text")
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = "网络错误,请稍后重试"
|
||||
setError(errorMessage)
|
||||
toast({
|
||||
title: "错误",
|
||||
description: errorMessage,
|
||||
variant: "destructive"
|
||||
})
|
||||
console.error("Failed to fetch message:", error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
@@ -47,7 +78,7 @@ export function MessageView({ emailId, messageId }: MessageViewProps) {
|
||||
}
|
||||
|
||||
fetchMessage()
|
||||
}, [emailId, messageId])
|
||||
}, [emailId, messageId, messageType, toast])
|
||||
|
||||
const updateIframeContent = () => {
|
||||
if (viewMode === "html" && message?.html && iframeRef.current) {
|
||||
@@ -151,6 +182,21 @@ export function MessageView({ emailId, messageId }: MessageViewProps) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-32">
|
||||
<Loader2 className="w-5 h-5 animate-spin text-primary/60" />
|
||||
<span className="ml-2 text-sm text-gray-500">加载邮件详情...</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-32 text-center">
|
||||
<p className="text-sm text-destructive mb-2">{error}</p>
|
||||
<button
|
||||
onClick={() => window.location.reload()}
|
||||
className="text-xs text-primary hover:underline"
|
||||
>
|
||||
点击重试
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -162,12 +208,17 @@ export function MessageView({ emailId, messageId }: MessageViewProps) {
|
||||
<div className="p-4 space-y-3 border-b border-primary/20">
|
||||
<h3 className="text-base font-bold">{message.subject}</h3>
|
||||
<div className="text-xs text-gray-500 space-y-1">
|
||||
<p>发件人:{message.from_address}</p>
|
||||
<p>时间:{new Date(message.received_at).toLocaleString()}</p>
|
||||
{message.from_address && (
|
||||
<p>发件人:{message.from_address}</p>
|
||||
)}
|
||||
{message.to_address && (
|
||||
<p>收件人:{message.to_address}</p>
|
||||
)}
|
||||
<p>时间:{new Date(message.sent_at || message.received_at || 0).toLocaleString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{message.html && (
|
||||
{message.html && message.content && (
|
||||
<div className="border-b border-primary/20 p-2">
|
||||
<RadioGroup
|
||||
value={viewMode}
|
||||
|
||||
Reference in New Issue
Block a user