diff --git a/app/api/email/route.ts b/app/api/email/route.ts
index 0315233..a63c0d0 100644
--- a/app/api/email/route.ts
+++ b/app/api/email/route.ts
@@ -45,14 +45,14 @@ export async function POST(req: NextRequest) {
return NextResponse.json("Missing userId or emailAddress", { status: 400 });
}
- const suffix = emailAddress.split("@")[0];
- if (!suffix || suffix < 5) {
+ const prefix = emailAddress.split("@")[0];
+ if (!prefix || prefix.length < 5) {
return NextResponse.json("Email address length must be at least 5", {
status: 400,
});
}
- if (reservedAddressSuffix.includes(suffix)) {
+ if (reservedAddressSuffix.includes(prefix)) {
return NextResponse.json("Invalid email address", { status: 400 });
}
diff --git a/app/api/v1/email/inbox/route.ts b/app/api/v1/email/inbox/route.ts
new file mode 100644
index 0000000..4a1d0c9
--- /dev/null
+++ b/app/api/v1/email/inbox/route.ts
@@ -0,0 +1,49 @@
+import { NextRequest, NextResponse } from "next/server";
+
+import { checkApiKey } from "@/lib/dto/api-key";
+import { getEmailsByEmailAddress } from "@/lib/dto/email";
+
+// 通过 emailAddress 查询所有相关 ForwardEmail
+export async function GET(req: NextRequest) {
+ const custom_api_key = req.headers.get("wrdo-api-key");
+ if (!custom_api_key) {
+ return Response.json("Unauthorized", {
+ status: 401,
+ });
+ }
+
+ // Check if the API key is valid
+ const user = await checkApiKey(custom_api_key);
+ if (!user?.id) {
+ return Response.json(
+ "Invalid API key. You can get your API key from https://wr.do/dashboard/settings.",
+ { status: 401 },
+ );
+ }
+
+ const { searchParams } = new URL(req.url);
+ const emailAddress = searchParams.get("emailAddress");
+ const page = parseInt(searchParams.get("page") || "1", 10);
+ const pageSize = parseInt(searchParams.get("size") || "10", 10);
+
+ if (!emailAddress) {
+ return NextResponse.json(
+ { error: "Missing emailAddress parameter" },
+ { status: 400 },
+ );
+ }
+
+ try {
+ const emails = await getEmailsByEmailAddress(emailAddress, page, pageSize);
+ return NextResponse.json(emails, { status: 200 });
+ } catch (error) {
+ console.error("Error fetching emails:", error);
+ if (error.message === "Email address not found") {
+ return NextResponse.json({ error: error.message }, { status: 404 });
+ }
+ return NextResponse.json(
+ { error: "Internal Server Error" },
+ { status: 500 },
+ );
+ }
+}
diff --git a/app/api/v1/email/route.ts b/app/api/v1/email/route.ts
new file mode 100644
index 0000000..04df139
--- /dev/null
+++ b/app/api/v1/email/route.ts
@@ -0,0 +1,73 @@
+import { NextRequest, NextResponse } from "next/server";
+
+import { checkApiKey } from "@/lib/dto/api-key";
+import { createUserEmail, getAllUserEmailsCount } from "@/lib/dto/email";
+import { reservedAddressSuffix } from "@/lib/enums";
+import { Team_Plan_Quota } from "@/lib/team";
+
+import { siteConfig } from "../../../../config/site";
+
+// 创建新 UserEmail
+export async function POST(req: NextRequest) {
+ const custom_api_key = req.headers.get("wrdo-api-key");
+ if (!custom_api_key) {
+ return Response.json("Unauthorized", {
+ status: 401,
+ });
+ }
+
+ // Check if the API key is valid
+ const user = await checkApiKey(custom_api_key);
+ if (!user?.id) {
+ return Response.json(
+ "Invalid API key. You can get your API key from https://wr.do/dashboard/settings.",
+ { status: 401 },
+ );
+ }
+
+ // check quota
+ const user_address_count = await getAllUserEmailsCount(user.id);
+ if (
+ user_address_count >= Team_Plan_Quota[user.team || "free"].EM_EmailAddresses
+ ) {
+ return Response.json("Your email addresses have reached the free limit.", {
+ status: 403,
+ });
+ }
+
+ const { emailAddress } = await req.json();
+
+ if (!emailAddress) {
+ return NextResponse.json("Missing userId or emailAddress", { status: 400 });
+ }
+
+ const [prefix, suffix] = emailAddress.split("@");
+ if (!prefix || prefix.length < 5) {
+ return NextResponse.json("Email address length must be at least 5", {
+ status: 400,
+ });
+ }
+ if (!siteConfig.emailDomains.includes(suffix)) {
+ return NextResponse.json("Invalid email suffix address", { status: 400 });
+ }
+
+ if (reservedAddressSuffix.includes(prefix)) {
+ return NextResponse.json("Invalid email address", { status: 400 });
+ }
+
+ try {
+ const userEmail = await createUserEmail(user.id, emailAddress);
+ return NextResponse.json(userEmail, { status: 201 });
+ } catch (error) {
+ // console.log("Error creating user email:", error);
+ if (error.message === "Invalid userId") {
+ return NextResponse.json({ error: error.message }, { status: 400 });
+ }
+ if (error.code === "P2002") {
+ return NextResponse.json("Email address already exists", {
+ status: 409,
+ });
+ }
+ return NextResponse.json(error.message, { status: 500 });
+ }
+}
diff --git a/app/emails/api-reference.tsx b/app/emails/api-reference.tsx
new file mode 100644
index 0000000..e42a212
--- /dev/null
+++ b/app/emails/api-reference.tsx
@@ -0,0 +1,28 @@
+import Link from "next/link";
+
+import { Badge } from "@/components/ui/badge";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+
+export default function ApiReference() {
+ return (
+
+
+ API Reference
+
+
+ POST /api/v1/email
+
+ We provide a simple API for creating emails. See usage instructions at{" "}
+
+ api reference
+
+ .
+
+
+
+ );
+}
diff --git a/components/email/EmailList.tsx b/components/email/EmailList.tsx
index 4f8ec7c..f2e17fd 100644
--- a/components/email/EmailList.tsx
+++ b/components/email/EmailList.tsx
@@ -364,6 +364,16 @@ export function EmptyInboxSection() {
What is the limit? It's free?
+
+
+ How to create emails with api?
+
+
diff --git a/components/email/EmailSidebar.tsx b/components/email/EmailSidebar.tsx
index af3d820..cfd3734 100644
--- a/components/email/EmailSidebar.tsx
+++ b/components/email/EmailSidebar.tsx
@@ -19,6 +19,7 @@ import { UserEmailList } from "@/lib/dto/email";
import { reservedAddressSuffix } from "@/lib/enums";
import { cn, fetcher, timeAgo } from "@/lib/utils";
import { useMediaQuery } from "@/hooks/use-media-query";
+import ApiReference from "@/app/emails/api-reference";
import CountUp from "../dashboard/count-up";
import { CopyButton } from "../shared/copy-button";
@@ -544,14 +545,14 @@ export default function EmailSidebar({
setDomainSuffix(value);
}}
name="suffix"
- defaultValue={domainSuffix || siteConfig.shortDomains[0]}
+ defaultValue={domainSuffix || siteConfig.emailDomains[0]}
disabled={isEdit}
>
- {siteConfig.shortDomains.map((v) => (
+ {siteConfig.emailDomains.map((v) => (
@{v}
diff --git a/config/site.ts b/config/site.ts
index 8917aa7..70e0172 100644
--- a/config/site.ts
+++ b/config/site.ts
@@ -6,6 +6,7 @@ const free_recored_quota = env.NEXT_PUBLIC_FREE_RECORD_QUOTA;
const free_url_quota = env.NEXT_PUBLIC_FREE_URL_QUOTA;
const open_signup = env.NEXT_PUBLIC_OPEN_SIGNUP;
const short_domains = env.NEXT_PUBLIC_SHORT_DOMAINS || "";
+const email_domains = env.NEXT_PUBLIC_EMAIL_DOMAINS || "";
const email_r2_domain = env.NEXT_PUBLIC_EMAIL_R2_DOMAIN || "";
export const siteConfig: SiteConfig = {
@@ -25,6 +26,7 @@ export const siteConfig: SiteConfig = {
},
openSignup: open_signup === "1" ? true : false,
shortDomains: short_domains.split(","),
+ emailDomains: email_domains.split(","),
emailR2Domain: email_r2_domain,
};
diff --git a/content/docs/developer/installation.mdx b/content/docs/developer/installation.mdx
index a0993f1..a568371 100644
--- a/content/docs/developer/installation.mdx
+++ b/content/docs/developer/installation.mdx
@@ -57,6 +57,7 @@ Copy/paste the `.env.example` in the `.env` file:
| SCREENSHOTONE_BASE_URL | `https://api.example.com` | pending |
| GITHUB_TOKEN | `ghp_sscsfarwetqet` | https://github.com/settings/tokens |
| NEXT_PUBLIC_SHORT_DOMAINS | `wr.do,uv.do` | The list of short domains. Separated by `,` |
+| NEXT_PUBLIC_EMAIL_DOMAINS | `wr.do,uv.do` | The list of email domains. Separated by `,` |
- How to get `GOOGLE_CLIENT_ID`、`GITHUB_ID`, see [Authentification](/docs/developer/authentification).
- How to get `RESEND_API_KEY`, see [Email](/docs/developer/email).
diff --git a/content/docs/emails.mdx b/content/docs/emails.mdx
index a107ef8..59e9c06 100644
--- a/content/docs/emails.mdx
+++ b/content/docs/emails.mdx
@@ -36,4 +36,124 @@ Each email address can receive unlimited emails
For send emails, the maximum number of emails is 10 per day.
+## API Reference
+The Email API allows you to create and manage email addresses and retrieve received emails in your inbox.
+
+### Create Email Address
+
+The `POST /api/v1/email` endpoint allows you to create a new email address.
+
+```bash
+curl -X POST \
+ -H "Content-Type: application/json" \
+ -H "wrdo-api-key: YOUR_API_KEY" \
+ -d '{
+ "emailAddress": "your-suffix@wr.do"
+ }' \
+ https://wr.do/api/v1/email
+```
+
+#### Request Body (Params)
+
+```json
+{
+ "emailAddress": "your-suffix@wr.do" // required, suffix must be at least 5 characters
+}
+```
+
+#### Authorization Header
+
+- `wrdo-api-key`: You can use your API key to authenticate your requests.
+You can find your API key in your [account settings](/dashboard/settings).
+Add the header `wrdo-api-key: YOUR_API_KEY` to your request.
+
+#### Response
+
+On success (Status 201):
+```json
+{
+ id: string;
+ userId: string;
+ emailAddress: string;
+ createdAt: Date;
+ updatedAt: Date;
+ deletedAt: Date | null;
+}
+```
+
+#### Error Responses
+
+- `401 Unauthorized`: Missing or invalid API key
+- `400 Bad Request`: Missing email address or invalid suffix (less than 5 characters)
+- `403 Forbidden`: Email address quota has been reached
+- `409 Conflict`: Email address already exists
+- `500 Internal Server Error`: Server error
+
+### Get Email Inbox
+
+The `GET /api/v1/email/inbox` endpoint allows you to retrieve all forwarded emails for a specific email address.
+
+
+ You must create a email address before you can get the inbox.
+
+
+```bash
+curl -X GET \
+ -H "wrdo-api-key: YOUR_API_KEY" \
+ "https://wr.do/api/v1/email/inbox?emailAddress=your-suffix@wr.do&page=1&size=10"
+```
+
+#### Query Parameters
+
+- `emailAddress`: The email address to get the inbox for (required)
+- `page`: Page number for pagination (optional, default: 1)
+- `size`: Number of emails per page (optional, default: 10)
+
+#### Authorization Header
+
+- `wrdo-api-key`: You can use your API key to authenticate your requests.
+You can find your API key in your [account settings](/dashboard/settings).
+Add the header `wrdo-api-key: YOUR_API_KEY` to your request.
+
+#### Response
+
+On success (Status 200):
+```json
+{
+ "list": [
+ {
+ id: string
+ from: string
+ fromName: string
+ to: string
+ subject: string | null
+ text: string | null
+ html: string | null
+ date: string | null
+ messageId: string | null
+ replyTo: string | null
+ cc: string | null
+ headers: string | null
+ attachments: string | null
+ readAt: Date | null
+ createdAt: Date
+ updatedAt: Date
+ },
+ ],
+ "total": 25
+}
+```
+
+#### Error Responses
+
+- `401 Unauthorized`: Missing or invalid API key
+- `400 Bad Request`: Missing emailAddress parameter
+- `404 Not Found`: Email address not found or has been deleted
+- `500 Internal Server Error`: Server error
+
+### Delete Email Address
+
+The `DELETE /api/v1/email` endpoint allows you to delete a specific email address.
+
+working on it.
\ No newline at end of file
diff --git a/env.mjs b/env.mjs
index dad2f3e..3c24a03 100644
--- a/env.mjs
+++ b/env.mjs
@@ -28,6 +28,7 @@ export const env = createEnv({
NEXT_PUBLIC_FREE_URL_QUOTA: z.string().min(1).default("100"),
NEXT_PUBLIC_OPEN_SIGNUP: z.string().min(1).default("1"),
NEXT_PUBLIC_SHORT_DOMAINS: z.string().min(1).default(""),
+ NEXT_PUBLIC_EMAIL_DOMAINS: z.string().min(1).default(""),
NEXT_PUBLIC_EMAIL_R2_DOMAIN: z.string().min(1),
},
runtimeEnv: {
@@ -44,6 +45,7 @@ export const env = createEnv({
NEXT_PUBLIC_FREE_URL_QUOTA: process.env.NEXT_PUBLIC_FREE_URL_QUOTA,
NEXT_PUBLIC_OPEN_SIGNUP: process.env.NEXT_PUBLIC_OPEN_SIGNUP,
NEXT_PUBLIC_SHORT_DOMAINS: process.env.NEXT_PUBLIC_SHORT_DOMAINS,
+ NEXT_PUBLIC_EMAIL_DOMAINS: process.env.NEXT_PUBLIC_EMAIL_DOMAINS,
NEXT_PUBLIC_EMAIL_R2_DOMAIN: process.env.NEXT_PUBLIC_EMAIL_R2_DOMAIN,
CLOUDFLARE_ZONE_ID: process.env.CLOUDFLARE_ZONE_ID,
CLOUDFLARE_ZONE_NAME: process.env.CLOUDFLARE_ZONE_NAME,
diff --git a/public/sw.js.map b/public/sw.js.map
index 016182b..cf4eef8 100644
--- a/public/sw.js.map
+++ b/public/sw.js.map
@@ -1 +1 @@
-{"version":3,"file":"sw.js","sources":["../../../../../../private/var/folders/9b/3qmyp8zd2xvdspdrp149fyg00000gn/T/d9ff9ace9f78542f0475e0a0f2664376/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-routing@6.6.0/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-core@6.6.0/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"sw.js","sources":["../../../../../../private/var/folders/9b/3qmyp8zd2xvdspdrp149fyg00000gn/T/da3d692c1ef39de85c047e11c0ef3389/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-routing@6.6.0/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-strategies@6.6.0/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/Users/songjunxi/Desktop/repos/wrdo-app/wr.do/node_modules/.pnpm/workbox-core@6.6.0/node_modules/workbox-core/clientsClaim.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\nimportScripts(\n \n);\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n\nworkbox_routing_registerRoute(\"/\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"start-url\", plugins: [{ cacheWillUpdate: async ({ request, response, event, state }) => { if (response && response.type === 'opaqueredirect') { return new Response(response.body, { status: 200, statusText: 'OK', headers: response.headers }) } return response } }] }), 'GET');\nworkbox_routing_registerRoute(/.*/i, new workbox_strategies_NetworkOnly({ \"cacheName\":\"dev\", plugins: [] }), 'GET');\n\n\n\n\n"],"names":["importScripts","self","skipWaiting","workbox_core_clientsClaim","workbox_routing_registerRoute","workbox_strategies_NetworkFirst","plugins","cacheWillUpdate","request","response","event","state","type","Response","body","status","statusText","headers","workbox_strategies_NetworkOnly"],"mappings":"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"}
\ No newline at end of file
diff --git a/types/index.d.ts b/types/index.d.ts
index 2515779..c167990 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -20,6 +20,7 @@ export type SiteConfig = {
};
openSignup: boolean;
shortDomains: string[];
+ emailDomains: string[];
emailR2Domain: string;
};