mirror of
https://github.com/Crazyco-xyz/48hr.email.git
synced 2026-01-09 11:19:36 +01:00
[Fix]: Update old config mentions and plug missing ones
This commit is contained in:
parent
0c8db0b597
commit
8151587036
10 changed files with 103 additions and 184 deletions
|
|
@ -1,3 +1,5 @@
|
|||
const templateContext = require('../template-context')
|
||||
|
||||
function checkLockAccess(req, res, next) {
|
||||
const inboxLock = req.app.get('inboxLock')
|
||||
const address = req.params.address
|
||||
|
|
@ -21,14 +23,10 @@ function checkLockAccess(req, res, next) {
|
|||
const unlockError = req.session ? req.session.unlockError : undefined
|
||||
if (req.session) delete req.session.unlockError
|
||||
|
||||
return res.render('error', {
|
||||
purgeTime: require('../../../application/helper').prototype.purgeTimeElemetBuilder(),
|
||||
address: address,
|
||||
message: 'This inbox is locked by another user. Only the owner can access it.',
|
||||
branding: req.app.get('config').http.branding,
|
||||
currentUser: req.session && req.session.username,
|
||||
authEnabled: req.app.get('config').user.authEnabled
|
||||
})
|
||||
return res.render('error', templateContext.build(req, {
|
||||
title: 'Access Denied',
|
||||
message: 'This inbox is locked by another user. Only the owner can access it.'
|
||||
}))
|
||||
}
|
||||
|
||||
// Update last access if they have access and are authenticated
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ const express = require('express')
|
|||
const router = express.Router()
|
||||
const { requireAuth } = require('../middleware/auth')
|
||||
const { body, validationResult } = require('express-validator')
|
||||
const templateContext = require('../template-context')
|
||||
|
||||
// GET /account - Account dashboard
|
||||
router.get('/account', requireAuth, async(req, res) => {
|
||||
|
|
@ -26,25 +27,20 @@ router.get('/account', requireAuth, async(req, res) => {
|
|||
const config = req.app.get('config')
|
||||
const stats = userRepository.getUserStats(req.session.userId, config.user)
|
||||
|
||||
// Get purge time for footer
|
||||
const purgeTime = helper.purgeTimeElemetBuilder()
|
||||
const successMessage = req.session.accountSuccess
|
||||
const errorMessage = req.session.accountError
|
||||
delete req.session.accountSuccess
|
||||
delete req.session.accountError
|
||||
|
||||
res.render('account', {
|
||||
res.render('account', templateContext.build(req, {
|
||||
title: 'Account Dashboard',
|
||||
username: req.session.username,
|
||||
forwardEmails,
|
||||
lockedInboxes,
|
||||
stats,
|
||||
branding: config.http.features.branding || ['48hr.email', 'Service', 'https://example.com'],
|
||||
purgeTime: purgeTime,
|
||||
smtpEnabled: config.email.features.smtp,
|
||||
successMessage: req.session.accountSuccess,
|
||||
errorMessage: req.session.accountError
|
||||
})
|
||||
|
||||
// Clear flash messages
|
||||
delete req.session.accountSuccess
|
||||
delete req.session.accountError
|
||||
successMessage,
|
||||
errorMessage
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('Account page error:', error)
|
||||
res.status(500).render('error', {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ const { body, validationResult } = require('express-validator')
|
|||
const debug = require('debug')('48hr-email:auth-routes')
|
||||
const { redirectIfAuthenticated } = require('../middleware/auth')
|
||||
const config = require('../../../application/config')
|
||||
const Helper = require('../../../application/helper')
|
||||
const helper = new Helper()
|
||||
|
||||
const purgeTime = helper.purgeTimeElemetBuilder()
|
||||
const templateContext = require('../template-context')
|
||||
|
||||
// Simple in-memory rate limiters for registration and login
|
||||
const registrationRateLimitStore = new Map()
|
||||
|
|
@ -96,21 +93,13 @@ router.use((req, res, next) => {
|
|||
// GET /auth - Show unified auth page (login or register)
|
||||
router.get('/auth', redirectIfAuthenticated, (req, res) => {
|
||||
const config = req.app.get('config')
|
||||
const errorMessage = req.session.errorMessage
|
||||
const successMessage = req.session.successMessage
|
||||
|
||||
// Clear messages after reading
|
||||
delete req.session.errorMessage
|
||||
delete req.session.successMessage
|
||||
|
||||
res.render('auth', {
|
||||
res.render('auth', templateContext.build(req, {
|
||||
title: `Login or Register | ${(config.http.features.branding || ['48hr.email'])[0]}`,
|
||||
branding: config.http.features.branding || ['48hr.email', 'Service', 'https://example.com'],
|
||||
purgeTime: purgeTime,
|
||||
smtpEnabled: config.email.features.smtp,
|
||||
errorMessage,
|
||||
successMessage
|
||||
})
|
||||
}))
|
||||
})
|
||||
|
||||
// POST /register - Process registration
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
const express = require('express')
|
||||
|
||||
const router = new express.Router()
|
||||
const config = require('../../../application/config')
|
||||
const Helper = require('../../../application/helper')
|
||||
const helper = new(Helper)
|
||||
const templateContext = require('../template-context')
|
||||
const debug = require('debug')('48hr-email:routes')
|
||||
|
||||
const purgeTime = helper.purgeTimeElemetBuilder()
|
||||
|
||||
router.get('/:address/:errorCode', async(req, res, next) => {
|
||||
try {
|
||||
const mailProcessingService = req.app.get('mailProcessingService')
|
||||
|
|
@ -21,14 +17,11 @@ router.get('/:address/:errorCode', async(req, res, next) => {
|
|||
debug(`Rendering error page ${errorCode} with message: ${message}`)
|
||||
const branding = config.http.features.branding || ['48hr.email', 'Service', 'https://example.com']
|
||||
res.status(errorCode)
|
||||
res.render('error', {
|
||||
res.render('error', templateContext.build(req, {
|
||||
title: `${branding[0]} | ${errorCode}`,
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
message: message,
|
||||
status: errorCode,
|
||||
branding: branding
|
||||
})
|
||||
status: errorCode
|
||||
}))
|
||||
} catch (error) {
|
||||
debug('Error loading error page:', error.message)
|
||||
console.error('Error while loading error page', error)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const debug = require('debug')('48hr-email:routes')
|
|||
const config = require('../../../application/config')
|
||||
const Helper = require('../../../application/helper')
|
||||
const CryptoDetector = require('../../../application/crypto-detector')
|
||||
const templateContext = require('../template-context')
|
||||
const helper = new(Helper)
|
||||
const cryptoDetector = new CryptoDetector()
|
||||
const { checkLockAccess } = require('../middleware/lock')
|
||||
|
|
@ -105,68 +106,11 @@ router.get('^/:address([^@/]+@[^@/]+)', sanitizeAddress, validateDomain, optiona
|
|||
throw new Error('Mail processing service not available')
|
||||
}
|
||||
debug(`Inbox request for ${req.params.address}`)
|
||||
const inboxLock = req.app.get('inboxLock')
|
||||
|
||||
// Check lock status
|
||||
const isLocked = inboxLock && inboxLock.isLocked(req.params.address)
|
||||
const userId = req.session && req.session.userId
|
||||
const isAuthenticated = req.session && req.session.isAuthenticated
|
||||
|
||||
// Check if user has access (either owns the lock or has session access)
|
||||
const hasAccess = isAuthenticated && userId && inboxLock ?
|
||||
(inboxLock.isLockedByUser(req.params.address, userId) || req.session.lockedInbox === req.params.address) :
|
||||
(req.session && req.session.lockedInbox === req.params.address)
|
||||
|
||||
// Get user's verified emails if logged in
|
||||
let userForwardEmails = []
|
||||
if (req.session && req.session.userId) {
|
||||
const userRepository = req.app.get('userRepository')
|
||||
if (userRepository) {
|
||||
userForwardEmails = userRepository.getForwardEmails(req.session.userId)
|
||||
}
|
||||
}
|
||||
|
||||
// Pull any lock error from session and clear it after reading
|
||||
const lockError = req.session ? req.session.lockError : undefined
|
||||
const unlockErrorSession = req.session ? req.session.unlockError : undefined
|
||||
const errorMessage = req.session ? req.session.errorMessage : undefined
|
||||
if (req.session) {
|
||||
delete req.session.lockError
|
||||
delete req.session.unlockError
|
||||
delete req.session.errorMessage
|
||||
}
|
||||
|
||||
// Check for forward all success flag
|
||||
const forwardAllSuccess = req.query.forwardedAll ? parseInt(req.query.forwardedAll) : null
|
||||
|
||||
// Check for verification sent flag
|
||||
const verificationSent = req.query.verificationSent === 'true'
|
||||
const verificationEmail = req.query.email || ''
|
||||
|
||||
res.render('inbox', {
|
||||
res.render('inbox', templateContext.build(req, {
|
||||
title: `${(config.http.features.branding || ['48hr.email'])[0]} | ` + req.params.address,
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
mailSummaries: mailProcessingService.getMailSummaries(req.params.address),
|
||||
branding: config.http.branding,
|
||||
authEnabled: config.user.authEnabled,
|
||||
smtpEnabled: config.email.features.smtp,
|
||||
isAuthenticated: req.session && req.session.userId ? true : false,
|
||||
userForwardEmails: userForwardEmails,
|
||||
isLocked: isLocked,
|
||||
hasAccess: hasAccess,
|
||||
unlockError: unlockErrorSession,
|
||||
locktimer: config.user.lockReleaseHours,
|
||||
error: lockError,
|
||||
redirectTo: req.originalUrl,
|
||||
expiryTime: config.email.purgeTime.time,
|
||||
expiryUnit: config.email.purgeTime.unit,
|
||||
refreshInterval: config.imap.refreshIntervalSeconds,
|
||||
errorMessage: errorMessage,
|
||||
forwardAllSuccess: forwardAllSuccess,
|
||||
verificationSent: verificationSent,
|
||||
verificationEmail: verificationEmail
|
||||
})
|
||||
mailSummaries: mailProcessingService.getMailSummaries(req.params.address)
|
||||
}))
|
||||
} catch (error) {
|
||||
debug(`Error loading inbox for ${req.params.address}:`, error.message)
|
||||
console.error('Error while loading inbox', error)
|
||||
|
|
@ -201,58 +145,13 @@ router.get(
|
|||
const cryptoAttachments = cryptoDetector.detectCryptoAttachments(mail.attachments)
|
||||
debug(`Found ${cryptoAttachments.length} cryptographic attachments`)
|
||||
|
||||
const inboxLock = req.app.get('inboxLock')
|
||||
const isLocked = inboxLock && inboxLock.isLocked(req.params.address)
|
||||
const userId = req.session && req.session.userId
|
||||
const isAuthenticated = req.session && req.session.isAuthenticated
|
||||
|
||||
// Check if user has access (either owns the lock or has session access)
|
||||
const hasAccess = isAuthenticated && userId && inboxLock ?
|
||||
(inboxLock.isLockedByUser(req.params.address, userId) || req.session.lockedInbox === req.params.address) :
|
||||
(req.session && req.session.lockedInbox === req.params.address)
|
||||
|
||||
// Get user's verified emails if logged in
|
||||
let userForwardEmails = []
|
||||
if (req.session && req.session.userId) {
|
||||
const userRepository = req.app.get('userRepository')
|
||||
if (userRepository) {
|
||||
userForwardEmails = userRepository.getForwardEmails(req.session.userId)
|
||||
}
|
||||
}
|
||||
|
||||
// Pull error message from session and clear it
|
||||
const errorMessage = req.session ? req.session.errorMessage : undefined
|
||||
if (req.session) {
|
||||
delete req.session.errorMessage
|
||||
}
|
||||
|
||||
// Check for forward success flag
|
||||
const forwardSuccess = req.query.forwarded === 'true'
|
||||
|
||||
// Check for verification sent flag
|
||||
const verificationSent = req.query.verificationSent === 'true'
|
||||
const verificationEmail = req.query.email || ''
|
||||
|
||||
debug(`Rendering email view for UID ${req.params.uid}`)
|
||||
res.render('mail', {
|
||||
res.render('mail', templateContext.build(req, {
|
||||
title: mail.subject + " | " + req.params.address,
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
mail,
|
||||
cryptoAttachments: cryptoAttachments,
|
||||
uid: req.params.uid,
|
||||
branding: config.http.features.branding || ['48hr.email', 'Service', 'https://example.com'],
|
||||
authEnabled: config.user.authEnabled,
|
||||
smtpEnabled: config.email.features.smtp,
|
||||
isAuthenticated: req.session && req.session.userId ? true : false,
|
||||
userForwardEmails: userForwardEmails,
|
||||
isLocked: isLocked,
|
||||
hasAccess: hasAccess,
|
||||
errorMessage: errorMessage,
|
||||
forwardSuccess: forwardSuccess,
|
||||
verificationSent: verificationSent,
|
||||
verificationEmail: verificationEmail
|
||||
})
|
||||
uid: req.params.uid
|
||||
}))
|
||||
} else {
|
||||
debug(`Email ${req.params.uid} not found for ${req.params.address}`)
|
||||
req.session.errorMessage = 'This mail could not be found. It either does not exist or has been deleted from our servers!'
|
||||
|
|
@ -424,11 +323,11 @@ router.get(
|
|||
// Emails are immutable, cache if found
|
||||
res.set('Cache-Control', 'private, max-age=600')
|
||||
debug(`Rendering raw email view for UID ${req.params.uid}`)
|
||||
res.render('raw', {
|
||||
res.render('raw', templateContext.build(req, {
|
||||
title: req.params.uid + " | raw | " + req.params.address,
|
||||
mail: rawMail,
|
||||
decoded: decodedMail
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
debug(`Raw email ${uid} not found for ${req.params.address}`)
|
||||
req.session.errorMessage = 'This mail could not be found. It either does not exist or has been deleted from our servers!'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const express = require('express')
|
||||
const router = new express.Router()
|
||||
const debug = require('debug')('48hr-email:stats-routes')
|
||||
const templateContext = require('../template-context')
|
||||
|
||||
// GET /stats - Statistics page with lazy loading
|
||||
router.get('/', async(req, res) => {
|
||||
|
|
@ -16,10 +17,7 @@ router.get('/', async(req, res) => {
|
|||
return res.redirect(redirectUrl)
|
||||
}
|
||||
|
||||
const Helper = require('../../../application/helper')
|
||||
const helper = new Helper()
|
||||
const branding = config.http.features.branding || ['48hr.email', 'Service', 'https://example.com']
|
||||
const purgeTime = helper.purgeTimeElemetBuilder()
|
||||
|
||||
// Return page with placeholder data immediately - real data loads via JS
|
||||
const placeholderStats = {
|
||||
|
|
@ -48,15 +46,11 @@ router.get('/', async(req, res) => {
|
|||
|
||||
debug(`Stats page requested - returning with lazy loading`)
|
||||
|
||||
res.render('stats', {
|
||||
res.render('stats', templateContext.build(req, {
|
||||
title: `Statistics | ${branding[0]}`,
|
||||
branding: branding,
|
||||
purgeTime: purgeTime,
|
||||
stats: placeholderStats,
|
||||
authEnabled: config.user.authEnabled,
|
||||
currentUser: req.session && req.session.username,
|
||||
lazyLoad: true
|
||||
})
|
||||
}))
|
||||
} catch (error) {
|
||||
debug(`Error loading stats page: ${error.message}`)
|
||||
console.error('Error while loading stats page', error)
|
||||
|
|
|
|||
|
|
@ -19,12 +19,36 @@ class TemplateContext {
|
|||
* @returns {Object} Base template context
|
||||
*/
|
||||
getBaseContext(req) {
|
||||
const inboxLock = req.app.get('inboxLock')
|
||||
const address = req.params && req.params.address
|
||||
const userId = req.session && req.session.userId
|
||||
const isAuthenticated = !!(req.session && req.session.userId)
|
||||
|
||||
// Calculate lock status for current address
|
||||
const isLocked = address && inboxLock ? inboxLock.isLocked(address) : false
|
||||
const hasAccess = address && isAuthenticated && userId && inboxLock ?
|
||||
(inboxLock.isLockedByUser(address, userId) || req.session.lockedInbox === address) :
|
||||
(address && req.session && req.session.lockedInbox === address)
|
||||
|
||||
// Get user's verified forward emails if logged in
|
||||
let userForwardEmails = []
|
||||
if (isAuthenticated && userId) {
|
||||
const userRepository = req.app.get('userRepository')
|
||||
if (userRepository) {
|
||||
userForwardEmails = userRepository.getForwardEmails(userId)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// Config values
|
||||
config: config,
|
||||
branding: config.http.features.branding || ['48hr.email', 'Service', 'https://example.com'],
|
||||
purgeTime: this.purgeTime,
|
||||
purgeTimeRaw: config.email.purgeTime,
|
||||
expiryTime: config.email.purgeTime.time,
|
||||
expiryUnit: config.email.purgeTime.unit,
|
||||
refreshInterval: config.imap.refreshIntervalSeconds,
|
||||
locktimer: config.user.lockReleaseHours,
|
||||
|
||||
// Feature flags
|
||||
authEnabled: config.user.authEnabled,
|
||||
|
|
@ -32,8 +56,29 @@ class TemplateContext {
|
|||
smtpEnabled: config.email.features.smtp,
|
||||
showInfoSection: config.http.features.infoSection,
|
||||
|
||||
// User session
|
||||
// User session & authentication
|
||||
currentUser: req.session && req.session.username ? req.session.username : null,
|
||||
isAuthenticated: isAuthenticated,
|
||||
userForwardEmails: userForwardEmails,
|
||||
|
||||
// Lock status
|
||||
isLocked: isLocked,
|
||||
hasAccess: hasAccess,
|
||||
|
||||
// Session messages/errors (auto-clear after reading)
|
||||
error: this._getAndClearSession(req, 'lockError'),
|
||||
unlockError: this._getAndClearSession(req, 'unlockError'),
|
||||
errorMessage: this._getAndClearSession(req, 'errorMessage'),
|
||||
|
||||
// Query parameters
|
||||
verificationSent: req.query && req.query.verificationSent === 'true',
|
||||
verificationEmail: req.query && req.query.email || '',
|
||||
forwardSuccess: req.query && req.query.forwarded === 'true',
|
||||
forwardAllSuccess: req.query && req.query.forwardedAll ? parseInt(req.query.forwardedAll) : null,
|
||||
|
||||
// Request info
|
||||
redirectTo: req.originalUrl,
|
||||
address: address,
|
||||
|
||||
// Common data
|
||||
domains: this.cachedDomains,
|
||||
|
|
@ -41,6 +86,17 @@ class TemplateContext {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get and clear session value
|
||||
* @private
|
||||
*/
|
||||
_getAndClearSession(req, key) {
|
||||
if (!req.session) return undefined
|
||||
const value = req.session[key]
|
||||
delete req.session[key]
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge base context with page-specific data
|
||||
* @param {Object} req - Express request object
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
{% block metaTags %}
|
||||
<!-- SEO Meta Tags -->
|
||||
<meta name="description" content="Your temporary Inbox. Create instant throwaway email addresses to protect your privacy. No registration required. Emails auto-delete after 48 hours.">
|
||||
<meta name="description" content="Your temporary Inbox. Create instant throwaway email addresses to protect your privacy. No registration required. Emails auto-delete after {{ purgeTime | raw }}.">
|
||||
<meta name="keywords" content="temporary email, disposable email, throwaway email, fake email, temp mail, anonymous email, 48hr email, privacy protection, burner email">
|
||||
<meta name="author" content="CrazyCo">
|
||||
<meta name="robots" content="index, follow">
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://48hr.email/">
|
||||
<meta property="og:title" content="48hr.email - Your temporary Inbox">
|
||||
<meta property="og:description" content="Protect your privacy with free temporary email addresses. No registration required. Emails auto-delete after 48 hours.">
|
||||
<meta property="og:description" content="Protect your privacy with free temporary email addresses. No registration required. Emails auto-delete after {{ purgeTime | raw }}.">
|
||||
<meta property="og:image" content="https://48hr.email/images/logo.png">
|
||||
<meta property="og:site_name" content="48hr.email">
|
||||
|
||||
|
|
|
|||
|
|
@ -71,12 +71,7 @@ function convertAndRound(time, unit) {
|
|||
*/
|
||||
exports.readablePurgeTime = function(purgeTime) {
|
||||
if (!purgeTime || !purgeTime.time || !purgeTime.unit) {
|
||||
// Fallback to config if not provided
|
||||
if (config.email.purgeTime) {
|
||||
purgeTime = config.email.purgeTime
|
||||
} else {
|
||||
return '48 hours'
|
||||
}
|
||||
purgeTime = config.email.purgeTime
|
||||
}
|
||||
|
||||
let result = `${purgeTime.time} ${purgeTime.unit}`
|
||||
|
|
|
|||
|
|
@ -18,12 +18,9 @@ const lockRouter = require('./routes/lock')
|
|||
const authRouter = require('./routes/auth')
|
||||
const accountRouter = require('./routes/account')
|
||||
const statsRouter = require('./routes/stats')
|
||||
const templateContext = require('./template-context')
|
||||
const { sanitizeHtmlTwigFilter, readablePurgeTime } = require('./views/twig-filters')
|
||||
|
||||
const Helper = require('../../application/helper')
|
||||
const helper = new(Helper)
|
||||
const purgeTime = helper.purgeTimeElemetBuilder()
|
||||
|
||||
// Utility function for consistent error handling in routes
|
||||
const handleRouteError = (error, req, res, next, context = 'route') => {
|
||||
debug(`Error in ${context}:`, error.message)
|
||||
|
|
@ -143,7 +140,9 @@ app.use(async(req, res, next) => {
|
|||
app.use((req, res, next) => {
|
||||
const isImapReady = req.app.get('isImapReady')
|
||||
if (!isImapReady && !req.path.startsWith('/images') && !req.path.startsWith('/javascripts') && !req.path.startsWith('/stylesheets') && !req.path.startsWith('/dependencies')) {
|
||||
return res.render('loading')
|
||||
return res.render('loading', templateContext.build(req, {
|
||||
title: 'Loading...'
|
||||
}))
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
|
@ -174,11 +173,11 @@ app.use(async(err, req, res, _next) => {
|
|||
|
||||
// Render the error page
|
||||
res.status(err.status || 500)
|
||||
res.render('error', {
|
||||
purgeTime: purgeTime,
|
||||
address: req.params && req.params.address,
|
||||
branding: config.http.features.branding || ['48hr.email', 'Service', 'https://example.com']
|
||||
})
|
||||
res.render('error', templateContext.build(req, {
|
||||
title: 'Error',
|
||||
message: err.message,
|
||||
status: err.status || 500
|
||||
}))
|
||||
} catch (renderError) {
|
||||
debug('Error in error handler:', renderError.message)
|
||||
console.error('Critical error in error handler', renderError)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue