Refactor email purge time configuration and usage to be more precise.
- New purgeTIme now allows to configure a purge to be every X minutes, hours or days. - Also remove a bit more trust by pulling footer deletion time from config. - TODO: implement 'convertUp' function, converting numbers up to the biggest possible value where `i > 2 (so 48hrs still works as per slogan and domain)`. I.e. 72hrs = 3 days, 360minutes = 6hrs, 1440minutes to 24hrs Co-authored-by: Johannes Bülow <kontakt@jmbit.de>pull/16/head
parent
d66d76c9f9
commit
71fd513bc0
|
@ -1,7 +1,11 @@
|
|||
const config = {
|
||||
email: {
|
||||
domains: process.env.EMAIL_DOMAINS,
|
||||
deleteMailsOlderThanDays: process.env.EMAIL_DELETE_MAILS_OLDER_THAN_DAYS || 2
|
||||
purgeTime: process.env.PURGE_TIME || {
|
||||
time: 48,
|
||||
unit: 'hours', // minutes, hours, days
|
||||
convert: true, // Convert to highest sensible unit
|
||||
}
|
||||
},
|
||||
imap: {
|
||||
user: process.env.IMAP_USER,
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
const config = require('./config')
|
||||
const moment = require('moment')
|
||||
|
||||
class Helper {
|
||||
|
||||
/**
|
||||
* Normalize our config into a proper timestamp, so we know what emails to purge
|
||||
* @returns {Date}
|
||||
*/
|
||||
purgeTimeStamp() {
|
||||
return moment()
|
||||
.subtract(config.email.purgeTime.time, config.email.purgeTime.unit)
|
||||
.toDate()
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if time difference between now and purgeTimeStamp is more than one day
|
||||
* @param {Date} now
|
||||
* @param {Date} past
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
moreThanOneDay(now, past) {
|
||||
const DAY_IN_MS = 24 * 60 * 60 * 1000;
|
||||
if((now - past) / DAY_IN_MS >= 1){
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert time to highest possible unit where i > 2
|
||||
* @returns {Date}
|
||||
*/
|
||||
convertUp(time, unit) {
|
||||
// TODO: Implement
|
||||
return time +` ${unit}`
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Helper
|
|
@ -8,7 +8,8 @@ const debug = require('debug')('48hr-email:imap')
|
|||
const _ = require('lodash')
|
||||
const moment = require('moment')
|
||||
const Mail = require('../domain/mail')
|
||||
|
||||
const Helper = require('./helper')
|
||||
const helper = new(Helper)
|
||||
|
||||
// Just adding some missing functions to imap-simple... :-)
|
||||
|
||||
|
@ -199,22 +200,30 @@ class ImapService extends EventEmitter {
|
|||
* @param {Date} deleteMailsBefore delete mails before this date instance
|
||||
*/
|
||||
async deleteOldMails(deleteMailsBefore) {
|
||||
let uids = await this._searchWithoutFetch([
|
||||
['!DELETED'],
|
||||
['BEFORE', deleteMailsBefore]
|
||||
])
|
||||
let uids = []
|
||||
if (helper.moreThanOneDay(moment(), deleteMailsBefore)) {
|
||||
//fetch mails from date -1day (calculated in MS) to avoid wasting resources
|
||||
deleteMailsBefore = deleteMailsBefore - 24 * 60 * 60 * 1000
|
||||
uids = await this._searchWithoutFetch([
|
||||
['!DELETED'],
|
||||
['BEFORE', deleteMailsBefore]
|
||||
])
|
||||
} else {
|
||||
uids = await this._searchWithoutFetch([
|
||||
['!DELETED']
|
||||
])
|
||||
}
|
||||
|
||||
if (uids.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const DeleteOlderThan = moment()
|
||||
.subtract(this.config.email.deleteMailsOlderThanDays, 'days')
|
||||
.toDate()
|
||||
const DeleteOlderThan = helper.purgeTimeStamp()
|
||||
|
||||
const uidsWithHeaders = await this._getMailHeaders(uids)
|
||||
uidsWithHeaders.forEach(mail => {
|
||||
if (mail['attributes'].date > DeleteOlderThan || this.config.http.examples.uids.includes(parseInt(mail['attributes'].id))) {
|
||||
uids.filter(uid => uid !== mail['attributes'].uid)
|
||||
uids = uids.filter(uid => uid !== mail['attributes'].uid)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ const debug = require('debug')('48hr-email:imap-manager')
|
|||
const mem = require('mem')
|
||||
const moment = require('moment')
|
||||
const ImapService = require('./imap-service')
|
||||
const Helper = require('./helper')
|
||||
const helper = new(Helper)
|
||||
|
||||
|
||||
class MailProcessingService extends EventEmitter {
|
||||
constructor(mailRepository, imapService, clientNotification, config) {
|
||||
|
@ -71,15 +74,7 @@ class MailProcessingService extends EventEmitter {
|
|||
|
||||
async _deleteOldMails() {
|
||||
try {
|
||||
await this.imapService.deleteOldMails(
|
||||
moment()
|
||||
// Because of how we have to handle the times (IMAP isnt time-aware), we need to subtract one day
|
||||
// to get all mails in their last few hours before technical purge
|
||||
//
|
||||
// This is a bit of a hack, but it works. See imap-service.js#deleteOldMails (L211-227) for more info
|
||||
.subtract(this.config.email.deleteMailsOlderThanDays - 1, 'days')
|
||||
.toDate()
|
||||
)
|
||||
await this.imapService.deleteOldMails(helper.purgeTimeStamp())
|
||||
} catch (error) {
|
||||
console.log('can not delete old messages', error)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,12 @@ const express = require('express')
|
|||
const router = new express.Router()
|
||||
const {param} = require('express-validator')
|
||||
const config = require('../../../application/config')
|
||||
const Helper = require('../../../application/helper')
|
||||
const helper = new(Helper)
|
||||
|
||||
const purgeTime = config.email.purgeTime.convert ? helper.convertUp(config.email.purgeTime.time, config.email.purgeTime.unit)
|
||||
: config.email.purgeTime.time +` ${config.email.purgeTime.unit}`;
|
||||
|
||||
const sanitizeAddress = param('address').customSanitizer(
|
||||
(value, {req}) => {
|
||||
return req.params.address
|
||||
|
@ -15,6 +21,7 @@ router.get('^/:address([^@/]+@[^@/]+)', sanitizeAddress, (req, res, _next) => {
|
|||
const mailProcessingService = req.app.get('mailProcessingService')
|
||||
res.render('inbox', {
|
||||
title: `${config.http.branding[0]} | ` + req.params.address,
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
mailSummaries: mailProcessingService.getMailSummaries(req.params.address),
|
||||
branding: config.http.branding,
|
||||
|
@ -41,6 +48,7 @@ router.get(
|
|||
res.set('Cache-Control', 'private, max-age=600')
|
||||
res.render('mail', {
|
||||
title: mail.subject + " | " + req.params.address,
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
mail,
|
||||
uid: req.params.uid,
|
||||
|
@ -50,6 +58,7 @@ router.get(
|
|||
res.render(
|
||||
'error',
|
||||
{
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
message: 'This mail could not be found. It either does not exist or has been deleted from our servers!',
|
||||
branding: config.http.branding
|
||||
|
@ -124,6 +133,7 @@ router.get(
|
|||
res.render(
|
||||
'error',
|
||||
{
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
message: 'This attachment could not be found. It either does not exist or has been deleted from our servers!',
|
||||
branding: config.http.branding,
|
||||
|
@ -163,6 +173,7 @@ router.get(
|
|||
res.render(
|
||||
'error',
|
||||
{
|
||||
purgeTime: purgeTime,
|
||||
address: req.params.address,
|
||||
message: 'This mail could not be found. It either does not exist or has been deleted from our servers!',
|
||||
branding: config.http.branding,
|
||||
|
|
|
@ -4,11 +4,17 @@ const router = new express.Router()
|
|||
const randomWord = require('random-word')
|
||||
const {check, validationResult} = require('express-validator')
|
||||
const config = require('../../../application/config')
|
||||
const Helper = require('../../../application/helper')
|
||||
const helper = new(Helper)
|
||||
|
||||
const purgeTime = config.email.purgeTime.convert ? helper.convertUp(config.email.purgeTime.time, config.email.purgeTime.unit)
|
||||
: config.email.purgeTime.time +` ${config.email.purgeTime.unit}`;
|
||||
|
||||
router.get('/', (req, res, _next) => {
|
||||
res.render('login', {
|
||||
title: `${config.http.branding[0]} | Your temporary Inbox`,
|
||||
username: randomWord(),
|
||||
purgeTime: purgeTime,
|
||||
domains: config.email.domains,
|
||||
branding: config.http.branding,
|
||||
})
|
||||
|
@ -39,6 +45,7 @@ router.post(
|
|||
return res.render('login', {
|
||||
userInputError: true,
|
||||
title: `${config.http.branding[0]} | Your temporary Inbox`,
|
||||
purgeTime: purgeTime,
|
||||
username: randomWord(),
|
||||
branding: config.http.branding,
|
||||
})
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
{% block footer %}
|
||||
<section class="container footer">
|
||||
<hr>
|
||||
<h4>{{ branding[0] }} offered by <a href="{{ branding[2] }}" style="text-decoration:underline" target="_blank">{{ branding[1] }}</a> | All Emails will be deleted after 48hrs | This project is <a href="https://github.com/crazyco-xyz/48hr.email" style="text-decoration:underline" target="_blank">open-source ♥</a></h4>
|
||||
<h4>{{ branding[0] }} offered by <a href="{{ branding[2] }}" style="text-decoration:underline" target="_blank">{{ branding[1] }}</a> | All Emails will be deleted after {{ purgeTime }} | This project is <a href="https://github.com/crazyco-xyz/48hr.email" style="text-decoration:underline" target="_blank">open-source ♥</a></h4>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
|
|
Loading…
Reference in New Issue