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; };