├── app
├── globals.css
├── favicon.ico
├── page.tsx
└── layout.tsx
├── public
├── robots.txt
├── vercel.svg
├── window.svg
├── file.svg
├── globe.svg
└── next.svg
├── postcss.config.mjs
├── next.config.ts
├── package.json
├── .gitignore
├── tsconfig.json
├── README.md
├── components
├── EmailView.tsx
└── Home.tsx
└── actions
└── actions.ts
/app/globals.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 |
3 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
3 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranavkdileep/TempMailo/HEAD/app/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | const config = {
2 | plugins: ["@tailwindcss/postcss"],
3 | };
4 |
5 | export default config;
6 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/next.config.ts:
--------------------------------------------------------------------------------
1 | import type { NextConfig } from "next";
2 |
3 | const nextConfig: NextConfig = {
4 | /* config options here */
5 | };
6 |
7 | export default nextConfig;
8 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | import HomePage from "@/components/Home";
2 |
3 |
4 | export default function Home() {
5 | return (
6 | <>
7 |
8 | >
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/public/window.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/file.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tempmailo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev --turbopack",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "lucide-react": "^0.513.0",
13 | "next": "15.3.3",
14 | "react": "^19.0.0",
15 | "react-dom": "^19.0.0"
16 | },
17 | "devDependencies": {
18 | "@tailwindcss/postcss": "^4",
19 | "@types/node": "^20",
20 | "@types/react": "^19",
21 | "@types/react-dom": "^19",
22 | "tailwindcss": "^4",
23 | "typescript": "^5"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.*
7 | .yarn/*
8 | !.yarn/patches
9 | !.yarn/plugins
10 | !.yarn/releases
11 | !.yarn/versions
12 |
13 | # testing
14 | /coverage
15 |
16 | # next.js
17 | /.next/
18 | /out/
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | *.pem
26 |
27 | # debug
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 | .pnpm-debug.log*
32 |
33 | # env files (can opt-in for committing if needed)
34 | .env*
35 |
36 | # vercel
37 | .vercel
38 |
39 | # typescript
40 | *.tsbuildinfo
41 | next-env.d.ts
42 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./*"]
23 | }
24 | },
25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Geist, Geist_Mono } from "next/font/google";
3 | import "./globals.css";
4 |
5 | const geistSans = Geist({
6 | variable: "--font-geist-sans",
7 | subsets: ["latin"],
8 | });
9 |
10 | const geistMono = Geist_Mono({
11 | variable: "--font-geist-mono",
12 | subsets: ["latin"],
13 | });
14 |
15 | export const metadata: Metadata = {
16 | title: "TempMailo - Free Temporary Email Service",
17 | description: "Get a free, temporary email address with TempMailo. Protect your privacy and avoid spam with our disposable email service.",
18 | };
19 |
20 | export default function RootLayout({
21 | children,
22 | }: Readonly<{
23 | children: React.ReactNode;
24 | }>) {
25 | return (
26 |
27 |
30 | {children}
31 |
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/public/globe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > **Disclaimer:**
2 | > This project is a client-only application that uses a third-party, unofficial API: [TempMail API Free on RapidAPI](https://rapidapi.com/pranavkdileep/api/tempmail-api-free).
3 | > We are not affiliated with, authorized by, or responsible for the operation, data, or security of the API or its server. Use at your own risk.
4 |
5 | # TempMail0 Next.js App
6 | 
7 | 
8 |
9 |
10 |
11 |
12 | This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
13 |
14 | ## Getting Started
15 |
16 | First, run the development server:
17 |
18 | ```bash
19 | npm run dev
20 | # or
21 | yarn dev
22 | # or
23 | pnpm dev
24 | # or
25 | bun dev
26 | ```
27 |
28 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
29 |
30 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
31 |
32 | This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
33 |
34 | ## Learn More
35 |
36 | To learn more about Next.js, take a look at the following resources:
37 |
38 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
39 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
40 |
41 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
42 |
43 | ## Deploy on Vercel
44 |
45 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
46 |
47 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
48 |
--------------------------------------------------------------------------------
/components/EmailView.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import { ArrowLeft } from "lucide-react";
5 |
6 | interface EmailViewProps {
7 | email: {
8 | id: string;
9 | from: string;
10 | to: string;
11 | cc: string;
12 | subject: string;
13 | body_text: string;
14 | body_html: string;
15 | created_at: string;
16 | isRead: boolean;
17 | isUnread?: boolean;
18 | };
19 | onBack: () => void;
20 | }
21 |
22 | function EmailView({ email, onBack }: EmailViewProps) {
23 | return (
24 |
25 |
26 |
27 |
31 |
32 | Back to Inbox
33 |
34 |
35 |
36 |
37 | Subject: {email.subject}
38 |
39 |
40 |
41 | From:
42 | {email.from}
43 |
44 |
45 | To:
46 | {email.to}
47 |
48 | {email.cc && (
49 |
50 | CC:
51 | {email.cc}
52 |
53 | )}
54 |
55 | Date:
56 | {email.created_at}
57 |
58 |
59 |
60 | {email.body_html ? (
61 |
62 | ) : (
63 | {email.body_text}
64 | )}
65 |
66 |
67 |
68 |
69 | );
70 | }
71 |
72 | export default EmailView;
--------------------------------------------------------------------------------
/actions/actions.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { cookies } from "next/headers";
3 |
4 | const baseUrl = process.env.BASE_URL || "https://tempmail-api-free.p.rapidapi.com";
5 | const x_rapidapi_key = process.env.X_RAPIDAPI_KEY || "50c9c3f974msh08092f88f044eedp10a9f2jsnfaf6222bc9c6";
6 | const x_rapidapi_host = process.env.X_RAPIDAPI_HOST || "tempmail-api-free.p.rapidapi.com";
7 |
8 | interface Email {
9 | id: string;
10 | from: string;
11 | to: string;
12 | cc: string;
13 | subject: string;
14 | body_text: string;
15 | body_html: string;
16 | created_at: string;
17 | isRead: boolean;
18 | isUnread?: boolean;
19 | }
20 |
21 | export const getcurrentEmail = async () => {
22 | try {
23 | const currentemail = (await cookies()).get("currentemail");
24 | if (!currentemail) {
25 | const newemail = await registerEmail();
26 | return newemail;
27 | }
28 | return currentemail!.value;
29 | } catch (error) {
30 | console.error("Error fetching current email:", error);
31 | throw new Error("Failed to fetch current email");
32 | }
33 | }
34 |
35 | export const registerEmail = async (name: string = Math.random().toString(36).substring(2, 8)) => {
36 | try {
37 | const domains = await getDomains();
38 | const randomDomain = domains[Math.floor(Math.random() * domains.length)];
39 | const response = await fetch(`${baseUrl}/api/v3/email/new`, {
40 | method: 'POST',
41 | headers: {
42 | 'x-rapidapi-key': x_rapidapi_key,
43 | 'x-rapidapi-host': x_rapidapi_host,
44 | 'Content-Type': 'application/json'
45 | },
46 | body: JSON.stringify({
47 | name: name,
48 | domain: randomDomain.name
49 | })
50 | }
51 | );
52 | const data = await response.json();
53 | console.log(data)
54 | if (!response.ok) {
55 | throw new Error("Failed to register email");
56 | }
57 |
58 | if (!data.email) {
59 | throw new Error("No email returned from API");
60 | }
61 | const currentemail = data.email;
62 | const currenttoken = data.token;
63 | const cookieStore = await cookies();
64 | cookieStore.set("currentemail", currentemail,{ maxAge: 60 * 60 * 24 * 30 });
65 | cookieStore.set("currenttoken", currenttoken,{ maxAge: 60 * 60 * 24 * 30 });
66 | return currentemail;
67 | } catch (error) {
68 | console.error("Error registering email:", error);
69 | throw new Error("Failed to register email");
70 | }
71 | }
72 |
73 | export const deletecurrentEmail = async () => {
74 | try {
75 | const currentemail = (await cookies()).get("currentemail");
76 | const currenttoken = (await cookies()).get("currenttoken");
77 | if (!currentemail || !currenttoken) {
78 | throw new Error("No current email or token found");
79 | }
80 | const response = await fetch(`${baseUrl}/api/v3/email/${currentemail.value}`, {
81 | method: 'DELETE',
82 | headers: {
83 | 'x-rapidapi-key': x_rapidapi_key,
84 | 'x-rapidapi-host': x_rapidapi_host,
85 | 'Content-Type': 'application/json'
86 | },
87 | body: JSON.stringify({
88 | token: currenttoken.value
89 | })
90 | }
91 | );
92 | if (!response.ok) {
93 | throw new Error("Failed to delete email");
94 | }
95 | const cookieStore = await cookies();
96 | cookieStore.delete("currentemail");
97 | cookieStore.delete("currenttoken");
98 | return true;
99 | } catch (error) {
100 | const cookieStore = await cookies();
101 | cookieStore.delete("currentemail");
102 | cookieStore.delete("currenttoken");
103 | return true;
104 | }
105 | }
106 |
107 | export const getEmails = async (email: string) => {
108 | try {
109 | const response = await fetch(`${baseUrl}/api/v3/email/${email}/messages`, {
110 | method: 'GET',
111 | headers: {
112 | 'x-rapidapi-key': x_rapidapi_key,
113 | 'x-rapidapi-host': x_rapidapi_host
114 | }
115 | });
116 | let data = await response.json();
117 | console.log(data);
118 | if (!response.ok) {
119 | throw new Error("Failed to fetch emails");
120 | }
121 |
122 |
123 | if (!data || data.length === 0) {
124 | throw new Error("No emails found");
125 | }
126 | // data = data.map((email: Email) => ({
127 | // ...email,
128 | // isUnread: true,
129 | // }));
130 | data.sort((a: Email, b: Email) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
131 | return data;
132 | } catch (error) {
133 | console.error("Error fetching emails:", error);
134 | throw new Error("Failed to fetch emails");
135 | }
136 | }
137 |
138 | export const getDomains = async () => {
139 | try {
140 | const response = await fetch(`${baseUrl}/api/v3/domains`, {
141 | method: 'GET',
142 | headers: {
143 | 'x-rapidapi-key': x_rapidapi_key,
144 | 'x-rapidapi-host': x_rapidapi_host
145 | }
146 | });
147 |
148 | if (!response.ok) {
149 | throw new Error("Failed to fetch domains");
150 | }
151 |
152 | const data = await response.json();
153 | if (!data.domains || data.domains.length === 0) {
154 | throw new Error("No domains found");
155 | }
156 | return data.domains;
157 | } catch (error) {
158 | console.error("Error fetching domains:", error);
159 | throw new Error("Failed to fetch domains");
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/components/Home.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useState, useEffect } from "react";
4 | import {
5 | Copy,
6 | Check,
7 | RefreshCw,
8 | Trash2,
9 | Github,
10 | Menu,
11 | MailOpen,
12 | MailCheck,
13 | } from "lucide-react";
14 | import EmailView from "./EmailView";
15 | import {
16 | deletecurrentEmail,
17 | getcurrentEmail,
18 | getEmails,
19 | registerEmail,
20 | } from "@/actions/actions";
21 |
22 | import Image from "next/image";
23 |
24 | interface Email {
25 | id: string;
26 | from: string;
27 | to: string;
28 | cc: string;
29 | subject: string;
30 | body_text: string;
31 | body_html: string;
32 | created_at: string;
33 | isRead: boolean;
34 | isUnread?: boolean;
35 | }
36 |
37 | function HomePage() {
38 | const [currentEmail, setCurrentEmail] = useState("loading...");
39 | const [selectedEmail, setSelectedEmail] = useState(null);
40 | const [emails, setEmails] = useState([]);
41 | const [loadingGenerate, setLoadingGenerate] = useState(false);
42 | const [loadingDelete, setLoadingDelete] = useState(false);
43 | const [loadingEmails, setLoadingEmails] = useState(true);
44 | const [isCopied, setIsCopied] = useState(false);
45 |
46 | useEffect(() => {
47 | setLoadingGenerate(true);
48 | getcurrentEmail()
49 | .then((email) => {
50 | console.log("Current email:", email);
51 | setCurrentEmail(email);
52 | })
53 | .catch((error) => {
54 | console.error("Error fetching current email:", error);
55 | setCurrentEmail("Failed to load email");
56 | });
57 | setLoadingGenerate(false);
58 | }, []);
59 | useEffect(() => {
60 | if(!currentEmail || currentEmail === "loading...") return;
61 | getEmails(currentEmail)
62 | .then((emails) => {
63 | console.log("Fetched emails:", emails);
64 | setEmails(emails);
65 | setLoadingEmails(false);
66 | })
67 | .catch((error) => {
68 | console.error("Error fetching emails:", error);
69 | setEmails([]);
70 | setLoadingEmails(false);
71 | });
72 | }, [currentEmail]);
73 |
74 | useEffect(() => {
75 | if (isCopied) {
76 | const timer = setTimeout(() => {
77 | setIsCopied(false);
78 | }, 2000);
79 | return () => clearTimeout(timer);
80 | }
81 | }, [isCopied]);
82 |
83 | const generateNewEmail = async () => {
84 | setLoadingGenerate(true);
85 | const randomString = Math.random().toString(36).substring(2, 8);
86 | const newemail = await registerEmail(randomString);
87 | setCurrentEmail(newemail);
88 | setLoadingGenerate(false);
89 | };
90 |
91 | const copyToClipboard = () => {
92 | navigator.clipboard.writeText(currentEmail).then(() => {
93 | setIsCopied(true);
94 | console.log("Email copied to clipboard:", currentEmail);
95 | }).catch((error) => {
96 | console.error("Failed to copy email:", error);
97 | });
98 | };
99 |
100 | const deleteEmail = async () => {
101 | await deletecurrentEmail();
102 | setCurrentEmail("");
103 | setSelectedEmail(null);
104 | setEmails([]);
105 | };
106 |
107 | const handleEmailClick = (email: Email) => {
108 | setSelectedEmail(email);
109 | };
110 |
111 | const handleBackToInbox = () => {
112 | setSelectedEmail(null);
113 | };
114 |
115 | if (selectedEmail) {
116 | return (
117 |
118 |
119 | {/* Header */}
120 |
121 |
122 |
123 |
129 |
130 |
131 | TempMailo
132 |
133 |
134 |
135 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | {/* Footer */}
150 |
155 |
156 |
157 | );
158 | }
159 |
160 | return (
161 |
162 |
163 | {/* Header */}
164 |
165 |
166 |
167 |
173 |
174 |
175 | TempMailo
176 |
177 |
178 |
179 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 | {/* Main Content */}
192 |
193 |
194 | {/* Email Address Section */}
195 |
196 |
197 | Your Temporary Email Address
198 |
199 |
200 |
201 |
202 |
208 |
213 | {isCopied ? (
214 |
215 | ) : (
216 |
217 | )}
218 |
219 |
220 |
221 |
222 |
226 |
227 | Generate New
228 |
229 |
233 |
234 | Delete Email
235 |
236 |
237 |
238 |
239 |
240 | {/* Inbox Section */}
241 |
242 |
243 |
244 | Inbox
245 |
246 | {
248 | setLoadingEmails(true);
249 | getEmails(currentEmail)
250 | .then((emails) => {
251 | console.log("Fetched emails:", emails);
252 | setEmails(emails);
253 | setLoadingEmails(false);
254 | })
255 | .catch((error) => {
256 | console.error("Error fetching emails:", error);
257 | setEmails([]);
258 | setLoadingEmails(false);
259 | });
260 | }}
261 | >
262 |
263 |
264 |
265 | {!loadingEmails ? <>
266 | { emails.length != 0 ? (
267 | {emails.map((email) => (
268 |
handleEmailClick(email)}
272 | >
273 |
280 | {email.isUnread ? (
281 |
282 | ) : (
283 |
284 | )}
285 |
286 |
287 |
294 | {email.from}
295 |
296 |
297 | {email.subject}
298 |
299 |
300 |
301 |
302 | {email.created_at}
303 |
304 | {email.isUnread && (
305 |
306 | 1
307 |
308 | )}
309 |
310 |
311 | ))}
312 |
):(
313 |
314 |
No emails found.
315 |
316 | )}
317 | >:(
318 |
319 |
Loading emails...
320 |
321 | )}
322 |
323 |
324 |
325 |
326 | {/* Footer */}
327 |
332 |
333 |
334 | );
335 | }
336 |
337 | export default HomePage;
338 |
--------------------------------------------------------------------------------