From 128a4891b790ce23aee6a7e3743a55ecf6a2ca61 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Tue, 22 Jun 2021 14:49:43 +0200 Subject: Working migrations with duplicate comparison --- Readme.md | 8 +++++ app/imap.js | 38 +++++++++++++++++++++++ app/src/pages/Home.vue | 16 +++++----- app/src/store.js | 14 ++++----- package.json | 5 ++- test/test.js | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 test/test.js diff --git a/Readme.md b/Readme.md index 4b71317..3ee8f90 100644 --- a/Readme.md +++ b/Readme.md @@ -1 +1,9 @@ - https://busylog.net/telnet-imap-commands-note/ + +## Test + +``` +cd test/docker +docker-compose up -d +npm run test +``` diff --git a/app/imap.js b/app/imap.js index 1ac76a4..f2e8cc2 100644 --- a/app/imap.js +++ b/app/imap.js @@ -3,6 +3,7 @@ const { ImapFlow } = require('imapflow'); ipcMain.on('imap:listTree:from', listTreeFrom); ipcMain.on('imap:listTree:to', listTreeTo); +ipcMain.on('imap:migrate', migrate); async function connect (options) { const client = new ImapFlow({ @@ -32,3 +33,40 @@ async function listTreeTo (event, options) { event.reply('imap:listTree:to:reply', await client.listTree()); await client.logout(); } + +async function migrate (event, { from, to }) { + const fromClient = await connect(from); + const toClient = await connect(to); + + const fromFolders = (await fromClient.list()).filter((folder) => folder.subscribed); + for (const fromFolder of fromFolders) { + try { + await toClient.mailboxCreate(fromFolder.path); + } catch (e) {} + + const fromMailbox = await fromClient.getMailboxLock(fromFolder.path); + const toMailbox = await toClient.getMailboxLock(fromFolder.path); + try { + const toMsgsGenerator = await toClient.fetch('1:*', { flags: true, envelope: true, source: true }); + const toMsgs = []; + for await (const toMsg of toMsgsGenerator) { + toMsgs.push(toMsg); + } + const fromMsgsGenerator = await fromClient.fetch('1:*', { flags: true, envelope: true, source: true }); + + for await (const fromMsg of fromMsgsGenerator) { + if (toMsgs.some((toMsg) => Buffer.compare(toMsg.source, fromMsg.source) === 0)) { + continue; + } + + await toClient.append(fromFolder.path, fromMsg.source, Array.from(fromMsg.flags), fromMsg.envelope.date); + } + } finally { + fromMailbox.release(); + toMailbox.release(); + } + } + + await fromClient.logout(); + await toClient.logout(); +} diff --git a/app/src/pages/Home.vue b/app/src/pages/Home.vue index 2fe4030..bfe92bf 100644 --- a/app/src/pages/Home.vue +++ b/app/src/pages/Home.vue @@ -12,17 +12,11 @@ - - {{ from.folders }} -

TO

- - {{ to.folders }} - @@ -79,7 +73,10 @@ export default { }, async migrate () { - + this.$electron.ipcRenderer.send('imap:migrate', { + from: JSON.parse(JSON.stringify(this.from)), + to: JSON.parse(JSON.stringify(this.to)), + }); }, }, }; @@ -96,4 +93,9 @@ body { display: flex; justify-content: space-between; } + +ul { + padding-left: 1em; + list-style-type: dot; +} diff --git a/app/src/store.js b/app/src/store.js index db5a9fa..818689b 100644 --- a/app/src/store.js +++ b/app/src/store.js @@ -5,15 +5,15 @@ export default createStore({ return { from: { server: 'localhost', - port: '3143', - username: 'd@cool.de', - password: 'lolo11', + port: 3143, + username: 'from@example.org', + password: 'password', }, to: { - server: '', - port: '', - username: '', - password: '', + server: 'localhost', + port: 31432, + username: 'to@example.org', + password: 'password', }, }; }, diff --git a/package.json b/package.json index 964c484..c202375 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,9 @@ "main": "app/main.js", "scripts": { "start": "electron ./app/main.js", - "build": "webpack", - "watch": "npm run build -- --watch", + "watch": "webpack --watch", "lint": "eslint .", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node ./test/test.js" }, "author": "", "license": "ISC", diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..dad4b9f --- /dev/null +++ b/test/test.js @@ -0,0 +1,82 @@ +const { ImapFlow } = require('imapflow'); + +const clientFrom = new ImapFlow({ + host: 'localhost', + port: 3143, + auth: { + user: 'from@example.org', + pass: 'password', + }, +}); + +const clientTo = new ImapFlow({ + host: 'localhost', + port: 31432, + auth: { + user: 'to@example.org', + pass: 'password', + }, +}); + +(async () => { + await clientFrom.connect(); + await clientTo.connect(); + + const fromMailboxes = [ + 'From Test Parent.From Test Child', + 'From Test Parent.From Test Child 2.From Test Child Inner', + ]; + const toMailboxes = [ + 'To Test Parent.To Test Child', + 'To Test Parent.To Test Child 2.To Test Child Inner', + ]; + for (const mailbox of fromMailboxes) { + try { + await clientFrom.mailboxDelete(mailbox); + } catch (e) {} + try { + await clientTo.mailboxDelete(mailbox); + } catch (e) {} + + try { + await clientFrom.mailboxCreate(mailbox); + } catch (e) {} + } + for (const mailbox of toMailboxes) { + try { + await clientTo.mailboxDelete(mailbox); + } catch (e) {} + + try { + await clientTo.mailboxCreate(mailbox); + } catch (e) {} + } + + await clientFrom.append('INBOX', + 'From: test@example.org\r\n' + + 'To: from@example.org\r\n' + + 'Subject: FROM INBOX MESSAGE SUBJECT\r\n' + + '\r\n' + + 'FROM INBOX MESSAGE BODY', [], new Date()); + + await clientFrom.append('From Test Parent.From Test Child', + 'From: test@example.org\r\n' + + 'To: from@example.org\r\n' + + 'Subject: FROM TEST CHILD MESSAGE FLAGGED SUBJECT\r\n' + + '\r\n' + + 'FROM TEST CHILD MESSAGE FLAGGED BODY', ['\\FLAGGED'], new Date()); + + await clientFrom.append('From Test Parent.From Test Child', + 'From: test@example.org\r\n' + + 'To: from@example.org\r\n' + + 'Subject: FROM TEST CHILD MESSAGE DRAFT SUBJECT\r\n' + + '\r\n' + + 'FROM TEST CHILD MESSAGE DRAFT BODY', ['\\DRAFT'], new Date()); + + await clientFrom.append('From Test Parent.From Test Child 2.From Test Child Inner', + 'From: test@example.org\r\n' + + 'To: from@example.org\r\n' + + 'Subject: FROM TEST CHILD 2 INNER MESSAGE SEEN SUBJECT\r\n' + + '\r\n' + + 'FROM TEST CHILD 2 INNER MESSAGE SEEN BODY', ['\\SEEN'], new Date()); +})(); -- cgit v1.2.3