add all methods to imap
This commit is contained in:
parent
d902e8e183
commit
d030e5482a
@ -12,7 +12,7 @@ const server = net.createServer((socket) => {
|
|||||||
|
|
||||||
socket.on("data", (data) => {
|
socket.on("data", (data) => {
|
||||||
const line = data.toString().trim();
|
const line = data.toString().trim();
|
||||||
console.debug("IMAP data:", line);
|
console.debug("IMAP request:", line);
|
||||||
const splitted = line.split(/\s{1,}/g);
|
const splitted = line.split(/\s{1,}/g);
|
||||||
if (splitted.length < 2) return socket.write(". BAD unknown command\r\n");
|
if (splitted.length < 2) return socket.write(". BAD unknown command\r\n");
|
||||||
const [tag, command, ...args] = splitted;
|
const [tag, command, ...args] = splitted;
|
||||||
|
159
imap/logic.js
159
imap/logic.js
@ -5,10 +5,12 @@ class IMAPController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
out (answer) {
|
out (answer) {
|
||||||
|
console.debug("IMAP response:", answer);
|
||||||
this.socket.write(`${this.tag} ${answer}`);
|
this.socket.write(`${this.tag} ${answer}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
untaggedOut (answer) {
|
untaggedOut (answer) {
|
||||||
|
console.debug("IMAP response:", answer);
|
||||||
this.socket.write(answer);
|
this.socket.write(answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,24 +19,177 @@ class IMAPController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const messages = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
uid: 101,
|
||||||
|
flags: ["\\Seen"],
|
||||||
|
raw: `From: Example <ex@example.com>\r\nTo: You <you@example.com>\r\nSubject: Hello\r\n\r\nThis is a test email.`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const parseUidRange = (input) => {
|
||||||
|
if (input === '*') return messages.map(msg => msg.uid);
|
||||||
|
if (input.includes(':')) {
|
||||||
|
const [start, end] = input.split(':').map(Number);
|
||||||
|
return messages
|
||||||
|
.map(msg => msg.uid)
|
||||||
|
.filter(uid => uid >= start && uid <= (isNaN(end) ? Infinity : end));
|
||||||
|
}
|
||||||
|
return [Number(input)];
|
||||||
|
};
|
||||||
|
|
||||||
class Commands {
|
class Commands {
|
||||||
constructor (client) {
|
constructor (client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
// Required commands
|
||||||
|
|
||||||
async capability (args, controller) {
|
async capability (args, controller) {
|
||||||
/*if (args.length > 0)
|
/*if (args.length > 0)
|
||||||
return out();*/
|
return out();*/
|
||||||
controller.untaggedOut("* CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED\r\n");
|
controller.untaggedOut("* CAPABILITY IMAP4rev1 IDLE\r\n");
|
||||||
controller.out("OK CAPABILITY completed\r\n");
|
controller.out("OK CAPABILITY completed\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
async logout(args, controller) {
|
async logout (args, controller) {
|
||||||
controller.untaggedOut("* BYE Logging out\r\n");
|
controller.untaggedOut("* BYE Logging out\r\n");
|
||||||
controller.out("OK LOGOUT completed\r\n");
|
controller.out("OK LOGOUT completed\r\n");
|
||||||
|
|
||||||
controller.close();
|
controller.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async noop(args, controller) {
|
||||||
|
controller.out("OK NOOP completed\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(args, controller) {
|
||||||
|
//this.client.state = "authenticated";
|
||||||
|
controller.out("OK LOGIN completed\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mailposts
|
||||||
|
|
||||||
|
async list(args, controller) {
|
||||||
|
controller.untaggedOut(`* LIST (\\HasNoChildren) "." "INBOX"\r\n`);
|
||||||
|
controller.out("OK LIST completed\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async select(args, controller) {
|
||||||
|
const messageCount = messages.length;
|
||||||
|
|
||||||
|
controller.untaggedOut("* FLAGS (\\Seen \\Answered \\Flagged \\Deleted \\Draft)\r\n");
|
||||||
|
controller.untaggedOut(`* ${messageCount} EXISTS\r\n`);
|
||||||
|
controller.untaggedOut(`* ${messageCount} RECENT\r\n`);
|
||||||
|
controller.untaggedOut("* OK [UNSEEN 1] First unseen\r\n");
|
||||||
|
controller.untaggedOut("* OK [UIDVALIDITY 1] UIDs valid\r\n");
|
||||||
|
controller.untaggedOut(`* OK [UIDNEXT ${messageCount + 1}] Predicted next UID\r\n`);
|
||||||
|
controller.out("OK [READ-WRITE] SELECT completed\r\n");
|
||||||
|
|
||||||
|
//this.client.state = "selected";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mailpost's messages
|
||||||
|
|
||||||
|
async fetch(args, controller) {
|
||||||
|
if (!args || args.length < 2) {
|
||||||
|
return controller.out("BAD FETCH requires message sequence and data item\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const seq = args[0];
|
||||||
|
const item = args.slice(1).join(" ").toUpperCase();
|
||||||
|
|
||||||
|
if (seq !== "1") {
|
||||||
|
return controller.out("NO FETCH only supports message 1 for now\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.includes("BODY[]")) {
|
||||||
|
return controller.out("NO FETCH only supports BODY[] for now\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const msg = messages.find(m => m.id === 1);
|
||||||
|
if (!msg) {
|
||||||
|
return controller.out("NO Message not found\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = msg.raw;
|
||||||
|
controller.untaggedOut(`* 1 FETCH (BODY[] {${body.length}}\r\n${body}\r\n)\r\n`);
|
||||||
|
controller.out("OK FETCH completed\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async uid(args, controller) {
|
||||||
|
if (!args || args.length < 2) {
|
||||||
|
return controller.out("BAD UID requires subcommand and arguments\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const subCommand = args[0].toUpperCase();
|
||||||
|
|
||||||
|
if (subCommand === "FETCH") {
|
||||||
|
const uidArg = args[1];
|
||||||
|
const fetchFields = args.slice(2).join(" ").toUpperCase();
|
||||||
|
|
||||||
|
const msg = messages.find(m => m.uid === Number(uidArg));
|
||||||
|
if (!msg) {
|
||||||
|
return controller.out("NO No such message\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const headersOnly = msg.raw.split("\r\n\r\n")[0] + "\r\n";
|
||||||
|
const headerLength = headersOnly.length;
|
||||||
|
const bodySize = msg.raw.length;
|
||||||
|
const flags = msg.flags.join(" ");
|
||||||
|
|
||||||
|
controller.untaggedOut(
|
||||||
|
`* ${msg.id} FETCH (` +
|
||||||
|
`UID ${msg.uid} ` +
|
||||||
|
`RFC822.SIZE ${bodySize} ` +
|
||||||
|
`FLAGS (${flags}) ` +
|
||||||
|
`BODY[HEADER.FIELDS (From To Subject Date Message-ID)] {${headerLength}}\r\n` +
|
||||||
|
headersOnly +
|
||||||
|
")\r\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
return controller.out("OK UID FETCH completed\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.out("BAD UID subcommand not supported\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async store(args, controller) {
|
||||||
|
controller.out("OK STORE not yet implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async expunge(args, controller) {
|
||||||
|
controller.out("OK EXPUNGE not yet implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async copy(args, controller) {
|
||||||
|
controller.out("OK COPY not yet implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async close(args, controller) {
|
||||||
|
controller.out("OK CLOSE not yet implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async search(args, controller) {
|
||||||
|
controller.out("* SEARCH\r\n");
|
||||||
|
controller.out("OK SEARCH completed\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async examine(args, controller) {
|
||||||
|
controller.out("OK EXAMINE not yet implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
async append(args, controller) {
|
||||||
|
controller.out("OK APPEND not yet implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push-notifications (IDLE)
|
||||||
|
|
||||||
|
async idle(args, controller) {
|
||||||
|
controller.untaggedOut("+ idling\r\n");
|
||||||
|
controller.out("OK IDLE not yet implemented\r\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
|
@ -51,6 +51,7 @@ class POP3 extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
const pop3 = new POP3();
|
const pop3 = new POP3();
|
||||||
pop3.init().then(() => {
|
pop3.init().then(() => {
|
||||||
let interval = setTimeout(async () => {
|
let interval = setTimeout(async () => {
|
||||||
@ -61,6 +62,7 @@ pop3.init().then(() => {
|
|||||||
//console.log(str);
|
//console.log(str);
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
imap.listen(
|
imap.listen(
|
||||||
global.config["imap-config"].port ?? 143,
|
global.config["imap-config"].port ?? 143,
|
||||||
|
Loading…
Reference in New Issue
Block a user