summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Weipert <code@drogueronin.de>2021-06-22 14:49:43 +0200
committerDaniel Weipert <code@drogueronin.de>2021-06-22 14:49:43 +0200
commit128a4891b790ce23aee6a7e3743a55ecf6a2ca61 (patch)
tree6d349ac096aef3f8e5a11242c4bf662990337119
parentf6096a18016be63c719d2ce5a27d64363862b0fd (diff)
Working migrations with duplicate comparison
-rw-r--r--Readme.md8
-rw-r--r--app/imap.js38
-rw-r--r--app/src/pages/Home.vue16
-rw-r--r--app/src/store.js14
-rw-r--r--package.json5
-rw-r--r--test/test.js82
6 files changed, 146 insertions, 17 deletions
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 @@
<ul v-if="from.folders">
<Folders :folder="from.folders" />
</ul>
- <code>
- {{ from.folders }}
- </code>
<h1>TO</h1>
<ul v-if="to.folders">
<Folders :folder="to.folders" />
</ul>
- <code>
- {{ to.folders }}
- </code>
</div>
</template>
@@ -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;
+}
</style>
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());
+})();