postfix_admin 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +54 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +19 -8
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +26 -20
- data/Rakefile +19 -1
- data/bin/console +6 -2
- data/docker-admin/Dockerfile +6 -0
- data/docker-admin/config.local.php +24 -0
- data/docker-app/Dockerfile +21 -0
- data/docker-app/my.cnf +5 -0
- data/docker-compose.yml +37 -11
- data/docker-db/postfix.v1841.sql +383 -0
- data/docker-db/postfix.v352.sql +223 -0
- data/docker-db/postfix.v740.sql +269 -0
- data/lib/postfix_admin/admin.rb +17 -2
- data/lib/postfix_admin/alias.rb +0 -19
- data/lib/postfix_admin/base.rb +120 -94
- data/lib/postfix_admin/cli.rb +184 -127
- data/lib/postfix_admin/concerns/dovecot_cram_md5_password.rb +0 -1
- data/lib/postfix_admin/domain.rb +35 -44
- data/lib/postfix_admin/doveadm.rb +11 -10
- data/lib/postfix_admin/mailbox.rb +14 -6
- data/lib/postfix_admin/runner.rb +35 -22
- data/lib/postfix_admin/version.rb +1 -1
- data/postfix_admin.gemspec +13 -9
- metadata +55 -21
- data/Dockerfile +0 -24
- data/docker-entrypoint.sh +0 -5
@@ -0,0 +1,269 @@
|
|
1
|
+
|
2
|
+
-- phpMyAdmin SQL Dump
|
3
|
+
-- version 3.5.7
|
4
|
+
-- http://www.phpmyadmin.net
|
5
|
+
--
|
6
|
+
-- ホスト: localhost
|
7
|
+
-- 生成日時: 2013 年 5 月 09 日 08:25
|
8
|
+
-- サーバのバージョン: 5.5.29
|
9
|
+
-- PHP のバージョン: 5.3.20
|
10
|
+
|
11
|
+
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
|
12
|
+
SET time_zone = "+00:00";
|
13
|
+
|
14
|
+
|
15
|
+
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
16
|
+
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
17
|
+
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
18
|
+
/*!40101 SET NAMES utf8 */;
|
19
|
+
|
20
|
+
--
|
21
|
+
-- データベース: `postfix`
|
22
|
+
--
|
23
|
+
|
24
|
+
-- --------------------------------------------------------
|
25
|
+
|
26
|
+
--
|
27
|
+
-- テーブルの構造 `admin`
|
28
|
+
--
|
29
|
+
|
30
|
+
CREATE TABLE IF NOT EXISTS `admin` (
|
31
|
+
`username` varchar(255) NOT NULL,
|
32
|
+
`password` varchar(255) NOT NULL,
|
33
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
34
|
+
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
35
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
36
|
+
PRIMARY KEY (`username`)
|
37
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Virtual Admins';
|
38
|
+
|
39
|
+
-- --------------------------------------------------------
|
40
|
+
|
41
|
+
--
|
42
|
+
-- テーブルの構造 `alias`
|
43
|
+
--
|
44
|
+
|
45
|
+
CREATE TABLE IF NOT EXISTS `alias` (
|
46
|
+
`address` varchar(255) NOT NULL,
|
47
|
+
`goto` text NOT NULL,
|
48
|
+
`domain` varchar(255) NOT NULL,
|
49
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
50
|
+
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
51
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
52
|
+
PRIMARY KEY (`address`),
|
53
|
+
KEY `domain` (`domain`)
|
54
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Virtual Aliases';
|
55
|
+
|
56
|
+
-- --------------------------------------------------------
|
57
|
+
|
58
|
+
--
|
59
|
+
-- テーブルの構造 `alias_domain`
|
60
|
+
--
|
61
|
+
|
62
|
+
CREATE TABLE IF NOT EXISTS `alias_domain` (
|
63
|
+
`alias_domain` varchar(255) NOT NULL,
|
64
|
+
`target_domain` varchar(255) NOT NULL,
|
65
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
66
|
+
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
67
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
68
|
+
PRIMARY KEY (`alias_domain`),
|
69
|
+
KEY `active` (`active`),
|
70
|
+
KEY `target_domain` (`target_domain`)
|
71
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Domain Aliases';
|
72
|
+
|
73
|
+
-- --------------------------------------------------------
|
74
|
+
|
75
|
+
--
|
76
|
+
-- テーブルの構造 `config`
|
77
|
+
--
|
78
|
+
|
79
|
+
CREATE TABLE IF NOT EXISTS `config` (
|
80
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
81
|
+
`name` varchar(20) CHARACTER SET utf8 NOT NULL DEFAULT '',
|
82
|
+
`value` varchar(20) CHARACTER SET utf8 NOT NULL DEFAULT '',
|
83
|
+
PRIMARY KEY (`id`),
|
84
|
+
UNIQUE KEY `name` (`name`)
|
85
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='PostfixAdmin settings' AUTO_INCREMENT=2 ;
|
86
|
+
|
87
|
+
--
|
88
|
+
-- テーブルのデータのダンプ `config`
|
89
|
+
--
|
90
|
+
|
91
|
+
INSERT INTO `config` (`id`, `name`, `value`) VALUES
|
92
|
+
(1, 'version', '740');
|
93
|
+
|
94
|
+
-- --------------------------------------------------------
|
95
|
+
|
96
|
+
--
|
97
|
+
-- テーブルの構造 `domain`
|
98
|
+
--
|
99
|
+
|
100
|
+
CREATE TABLE IF NOT EXISTS `domain` (
|
101
|
+
`domain` varchar(255) NOT NULL,
|
102
|
+
`description` varchar(255) CHARACTER SET utf8 NOT NULL,
|
103
|
+
`aliases` int(10) NOT NULL DEFAULT '0',
|
104
|
+
`mailboxes` int(10) NOT NULL DEFAULT '0',
|
105
|
+
`maxquota` bigint(20) NOT NULL DEFAULT '0',
|
106
|
+
`quota` bigint(20) NOT NULL DEFAULT '0',
|
107
|
+
`transport` varchar(255) NOT NULL,
|
108
|
+
`backupmx` tinyint(1) NOT NULL DEFAULT '0',
|
109
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
110
|
+
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
111
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
112
|
+
PRIMARY KEY (`domain`)
|
113
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Virtual Domains';
|
114
|
+
|
115
|
+
--
|
116
|
+
-- テーブルのデータのダンプ `domain`
|
117
|
+
--
|
118
|
+
|
119
|
+
INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `maxquota`, `quota`, `transport`, `backupmx`, `created`, `modified`, `active`) VALUES
|
120
|
+
('ALL', '', 0, 0, 0, 0, '', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1);
|
121
|
+
|
122
|
+
-- --------------------------------------------------------
|
123
|
+
|
124
|
+
--
|
125
|
+
-- テーブルの構造 `domain_admins`
|
126
|
+
--
|
127
|
+
|
128
|
+
CREATE TABLE IF NOT EXISTS `domain_admins` (
|
129
|
+
`username` varchar(255) NOT NULL,
|
130
|
+
`domain` varchar(255) NOT NULL,
|
131
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
132
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
133
|
+
KEY `username` (`username`)
|
134
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Domain Admins';
|
135
|
+
|
136
|
+
-- --------------------------------------------------------
|
137
|
+
|
138
|
+
--
|
139
|
+
-- テーブルの構造 `fetchmail`
|
140
|
+
--
|
141
|
+
|
142
|
+
CREATE TABLE IF NOT EXISTS `fetchmail` (
|
143
|
+
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
144
|
+
`mailbox` varchar(255) NOT NULL,
|
145
|
+
`src_server` varchar(255) NOT NULL,
|
146
|
+
`src_auth` enum('password','kerberos_v5','kerberos','kerberos_v4','gssapi','cram-md5','otp','ntlm','msn','ssh','any') CHARACTER SET utf8 DEFAULT NULL,
|
147
|
+
`src_user` varchar(255) NOT NULL,
|
148
|
+
`src_password` varchar(255) NOT NULL,
|
149
|
+
`src_folder` varchar(255) NOT NULL,
|
150
|
+
`poll_time` int(11) unsigned NOT NULL DEFAULT '10',
|
151
|
+
`fetchall` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
152
|
+
`keep` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
153
|
+
`protocol` enum('POP3','IMAP','POP2','ETRN','AUTO') CHARACTER SET utf8 DEFAULT NULL,
|
154
|
+
`usessl` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
155
|
+
`extra_options` text,
|
156
|
+
`returned_text` text,
|
157
|
+
`mda` varchar(255) NOT NULL,
|
158
|
+
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
159
|
+
PRIMARY KEY (`id`)
|
160
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
|
161
|
+
|
162
|
+
-- --------------------------------------------------------
|
163
|
+
|
164
|
+
--
|
165
|
+
-- テーブルの構造 `log`
|
166
|
+
--
|
167
|
+
|
168
|
+
CREATE TABLE IF NOT EXISTS `log` (
|
169
|
+
`timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
170
|
+
`username` varchar(255) NOT NULL,
|
171
|
+
`domain` varchar(255) NOT NULL,
|
172
|
+
`action` varchar(255) NOT NULL,
|
173
|
+
`data` text NOT NULL,
|
174
|
+
KEY `timestamp` (`timestamp`)
|
175
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Log';
|
176
|
+
|
177
|
+
|
178
|
+
-- --------------------------------------------------------
|
179
|
+
|
180
|
+
--
|
181
|
+
-- テーブルの構造 `mailbox`
|
182
|
+
--
|
183
|
+
|
184
|
+
CREATE TABLE IF NOT EXISTS `mailbox` (
|
185
|
+
`username` varchar(255) NOT NULL,
|
186
|
+
`password` varchar(255) NOT NULL,
|
187
|
+
`name` varchar(255) CHARACTER SET utf8 NOT NULL,
|
188
|
+
`maildir` varchar(255) NOT NULL,
|
189
|
+
`quota` bigint(20) NOT NULL DEFAULT '0',
|
190
|
+
`local_part` varchar(255) NOT NULL,
|
191
|
+
`domain` varchar(255) NOT NULL,
|
192
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
193
|
+
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
194
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
195
|
+
PRIMARY KEY (`username`),
|
196
|
+
KEY `domain` (`domain`)
|
197
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Virtual Mailboxes';
|
198
|
+
|
199
|
+
|
200
|
+
-- --------------------------------------------------------
|
201
|
+
|
202
|
+
--
|
203
|
+
-- テーブルの構造 `quota`
|
204
|
+
--
|
205
|
+
|
206
|
+
CREATE TABLE IF NOT EXISTS `quota` (
|
207
|
+
`username` varchar(255) CHARACTER SET utf8 NOT NULL,
|
208
|
+
`path` varchar(100) CHARACTER SET utf8 NOT NULL,
|
209
|
+
`current` bigint(20) DEFAULT NULL,
|
210
|
+
PRIMARY KEY (`username`,`path`)
|
211
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
212
|
+
|
213
|
+
-- --------------------------------------------------------
|
214
|
+
|
215
|
+
--
|
216
|
+
-- テーブルの構造 `quota2`
|
217
|
+
--
|
218
|
+
|
219
|
+
CREATE TABLE IF NOT EXISTS `quota2` (
|
220
|
+
`username` varchar(100) CHARACTER SET utf8 NOT NULL,
|
221
|
+
`bytes` bigint(20) NOT NULL DEFAULT '0',
|
222
|
+
`messages` int(11) NOT NULL DEFAULT '0',
|
223
|
+
PRIMARY KEY (`username`)
|
224
|
+
) ENGINE=INNODB DEFAULT CHARSET=utf8;
|
225
|
+
|
226
|
+
-- --------------------------------------------------------
|
227
|
+
|
228
|
+
--
|
229
|
+
-- テーブルの構造 `vacation`
|
230
|
+
--
|
231
|
+
|
232
|
+
CREATE TABLE IF NOT EXISTS `vacation` (
|
233
|
+
`email` varchar(255) NOT NULL,
|
234
|
+
`subject` varchar(255) CHARACTER SET utf8 NOT NULL,
|
235
|
+
`body` text CHARACTER SET utf8 NOT NULL,
|
236
|
+
`cache` text NOT NULL,
|
237
|
+
`domain` varchar(255) NOT NULL,
|
238
|
+
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
239
|
+
`active` tinyint(1) NOT NULL DEFAULT '1',
|
240
|
+
PRIMARY KEY (`email`),
|
241
|
+
KEY `email` (`email`)
|
242
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Virtual Vacation';
|
243
|
+
|
244
|
+
-- --------------------------------------------------------
|
245
|
+
|
246
|
+
--
|
247
|
+
-- テーブルの構造 `vacation_notification`
|
248
|
+
--
|
249
|
+
|
250
|
+
CREATE TABLE IF NOT EXISTS `vacation_notification` (
|
251
|
+
`on_vacation` varchar(150) CHARACTER SET utf8 NOT NULL,
|
252
|
+
`notified` varchar(150) NOT NULL,
|
253
|
+
`notified_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
254
|
+
PRIMARY KEY (`on_vacation`,`notified`)
|
255
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Postfix Admin - Virtual Vacation Notifications';
|
256
|
+
|
257
|
+
--
|
258
|
+
-- ダンプしたテーブルの制約
|
259
|
+
--
|
260
|
+
|
261
|
+
--
|
262
|
+
-- テーブルの制約 `vacation_notification`
|
263
|
+
--
|
264
|
+
ALTER TABLE `vacation_notification`
|
265
|
+
ADD CONSTRAINT `vacation_notification_pkey` FOREIGN KEY (`on_vacation`) REFERENCES `vacation` (`email`) ON DELETE CASCADE;
|
266
|
+
|
267
|
+
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
268
|
+
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
269
|
+
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
data/lib/postfix_admin/admin.rb
CHANGED
@@ -22,9 +22,18 @@ module PostfixAdmin
|
|
22
22
|
admin.errors.add(:username, 'cannot be changed') if admin.username_changed?
|
23
23
|
end
|
24
24
|
|
25
|
+
def reload
|
26
|
+
@super_admin = nil
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
25
30
|
def super_admin?
|
26
31
|
if @super_admin.nil?
|
27
|
-
@super_admin =
|
32
|
+
@super_admin = if has_superadmin_column?
|
33
|
+
self.superadmin && rel_domains.exists?("ALL")
|
34
|
+
else
|
35
|
+
rel_domains.exists?("ALL")
|
36
|
+
end
|
28
37
|
else
|
29
38
|
@super_admin
|
30
39
|
end
|
@@ -35,10 +44,16 @@ module PostfixAdmin
|
|
35
44
|
domain_ids = self.rel_domain_ids.dup
|
36
45
|
domain_ids << "ALL"
|
37
46
|
self.rel_domain_ids = domain_ids
|
38
|
-
|
47
|
+
self.superadmin = true if has_superadmin_column?
|
39
48
|
else
|
40
49
|
domain_admins.where(domain: "ALL").delete_all
|
50
|
+
self.superadmin = false if has_superadmin_column?
|
41
51
|
end
|
52
|
+
save!
|
53
|
+
end
|
54
|
+
|
55
|
+
def has_superadmin_column?
|
56
|
+
has_attribute?(:superadmin)
|
42
57
|
end
|
43
58
|
|
44
59
|
def has_admin?(admin)
|
data/lib/postfix_admin/alias.rb
CHANGED
@@ -24,30 +24,11 @@ module PostfixAdmin
|
|
24
24
|
scope :pure, -> { joins("LEFT OUTER JOIN mailbox ON alias.address = mailbox.username").where("mailbox.username" => nil) }
|
25
25
|
|
26
26
|
attribute :local_part, :string
|
27
|
-
attr_writer :forward_addresses
|
28
|
-
|
29
|
-
def forward_addresses
|
30
|
-
if @forward_addresses.nil?
|
31
|
-
if goto.nil?
|
32
|
-
[nil]
|
33
|
-
else
|
34
|
-
goto.split(",") + [nil]
|
35
|
-
end
|
36
|
-
else
|
37
|
-
@forward_addresses
|
38
|
-
end
|
39
|
-
end
|
40
27
|
|
41
28
|
before_validation do |a|
|
42
29
|
unless a.address
|
43
30
|
a.address = "#{a.local_part}@#{a.domain}" unless a.local_part.empty?
|
44
31
|
end
|
45
|
-
|
46
|
-
unless a.forward_addresses.empty?
|
47
|
-
forward_addresses = a.forward_addresses.dup
|
48
|
-
forward_addresses.delete_if { |f| f.blank? }
|
49
|
-
a.goto = forward_addresses.join(",")
|
50
|
-
end
|
51
32
|
end
|
52
33
|
|
53
34
|
def mailbox?
|
data/lib/postfix_admin/base.rb
CHANGED
@@ -8,40 +8,41 @@ module PostfixAdmin
|
|
8
8
|
attr_reader :config
|
9
9
|
|
10
10
|
DEFAULT_CONFIG = {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
"database" => "mysql2://postfix:password@localhost/postfix",
|
12
|
+
"aliases" => 30,
|
13
|
+
"mailboxes" => 30,
|
14
|
+
"maxquota" => 100,
|
15
|
+
"scheme" => "CRAM-MD5",
|
16
|
+
"passwordhash_prefix" => true
|
17
|
+
}.freeze
|
17
18
|
|
18
19
|
def initialize(config)
|
19
20
|
@config = {}
|
20
|
-
@config[:database] = config[
|
21
|
-
@config[:aliases] = config[
|
22
|
-
@config[:mailboxes] = config[
|
23
|
-
@config[:maxquota] = config[
|
24
|
-
@config[:scheme] = config[
|
21
|
+
@config[:database] = config["database"]
|
22
|
+
@config[:aliases] = config["aliases"] || DEFAULT_CONFIG["aliases"]
|
23
|
+
@config[:mailboxes] = config["mailboxes"] || DEFAULT_CONFIG["mailboxes"]
|
24
|
+
@config[:maxquota] = config["maxquota"] || DEFAULT_CONFIG["maxquota"]
|
25
|
+
@config[:scheme] = config["scheme"] || DEFAULT_CONFIG["scheme"]
|
26
|
+
@config[:passwordhash_prefix] = if config.has_key?("passwordhash_prefix")
|
27
|
+
config["passwordhash_prefix"]
|
28
|
+
else
|
29
|
+
DEFAULT_CONFIG["passwordhash_prefix"]
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
def db_setup
|
28
|
-
|
34
|
+
database = ENV.fetch("DATABASE_URL") { @config[:database] }
|
29
35
|
|
30
|
-
|
31
|
-
|
32
|
-
if uri.scheme == "mysql"
|
33
|
-
uri.scheme = "mysql2"
|
34
|
-
warn("Deprecation Warning: Use 'mysql2' as a DB adopter instead of 'mysql' in '#{CLI.config_file}'")
|
36
|
+
unless database
|
37
|
+
raise_error "'database' parameter is required in '#{CLI.config_file}' or specify 'DATABASE_URL' environment variable"
|
35
38
|
end
|
36
39
|
|
37
|
-
|
38
|
-
raise "'#{uri.scheme}' is not supported as a DB adopter. Use 'mysql2' instead in '#{CLI.config_file}'."
|
39
|
-
end
|
40
|
+
uri = URI.parse(database)
|
40
41
|
|
41
42
|
ActiveRecord::Base.establish_connection(uri.to_s)
|
42
43
|
|
43
44
|
rescue LoadError => e
|
44
|
-
|
45
|
+
raise_error e.message
|
45
46
|
end
|
46
47
|
|
47
48
|
def add_admin_domain(user_name, domain_name)
|
@@ -51,11 +52,11 @@ module PostfixAdmin
|
|
51
52
|
domain = Domain.find(domain_name)
|
52
53
|
|
53
54
|
if admin.has_domain?(domain)
|
54
|
-
|
55
|
+
raise_error "Admin '#{user_name}' has already been registered for Domain '#{domain_name}'"
|
55
56
|
end
|
56
57
|
|
57
58
|
admin.rel_domains << domain
|
58
|
-
admin.save
|
59
|
+
admin.save || raise_error("Relation Error: Domain of Admin")
|
59
60
|
end
|
60
61
|
|
61
62
|
def delete_admin_domain(user_name, domain_name)
|
@@ -65,135 +66,116 @@ module PostfixAdmin
|
|
65
66
|
domain_admin_query = admin.domain_admins.where(domain: domain_name)
|
66
67
|
|
67
68
|
unless domain_admin_query.take
|
68
|
-
|
69
|
+
raise_error "#{user_name} is not registered as admin of #{domain_name}."
|
69
70
|
end
|
70
71
|
|
71
72
|
domain_admin_query.delete_all
|
72
73
|
end
|
73
74
|
|
74
75
|
def add_admin(username, password)
|
75
|
-
|
76
|
+
validate_password(password)
|
76
77
|
|
77
78
|
if Admin.exists?(username)
|
78
|
-
|
79
|
+
raise_error "Admin has already been registered: #{username}"
|
79
80
|
end
|
81
|
+
|
80
82
|
admin = Admin.new
|
81
83
|
admin.attributes = {
|
82
84
|
username: username,
|
83
|
-
password: password
|
85
|
+
password: password
|
84
86
|
}
|
85
|
-
unless admin.save
|
86
|
-
raise "Could not save Admin #{admin.errors.map(&:to_s).join}"
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def add_account(address, password, in_name = nil)
|
91
|
-
name = in_name || ''
|
92
|
-
password_check(password)
|
93
|
-
|
94
|
-
if address !~ /.+\@.+\..+/
|
95
|
-
raise Error, "Invalid mail address #{address}"
|
96
|
-
end
|
97
|
-
user, domain_name = address_split(address)
|
98
|
-
path = "#{domain_name}/#{address}/"
|
99
87
|
|
100
|
-
unless
|
101
|
-
|
102
|
-
end
|
88
|
+
raise_save_error(admin) unless admin.save
|
89
|
+
end
|
103
90
|
|
104
|
-
|
105
|
-
|
106
|
-
|
91
|
+
# Adds an email account that consists of a Mailbox and an Alias.
|
92
|
+
def add_account(address, password, name: "")
|
93
|
+
validate_account(address, password)
|
107
94
|
|
108
|
-
|
95
|
+
local_part, domain_name = address_split(address)
|
96
|
+
domain_must_exist!(domain_name)
|
109
97
|
|
110
98
|
attributes = {
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
quota_mb: @config[:maxquota]
|
99
|
+
local_part: local_part,
|
100
|
+
domain: domain_name,
|
101
|
+
password: password,
|
102
|
+
name: name,
|
103
|
+
quota_mb: @config[:maxquota]
|
117
104
|
}
|
118
105
|
|
106
|
+
# An Alias also will be added when a Mailbox is saved.
|
119
107
|
mailbox = Mailbox.new(attributes)
|
120
108
|
|
121
|
-
|
122
|
-
|
123
|
-
unless domain.save
|
124
|
-
raise "Could not save Mailbox and Domain #{mailbox.errors.map(&:to_s).join} #{domain.errors.map(&:to_s).join}"
|
125
|
-
end
|
109
|
+
raise_save_error(mailbox) unless mailbox.save
|
126
110
|
end
|
127
111
|
|
128
112
|
def add_alias(address, goto)
|
129
113
|
if Mailbox.exists?(address)
|
130
|
-
|
131
|
-
end
|
132
|
-
if Alias.exists?(address)
|
133
|
-
raise Error, "alias #{address} is already registered!"
|
114
|
+
raise_error "Mailbox has already been registered: #{address}"
|
134
115
|
end
|
135
116
|
|
136
|
-
|
117
|
+
alias_must_not_exist!(address)
|
137
118
|
|
138
|
-
|
139
|
-
raise Error, "Invalid domain! #{domain_name}"
|
140
|
-
end
|
119
|
+
local_part, domain_name = address_split(address)
|
141
120
|
|
142
|
-
domain =
|
121
|
+
domain = find_domain(domain_name)
|
143
122
|
|
144
123
|
attributes = {
|
145
124
|
local_part: local_part,
|
146
125
|
goto: goto
|
147
126
|
}
|
127
|
+
|
148
128
|
domain.rel_aliases << Alias.new(attributes)
|
149
|
-
|
129
|
+
|
130
|
+
raise_save_error(domain) unless domain.save
|
150
131
|
end
|
151
132
|
|
152
133
|
def delete_alias(address)
|
153
134
|
if Mailbox.exists?(address)
|
154
|
-
|
135
|
+
raise_error "Can not delete mailbox by delete_alias. Use delete_account"
|
155
136
|
end
|
156
137
|
|
157
138
|
unless Alias.exists?(address)
|
158
|
-
|
139
|
+
raise_error "#{address} is not found!"
|
159
140
|
end
|
160
141
|
|
161
142
|
Alias.where(address: address).delete_all
|
162
143
|
end
|
163
144
|
|
164
|
-
def add_domain(domain_name)
|
145
|
+
def add_domain(domain_name, description: nil)
|
165
146
|
domain_name = domain_name.downcase
|
166
|
-
|
167
|
-
|
147
|
+
|
148
|
+
unless valid_domain_name?(domain_name)
|
149
|
+
raise_error "Invalid domain name: #{domain_name}"
|
168
150
|
end
|
151
|
+
|
169
152
|
if Domain.exists?(domain_name)
|
170
|
-
|
153
|
+
raise_error "Domain has already been registered: #{domain_name}"
|
171
154
|
end
|
155
|
+
|
156
|
+
new_description = description || domain_name
|
157
|
+
|
172
158
|
domain = Domain.new
|
173
159
|
domain.attributes = {
|
174
160
|
domain: domain_name,
|
175
|
-
description:
|
161
|
+
description: new_description,
|
176
162
|
aliases: @config[:aliases],
|
177
163
|
mailboxes: @config[:mailboxes],
|
178
|
-
maxquota: @config[:maxquota]
|
164
|
+
maxquota: @config[:maxquota]
|
179
165
|
}
|
180
166
|
domain.save!
|
181
167
|
end
|
182
168
|
|
183
169
|
def delete_domain(domain_name)
|
184
170
|
domain_name = domain_name.downcase
|
185
|
-
unless Domain.exists?(domain_name)
|
186
|
-
raise Error, "Could not find domain #{domain_name}"
|
187
|
-
end
|
188
171
|
|
189
|
-
domain =
|
190
|
-
domain.rel_mailboxes.delete_all
|
191
|
-
domain.rel_aliases.delete_all
|
172
|
+
domain = find_domain(domain_name)
|
192
173
|
|
193
174
|
admin_names = domain.admins.map(&:username)
|
194
175
|
|
195
|
-
domain.
|
176
|
+
domain.destroy!
|
196
177
|
|
178
|
+
# Remove admins who had the deleted domain only
|
197
179
|
admin_names.each do |name|
|
198
180
|
next unless Admin.exists?(name)
|
199
181
|
|
@@ -201,16 +183,14 @@ module PostfixAdmin
|
|
201
183
|
|
202
184
|
# check if the admin is needed or not
|
203
185
|
if admin.rel_domains.empty?
|
204
|
-
admin.destroy
|
186
|
+
admin.destroy!
|
205
187
|
end
|
206
188
|
end
|
207
|
-
|
208
|
-
domain.destroy
|
209
189
|
end
|
210
190
|
|
211
191
|
def delete_admin(user_name)
|
212
192
|
unless Admin.exists?(user_name)
|
213
|
-
|
193
|
+
raise_error "Could not find admin #{user_name}"
|
214
194
|
end
|
215
195
|
|
216
196
|
admin = Admin.find(user_name)
|
@@ -220,26 +200,72 @@ module PostfixAdmin
|
|
220
200
|
|
221
201
|
def delete_account(address)
|
222
202
|
unless Alias.exists?(address) && Mailbox.exists?(address)
|
223
|
-
|
203
|
+
raise_error "Could not find account: #{address}"
|
224
204
|
end
|
225
205
|
|
226
206
|
Mailbox.where(username: address).delete_all
|
227
207
|
Alias.where(address: address).delete_all
|
228
208
|
end
|
229
209
|
|
210
|
+
private
|
211
|
+
|
212
|
+
def find_domain(domain_name)
|
213
|
+
domain_must_exist!(domain_name)
|
214
|
+
Domain.find(domain_name)
|
215
|
+
end
|
216
|
+
|
217
|
+
def raise_error(message)
|
218
|
+
raise PostfixAdmin::Error, message
|
219
|
+
end
|
220
|
+
|
221
|
+
def raise_save_error(obj)
|
222
|
+
raise_error "Failed to save #{obj.class}: #{obj.errors.full_messages.join(', ')}"
|
223
|
+
end
|
224
|
+
|
230
225
|
def address_split(address)
|
231
226
|
address.split('@')
|
232
227
|
end
|
233
228
|
|
234
|
-
|
229
|
+
def valid_domain_name?(domain_name)
|
230
|
+
/.+\..+/.match?(domain_name)
|
231
|
+
end
|
232
|
+
|
233
|
+
def valid_email_address?(address)
|
234
|
+
/.+@.+\..+/.match?(address)
|
235
|
+
end
|
236
|
+
|
237
|
+
def domain_must_exist!(domain_name)
|
238
|
+
unless Domain.exists?(domain_name)
|
239
|
+
raise_error "Could not find domain: #{domain_name}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def alias_must_not_exist!(address)
|
244
|
+
if Alias.exists?(address)
|
245
|
+
raise_error "Alias has already been registered: #{address}"
|
246
|
+
end
|
247
|
+
end
|
235
248
|
|
236
249
|
def admin_domain_check(user_name, domain_name)
|
237
|
-
|
238
|
-
|
250
|
+
unless Admin.exists?(user_name)
|
251
|
+
raise_error "#{user_name} is not registered as admin."
|
252
|
+
end
|
253
|
+
|
254
|
+
domain_must_exist!(domain_name)
|
255
|
+
end
|
256
|
+
|
257
|
+
def validate_password(password)
|
258
|
+
raise_error "Empty password" if password.nil? || password.empty?
|
239
259
|
end
|
240
260
|
|
241
|
-
def
|
242
|
-
|
261
|
+
def validate_account(address, password)
|
262
|
+
validate_password(password)
|
263
|
+
|
264
|
+
unless valid_email_address?(address)
|
265
|
+
raise_error "Invalid email address: #{address}"
|
266
|
+
end
|
267
|
+
|
268
|
+
alias_must_not_exist!(address)
|
243
269
|
end
|
244
270
|
end
|
245
271
|
end
|