summaryrefslogtreecommitdiffstats
path: root/postfix-model.lua
blob: 33d452010d2f9b4ceb96ddfecbcb51c55601b543 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
module(..., package.seeall)

-- Load libraries
require("modelfunctions")
require("posix")
require("fs")
require("format")
require("validator")

-- Set variables
local processname = "postfix"
local packagename = "postfix"
local baseurl = "/etc/postfix/"
local aliasesfile = "/etc/mail/aliases"

local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin "

-- ################################################################################
-- LOCAL FUNCTIONS

-- ################################################################################
-- PUBLIC FUNCTIONS

function startstop_service(action)
	return modelfunctions.startstop_service(processname, action, {"start", "stop", "restart", "reload"})
end

function getstatus()
	local status = modelfunctions.getstatus(processname, packagename, "Postfix Status")

	-- Enabled status is unique for postfix
	-- Look for pid file stored in queue_directory .. /pid/
	local config = format.parse_ini_file(fs.read_file(baseurl.."main.cf") or "", "") or {}
	if config.queue_directory then
		local pidfiles = fs.find_files_as_array(".*\.pid", config.queue_directory.."/pid/")
		if pidfiles and pidfiles[1] then
			local file = pidfiles[1]
			-- check to see if there's a matching proc directory and that it was created slightly after the pid file
			-- this allows us to avoid the problem with proc numbers wrapping
			local tmp = string.match(fs.read_file(file) or "", "%d+")
			if tmp then
				local dir = "/proc/" .. tmp
				filetime = posix.stat(file, "ctime")
				dirtime = posix.stat(dir, "ctime")
				if dirtime and (tonumber(dirtime) - tonumber(filetime) < 100) then
					status.value.status.value = "Running"
				end
			end
		end
	end

	return status
end

function getstatusdetails()
	return cfe({ type="longtext", value="", label="Postfix Status Details" })
end

local function geteditablefilelist()
	local listed_files = fs.find_files_as_array("[^%.].*", baseurl)
	table.insert(listed_files, aliasesfile)
	return listed_files
end

function getfilelist()
	local listed_files = {}

	for i,name in ipairs(geteditablefilelist()) do
		local filedetails = fs.stat(name) or {}
		table.insert ( listed_files , {filename=name, mtime=filedetails.mtime or "---", filesize=filedetails.size or "0"} )
	end

	table.sort(listed_files, function (a,b) return (a.filename < b.filename) end )

	return cfe({ type="list", value=listed_files, label="Postfix File List" })
end

function getfiledetails(filename)
	return modelfunctions.getfiledetails(filename, geteditablefilelist())
end

function updatefiledetails(filedetails)
	return modelfunctions.setfiledetails(filedetails, geteditablefilelist())
end

function getnewfile()
	local options = {}
	options.filename = cfe({ label="File Name" })
	return cfe({ type="group", value=options, label="New File" })
end

function createfile(newfile)
	newfile.errtxt = "Failed to create file"
	local path = newfile.value.filename.value
	if not string.find(path, "/") then
		path = baseurl..path
	end
	if validator.is_valid_filename(path, baseurl) then
		if posix.stat(path) then
			newfile.value.filename.errtxt = "File already exists"
		else
			fs.create_file(path)
			newfile.errtxt = nil
		end
	else
		newfile.value.filename.errtxt = "Invalid filename"
	end

	return newfile
end

function deletefile(filename)
	local result = cfe({ value="Failed to delete file", label="Delete file result" })
	if not validator.is_valid_filename(filename, baseurl) then
		result.errtxt = "Not a valid filename!"
	elseif not fs.is_file(filename) then
		result.errtxt = "File doesn't exist!"
	else
		os.remove(filename)
		result.value = "File Deleted"
	end
	return result
end

function rebuild_databases()
	local result = cfe({ value={"Rebuilding databases"}, label="Rebuild Databases result" })
	table.insert(result.value, " See logfile for possible errors")
	local cmd,f,cmdresult
	-- parse main.cf looking for hash files
	local config = format.parse_ini_file(fs.read_file("/etc/postfix/main.cf") or "", "") or {}
	for name,val in pairs(config) do
		-- run postmap on files
		local filename = string.match(val, "hash:(.*)")
		if filename and not string.find(filename, aliasesfile) then
			cmd = "postmap "..filename
			table.insert(result.value, "Running: "..cmd)
			f = io.popen(format.escapespecialcharacters(path..cmd))
			table.insert(result.value, f:read("*a"))
			f:close()
		end
	end
	-- finally, run newaliases
	cmd = "newaliases"
	table.insert(result.value, "Running: "..cmd)
	f = io.popen(format.escapespecialcharacters(path..cmd))
	table.insert(result.value, f:read("*a"))
	f:close()

	result.value = table.concat(result.value, "\n")
	return result
end