Skip to content

Commit

Permalink
Only allow changing IMAP indexer by account flush
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Oct 13, 2024
1 parent 6c8dd93 commit 2180b23
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
7 changes: 7 additions & 0 deletions lib/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,8 @@ class Account {
let error = Boom.boomify(new Error(message), { statusCode: 400 });
throw error;
}
} else if (accountData.imap && !accountData.imapIndexer) {
accountData.imapIndexer = (await settings.get('imapIndexer')) || 'full';
}

const runIndex = await this.call({
Expand Down Expand Up @@ -2062,6 +2064,7 @@ class Account {
});

let notifyFrom = data.notifyFrom && data.notifyFrom !== 'now' ? data.notifyFrom : new Date();
let imapIndexer = data.imapIndexer;

const dateKeyTdy = new Date().toISOString().substring(0, 10).replace(/-/g, '');
const dateKeyYdy = new Date(Date.now() - 24 * 3600 * 1000).toISOString().substring(0, 10).replace(/-/g, '');
Expand All @@ -2083,6 +2086,10 @@ class Account {
.del(tombstoneTdy)
.del(tombstoneYdy);

if (imapIndexer) {
pipeline = pipeline.hset(this.getAccountKey(), 'imapIndexer', imapIndexer);
}

if (data.syncFrom || data.syncFrom === null) {
pipeline = pipeline.hset(this.getAccountKey(), 'syncFrom', data.syncFrom ? data.syncFrom.toISOString() : 'null');
}
Expand Down
28 changes: 11 additions & 17 deletions lib/email-client/imap/mailbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const {
DEFAULT_FETCH_BATCH_SIZE,
MAILBOX_HASH
} = require('../../consts');
const { should } = require('chai');

const FETCH_BATCH_SIZE = Number(readEnvValue('EENGINE_FETCH_BATCH_SIZE') || config.service.fetchBatchSize) || DEFAULT_FETCH_BATCH_SIZE;

Expand Down Expand Up @@ -174,16 +175,6 @@ class Mailbox {
await op.hmset(this.getMailboxKey(), Object.fromEntries(list)).exec();
}

async getImapIndexer(skipCache) {
const imapIndexer = this.imapIndexer || (!skipCache && this._cachedImapIndexer) || (await settings.get('imapIndexer')) || 'full';

if (!this.imapIndexer && (skipCache || !this._cachedImapIndexer)) {
this._cachedImapIndexer = imapIndexer;
}

return imapIndexer;
}

/**
* Sets message entry object. Entries are ordered by `uid` property
* @param {Object} data
Expand Down Expand Up @@ -436,7 +427,6 @@ class Mailbox {
this.shouldRunPartialSyncAfterExists()
.then(shouldRun => {
if (shouldRun) {
this.logger.trace({ msg: 'Running partial sync' });
return this.partialSync();
}
return false;
Expand All @@ -447,10 +437,10 @@ class Mailbox {
}

async onExpunge(event) {
const imapIndexer = this.imapIndexer;
event.imapIndexer = imapIndexer;
this.logEvent('Untagged EXPUNGE', event);

const imapIndexer = await this.getImapIndexer();

if (imapIndexer !== 'full') {
// ignore as we can not compare this value against the index
return null;
Expand All @@ -473,10 +463,10 @@ class Mailbox {
}

async onFlags(event) {
const imapIndexer = this.imapIndexer;
event.imapIndexer = imapIndexer;
this.logEvent('Untagged FETCH', event);

const imapIndexer = await this.getImapIndexer();

if (imapIndexer !== 'full') {
// ignore as we can not compare this value against the index
return null;
Expand Down Expand Up @@ -1513,7 +1503,9 @@ class Mailbox {
}

async fullSync() {
const imapIndexer = await this.getImapIndexer(true);
const imapIndexer = this.imapIndexer;

this.logger.trace({ msg: 'Running full sync', imapIndexer });

switch (imapIndexer) {
case 'fast':
Expand All @@ -1525,7 +1517,9 @@ class Mailbox {
}

async partialSync(storedStatus) {
const imapIndexer = await this.getImapIndexer(true);
const imapIndexer = this.imapIndexer;

this.logger.trace({ msg: 'Running partial sync', imapIndexer });

switch (imapIndexer) {
case 'fast':
Expand Down
12 changes: 11 additions & 1 deletion lib/schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,17 @@ const accountSchemas = {
.description(
'An array of mailbox paths. If set, then EmailEngine opens additional IMAP connections against these paths to detect changes faster. NB! connection counts are usually highly limited.'
)
.label('SubconnectionPaths')
.label('SubconnectionPaths'),

imapIndexer: Joi.string()
.empty('')
.trim()
.allow(null)
.valid('full', 'fast')
.example('full')
.description(
'Sets the account-specific IMAP indexing method. Choose "full" to build a complete index that tracks deleted and updated emails, or "fast" to only detect newly received emails. Defaults to global setting.'
)
};

const googleProjectIdSchema = Joi.string().trim().allow('', false, null).max(256).example('project-name-425411').description('Google Cloud Project ID');
Expand Down
4 changes: 4 additions & 0 deletions workers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2604,6 +2604,8 @@ const init = async () => {
proxy: settingsSchema.proxyUrl,
smtpEhloName: settingsSchema.smtpEhloName,

imapIndexer: accountSchemas.imapIndexer,

imap: Joi.object(imapSchema).allow(false).description('IMAP configuration').label('ImapConfiguration'),

smtp: Joi.object(smtpSchema).allow(false).description('SMTP configuration').label('SmtpConfiguration'),
Expand Down Expand Up @@ -3170,6 +3172,7 @@ const init = async () => {
payload: Joi.object({
flush: Joi.boolean().truthy('Y', 'true', '1').falsy('N', 'false', 0).default(false).description('Only flush the account if true'),
notifyFrom: accountSchemas.notifyFrom.default('now'),
imapIndexer: accountSchemas.imapIndexer,
syncFrom: accountSchemas.syncFrom
}).label('RequestFlush')
},
Expand Down Expand Up @@ -3342,6 +3345,7 @@ const init = async () => {
'webhooks',
'proxy',
'smtpEhloName',
'imapIndexer',
'imap',
'smtp',
'oauth2',
Expand Down
2 changes: 1 addition & 1 deletion workers/imap.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class ConnectionHandler {
}

if (!accountObject.connection) {
let imapIndexer = typeof accountData.imap?.imapIndexer === 'string' && accountData.imap?.imapIndexer ? accountData.imap?.indexer : null;
let imapIndexer = typeof accountData.imapIndexer === 'string' && accountData.imapIndexer ? accountData.imapIndexer : 'full';

accountObject.connection = new IMAPClient(account, {
runIndex,
Expand Down

0 comments on commit 2180b23

Please sign in to comment.