spamreport is using the new storage. see #675

This commit is contained in:
mic 2026-03-22 22:29:31 +01:00
parent b30da27c84
commit 55240868dd
3 changed files with 106 additions and 26 deletions

View file

@ -16,11 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { taStorage } from './mzta-storage.js';
export const taSpamReport = {
logger: console,
do_debug: false,
_data_prefix: 'mzta-spam-report-',
_processing_prefix: 'mzta-spam-processing-',
_max_reports: 100,
_storage: null,
_getStorage() {
if (!this._storage) this._storage = new taStorage(this.do_debug);
return this._storage;
},
async setProcessing(data_id) {
const key = this._processing_prefix + data_id;
@ -34,8 +43,7 @@ export const taSpamReport = {
},
async saveReportData(data, data_id) {
const key = this._data_prefix + data_id;
await browser.storage.session.set({ [key]: data });
await this._getStorage().writeSpam(data_id, data, true);
await browser.storage.session.remove(this._processing_prefix + data_id);
},
@ -51,47 +59,53 @@ export const taSpamReport = {
},
async loadReportData(data_id) {
const key = this._data_prefix + data_id;
let output = await browser.storage.session.get(key);
return output[key] || null;
let record = await this._getStorage().getRecord(data_id);
if (!record || !this._getStorage().hasField(record, 'spam')) return null;
let spam = record.spam;
return {
headerMessageId: data_id,
spamValue: spam.spamValue,
explanation: spam.explanation,
report_date: new Date(spam.ts),
subject: spam.subject,
from: spam.from,
message_date: spam.message_date,
moved: spam.moved,
SpamThreshold: spam.SpamThreshold,
};
},
async removeReportData(data_id) {
const key = this._data_prefix + data_id;
await browser.storage.session.remove(key);
await this._getStorage().deleteSpamField(data_id);
await browser.storage.session.remove(this._processing_prefix + data_id);
},
async getAllReportData() {
let allData = await browser.storage.session.get(null);
let reportData = {};
for (const [key, value] of Object.entries(allData)) {
if (key.startsWith(this._data_prefix)) {
reportData[key.replace(this._data_prefix, '')] = value;
}
}
return reportData;
return await this._getStorage().getAllSpamRecords();
},
async clearReportData() {
let allData = await browser.storage.session.get(null);
let keysToDelete = Object.keys(allData).filter(key => key.startsWith(this._data_prefix) || key.startsWith(this._processing_prefix));
let storage = this._getStorage();
let allSpam = await storage.getAllSpamRecords();
for (let messageId of Object.keys(allSpam)) {
await storage.deleteSpamField(messageId);
}
let allSession = await browser.storage.session.get(null);
let keysToDelete = Object.keys(allSession).filter(k => k.startsWith(this._processing_prefix));
for (let key of keysToDelete) {
await browser.storage.session.remove(key);
}
},
async truncReportData() {
let data = await this.getAllReportData();
let data = await this._getStorage().getAllSpamRecords();
let sortedData = this.sortReportsByDate(data);
let keys = Object.keys(sortedData);
if (keys.length > this._max_reports) {
let storage = this._getStorage();
for (let i = this._max_reports; i < keys.length; i++) {
await browser.storage.session.remove(this._data_prefix + keys[i]);
await storage.deleteSpamField(keys[i]);
}
}
},

View file

@ -72,11 +72,11 @@ export class taStorage {
/**
* Write the spam field for a given Message-ID.
* @param {string} messageId - The Message-ID header string.
* @param {number} score - Spam score (float 0-1).
* @param {string} reason - Textual motivation for the score.
* @param {object} report_data - The full spam report object with fields:
* spamValue, explanation, subject, from, message_date, moved, SpamThreshold.
* @param {boolean} [force=true] - If true, overwrite existing spam data.
*/
async writeSpam(messageId, score, reason, force = true) {
async writeSpam(messageId, report_data, force = true) {
try {
let key = this._buildKey(messageId);
let record = await this.getRecord(messageId) || { v: taStorage.SCHEMA_VERSION };
@ -84,7 +84,18 @@ export class taStorage {
return;
}
let now = Date.now();
record.spam = { score: score, reason: reason, ts: now };
record.spam = {
spamValue: report_data.spamValue,
explanation: report_data.explanation,
subject: report_data.subject,
from: report_data.from,
message_date: report_data.message_date instanceof Date
? report_data.message_date.toISOString()
: report_data.message_date,
moved: report_data.moved,
SpamThreshold: report_data.SpamThreshold,
ts: now,
};
record.ts = now;
await messenger.storage.local.set({ [key]: record });
} catch (e) {
@ -92,6 +103,60 @@ export class taStorage {
}
}
/**
* Get all records that contain a spam field.
* @returns {Promise<object>} Map of messageId -> spam data object (legacy shape).
*/
async getAllSpamRecords() {
try {
let all = await messenger.storage.local.get(null);
let result = {};
for (let [key, record] of Object.entries(all)) {
if (!key.startsWith(taStorage.STORAGE_KEY_PREFIX)) continue;
if (!this.hasField(record, 'spam')) continue;
let messageId = key.slice(taStorage.STORAGE_KEY_PREFIX.length);
let spam = record.spam;
result[messageId] = {
headerMessageId: messageId,
spamValue: spam.spamValue,
explanation: spam.explanation,
report_date: new Date(spam.ts),
subject: spam.subject,
from: spam.from,
message_date: spam.message_date,
moved: spam.moved,
SpamThreshold: spam.SpamThreshold,
};
}
return result;
} catch (e) {
this.taLog.error('getAllSpamRecords error: ' + e);
return {};
}
}
/**
* Delete only the spam field from a record.
* Deletes the entire record if no other data fields remain.
* @param {string} messageId - The Message-ID header string.
*/
async deleteSpamField(messageId) {
try {
let key = this._buildKey(messageId);
let record = await this.getRecord(messageId);
if (!record || !('spam' in record)) return;
delete record.spam;
const remainingFields = Object.keys(record).filter(k => k !== 'v' && k !== 'ts');
if (remainingFields.length === 0) {
await messenger.storage.local.remove(key);
} else {
await messenger.storage.local.set({ [key]: record });
}
} catch (e) {
this.taLog.error('deleteSpamField error: ' + e);
}
}
/**
* Write the summary field for a given Message-ID.
* @param {string} messageId - The Message-ID header string.

View file

@ -1043,6 +1043,7 @@ const newEmailListener = (folder, messagesList) => {
let messages = getMessages(messagesList);
taSpamReport.logger = taLog;
taSpamReport.do_debug = prefs_init.do_debug;
let add_tags_auto_enabled = prefs_init.add_tags && prefs_init.add_tags_auto;