import config from '../lib/config' class ManageSieve { constructor(login, authname, password) { const Telnet = require('telnet-client') this.login = login this.authname = authname this.password = password this.params = { host: config.sieve_server, port: config.sieve_port, shellPrompt: /\bOK/, timeout: 1500 } this.connection = new Telnet() this.sasl = [] this.ready = false } async connect(force = false) { let response, parsedResponse if (!this.ready || force) { await this.connection.connect(this.params) response = await this.connection.send('CAPABILITY', { waitfor: /\b(OK|NO)/ }) // console.debug(`ManageSieve.connect => ${response}`) parsedResponse = this.parseResponse(response) if (!Object.keys(parsedResponse).includes('OK')) { throw new Error(`Connection failed: ${parsedResponse['NO']}`) } this.ready = true if (parsedResponse['SASL']) { this.sasl = parsedResponse['SASL'].split(/ /) } } } async authenticate(force) { let buff, base64, response, parsedResponse await this.connect(force) buff = Buffer.from(`${this.login}\0${this.authname}\0${this.password}`) base64 = buff.toString('base64') response = await this.connection.send(`AUTHENTICATE "PLAIN" {${base64.length}+}\r\n${base64}`, { waitfor: /\b(OK|NO)/ }) // console.debug(`ManageSieve.authenticate => ${response}`) // console.log(`AUTHENTICATE "PLAIN" {${base64.length}+}\r\n${base64}`) parsedResponse = this.parseResponse(response) if (!Object.keys(parsedResponse).includes('OK')) { throw new Error(`Authentication failed: ${parsedResponse['NO']}`) } } async listScripts() { let response, parsedResponse await this.connect() response = await this.connection.send(`LISTSCRIPTS`, { waitfor: /\b(OK|NO)/ }) parsedResponse = this.parseResponse(response) // console.debug(`ManageSieve.listScripts => ${JSON.stringify(parsedResponse, undefined, 2)}`) if (!Object.keys(parsedResponse).includes('OK')) { throw new Error(`List scripts failed: ${parsedResponse['NO']}`) } return parsedResponse } async getScript(scriptname) { let response, parsedResponse, script = null await this.connect() response = await this.connection.send(`GETSCRIPT "${scriptname}"`, { waitfor: /\b(OK|NO)/ }) // console.debug(`ManageSieve.getScript(${scriptname}) => |${response}|`) const lengthMatch = response.match(/{([0-9]+)}\r?\n/) if (lengthMatch) { const scriptLength = lengthMatch[1] script = response.substr(lengthMatch[0].length, scriptLength) } else throw new Error(`Can't find length of Sieve script`) return script } parseResponse(str) { const re = new RegExp(/[^\s"]+|"([^"]*)"/gi) let parsed = {} for (let line of (str.split(/\r?\n/))) { if (line.length) { let rematch, key, value, i = 0 while ((rematch = re.exec(line))) { value = rematch[1] ? rematch[1] : rematch[0] if (key && i > 0) parsed[key] = value else key = value i++ } if (key && i == 1) { parsed[key] = null } } } // console.debug(`ManageSieve.parseResponse => ${JSON.stringify(parsed, undefined, 2)}`) return parsed } } export default ManageSieve