postfix_admin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in postfix_admin.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Hitoshi Kurokawa
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # PostfixAdmin
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'postfix_admin'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install postfix_admin
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/postfix_admin ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'postfix_admin'
5
+ require 'postfix_admin/cli'
6
+
7
+ class PostfixAdminCommand < Thor
8
+ def initialize(*args)
9
+ super
10
+ @cli = PostfixAdmin::CLI.new
11
+ end
12
+ desc "show", "List of domains"
13
+ def show(domain=nil)
14
+ if domain
15
+ @cli.show_domain_account(domain)
16
+ else
17
+ @cli.show_domain
18
+ @cli.show_admin
19
+ end
20
+ end
21
+
22
+ desc "add_domain", "add a domain"
23
+ def add_domain(domain=nil)
24
+ if domain
25
+ if @cli.add_domain(domain)
26
+ puts %Q!"#{domain}" is successfully registered.!
27
+ end
28
+ @cli.show_domain
29
+ else
30
+ puts "USAGE: #{$0} add_domain example.com"
31
+ exit
32
+ end
33
+ end
34
+
35
+ desc "delete_domain", "delete a domain"
36
+ def delete_domain(domain=nil)
37
+ if domain
38
+ if @cli.delete_domain(domain)
39
+ puts %Q!"#{domain}" is successfully deleted.!
40
+ end
41
+ @cli.show_domain
42
+ else
43
+ puts "USAGE: #{$0} delete_domain example.com"
44
+ exit
45
+ end
46
+ end
47
+
48
+ desc "add_account", "add an account"
49
+ def add_account(address=nil,password=nil)
50
+ if address && password
51
+ if @cli.add_account(address, password)
52
+ puts %Q!"#{address}" is successfully registered.!
53
+ end
54
+ @cli.show_domain_account(address.split(/@/)[1])
55
+ else
56
+ puts "USAGE: #{$0} add_account user@example.com password"
57
+ exit
58
+ end
59
+ end
60
+
61
+ desc "add_admin", "add an admin user"
62
+ def add_admin(user_name=nil, password=nil)
63
+ if user_name && password
64
+ if @cli.add_admin(user_name, password)
65
+ puts %Q!"#{user_name}" is successfully registered as admin.!
66
+ end
67
+ @cli.show_admin
68
+ else
69
+ puts "USAGE: #{$0} add_admin user@example.com password"
70
+ exit
71
+ end
72
+ end
73
+
74
+ desc "add_admin_domain", "add admin_domain"
75
+ def add_admin_domain(user_name=nil, domain=nil)
76
+ if user_name && domain
77
+ if @cli.add_admin_domain(user_name, domain)
78
+ puts %Q!"#{domain}" is appended in the domains of #{user_name}.!
79
+ end
80
+ @cli.show_admin_domain(user_name)
81
+ else
82
+ puts "USAGE: #{$0} add_admin_domain user@example.com example.com"
83
+ exit
84
+ end
85
+ end
86
+
87
+ desc "add_alias", "add an alias"
88
+ def add_alias(address=nil, goto=nil)
89
+ if address && goto
90
+ if @cli.add_alias(address, goto)
91
+ puts %Q!"#{address}: #{goto}" is successfully registered as alias.!
92
+ end
93
+ @cli.show_domain_account(address.split(/@/)[1])
94
+ else
95
+ puts "USAGE: #{$0} add_alias user@example.com goto@example.com"
96
+ exit
97
+ end
98
+ end
99
+ end
100
+
101
+ PostfixAdminCommand.start
@@ -0,0 +1,123 @@
1
+ require 'yaml'
2
+ require 'postfix_admin'
3
+
4
+ class PostfixAdmin
5
+ class CLI
6
+ CONFIG_FILE = '.postfix_admin.conf'
7
+ MIN_NUM_PASSWORD_CHARACTER = 5
8
+
9
+ def initialize
10
+ @config = load_config
11
+ @admin = PostfixAdmin.new(@config)
12
+ end
13
+ # ~/.postfix_adminrc
14
+ # database: mysql://postfix:password@localhost/postfix
15
+ # aliases: 30
16
+ # mailboxes: 30
17
+ # maxquota: 100
18
+ def load_config
19
+ unless File.exist?(config_file)
20
+ create_config
21
+ puts "configure file: #{config_file} was generated.\nPlease execute after edit it."
22
+ exit
23
+ end
24
+ open(config_file) do |f|
25
+ YAML.load(f.read)
26
+ end
27
+ end
28
+ def create_config
29
+ config = {
30
+ 'database' => 'mysql://postfix:password@localhost/postfix',
31
+ 'aliases' => 30,
32
+ 'mailboxes' => 30,
33
+ 'maxquota' => 100
34
+ }
35
+ open(config_file, 'w') do |f|
36
+ f.write config.to_yaml
37
+ end
38
+ File.chmod(0600, config_file)
39
+ end
40
+ def config_file
41
+ File.expand_path(CONFIG_FILE, ENV['HOME'])
42
+ end
43
+ def print_line
44
+ puts "-"*85
45
+ end
46
+ def show_domain
47
+ print_line
48
+ puts " No. domain alias mail quota"
49
+ print_line
50
+ @admin.domains.each_with_index do |domain, i|
51
+ printf("%4d %-20s %4d %4d %4d\n", i+1, domain.domain, domain.aliases, domain.mailboxes, domain.maxquota)
52
+ end
53
+ print_line
54
+ end
55
+ def show_admin
56
+ admins = @admin.admins
57
+ if admins.count == 0
58
+ puts "No admin in database\n"
59
+ return
60
+ end
61
+ print_line
62
+ puts " No. username password"
63
+ print_line
64
+ admins.each_with_index do |admin, i|
65
+ printf("%4d %-20s %10s\n", i+1, admin.username, admin.password)
66
+ end
67
+ print_line
68
+ end
69
+ def show_domain_account(domain)
70
+ mailboxes = @admin.mailboxes(domain)
71
+ if mailboxes.count == 0
72
+ puts "No address in #{domain}\n"
73
+ return
74
+ end
75
+ print_line
76
+ puts " No. address password quota(M) maildir"
77
+ print_line
78
+ mailboxes.each_with_index do |mailbox, i|
79
+ printf("%4d %-20s %10s %7.1f %-30s\n", i+1, mailbox.username, mailbox.password, mailbox.quota.to_f/1024000.0, mailbox.maildir)
80
+ end
81
+ print_line
82
+ end
83
+ def show_admin_domain(user_name)
84
+ domain_admins = @admin.admin_domains(user_name)
85
+ if domain_admins.count == 0
86
+ puts "No domain in database\n"
87
+ return
88
+ end
89
+ print_line
90
+ puts " No. domain"
91
+ print_line
92
+ domain_admins.each_with_index do |domain_admin, i|
93
+ printf("%4d %-20s\n", i+1, domain_admin.domain)
94
+ end
95
+ print_line
96
+ end
97
+ def add_domain(domain)
98
+ @admin.add_domain(domain)
99
+ end
100
+ def add_admin(user_name, password)
101
+ validate_password(password)
102
+ @admin.add_admin(user_name, password)
103
+ end
104
+ def add_account(address, password)
105
+ validate_password(password)
106
+ @admin.add_account(address, password)
107
+ end
108
+ def add_alias(address, goto)
109
+ @admin.add_alias(address, goto)
110
+ end
111
+ def add_admin_domain(user_name, domain)
112
+ @admin.add_admin_domain(user_name, domain)
113
+ end
114
+ def delete_domain(domain)
115
+ @admin.delete_domain(domain)
116
+ end
117
+ def validate_password(password)
118
+ if password.size < MIN_NUM_PASSWORD_CHARACTER
119
+ raise "Error: Password is too short. It should be larger than #{MIN_NUM_PASSWORD_CHARACTER}"
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,61 @@
1
+ require 'data_mapper'
2
+
3
+ class PostfixAdmin
4
+ class Admin
5
+ include ::DataMapper::Resource
6
+ property :username, String, :key => true
7
+ property :password, String
8
+ property :created, DateTime
9
+ property :modified, DateTime
10
+
11
+ storage_names[:default] = 'admin'
12
+ end
13
+
14
+ class Domain
15
+ include ::DataMapper::Resource
16
+ property :domain, String, :key => true
17
+ property :aliases, Integer
18
+ property :mailboxes, Integer
19
+ property :maxquota, Integer
20
+ property :transport, String
21
+ property :backupmx, Integer
22
+ property :description, String
23
+
24
+ storage_names[:default] = 'domain'
25
+ end
26
+
27
+ class DomainAdmin
28
+ include ::DataMapper::Resource
29
+ property :username, String, :key => true
30
+ property :domain, String, :key => true
31
+ property :created, DateTime
32
+
33
+ storage_names[:default] = 'domain_admins'
34
+ end
35
+
36
+ class Mailbox
37
+ include ::DataMapper::Resource
38
+ property :username, String, :key => true
39
+ property :name, String
40
+ property :password, String
41
+ property :domain, String
42
+ property :maildir, String
43
+ property :quota, Integer
44
+ # property :local_part, String
45
+ property :created, DateTime
46
+ property :modified, DateTime
47
+
48
+ storage_names[:default] = 'mailbox'
49
+ end
50
+
51
+ class Alias
52
+ include ::DataMapper::Resource
53
+ property :address, String, :key => true
54
+ property :goto, Text, :key => true
55
+ property :domain, String
56
+ property :created, DateTime
57
+ property :modified, DateTime
58
+
59
+ storage_names[:default] = 'alias'
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ class PostfixAdmin
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,158 @@
1
+ require "postfix_admin/version"
2
+ require 'postfix_admin/models'
3
+
4
+ require 'date'
5
+ require 'data_mapper'
6
+
7
+ class PostfixAdmin
8
+ def initialize(config)
9
+ DataMapper.setup(:default, config['database'])
10
+ DataMapper.finalize
11
+ @config = {}
12
+ @config[:aliases] = config['aliases'] || 30
13
+ @config[:mailboxes] = config['mailboxes'] || 30
14
+ @config[:maxquota] = config['maxquota'] || 100
15
+ @config[:mailbox_quota] = @config[:maxquota] * 1024 * 1000
16
+ end
17
+ def add_admin_domain(username, domain)
18
+ unless admin_exist?(username)
19
+ raise "Error: #{username} is not resistered as admin."
20
+ end
21
+ unless domain_exist?(domain)
22
+ raise "Error: Invalid domain #{domain}!"
23
+ end
24
+ if admin_domain_exist?(username, domain)
25
+ raise "Error: #{username} is already resistered as admin of #{domain}."
26
+ end
27
+
28
+ domain_admin = DomainAdmin.new
29
+ domain_admin.attributes = {
30
+ :username => username,
31
+ :domain => domain,
32
+ :created => DateTime.now
33
+ }
34
+ domain_admin.save
35
+ end
36
+ def add_admin(username, password)
37
+ if admin_exist?(username)
38
+ raise "Error: #{username} is already resistered as admin."
39
+ end
40
+ admin = Admin.new
41
+ admin.attributes = {
42
+ :username => username,
43
+ :password => password,
44
+ :created => DateTime.now,
45
+ :modified => DateTime.now
46
+ }
47
+ admin.save
48
+ end
49
+ def add_account(address, password)
50
+ if address !~ /.+\@.+\..+/
51
+ raise "Error: Invalid mail address! #{address}"
52
+ end
53
+ user, domain = address.split(/@/)
54
+ path = "#{domain}/#{address}/"
55
+
56
+ unless domain_exist?(domain)
57
+ raise "Error: Invalid domain! #{address}"
58
+ end
59
+
60
+ if alias_exist?(address)
61
+ raise "Error: #{address} is already resistered."
62
+ end
63
+ mail_alias = Alias.new
64
+ mail_alias.attributes = {
65
+ :address => address,
66
+ :goto => address,
67
+ :domain => domain,
68
+ :created => DateTime.now,
69
+ :modified => DateTime.now
70
+ }
71
+ mail_alias.save
72
+
73
+ mailbox = Mailbox.new
74
+ mailbox.attributes = {
75
+ :username => address,
76
+ :password => password,
77
+ :name => '',
78
+ :maildir => path,
79
+ :quota => @config[:mailbox_quota],
80
+ :domain => domain,
81
+ # :local_part => user,
82
+ :created => DateTime.now,
83
+ :modified => DateTime.now
84
+ }
85
+ mailbox.save
86
+ end
87
+ def add_alias(address, goto)
88
+ if alias_exist?(address)
89
+ goto_text = "#{address},#{goto}"
90
+ mail_alias = Alias.first(:address => address)
91
+ mail_alias.update(:goto => goto_text, :modified => DateTime.now)
92
+ else
93
+ raise "Error: Invalid mail address! #{address}"
94
+ end
95
+ end
96
+ def add_domain(domain_name)
97
+ if domain_name !~ /.+\..+/
98
+ raise "Error: Ivalid domain! #{domain_name}"
99
+ end
100
+ if domain_exist?(domain_name)
101
+ raise "Error: #{domain_name} is already registered!"
102
+ end
103
+ domain = Domain.new
104
+ domain.attributes = {
105
+ :domain => domain_name,
106
+ :description => domain_name,
107
+ :aliases => @config[:aliases],
108
+ :mailboxes => @config[:mailboxes],
109
+ :maxquota => @config[:maxquota],
110
+ :transport => "virtual",
111
+ :backupmx => 0
112
+ }
113
+ domain.save
114
+ end
115
+ def delete_domain(domain)
116
+ unless domain_exist?(domain)
117
+ raise "Error: #{domain} is not found!"
118
+ end
119
+ username = "admin@#{domain}"
120
+ Admin.all(:username => username).destroy
121
+ DomainAdmin.all(:username => username).destroy
122
+ Mailbox.all(:domain => domain).destroy
123
+ Alias.all(:domain => domain).destroy
124
+ Domain.all(:domain => domain).destroy
125
+ end
126
+ def admin_domain_exist?(username, domain)
127
+ DomainAdmin.all(:username => username, :domain => domain).count != 0
128
+ end
129
+ def admin_exist?(admin)
130
+ Admin.all(:username => admin).count != 0
131
+ end
132
+ def alias_exist?(address)
133
+ Alias.all(:address => address).count != 0
134
+ end
135
+ def domain_exist?(domain)
136
+ Domain.all(:domain => domain).count != 0
137
+ end
138
+ def domains
139
+ Domain.all(:domain.not => 'ALL', :order => :domain)
140
+ end
141
+ def admins
142
+ Admin.all(:order => 'username')
143
+ end
144
+ def mailboxes(domain=nil)
145
+ if domain
146
+ Mailbox.all(:domain => domain, :order => :username)
147
+ else
148
+ Mailbox.all(:order => :username)
149
+ end
150
+ end
151
+ def admin_domains(username=nil)
152
+ if username
153
+ DomainAdmin.all(:username => username, :order => :domain)
154
+ else
155
+ DomainAdmin.all(:order => :domain)
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/postfix_admin/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.add_development_dependency 'thor'
6
+ gem.add_development_dependency 'data_mapper'
7
+ gem.add_development_dependency 'dm-mysql-adapter'
8
+
9
+ gem.authors = ["Hitoshi Kurokawa"]
10
+ gem.email = ["hitoshi@nextseed.jp"]
11
+ gem.description = %q{Command Line Tools of PostfixAdmin}
12
+ gem.summary = gem.description
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($\)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.name = "postfix_admin"
19
+ gem.require_paths = ["lib"]
20
+ gem.version = PostfixAdmin::VERSION
21
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: postfix_admin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Hitoshi Kurokawa
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: data_mapper
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: dm-mysql-adapter
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Command Line Tools of PostfixAdmin
63
+ email:
64
+ - hitoshi@nextseed.jp
65
+ executables:
66
+ - postfix_admin
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - LICENSE
73
+ - README.md
74
+ - Rakefile
75
+ - bin/postfix_admin
76
+ - lib/postfix_admin.rb
77
+ - lib/postfix_admin/cli.rb
78
+ - lib/postfix_admin/models.rb
79
+ - lib/postfix_admin/version.rb
80
+ - postfix_admin.gemspec
81
+ homepage: ''
82
+ licenses: []
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.24
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Command Line Tools of PostfixAdmin
105
+ test_files: []