Used: {Math.ceil((mailbox.storageUsed / 1e6) * 10) / 10}MB / {storageLimit[mailbox.plan] / 1e6}MB
- Custom domains
+ Custom domains{" "}
({mailbox.customDomains.length}/3)
@@ -675,7 +679,7 @@ export default async function EmailConfig({
- If you would like to send emails via the API, see the documentation here:
+ If you would like to send emails via the API, see the documentation here:{" "}
API Documentation
diff --git a/app/(email)/mail/[mailbox]/draft/[draft]/editor.client.tsx b/app/(email)/mail/[mailbox]/draft/[draft]/editor.client.tsx
index 510b174..3dfa67d 100644
--- a/app/(email)/mail/[mailbox]/draft/[draft]/editor.client.tsx
+++ b/app/(email)/mail/[mailbox]/draft/[draft]/editor.client.tsx
@@ -700,8 +700,8 @@ export function RecipientInput({ savedTo }: RecipientInputProps) {
cc: type === "to" ? null : (type as any),
},
]);
- update();
element.value = "";
+ update();
} else if (toastOnError) {
toast.error("Invalid email address");
}
@@ -855,6 +855,7 @@ export function RecipientInput({ savedTo }: RecipientInputProps) {
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
if (!e.currentTarget.value) return toast.warning("Please add an email first");
validate(e.currentTarget, type);
} else if (e.key === "Backspace" && e.currentTarget.value === "") {
diff --git a/app/(email)/mail/[mailbox]/draft/[draft]/email.html/route.ts b/app/(email)/mail/[mailbox]/draft/[draft]/email.html/route.ts
index 241d66e..8e2285a 100644
--- a/app/(email)/mail/[mailbox]/draft/[draft]/email.html/route.ts
+++ b/app/(email)/mail/[mailbox]/draft/[draft]/email.html/route.ts
@@ -9,15 +9,14 @@ import { makeHtml } from "../tools";
export async function GET(
request: Request,
- {
- params,
- }: {
- params: {
+ props: {
+ params: Promise<{
mailbox: string;
draft: string;
- };
+ }>;
},
) {
+ const params = await props.params;
const userId = await getCurrentUser();
if (!(userId && (await userMailboxAccess(params.mailbox, userId)))) return notFound();
diff --git a/app/(email)/mail/[mailbox]/draft/[draft]/email.txt/route.ts b/app/(email)/mail/[mailbox]/draft/[draft]/email.txt/route.ts
index 182825e..2d9315f 100644
--- a/app/(email)/mail/[mailbox]/draft/[draft]/email.txt/route.ts
+++ b/app/(email)/mail/[mailbox]/draft/[draft]/email.txt/route.ts
@@ -8,15 +8,14 @@ import { userMailboxAccess } from "../../../tools";
export async function GET(
request: Request,
- {
- params,
- }: {
- params: {
+ props: {
+ params: Promise<{
mailbox: string;
draft: string;
- };
+ }>;
},
) {
+ const params = await props.params;
const userId = await getCurrentUser();
if (!(userId && (await userMailboxAccess(params.mailbox, userId)))) return notFound();
diff --git a/app/(email)/mail/[mailbox]/draft/[draft]/page.tsx b/app/(email)/mail/[mailbox]/draft/[draft]/page.tsx
index f25cd13..ca68857 100644
--- a/app/(email)/mail/[mailbox]/draft/[draft]/page.tsx
+++ b/app/(email)/mail/[mailbox]/draft/[draft]/page.tsx
@@ -27,11 +27,11 @@ import {
} from "./editor.client";
export async function generateMetadata(props: {
- params: { mailbox: string; draft: string };
+ params: Promise<{ mailbox: string; draft: string }>;
}) {
- if (!(await pageMailboxAccess(props.params.mailbox, false))) return {};
+ if (!(await pageMailboxAccess((await props.params).mailbox, false))) return {};
- const mail = await fetchDraft(props.params.mailbox, props.params.draft);
+ const mail = await fetchDraft((await props.params).mailbox, (await props.params).draft);
return {
title: mail?.subject || "(Unnamed draft)",
};
@@ -51,14 +51,13 @@ const fetchDraft = cache(async (mailboxId: string, draftId: string) => {
});
});
-export default async function DraftPage({
- params,
-}: {
- params: {
+export default async function DraftPage(props: {
+ params: Promise<{
mailbox: string;
draft: string;
- };
+ }>;
}) {
+ const params = await props.params;
await pageMailboxAccess(params.mailbox);
const { aliases, default: defaultAlias } = await mailboxAliases(params.mailbox);
diff --git a/app/(email)/mail/[mailbox]/draft/new/page.ts b/app/(email)/mail/[mailbox]/draft/new/page.ts
index 481c899..c9258e9 100644
--- a/app/(email)/mail/[mailbox]/draft/new/page.ts
+++ b/app/(email)/mail/[mailbox]/draft/new/page.ts
@@ -8,19 +8,18 @@ import { parseHTML } from "../../[email]/parse-html";
import { mailboxAliases, pageMailboxAccess } from "../../tools";
import type { Recipient } from "../[draft]/tools";
-export default async function Page({
- params,
- searchParams,
-}: {
- params: {
+export default async function Page(props: {
+ params: Promise<{
mailbox: string;
- };
- searchParams: {
+ }>;
+ searchParams: Promise<{
reply?: string;
replyAll?: string;
forward?: string;
- };
+ }>;
}) {
+ const searchParams = await props.searchParams;
+ const params = await props.params;
// make new draft
await pageMailboxAccess(params.mailbox);
@@ -91,7 +90,7 @@ export default async function Page({
}
}
- const timeZone = headers().get("x-vercel-ip-timezone") || undefined;
+ const timeZone = (await headers()).get("x-vercel-ip-timezone") || undefined;
const emailBody = await parseHTML(
await marked.parse(
`
\n
\nOn ${email.createdAt.toLocaleString([], { timeZone })}, ${email.from?.name ? `${email.from.name} <${email.from.address}>` : `${email.from.address}`} wrote:\n\n> ${email.body.split("\n").join("\n> ")}`,
diff --git a/app/(email)/mail/[mailbox]/layout.tsx b/app/(email)/mail/[mailbox]/layout.tsx
index ba8bb9a..2020dd9 100644
--- a/app/(email)/mail/[mailbox]/layout.tsx
+++ b/app/(email)/mail/[mailbox]/layout.tsx
@@ -3,7 +3,8 @@ import Header from "./header";
import Sidebar from "./sidebar";
import { mailboxAliases, pageMailboxAccess } from "./tools";
-export async function generateMetadata({ params }: { params: { mailbox: string } }): Promise
{
+export async function generateMetadata(props: { params: Promise<{ mailbox: string }> }): Promise {
+ const params = await props.params;
await pageMailboxAccess(params.mailbox);
const { default: defaultAlias } = await mailboxAliases(params.mailbox);
@@ -17,15 +18,16 @@ export async function generateMetadata({ params }: { params: { mailbox: string }
};
}
-export default async function MailLayout({
- children,
- params,
-}: {
+export default async function MailLayout(props: {
children: React.ReactNode;
- params: {
+ params: Promise<{
mailbox: string;
- };
+ }>;
}) {
+ const params = await props.params;
+
+ const { children } = props;
+
// const userId = await getCurrentUser()
// if (!userId) return redirect("/login?from=/mail/" + params.mailbox)
diff --git a/app/(email)/mail/[mailbox]/nav.search.tsx b/app/(email)/mail/[mailbox]/nav.search.tsx
index 16b75e6..d3bfdbd 100644
--- a/app/(email)/mail/[mailbox]/nav.search.tsx
+++ b/app/(email)/mail/[mailbox]/nav.search.tsx
@@ -2,6 +2,7 @@
import { Button } from "@/components/ui/button";
import { cn } from "@/utils/tw";
import { ChevronDownIcon, Loader2, SearchIcon } from "lucide-react";
+import Form from "next/form";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useEffect, useRef, useTransition } from "react";
@@ -41,8 +42,9 @@ export function Search({ className, mailboxId }: { className?: string; mailboxId
};
return (
-
-
+
);
}
diff --git a/app/(email)/mail/route.ts b/app/(email)/mail/route.ts
index 79cbdc7..fb8c4fc 100644
--- a/app/(email)/mail/route.ts
+++ b/app/(email)/mail/route.ts
@@ -13,12 +13,12 @@ export async function GET() {
const userId = await getCurrentUser();
if (!userId) {
- removeToken();
+ await removeToken();
return redirect("/login");
}
// get the mailbox based on mailboxId cookie
- const mailboxId = cookies().get("mailboxId");
+ const mailboxId = (await cookies()).get("mailboxId");
if (mailboxId) {
return redirect(`/mail/${mailboxId.value}`);
@@ -28,13 +28,13 @@ export async function GET() {
columns: { mailboxId: true },
});
if (firstMailbox) {
- cookies().set("mailboxId", firstMailbox.mailboxId, {
+ (await cookies()).set("mailboxId", firstMailbox.mailboxId, {
path: "/",
expires: new Date("2038-01-19 04:14:07"),
});
return redirect(`/mail/${firstMailbox.mailboxId}`);
}
- removeToken();
- cookies().delete("mailboxId");
+ await removeToken();
+ (await cookies()).delete("mailboxId");
return redirect("/login");
}
diff --git a/app/(emailthing.me)/emailme/[username]/action.ts b/app/(emailthing.me)/emailme/[username]/action.ts
index 5986df8..350b28a 100644
--- a/app/(emailthing.me)/emailme/[username]/action.ts
+++ b/app/(emailthing.me)/emailme/[username]/action.ts
@@ -34,7 +34,7 @@ export async function emailMeForm(
// formData.append("secret", "1x0000000000000000000000000000000AA")
formData.append("secret", env.TURNSTILE_SECRET_KEY);
formData.append("response", data.get("cf-turnstile-response") as string);
- formData.append("remoteip", headers().get("CF-Connecting-IP") as string);
+ formData.append("remoteip", (await headers()).get("CF-Connecting-IP") as string);
const turnstile = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
method: "POST",
diff --git a/app/(emailthing.me)/emailme/[username]/components.client.tsx b/app/(emailthing.me)/emailme/[username]/components.client.tsx
index 3ce6f6e..4f2fa13 100644
--- a/app/(emailthing.me)/emailme/[username]/components.client.tsx
+++ b/app/(emailthing.me)/emailme/[username]/components.client.tsx
@@ -1,15 +1,17 @@
"use client";
import { ClientInput, ClientTextarea } from "@/(user)/components.client";
+import DisableFormReset from "@/components/disable-reset.client";
import { Button } from "@/components/ui/button";
import { CheckIcon, Loader2 } from "lucide-react";
import { useEffect } from "react";
-import { useFormState, useFormStatus } from "react-dom";
+import { useActionState } from "react";
+import { useFormStatus } from "react-dom";
import { toast } from "sonner";
import { emailMeForm } from "./action";
export function Form({ publicEmail, username }: { className?: string; publicEmail?: string; username?: string }) {
- const [state, formAction] = useFormState(emailMeForm, {});
+ const [state, formAction] = useActionState(emailMeForm, {});
useEffect(() => {
if (state?.error) {
@@ -23,6 +25,7 @@ export function Form({ publicEmail, username }: { className?: string; publicEmai
action={formAction}
className="flex w-full max-w-[35rem] flex-col gap-2 self-center"
suppressHydrationWarning
+ id="emailme-form"
>
@@ -102,6 +105,7 @@ export function Form({ publicEmail, username }: { className?: string; publicEmai