[Chore]: Various tiny fixes and updates

This commit is contained in:
ClaraCrazy 2025-12-26 13:26:04 +01:00
parent ed2cc90852
commit 2f7194e6bd
No known key found for this signature in database
GPG key ID: EBBC896ACB497011
4 changed files with 48 additions and 49 deletions

37
app.js
View file

@ -19,7 +19,24 @@ const clientNotification = new ClientNotification()
debug('Client notification service initialized')
clientNotification.use(io)
const imapService = new ImapService(config)
let inboxLock = null
// Initialize inbox locking if enabled
if (config.lock.enabled) {
inboxLock = new InboxLock(config.lock.dbPath)
app.set('inboxLock', inboxLock)
console.log(`Inbox locking enabled (auto-release after ${config.lock.releaseHours} hours)`)
// Check for inactive locked inboxes
setInterval(() => {
const inactive = inboxLock.getInactive(config.lock.releaseHours)
if (inactive.length > 0) {
console.log(`Releasing ${inactive.length} inactive locked inbox(es)`)
inactive.forEach(address => inboxLock.release(address))
}
}, config.imap.refreshIntervalSeconds * 1000)
}
const imapService = new ImapService(config, inboxLock)
debug('IMAP service initialized')
const mailProcessingService = new MailProcessingService(
new MailRepository(),
@ -58,22 +75,6 @@ imapService.on(ImapService.EVENT_ERROR, error => {
app.set('mailProcessingService', mailProcessingService)
app.set('config', config)
// Initialize inbox locking if enabled
if (config.lock.enabled) {
const inboxLock = new InboxLock(config.lock.dbPath)
app.set('inboxLock', inboxLock)
console.log(`Inbox locking enabled (auto-release after ${config.lock.releaseHours} hours)`)
// Check for inactive locked inboxes
setInterval(() => {
const inactive = inboxLock.getInactive(config.lock.releaseHours)
if (inactive.length > 0) {
console.log(`Releasing ${inactive.length} inactive locked inbox(es)`)
inactive.forEach(address => inboxLock.release(address))
}
}, config.imap.refreshIntervalSeconds * 1000)
}
app.locals.imapService = imapService
app.locals.mailProcessingService = mailProcessingService
@ -104,4 +105,4 @@ server.on('error', error => {
console.error('Fatal web server error', error)
process.exit(1)
}
})
})

View file

@ -89,13 +89,13 @@ imaps.ImapSimple.prototype.closeBox = function(autoExpunge = true, callback) {
* With this abstraction it would be easy to replace this with any inbound mail service like mailgun.com.
*/
class ImapService extends EventEmitter {
constructor(config) {
constructor(config, inboxLock = null) {
super()
if (!config || !config.imap) {
throw new Error("ImapService requires a valid config with 'imap' object");
}
this.config = config
this.inboxLock = inboxLock
this.loadedUids = new Set()
this.connection = null
this.initialLoadDone = false
@ -255,15 +255,10 @@ class ImapService extends EventEmitter {
// Get locked inboxes if available
let lockedAddresses = [];
if (typeof this.config.lock !== 'undefined' && this.config.lock.enabled && this.config.lock.dbPath) {
if (this.inboxLock && typeof this.inboxLock.getAllLocked === 'function') {
try {
// Try to get the app instance and inboxLock
const app = require('../app');
const inboxLock = app.get('inboxLock');
if (inboxLock && typeof inboxLock.getAllLocked === 'function') {
lockedAddresses = inboxLock.getAllLocked().map(addr => addr.toLowerCase());
debug(`Locked inboxes (excluded from purge): ${lockedAddresses.join(', ')}`);
}
lockedAddresses = this.inboxLock.getAllLocked().map(addr => addr.toLowerCase());
debug(`Locked inboxes (excluded from purge): ${lockedAddresses.length > 0 ? lockedAddresses.join(', ') : '0'}`);
} catch (err) {
debug('Could not get locked inboxes for purge:', err.message);
}
@ -275,8 +270,7 @@ class ImapService extends EventEmitter {
const date = mail.attributes.date;
const uid = parseInt(mail.attributes.uid);
const toAddresses = Array.isArray(mail.parts[0].body.to) ?
mail.parts[0].body.to.map(a => a.toLowerCase()) :
[String(mail.parts[0].body.to).toLowerCase()];
mail.parts[0].body.to.map(a => a.toLowerCase()) : [String(mail.parts[0].body.to).toLowerCase()];
if (exampleUids.includes(uid)) return false;
if (toAddresses.some(addr => lockedAddresses.includes(addr))) return false;

View file

@ -70,6 +70,7 @@ class MailProcessingService extends EventEmitter {
}
onNewMail(mail) {
debug('onNewMail called for:', mail.to)
if (this.initialLoadDone) {
// For now, only log messages if they arrive after the initial load
debug('New mail for', mail.to[0])
@ -79,7 +80,9 @@ class MailProcessingService extends EventEmitter {
debug('Adding mail to repository for recipient:', to)
this.mailRepository.add(to, mail)
debug('Emitting notification for:', to)
return this.clientNotification.emit(to)
const emitResult = this.clientNotification.emit(to)
debug('clientNotification.emit result:', emitResult)
return emitResult
})
}

View file

@ -6,27 +6,28 @@ require('events').defaultMaxListeners = 50;
* Receives sign-ins from users and notifies them when new mails are available.
*/
class ClientNotification extends EventEmitter {
use(io) {
io.on('connection', socket => {
socket.on('sign in', address => this._signIn(socket, address))
})
}
use(io) {
io.on('connection', socket => {
socket.on('sign in', address => this._signIn(socket, address))
})
}
_signIn(socket, address) {
debug(`socketio signed in: ${address}`)
_signIn(socket, address) {
debug(`socketio signed in: ${address}`)
const newMailListener = () => {
debug(`${address} has new messages, sending notification`)
socket.emit('new emails')
}
const newMailListener = () => {
debug(`${address} has new messages, sending notification`)
socket.emit('new emails')
debug(`socket.emit('new emails') sent to ${address}`)
}
this.on(address, newMailListener)
this.on(address, newMailListener)
socket.on('disconnect', reason => {
debug(`client disconnect: ${address} (${reason})`)
this.removeListener(address, newMailListener)
})
}
socket.on('disconnect', reason => {
debug(`client disconnect: ${address} (${reason})`)
this.removeListener(address, newMailListener)
})
}
}
module.exports = ClientNotification
module.exports = ClientNotification