diff options
author | Ted Trask <ttrask01@yahoo.com> | 2008-08-29 17:48:19 +0000 |
---|---|---|
committer | Ted Trask <ttrask01@yahoo.com> | 2008-08-29 17:48:19 +0000 |
commit | 7675a3125618bad993398d89e2ef91eb238c8bc3 (patch) | |
tree | 3ca00a9c5c7b43b9b4a5664a84cdc18a30640838 /fetchmail-model.lua | |
parent | 0441e224f891306f238eac938692a0088eda1e43 (diff) | |
download | acf-fetchmail-7675a3125618bad993398d89e2ef91eb238c8bc3.tar.bz2 acf-fetchmail-7675a3125618bad993398d89e2ef91eb238c8bc3.tar.xz |
Added config to fetchmail to configure globals and multiple entries. Also added ability to run once and test. Still need support for ETRN and SSL.
git-svn-id: svn://svn.alpinelinux.org/acf/fetchmail/trunk@1437 ab2d0c66-481e-0410-8bed-d214d4d58bed
Diffstat (limited to 'fetchmail-model.lua')
-rw-r--r-- | fetchmail-model.lua | 657 |
1 files changed, 449 insertions, 208 deletions
diff --git a/fetchmail-model.lua b/fetchmail-model.lua index d619f0e..8c3fd84 100644 --- a/fetchmail-model.lua +++ b/fetchmail-model.lua @@ -2,186 +2,304 @@ module(..., package.seeall) -- Load libraries require("modelfunctions") +require("posix") require("fs") +require("getopts") +require("validator") -- Set variables local packagename = "fetchmail" local processname = "fetchmail" -local configfile = "/root/.fetchmailrc" -local config = {} +local configfile = "/etc/fetchmailrc" +local confdfile = "/etc/conf.d/fetchmail" +local config + +local methods = {"pop3","imap","pop3domain", } -- ################################################################################ -- LOCAL FUNCTIONS -local function getloglevels() - local loglevels = {} - for i=1,8 do - table.insert(loglevels,i) - end - return loglevels -end - -local function getmethods() - local methods = {"pop3","imap","pop3domain", } - return methods -end - -local function getmailboxes(t) - local objects = cfe({}) - objects.label = "Mailbox " .. tostring(t["RBOX"]) - objects.method = cfe({ - name="method", - label = "Method", - type = "select", - value = t["METHOD"], - option = getmethods(), - }) - objects.disabled = cfe({ - name="disabled", - type="checkbox", - label = "Disabled", - checked = t["DISABLED"], - }) - objects.remotehost = cfe({ - name="remotehost", - label = "RemoteHost", - value = t["RHOST"], - }) - objects.remotemailbox = cfe({ - name="remotemailbox", - label = "Mailbox", - value = t["RBOX"], - }) - objects.remotepassword = cfe({ - name="remotepassword", - label = "Password", - type = "passwd", - value = t["PASSWD"], - }) - objects.localhost = cfe({ - name="localhost", - label = "LocalHost", - value = t["LHOST"], - }) - objects.localmailbox = cfe({ - name="localmailbox", - label = "LocalMailbox", - value = t["LBOX"], - }) - objects.localdomain = cfe({ - name="localdomain", - label = "LocalDomain", - value = t["DOMAIN"], - }) - return objects -end - -local function read_config() ---[[ -imap/pop3 lines are: -1 2 3 4 5 6 7 8 9 10 -poll <host> protocol <proto> no dns username <uname> password <passwd> -11 12 13 14 15 16 17 -is <localmailbox> smtphost <desthost> no rewrite fetchall - -pop3domain lines are: -1 2 3 4 5 6 7 8 9 10 11 12 -poll <host> localdomainst <domain> protocol pop3 no dns username <uname> password <passwd> -13 14 15 16 17 18 19 20 21 22 -to * here smtphost <desthost> smtpaddress <domain> no rewrite fetchall - -etrn is: -1 2 3 4 5 6 -pool <host> protocol etrn smtpdomain <mydomain> ---]] - local mailboxes = {} - local configcontent_postmaster = {} - local configcontent_etrn = {} - local path = configfile - local valid = nil - configcontenttable = fs.read_file_as_array(path) or {} - for k,v in pairs(configcontenttable) do - if (string.match(v, "^%s*#Begin Fetchmail")) then valid=1 end - if (valid) then - -- - local DISABLED = string.match(v, "^%s*(#)") - - -- Set parameters for POP3 or IMAP - local val = {RHOST=2, CHECK=9 ,METHOD=4, RBOX=8, PASSWD=10, LBOX=12, LHOST=14} - local configcontent = {} - configcontent[k] = {} - configcontent[k]["DISABLED"] = DISABLED - for kk,vv in pairs(val) do - configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) - end - -- Remove quotes from passwords - if (configcontent[k]["PASSWD"]) then - configcontent[k]["PASSWD"] = string.match(configcontent[k]["PASSWD"], "^\"(.-)\"") - end - -- Check if row is valid config - if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "password") then - table.insert(mailboxes,getmailboxes(configcontent[k])) - end - - -- Set parameters for POP3domain - local val = {RHOST=2, METHOD=6, RBOX=10, CHECK=11, PASSWD=12, LHOST=17, DOMAIN=19,} - local configcontent = {} - configcontent[k] = {} - configcontent[k]["DISABLED"] = DISABLED - for kk,vv in pairs(val) do - configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) - end - -- Display this config as Method=pop3domain (as the current options in the view) - configcontent[k]["METHOD"] = "pop3domain" - -- Remove quotes from passwords - if (configcontent[k]["PASSWD"]) then - configcontent[k]["PASSWD"] = string.match(configcontent[k]["PASSWD"], "^\"(.-)\"") - end - -- Check if row is valid config - if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "password") then - table.insert(mailboxes,getmailboxes(configcontent[k])) - end - - -- Set parameters for etrn - local val = {ETRNSMTPHOST=2, CHECK=4, ETRNDOMAIN=6} - local configcontent = {} - configcontent[k] = {} - configcontent[k]["DISABLED"] = DISABLED - for kk,vv in pairs(val) do - configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) - end - -- Check if row is valid config - if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "etrn") then - configcontent_etrn=configcontent[k] - end - - -- Set parameters for postmaster - local val = {CHECK=2, POSTMASTER=3} - local configcontent = {} - configcontent[k] = {} - configcontent[k]["DISABLED"] = DISABLED - for kk,vv in pairs(val) do - configcontent[k][kk] = tostring(string.match(v,"^%s*" .. string.rep("%S*%s*",vv-1) .. "(%S*)%s*")) - end - -- Check if row is valid config - if (configcontent[k]["CHECK"]) and (string.lower(configcontent[k]["CHECK"]) == "postmaster") then - configcontent_postmaster=configcontent[k] - end - - end - if (string.match(v, "^%s*#End Fetchmail")) then valid=nil end - end - -- Create one empty record so that user can add settings - table.insert(mailboxes,getmailboxes({})) - return mailboxes,configcontent_postmaster,configcontent_etrn +local function parseconfigfile(file) + file = file or "" + local retval = {} + local linenum=0 + for line in string.gmatch(file, "([^\n]*)\n?") do + linenum=linenum+1 + if not string.match(line, "^%s*$") and not string.match(line, "^%s*#") then + table.insert(retval, {linenum=linenum}) + -- Iterate through each word, being careful about quoted strings and comments + local offset = 1 + while string.find(line, "%S+", offset) do + local word = string.match(line, "%S+", offset) + local endword = select(2, string.find(line, "%S+", offset)) + if string.find(word, "^#") then + break + elseif string.find(word, "^\"") then + endword = select(2, string.find(line, "\"[^\"]*\"", offset)) + word = string.sub(line, string.find(line, "\"", offset), endword) + end + table.insert(retval[#retval], word) + offset = endword + 1 + end + end + end + return retval +end + +local function findentryline(entryname) + if entryname and entryname ~= "" then + config = config or parseconfigfile(fs.read_file(configfile)) + for i,entry in ipairs(config or {}) do + if (entry[1] == "server" or entry[1] == "poll" or entry[1] == "skip") and entry[2] == entryname then + return entry + end + end + end + return nil +end + +local function writeentryline(entrystruct, entryline) + if not entrystruct and not entryline then + return + end + + -- If there is a structure, create the entryline array + if entrystruct then + entryline = entryline or {} + if entrystruct.value.enabled.value then + entryline[1] = "poll" + else + entryline[1] = "skip" + end + entryline[2] = entrystruct.value.remotehost.value + local reverseentry = {} + for i,word in ipairs(entryline) do reverseentry[word] = i end + -- server options must come before user options, so add user option to end + -- and add server options just after remotehost (3) + -- start with the user options so we can add to the end and not mess up reverseentry + -- this means that we do method last + if reverseentry["user"] or reverseentry["username"] then + entryline[(reverseentry["user"] or reverseentry["username"])+1] = entrystruct.value.remotemailbox.value + else + entryline[#entryline+1] = "username" + entryline[#entryline+1] = entrystruct.value.remotemailbox.value + end + if reverseentry["pass"] or reverseentry["password"] then + entryline[(reverseentry["pass"] or reverseentry["password"])+1] = '"'..entrystruct.value.remotepassword.value..'"' + else + entryline[#entryline+1] = "password" + entryline[#entryline+1] = '"'..entrystruct.value.remotepassword.value..'"' + end + if reverseentry["smtphost"] then + entryline[reverseentry["smtphost"]+1] = entrystruct.value.localhost.value + else + entryline[#entryline+1] = "smtphost" + entryline[#entryline+1] = entrystruct.value.localhost.value + end + -- add in some user options + if not reverseentry["rewrite"] then + entryline[#entryline+1] = "no" + entryline[#entryline+1] = "rewrite" + end + if not reverseentry["fetchall"] then + entryline[#entryline+1] = "fetchall" + end + -- now handle the method, localmailbox, and localdomain + if entrystruct.value.method.value == "pop3domain" then + if reverseentry["to"] then + entryline[reverseentry["to"]+1] = "*" + else + entryline[#entryline+1] = "to" + entryline[#entryline+1] = "*" + end + if reverseentry["smtpaddress"] then + entryline[reverseentry["smtpaddress"]+1] = entrystruct.value.localdomain.value + else + entryline[#entryline+1] = "smtpaddress" + entryline[#entryline+1] = entrystruct.value.localdomain.value + end + if reverseentry["is"] then + -- THIS MESSES UP reverseentry FOR THE USER OPTIONS + table.remove(entryline, reverseentry["is"]) + table.remove(entryline, reverseentry["is"]) + end + if reverseentry["proto"] or reverseentry["protocol"] then + entryline[(reverseentry["proto"] or reverseentry["protocol"])+1] = "pop3" + else + -- THIS MESSES UP reverseentry FOR EVERYTHING + table.insert(entryline, 3, "pop3") + table.insert(entryline, 3, "protocol") + -- FIX reverseentry + reverseentry = {} + for i,word in ipairs(entryline) do reverseentry[word] = i end + end + if reverseentry["local"] or reverseentry["localdomains"] then + entryline[(reverseentry["local"] or reverseentry["localdomains"])+1] = entrystruct.value.localdomain.value + else + -- THIS MESSES UP reverseentry FOR EVERYTHING + table.insert(entryline, 3, entrystruct.value.localdomain.value) + table.insert(entryline, 3, "localdomains") + end + if not reverseentry["dns"] then + -- THIS MESSES UP reverseentry FOR EVERYTHING + table.insert(entryline, 3, "dns") + table.insert(entryline, 3, "no") + end + else + if reverseentry["is"] then + entryline[reverseentry["is"]+1] = entrystruct.value.localmailbox.value + else + entryline[#entryline+1] = "is" + entryline[#entryline+1] = entrystruct.value.localmailbox.value + end + if reverseentry["to"] then + -- THIS MESSES UP reverseentry FOR THE USER OPTIONS + table.remove(entryline, reverseentry["to"]) + table.remove(entryline, reverseentry["to"]) + -- FIX reverseentry + reverseentry = {} + for i,word in ipairs(entryline) do reverseentry[word] = i end + end + if reverseentry["smtpaddress"] then + -- THIS MESSES UP reverseentry FOR THE USER OPTIONS + table.remove(entryline, reverseentry["smtpaddress"]) + table.remove(entryline, reverseentry["smtpaddress"]) + end + if reverseentry["proto"] or reverseentry["protocol"] then + entryline[(reverseentry["proto"] or reverseentry["protocol"])+1] = entrystruct.value.method.value + else + -- THIS MESSES UP reverseentry FOR EVERYTHING + table.insert(entryline, 3, entrystruct.value.method.value) + table.insert(entryline, 3, "protocol") + -- FIX reverseentry + reverseentry = {} + for i,word in ipairs(entryline) do reverseentry[word] = i end + end + if reverseentry["local"] or reverseentry["localdomains"] then + -- THIS MESSES UP reverseentry FOR EVERYTHING + table.remove(entryline, (reverseentry["local"] or reverseentry["localdomains"])) + table.remove(entryline, (reverseentry["local"] or reverseentry["localdomains"])) + end + if not reverseentry["dns"] then + -- THIS MESSES UP reverseentry FOR EVERYTHING + table.insert(entryline, 3, "dns") + table.insert(entryline, 3, "no") + end + end + + -- remove here and there + for i=#entryline,1,-1 do + if entryline[i] == "here" or entryline[i] == "there" then + table.remove(entryline, i) + end + end + end + + local file = fs.read_file(configfile) + local lines = {file} + + if entryline and entryline.linenum then + -- Split the file to remove the line + local startchar, endchar = string.match(file, string.rep("[^\n]*\n", entryline.linenum-1) .. "()[^\n]*\n()") + if startchar and endchar then + lines[1] = string.sub(file, 1, startchar-1) + lines[2] = string.sub(file, endchar, -1) + end + end + if entryline and entrystruct then + table.insert(lines, 2, table.concat(entryline," ").."\n") + end + + fs.write_file(configfile, string.gsub(table.concat(lines), "\n+$", "")) + posix.chmod(configfile, "rwx--x---") + config = nil +end + +local function validateentry(entry) + local success = true + success = modelfunctions.validateselect(entry.value.method) and success + if entry.value.remotehost.value == "" then + entry.value.remotehost.errtxt = "Invalid entry - cannot be blank" + success = false + elseif string.find(entry.value.remotehost.value, "[^%w.-]") then + entry.value.remotehost.errtxt = "Invalid entry - may only contain alphanumeric, '.', or '-'" + success = false + end + if entry.value.remotemailbox.value == "" then + entry.value.remotemailbox.errtxt = "Invalid entry - cannot be blank" + success = false + elseif string.find(entry.value.remotemailbox.value, "[^%w.-_@]") then + entry.value.remotemailbox.errtxt = "Invalid entry" + success = false + end + if entry.value.remotepassword.value == "" then + entry.value.remotepassword.errtxt = "Invalid entry - cannot be blank" + success = false + elseif string.find(entry.value.remotepassword.value, "%s") then + entry.value.remotepassword.errtxt = "Invalid entry - cannot contain whitespace" + success = false + end + if entry.value.localhost.value == "" then + entry.value.localhost.errtxt = "Invalid entry - cannot be blank" + success = false + elseif string.find(entry.value.localhost.value, "[^%w.-]") then + entry.value.localhost.errtxt = "Invalid entry - may only contain alphanumeric, '.', or '-'" + success = false + end + if entry.value.method.value == "pop3domain" and entry.value.localmailbox.value ~= "" then + entry.value.localmailbox.errtxt = "Cannot define local mailbox for pop3domain method" + success = false + elseif entry.value.method.value ~= "pop3domain" and entry.value.localmailbox.value == "" then + entry.value.localmailbox.errtxt = "Invalid entry - cannot be blank" + success = false + elseif string.find(entry.value.localmailbox.value, "[^%w.-_@]") then + entry.value.localmailbox.errtxt = "Invalid entry" + success = false + end + if entry.value.method.value ~= "pop3domain" and entry.value.localdomain.value ~= "" then + entry.value.localdomain.errtxt = "Cannot define local domain unless pop3domain method" + success = false + elseif entry.value.method.value == "pop3domain" and entry.value.localdomain.value == "" then + entry.value.localdomain.errtxt = "Invalid entry - cannot be blank" + success = false + elseif string.find(entry.value.localdomain.value, "[^%w.-]") then + entry.value.localdomain.errtxt = "Invalid entry - may only contain alphanumeric, '.', or '-'" + success = false + end + + return success, entry +end + +local function validateconfig(conf) + local success = true + if not validator.is_integer(conf.value.interval.value) then + conf.value.interval.errtxt = "Invalid entry - must be an integer number" + success = false + end + if string.find(conf.value.postmaster.value, "[^%w%.%-_@]") then + conf.value.postmaster.errtxt = "Invalid entry" + success = false + end + return success, conf end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) - return modelfunctions.startstop_service(processname, action) + local cmd + if action:lower() == "run" then + cmd = "/usr/bin/fetchmail -d0 -v 2>&1" + elseif action:lower() == "test" then + cmd = "/usr/bin/fetchmail -d0 -v -k 2>&1" + else + return modelfunctions.startstop_service(processname, action) + end + local f = io.popen(cmd) + cmdresult = f:read("*a") + f:close() + return cfe({ value=cmdresult, label="Start/Stop result" }) end function getstatus() @@ -196,52 +314,175 @@ end function update_filecontent(filedetails) filedetails.value.filename.value = configfile -- FIXME - validation - return modelfunctions.setfiledetails(filedetails) + local retvel = modelfunctions.setfiledetails(filedetails) + posix.chmod(configfile, "rwx--x---") + config = nil + return retval end function getconfig() - local config = {} - local mailboxes,configcontent_postmaster,configcontent_etrn = read_config() - if not (fs.is_file(configfile)) then - config["configfile"] = "Config file '".. configfile .. "' is missing!" - end - - config["debug"] = cfe({ - name="debug", - label = "Debug info", - type = "longtext", - value = configcontent, - }) - - -- Next section selects which configurations we should show to the user - config["freq"] = cfe({ - name="freq", - label = "Check mail once every", - type = "select", - value = "123", - option = {"15min", "hour","day",}, - }) - config["mailboxes"] = cfe({ - name="mailboxes", - label = "Mailboxes", - value = mailboxes, - }) - config["postmaster"] = cfe({ - name="postmaster", - label = "Postmaster", - value = configcontent_postmaster["POSTMASTER"], - }) - config["etrnremote"] = cfe({ - name="etrnremote", - label = "Remote server", - value = configcontent_etrn["ETRNSMTPHOST"], - }) - config["etrnquedomain"] = cfe({ - name="etrnquedomain", - label = "Queued domain", - value = configcontent_etrn["ETRNDOMAIN"], - }) - - return config + local interval = cfe({ value=60, label="Polling Interval", descr="Interval in seconds" }) + local postmaster = cfe({ label="Postmaster", descr="If defined, undeliverable mail is sent to this account, otherwise it is discarded" }) + local bounceerrors = cfe({ type="boolean", value=true, label="Bounce Errors", descr="Bounce errors back to the sender or send them to the postmaster" }) + + config = config or parseconfigfile(fs.read_file(configfile)) + for i,entry in ipairs(config or {}) do + if entry[2] == "postmaster" and entry[1] == "set" then + postmaster.value = entry[3] or "" + elseif entry[3] == "bouncemail" and entry[2] == "no" and entry[1] == "set" then + bounceerrors.value = false + end + end + + local confd = getopts.getoptsfromfile(confdfile, "", "polling_period") + if confd then + interval.value = confd + end + + return cfe({ type="group", value={interval=interval, postmaster=postmaster, bounceerrors=bounceerrors}, label="Fetchmail Global Config" }) +end + +function updateconfig(conf) + local success, conf = validateconfig(conf) + + if success then + local file = fs.read_file(configfile) + local foundpostmaster, foundbounceerrors + local lines = {} + for line in string.gmatch(file, "([^\n]*\n?)") do + if not foundpostmaster and string.match(line, "^%s*set%s+postmaster%s") then + foundpostmaster = true + line = "set postmaster "..conf.value.postmaster.value.."\n" + elseif not foundbounceerrors and string.match(line, "^%s*set%s+no%s+bouncemail%s") then + foundbounceerrors = true + if conf.value.bounceerrors.value then + line = nil + end + end + lines[#lines + 1] = line + end + if not foundpostmaster then + table.insert(lines, 1, "set postmaster "..conf.value.postmaster.value.."\n") + end + if not foundbounceerrors and not conf.value.bounceerrors.value then + table.insert(lines, 1, "set no bouncemail\n") + end + + fs.write_file(configfile, table.concat(lines)) + posix.chmod(configfile, "rwx--x---") + config = nil + + getopts.setoptsinfile(confdfile, "", "polling_period", '"'..conf.value.interval.value..'"') + else + conf.errtxt = "Failed to set configuration" + end + + return conf +end + +function readentries() + local entries = cfe({ type="structure", value={}, label="List of Fetchmail entries" }) + config = config or parseconfigfile(fs.read_file(configfile)) + for i,entry in ipairs(config or {}) do + if (entry[1] == "server" or entry[1] == "poll" or entry[1] == "skip") and entry[2] then + local reverseentry = {} + for i,word in ipairs(entry) do reverseentry[word] = i end + local method = "error" + if reverseentry["local"] or reverseentry["localdomains"] then + method = "pop3domain" + elseif reverseentry["proto"] or reverseentry["protocol"] then + method = entry[(reverseentry["proto"] or reverseentry["protocol"])+1] or method + end + local enabled = true + if entry[1] == "skip" then enabled=false end + table.insert(entries.value, {entry=entry[2], method=method, enabled=enabled}) + end + end + return entries end +function readentry(entryname) + local enabled = cfe({ type="boolean", value=true, label="Enable" }) + local method = cfe({ type="select", value="pop3", label="Method", option=methods }) + local remotehost = cfe({ value=entryname, label="Remote Host" }) + local remotemailbox = cfe({ label="Remote Mailbox" }) + local remotepassword = cfe({ label="Password" }) + local localhost = cfe({ label="Local Host" }) + local localmailbox = cfe({ label="Local Mailbox" }) + local localdomain = cfe({ label="Local Domain" }) + + local entry = findentryline(entryname) + if entry then + if entry[1] == "skip" then + enabled.value = false + end + local reverseentry = {} + for i,word in ipairs(entry) do reverseentry[word] = i end + if reverseentry["local"] or reverseentry["localdomains"] then + localdomain.value = entry[(reverseentry["local"] or reverseentry["localdomains"])+1] or localdomain.value + method.value = "pop3domain" + elseif reverseentry["proto"] or reverseentry["protocol"] then + method.value = entry[(reverseentry["proto"] or reverseentry["protocol"])+1] or method.value + end + if reverseentry["user"] or reverseentry["username"] then + remotemailbox.value = entry[(reverseentry["user"] or reverseentry["username"])+1] or remotemailbox.value + end + if reverseentry["pass"] or reverseentry["password"] then + remotepassword.value = string.sub(entry[(reverseentry["pass"] or reverseentry["password"])+1] or "", 2, -2) or remotepassword.value + end + if reverseentry["smtphost"] then + localhost.value = entry[reverseentry["smtphost"]+1] or localhost.value + end + if reverseentry["is"] then + localmailbox.value = entry[reverseentry["is"]+1] or localmailbox.value + end + end + + return cfe({ type="group", value={enabled=enabled, method=method, remotehost=remotehost, remotemailbox=remotemailbox, remotepassword=remotepassword, localhost=localhost, localmailbox=localmailbox, localdomain=localdomain}, label="Fetchmail Entry" }) +end + +function updateentry(entrystruct) + local success, entrystruct = validateentry(entrystruct) + local entry = findentryline(entrystruct.value.remotehost.value) + if not entry then + entrystruct.value.remotehost.errtxt = "Entry not found" + success = false + end + + if success then + writeentryline(entrystruct, entry) + else + entrystruct.errtxt = "Failed to update entry" + end + + return entrystruct +end + +function createentry(entrystruct) + local success, entrystruct = validateentry(entrystruct) + local entry = findentryline(entrystruct.value.remotehost.value) + if entry then + entrystruct.value.remotehost.errtxt = "Entry already exists" + success = false + end + + if success then + writeentryline(entrystruct) + else + entrystruct.errtxt = "Failed to update entry" + end + + return entrystruct +end + +function deleteentry(entryname) + local retval = cfe({ value="Deleted entry", label="Delete Fetchmail Entry Result" }) + local entry = findentryline(entryname) + if entry then + writeentryline(nil, entry) + else + retval.value = "Failed to delete entry - not found" + end + + return retval +end |