[Chore]: Final Cleanup
BIN
.github/assets/account.png
vendored
Normal file
|
After Width: | Height: | Size: 209 KiB |
BIN
.github/assets/home.png
vendored
Normal file
|
After Width: | Height: | Size: 346 KiB |
BIN
.github/assets/inbox.png
vendored
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 241 KiB |
BIN
.github/assets/keys.png
vendored
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 281 KiB |
BIN
.github/assets/raw.png
vendored
|
Before Width: | Height: | Size: 265 KiB |
15
README.md
|
|
@ -33,7 +33,7 @@ All data is being removed 48hrs after they have reached the mail server.
|
||||||
- Delete your emails ahead of time by pressing the delete button
|
- Delete your emails ahead of time by pressing the delete button
|
||||||
- View the raw email, showing all the headers etc.
|
- View the raw email, showing all the headers etc.
|
||||||
- Download Attachments with one click
|
- Download Attachments with one click
|
||||||
- Password-protected inboxes
|
- <u>Optional</u> User Account System with email forwarding and inbox locking
|
||||||
- and more...
|
- and more...
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
@ -42,13 +42,14 @@ All data is being removed 48hrs after they have reached the mail server.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
| Inbox | Email using HTML and CSS |
|
| Homepage | Account Panel |
|
||||||
|:---:|:---:|
|
|:---:|:---:|
|
||||||
| <img src=".github/assets/inbox.png" width="500px" height="300px" style="object-fit: cover;"> | <img src=".github/assets/html.png" width="500px" height="300px" style="object-fit: cover;"> |
|
| <img src=".github/assets/home.png" width="500px" height="300px" style="object-fit: fit;"> | <img src=".github/assets/account.png" width="500px" height="300px" style="object-fit: fit;"> |
|
||||||
|
|
||||||
|
| Inbox | Email using HTML and CSS | Attachments and Cryptographic Keys view |
|
||||||
|
|:---:|:---:|:---:|
|
||||||
|
| <img src=".github/assets/inbox.png" width="500px" height="300px" style="object-fit: fit;"> | <img src=".github/assets/html.png" width="500px" height="300px" style="object-fit: fit;"> | <img src=".github/assets/keys.png" width="500px" height="300px" style="object-fit: fit;"> |
|
||||||
|
|
||||||
| Email without CSS | Dropdown for cryptographic Keys and Signatures |
|
|
||||||
|:---:|:---:|
|
|
||||||
| <img src=".github/assets/raw.png" width="500px" height="300px" style="object-fit: cover;"> | <img src=".github/assets/keys.png" width="500px" height="300px" style="object-fit: cover;"> |
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
@ -65,7 +66,7 @@ All data is being removed 48hrs after they have reached the mail server.
|
||||||
## How can I set this up myself?
|
## How can I set this up myself?
|
||||||
|
|
||||||
**Prerequisites:**
|
**Prerequisites:**
|
||||||
- Mail server with IMAP (Optionally also SMTP for email forwarding feature)
|
- Mail server with IMAP (Optionally also SMTP for registration and protected features)
|
||||||
- One or multiple domains dedicated to this
|
- One or multiple domains dedicated to this
|
||||||
- git & nodejs
|
- git & nodejs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ router.get('/auth', redirectIfAuthenticated, (req, res) => {
|
||||||
delete req.session.errorMessage
|
delete req.session.errorMessage
|
||||||
delete req.session.successMessage
|
delete req.session.successMessage
|
||||||
|
|
||||||
res.render('login-auth', {
|
res.render('auth', {
|
||||||
title: `Login or Register | ${config.http.branding[0]}`,
|
title: `Login or Register | ${config.http.branding[0]}`,
|
||||||
branding: config.http.branding,
|
branding: config.http.branding,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
|
|
|
||||||
|
|
@ -658,8 +658,9 @@ router.get('/verify', async(req, res, next) => {
|
||||||
|
|
||||||
debug(`Email ${destinationEmail} verified successfully, cookie set for 24 hours`)
|
debug(`Email ${destinationEmail} verified successfully, cookie set for 24 hours`)
|
||||||
|
|
||||||
// Redirect to success page
|
// Show success on account page
|
||||||
return res.redirect(`/inbox/verify-success?email=${encodeURIComponent(destinationEmail)}`)
|
req.session.accountSuccess = `Successfully verified ${destinationEmail}!`
|
||||||
|
return res.redirect('/account')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
debug(`Error during verification: ${error.message}`)
|
debug(`Error during verification: ${error.message}`)
|
||||||
console.error('Error during email verification', error)
|
console.error('Error during email verification', error)
|
||||||
|
|
@ -667,29 +668,4 @@ router.get('/verify', async(req, res, next) => {
|
||||||
res.redirect('/')
|
res.redirect('/')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// GET route for verification success page
|
|
||||||
router.get('/verify-success', async(req, res) => {
|
|
||||||
const { email } = req.query
|
|
||||||
|
|
||||||
if (!email) {
|
|
||||||
return res.redirect('/')
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = req.app.get('config')
|
|
||||||
const mailProcessingService = req.app.get('mailProcessingService')
|
|
||||||
const count = await mailProcessingService.getCount()
|
|
||||||
const largestUid = await req.app.locals.imapService.getLargestUid()
|
|
||||||
const totalcount = helper.countElementBuilder(count, largestUid)
|
|
||||||
|
|
||||||
res.render('verify-success', {
|
|
||||||
title: `Email Verified | ${config.http.branding[0]}`,
|
|
||||||
email: email,
|
|
||||||
branding: config.http.branding,
|
|
||||||
purgeTime: purgeTime,
|
|
||||||
totalcount: totalcount
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if verificationSent %}
|
{% if verificationSent %}
|
||||||
<div class="verification-message">
|
<div class="verification-message">
|
||||||
📧 Verification email sent to <strong>{{ verificationEmail }}</strong>. Please check your inbox and click the verification link (expires in 15 minutes).
|
Verification email sent to <strong>{{ verificationEmail }}</strong>. Please check your inbox and click the verification link (expires in 15 minutes).
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if errorMessage %}
|
{% if errorMessage %}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if verificationSent %}
|
{% if verificationSent %}
|
||||||
<div class="verification-message">
|
<div class="verification-message">
|
||||||
📧 Verification email sent to <strong>{{ verificationEmail }}</strong>. Please check your inbox and click the verification link (expires in 15 minutes).
|
Verification email sent to <strong>{{ verificationEmail }}</strong>. Please check your inbox and click the verification link (expires in 15 minutes).
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="mail-container">
|
<div class="mail-container">
|
||||||
|
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block header %}
|
|
||||||
<div class="action-links">
|
|
||||||
<a href="/" aria-label="Return to home">← Home</a>
|
|
||||||
<a href="/login" aria-label="Login">Login</a>
|
|
||||||
<button class="theme-toggle" id="themeToggle" aria-label="Toggle dark/light mode">
|
|
||||||
<svg class="theme-icon theme-icon-dark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
<svg class="theme-icon theme-icon-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<div id="register" class="auth-container">
|
|
||||||
<div class="auth-card">
|
|
||||||
<h1>Create Account</h1>
|
|
||||||
<p class="auth-subtitle">Sign up to unlock email forwarding and inbox locking</p>
|
|
||||||
|
|
||||||
{% if errorMessage %}
|
|
||||||
<div class="unlock-error">
|
|
||||||
{{ errorMessage }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if successMessage %}
|
|
||||||
<div class="success-message">
|
|
||||||
{{ successMessage }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<form method="POST" action="/register">
|
|
||||||
<fieldset>
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="username"
|
|
||||||
name="username"
|
|
||||||
placeholder="3-20 characters, alphanumeric and underscore"
|
|
||||||
required
|
|
||||||
minlength="3"
|
|
||||||
maxlength="20"
|
|
||||||
pattern="[a-zA-Z0-9_]+"
|
|
||||||
autocomplete="username"
|
|
||||||
>
|
|
||||||
<small>Only letters, numbers, and underscores allowed</small>
|
|
||||||
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
placeholder="Min 8 characters"
|
|
||||||
required
|
|
||||||
minlength="8"
|
|
||||||
autocomplete="new-password"
|
|
||||||
>
|
|
||||||
<small>Must contain uppercase, lowercase, and number</small>
|
|
||||||
|
|
||||||
<label for="confirmPassword">Confirm Password</label>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
id="confirmPassword"
|
|
||||||
name="confirmPassword"
|
|
||||||
placeholder="Re-enter your password"
|
|
||||||
required
|
|
||||||
minlength="8"
|
|
||||||
autocomplete="new-password"
|
|
||||||
>
|
|
||||||
|
|
||||||
<div class="auth-actions">
|
|
||||||
<button class="button button-primary" type="submit">Create Account</button>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="auth-footer">
|
|
||||||
<p>Already have an account? <a href="/login">Login here</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="auth-features">
|
|
||||||
<h3>Why Register?</h3>
|
|
||||||
<ul>
|
|
||||||
<li>✓ Forward emails to your real address</li>
|
|
||||||
<li>✓ Lock up to 5 inboxes with passwords</li>
|
|
||||||
<li>✓ Manage multiple verified forwarding emails</li>
|
|
||||||
<li>✓ Access your locked inboxes from anywhere</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block header %}
|
|
||||||
<div class="action-links">
|
|
||||||
{% if currentUser %}
|
|
||||||
<!-- Account Dropdown (logged in) -->
|
|
||||||
{% if authEnabled %}
|
|
||||||
<div class="action-dropdown">
|
|
||||||
<button class="dropdown-toggle" aria-label="Account menu">Account ▾</button>
|
|
||||||
<div class="dropdown-menu">
|
|
||||||
<a href="/account" aria-label="Account settings">Settings</a>
|
|
||||||
<a href="/logout?redirect=/" aria-label="Logout">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
{% if authEnabled %}
|
|
||||||
<a href="/auth" aria-label="Login or Register">Account</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<a href="/" aria-label="Return to home">Home</a>
|
|
||||||
<button class="theme-toggle" id="themeToggle" aria-label="Toggle dark/light mode">
|
|
||||||
<svg class="theme-icon theme-icon-dark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
<svg class="theme-icon theme-icon-light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
||||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<div class="verification-success-container">
|
|
||||||
<div class="verification-success-card">
|
|
||||||
<div class="verification-success-icon">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
||||||
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1>Email Verified Successfully!</h1>
|
|
||||||
|
|
||||||
<div class="verification-details">
|
|
||||||
<p>You have verified ownership of:</p>
|
|
||||||
<p class="verified-email">{{ email }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="verification-info">
|
|
||||||
<p>✓ You can now forward emails to this address for the next <strong>24 hours</strong></p>
|
|
||||||
<p>✓ After 24 hours, you'll need to verify again</p>
|
|
||||||
<p>✓ You can close this tab and return to your inbox</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="verification-actions">
|
|
||||||
<a href="/" class="button button-primary">Return to {{ branding[0] }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "48hr.email",
|
"name": "48hr.email",
|
||||||
"version": "1.8.2",
|
"version": "1.9.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "48hr.email is your favorite open-source tempmail client.",
|
"description": "48hr.email is your favorite open-source tempmail client.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|
|
||||||