summaryrefslogtreecommitdiffstats
path: root/fetchmail-model.lua
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2008-08-29 17:48:19 +0000
committerTed Trask <ttrask01@yahoo.com>2008-08-29 17:48:19 +0000
commit7675a3125618bad993398d89e2ef91eb238c8bc3 (patch)
tree3ca00a9c5c7b43b9b4a5664a84cdc18a30640838 /fetchmail-model.lua
parent0441e224f891306f238eac938692a0088eda1e43 (diff)
downloadacf-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.lua657
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