mirror of
https://github.com/beilunyang/moemail.git
synced 2026-09-02 05:46:36 +08:00
125 lines
3.2 KiB
TypeScript
125 lines
3.2 KiB
TypeScript
import { createDb } from "@/lib/db"
|
|
import { emailShares, messages } from "@/lib/schema"
|
|
import { eq, and, lt, or, sql, ne, isNull } from "drizzle-orm"
|
|
import { NextResponse } from "next/server"
|
|
import { encodeCursor, decodeCursor } from "@/lib/cursor"
|
|
|
|
export const runtime = "edge"
|
|
|
|
const PAGE_SIZE = 20
|
|
|
|
// 通过分享token获取邮箱的消息列表
|
|
export async function GET(
|
|
request: Request,
|
|
{ params }: { params: Promise<{ token: string }> }
|
|
) {
|
|
const { token } = await params
|
|
const db = createDb()
|
|
const { searchParams } = new URL(request.url)
|
|
const cursor = searchParams.get('cursor')
|
|
|
|
try {
|
|
// 验证分享token
|
|
const share = await db.query.emailShares.findFirst({
|
|
where: eq(emailShares.token, token),
|
|
with: {
|
|
email: true
|
|
}
|
|
})
|
|
|
|
if (!share) {
|
|
return NextResponse.json(
|
|
{ error: "Share link not found or expired" },
|
|
{ status: 404 }
|
|
)
|
|
}
|
|
|
|
// 检查分享是否过期
|
|
if (share.expiresAt && share.expiresAt < new Date()) {
|
|
return NextResponse.json(
|
|
{ error: "Share link has expired" },
|
|
{ status: 410 }
|
|
)
|
|
}
|
|
|
|
// 检查邮箱是否过期
|
|
if (share.email.expiresAt < new Date()) {
|
|
return NextResponse.json(
|
|
{ error: "Email has expired" },
|
|
{ status: 410 }
|
|
)
|
|
}
|
|
|
|
const emailId = share.email.id
|
|
|
|
// 只显示接收的邮件,不显示发送的邮件
|
|
const baseConditions = and(
|
|
eq(messages.emailId, emailId),
|
|
or(
|
|
ne(messages.type, "sent"),
|
|
isNull(messages.type)
|
|
)
|
|
)
|
|
|
|
// 获取消息总数(只统计接收的邮件)
|
|
const totalResult = await db.select({ count: sql<number>`count(*)` })
|
|
.from(messages)
|
|
.where(baseConditions)
|
|
const totalCount = Number(totalResult[0].count)
|
|
|
|
const conditions = [baseConditions]
|
|
|
|
if (cursor) {
|
|
const { timestamp, id } = decodeCursor(cursor)
|
|
const cursorCondition = or(
|
|
lt(messages.receivedAt, new Date(timestamp)),
|
|
and(
|
|
eq(messages.receivedAt, new Date(timestamp)),
|
|
lt(messages.id, id)
|
|
)
|
|
)
|
|
if (cursorCondition) {
|
|
conditions.push(cursorCondition)
|
|
}
|
|
}
|
|
|
|
const results = await db.query.messages.findMany({
|
|
where: and(...conditions),
|
|
orderBy: (messages, { desc }) => [
|
|
desc(messages.receivedAt),
|
|
desc(messages.id)
|
|
],
|
|
limit: PAGE_SIZE + 1
|
|
})
|
|
|
|
const hasMore = results.length > PAGE_SIZE
|
|
const nextCursor = hasMore
|
|
? encodeCursor(
|
|
results[PAGE_SIZE - 1].receivedAt.getTime(),
|
|
results[PAGE_SIZE - 1].id
|
|
)
|
|
: null
|
|
const messageList = hasMore ? results.slice(0, PAGE_SIZE) : results
|
|
|
|
return NextResponse.json({
|
|
messages: messageList.map(msg => ({
|
|
id: msg.id,
|
|
from_address: msg.fromAddress,
|
|
to_address: msg.toAddress,
|
|
subject: msg.subject,
|
|
received_at: msg.receivedAt,
|
|
sent_at: msg.sentAt
|
|
})),
|
|
nextCursor,
|
|
total: totalCount
|
|
})
|
|
} catch (error) {
|
|
console.error("Failed to fetch shared messages:", error)
|
|
return NextResponse.json(
|
|
{ error: "Failed to fetch messages" },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|