sugoi-mail 0.0.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.
- data/README +35 -0
- data/Rakefile +10 -0
- data/app/apis/mailservice_api.rb +178 -0
- data/app/controllers/.sugoi_admin_controller.rb.swp +0 -0
- data/app/controllers/account_controller.rb +39 -0
- data/app/controllers/address_controller.rb +49 -0
- data/app/controllers/application.rb +4 -0
- data/app/controllers/commandline_controller.rb +15 -0
- data/app/controllers/domain_controller.rb +37 -0
- data/app/controllers/mailinglist_controller.rb +51 -0
- data/app/controllers/mailservice_controller.rb +497 -0
- data/app/controllers/sugoi_admin_controller.rb +93 -0
- data/app/helpers/account_helper.rb +2 -0
- data/app/helpers/address_helper.rb +2 -0
- data/app/helpers/application_helper.rb +3 -0
- data/app/helpers/domain_helper.rb +2 -0
- data/app/helpers/mailservice_helper.rb +2 -0
- data/app/helpers/sugoi_admin_helper.rb +2 -0
- data/app/models/address.rb +110 -0
- data/app/models/admin_message.rb +45 -0
- data/app/models/confirmationcode.rb +59 -0
- data/app/models/domain.rb +76 -0
- data/app/models/mailinglist.rb +336 -0
- data/app/models/mailinglist_class.rb +39 -0
- data/app/models/message.rb +293 -0
- data/app/models/proxy_link.rb +25 -0
- data/app/models/user.rb +150 -0
- data/app/views/account/login.rhtml +22 -0
- data/app/views/account/logout.rhtml +10 -0
- data/app/views/account/signup.rhtml +17 -0
- data/app/views/account/welcome.rhtml +13 -0
- data/app/views/address/_form.rhtml +7 -0
- data/app/views/address/edit.rhtml +10 -0
- data/app/views/address/list.rhtml +27 -0
- data/app/views/address/new.rhtml +8 -0
- data/app/views/address/show.rhtml +8 -0
- data/app/views/domain/login.rhtml +22 -0
- data/app/views/domain/logout.rhtml +10 -0
- data/app/views/domain/signup.rhtml +17 -0
- data/app/views/domain/welcome.rhtml +13 -0
- data/app/views/layouts/address.rhtml +13 -0
- data/app/views/layouts/scaffold.rhtml +13 -0
- data/app/views/mailinglist/_form.rhtml +28 -0
- data/app/views/mailinglist/edit.rhtml +10 -0
- data/app/views/mailinglist/list.rhtml +27 -0
- data/app/views/mailinglist/new.rhtml +8 -0
- data/app/views/mailinglist/show.rhtml +16 -0
- data/app/views/sugoi_admin/create_domain.rhtml +1 -0
- data/app/views/sugoi_admin/list_addresses.rhtml +1 -0
- data/app/views/sugoi_admin/list_domains.rhtml +2 -0
- data/app/views/sugoi_admin/list_mailinglists.rhtml +1 -0
- data/bin/mailc +32 -0
- data/bin/maild +133 -0
- data/bin/sugoi-admin +21 -0
- data/bin/sugoi-mail +20 -0
- data/config/boot.rb +44 -0
- data/config/environment.rb +54 -0
- data/config/environments/bench.rb +21 -0
- data/config/environments/coverage.rb +21 -0
- data/config/environments/development.rb +21 -0
- data/config/environments/production.rb +18 -0
- data/config/environments/test.rb +19 -0
- data/config/lighttpd.conf +46 -0
- data/config/routes.rb +29 -0
- data/db/migrate/001_mailproxy.rb +7 -0
- data/db/migrate/002_create_users.rb +13 -0
- data/db/migrate/003_create_mailinglists.rb +13 -0
- data/db/migrate/004_create_addresses.rb +12 -0
- data/db/migrate/005_create_addresses_mailinglists.rb +13 -0
- data/db/migrate/006_alter_mailinglists.rb +9 -0
- data/db/migrate/007_create_messages.rb +25 -0
- data/db/migrate/008_add_mailinglistid_to_users.rb +14 -0
- data/db/migrate/009_add_domainadmin_to_users.rb +9 -0
- data/db/migrate/010_add_domain_to_users.rb +16 -0
- data/db/migrate/011_add_active_to_addresses.rb +14 -0
- data/db/migrate/012_create_confirmationcodes.rb +14 -0
- data/db/migrate/013_add_description_to_mailinglists.rb +9 -0
- data/db/migrate/014_create_admin_messages.rb +69 -0
- data/db/migrate/015_add_messages_to_mailinglists.rb +26 -0
- data/db/migrate/016_add_mailinglist_admin_to_users.rb +9 -0
- data/db/migrate/017_add_mailinglist_types.rb +94 -0
- data/db/migrate/018_add_bounciness_to_addresses.rb +20 -0
- data/db/migrate/019_add_archived_to_mailinglist_classes.rb +25 -0
- data/db/migrate/020_add_envelope_data_to_messages.rb +11 -0
- data/db/migrate/021_add_addresses_users.rb +14 -0
- data/db/migrate/022_add_virtual_to_users.rb +14 -0
- data/db/migrate/023_drop_openposting_from_mailinglists.rb +9 -0
- data/db/migrate/024_add_proxy_links.rb +21 -0
- data/db/migrate/025_add_proxify_to_mailinglist_classes.rb +25 -0
- data/db/schema.mysql.sql +104 -0
- data/db/schema.postgresql.sql +104 -0
- data/db/schema.rb +85 -0
- data/db/schema.sqlite.sql +104 -0
- data/db/schema.sqlserver.sql +113 -0
- data/db/schema_version +1 -0
- data/doc/README_FOR_APP +179 -0
- data/doc/mailinglist_classes description.txt +28 -0
- data/installer/rails_installer_defaults.yml +5 -0
- data/lib/daemonize.rb +56 -0
- data/lib/domain_system.rb +87 -0
- data/lib/gurgitate-rules.rb +69 -0
- data/lib/limitedfork.rb +66 -0
- data/lib/login_system.rb +87 -0
- data/public/.htaccess +40 -0
- data/public/404.html +8 -0
- data/public/500.html +8 -0
- data/public/dispatch.cgi +10 -0
- data/public/dispatch.fcgi +24 -0
- data/public/dispatch.rb +10 -0
- data/public/favicon.ico +0 -0
- data/public/images/rails.png +0 -0
- data/public/javascripts/application.js +2 -0
- data/public/javascripts/controls.js +815 -0
- data/public/javascripts/dragdrop.js +913 -0
- data/public/javascripts/effects.js +958 -0
- data/public/javascripts/prototype.js +2006 -0
- data/public/robots.txt +1 -0
- data/public/stylesheets/scaffold.css +74 -0
- data/public/stylesheets/trestle.css +74 -0
- data/script/about +3 -0
- data/script/breakpointer +3 -0
- data/script/console +3 -0
- data/script/destroy +3 -0
- data/script/fakedeliver +19 -0
- data/script/generate +3 -0
- data/script/performance/benchmarker +3 -0
- data/script/performance/profiler +3 -0
- data/script/plugin +3 -0
- data/script/process/reaper +3 -0
- data/script/process/spawner +3 -0
- data/script/runner +3 -0
- data/script/server +3 -0
- data/sugoi-mail.gemspec +36 -0
- data/test/fixtures/addresses.yml +70 -0
- data/test/fixtures/addresses_mailinglists.yml +20 -0
- data/test/fixtures/admin_messages.yml +65 -0
- data/test/fixtures/confirmationcodes.yml +13 -0
- data/test/fixtures/domains.yml +9 -0
- data/test/fixtures/mailinglist_classes.yml +45 -0
- data/test/fixtures/mailinglists.yml +80 -0
- data/test/fixtures/messages.yml +154 -0
- data/test/fixtures/proxy_links.yml +5 -0
- data/test/fixtures/users.yml +50 -0
- data/test/functional/domain_controller_test.rb +74 -0
- data/test/functional/mailservice_controller_test.rb +546 -0
- data/test/integration/test_soap.rb +413 -0
- data/test/integration/test_xmlrpc.rb +198 -0
- data/test/mocks/test/net-smtp-stub.rb +24 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/address_test.rb +44 -0
- data/test/unit/admin_message_test.rb +41 -0
- data/test/unit/confirmationcode_test.rb +64 -0
- data/test/unit/domain_test.rb +128 -0
- data/test/unit/mailinglist_class_test.rb +82 -0
- data/test/unit/mailinglist_test.rb +145 -0
- data/test/unit/message_test.rb +151 -0
- data/test/unit/user_test.rb +126 -0
- data/test/units.rb +4 -0
- data/vendor/plugins/active_command/init.rb +1 -0
- data/vendor/plugins/active_command/lib/active_command/request.rb +137 -0
- data/vendor/plugins/active_command/lib/active_command/response.rb +132 -0
- data/vendor/plugins/active_command/lib/active_command.rb +2 -0
- data/vendor/plugins/ar_fixtures/CHANGELOG +10 -0
- data/vendor/plugins/ar_fixtures/MIT-LICENSE +20 -0
- data/vendor/plugins/ar_fixtures/README +19 -0
- data/vendor/plugins/ar_fixtures/Rakefile +54 -0
- data/vendor/plugins/ar_fixtures/about.yml +7 -0
- data/vendor/plugins/ar_fixtures/init.rb +1 -0
- data/vendor/plugins/ar_fixtures/lib/ar_fixtures.rb +102 -0
- data/vendor/plugins/ar_fixtures/tasks/ar_fixtures.rake +39 -0
- data/vendor/plugins/ar_fixtures/test/ar_fixtures_test.rb +53 -0
- data/vendor/plugins/ar_fixtures/test/database.yml +18 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/beer.rb +5 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/beers.yml +9 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/beers_drunkards.yml +8 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/drunkard.rb +6 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/drunkards.yml +8 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/glass.rb +2 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/glasses.yml +9 -0
- data/vendor/plugins/ar_fixtures/test/schema.rb +21 -0
- data/vendor/plugins/ar_fixtures/test/test_helper.rb +37 -0
- metadata +320 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
-- This file is autogenerated by the Rail schema generator, using
|
2
|
+
-- the schema defined in db/migration/*.rb
|
3
|
+
--
|
4
|
+
-- Do not edit this file. Instead, add a new migration using
|
5
|
+
-- ./script/generate migration <name>, and then run
|
6
|
+
-- ./script/generate schema
|
7
|
+
|
8
|
+
-- tables
|
9
|
+
|
10
|
+
CREATE TABLE addresses (
|
11
|
+
"id" serial primary key,
|
12
|
+
"address" text,
|
13
|
+
"active" boolean DEFAULT 't',
|
14
|
+
"delivery_attempts" integer DEFAULT 0,
|
15
|
+
"bounces" integer DEFAULT 0
|
16
|
+
);
|
17
|
+
|
18
|
+
CREATE TABLE addresses_mailinglists (
|
19
|
+
"address_id" integer,
|
20
|
+
"mailinglist_id" integer
|
21
|
+
);
|
22
|
+
|
23
|
+
CREATE TABLE admin_messages (
|
24
|
+
"id" serial primary key,
|
25
|
+
"message" text NOT NULL
|
26
|
+
);
|
27
|
+
|
28
|
+
CREATE TABLE confirmationcodes (
|
29
|
+
"id" serial primary key,
|
30
|
+
"mailinglist_id" integer,
|
31
|
+
"address_id" integer,
|
32
|
+
"code" text NOT NULL,
|
33
|
+
"confirmed" boolean DEFAULT 'f'
|
34
|
+
);
|
35
|
+
|
36
|
+
CREATE TABLE domains (
|
37
|
+
"id" serial primary key,
|
38
|
+
"name" character varying(255) NOT NULL,
|
39
|
+
"password" text NOT NULL
|
40
|
+
);
|
41
|
+
|
42
|
+
CREATE TABLE mailinglist_classes (
|
43
|
+
"id" serial primary key,
|
44
|
+
"name" text NOT NULL,
|
45
|
+
"description" text,
|
46
|
+
"public" boolean DEFAULT 'f' NOT NULL,
|
47
|
+
"closed" boolean DEFAULT 'f' NOT NULL,
|
48
|
+
"moderated" boolean DEFAULT 'f' NOT NULL,
|
49
|
+
"confirmation" boolean DEFAULT 't' NOT NULL,
|
50
|
+
"joinable" boolean DEFAULT 't' NOT NULL,
|
51
|
+
"archived" boolean DEFAULT 'f',
|
52
|
+
"proxify" boolean DEFAULT 'f'
|
53
|
+
);
|
54
|
+
|
55
|
+
CREATE TABLE mailinglists (
|
56
|
+
"id" serial primary key,
|
57
|
+
"user_id" integer,
|
58
|
+
"name" text NOT NULL,
|
59
|
+
"description" text,
|
60
|
+
"welcome_admin_message_id" integer DEFAULT 1,
|
61
|
+
"confirmed_admin_message_id" integer DEFAULT 2,
|
62
|
+
"sayonara_admin_message_id" integer DEFAULT 3,
|
63
|
+
"mailinglist_class_id" integer
|
64
|
+
);
|
65
|
+
|
66
|
+
CREATE TABLE messages (
|
67
|
+
"id" serial primary key,
|
68
|
+
"mailinglist_id" integer,
|
69
|
+
"address_id" integer,
|
70
|
+
"parent_id" integer,
|
71
|
+
"subject" character varying(255),
|
72
|
+
"messageid" character varying(255),
|
73
|
+
"timestamp" timestamp,
|
74
|
+
"headers" text,
|
75
|
+
"body" text,
|
76
|
+
"envelope_from" text,
|
77
|
+
"envelope_to" text
|
78
|
+
);
|
79
|
+
|
80
|
+
CREATE TABLE proxy_links (
|
81
|
+
"id" serial primary key,
|
82
|
+
"mailinglist_id" integer NOT NULL,
|
83
|
+
"address_id" integer NOT NULL
|
84
|
+
);
|
85
|
+
|
86
|
+
CREATE TABLE users (
|
87
|
+
"id" serial primary key,
|
88
|
+
"login" text NOT NULL,
|
89
|
+
"password" text NOT NULL,
|
90
|
+
"mailinglist_id" integer,
|
91
|
+
"domainadmin" boolean DEFAULT 'f',
|
92
|
+
"domain_id" integer,
|
93
|
+
"mailinglistadmin" boolean DEFAULT 'f',
|
94
|
+
"virtual" boolean DEFAULT 'f'
|
95
|
+
);
|
96
|
+
|
97
|
+
|
98
|
+
-- schema version meta-info
|
99
|
+
|
100
|
+
CREATE TABLE schema_info (
|
101
|
+
"version" integer
|
102
|
+
);
|
103
|
+
|
104
|
+
insert into schema_info (version) values (25);
|
data/db/schema.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# This file is autogenerated. Instead of editing this file, please use the
|
2
|
+
# migrations feature of ActiveRecord to incrementally modify your database, and
|
3
|
+
# then regenerate this schema definition.
|
4
|
+
|
5
|
+
ActiveRecord::Schema.define(:version => 25) do
|
6
|
+
|
7
|
+
create_table "addresses", :force => true do |t|
|
8
|
+
t.column "address", :text
|
9
|
+
t.column "active", :boolean, :default => true
|
10
|
+
t.column "delivery_attempts", :integer, :default => 0
|
11
|
+
t.column "bounces", :integer, :default => 0
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table "addresses_mailinglists", :id => false, :force => true do |t|
|
15
|
+
t.column "address_id", :integer
|
16
|
+
t.column "mailinglist_id", :integer
|
17
|
+
end
|
18
|
+
|
19
|
+
create_table "admin_messages", :force => true do |t|
|
20
|
+
t.column "message", :text, :null => false
|
21
|
+
end
|
22
|
+
|
23
|
+
create_table "confirmationcodes", :force => true do |t|
|
24
|
+
t.column "mailinglist_id", :integer
|
25
|
+
t.column "address_id", :integer
|
26
|
+
t.column "code", :text, :null => false
|
27
|
+
t.column "confirmed", :boolean, :default => false
|
28
|
+
end
|
29
|
+
|
30
|
+
create_table "domains", :force => true do |t|
|
31
|
+
t.column "name", :string, :null => false
|
32
|
+
t.column "password", :text, :null => false
|
33
|
+
end
|
34
|
+
|
35
|
+
create_table "mailinglist_classes", :force => true do |t|
|
36
|
+
t.column "name", :text, :null => false
|
37
|
+
t.column "description", :text
|
38
|
+
t.column "public", :boolean, :default => false, :null => false
|
39
|
+
t.column "closed", :boolean, :default => false, :null => false
|
40
|
+
t.column "moderated", :boolean, :default => false, :null => false
|
41
|
+
t.column "confirmation", :boolean, :default => true, :null => false
|
42
|
+
t.column "joinable", :boolean, :default => true, :null => false
|
43
|
+
t.column "archived", :boolean, :default => false, :null => false
|
44
|
+
t.column "proxify", :boolean, :default => false
|
45
|
+
end
|
46
|
+
|
47
|
+
create_table "mailinglists", :force => true do |t|
|
48
|
+
t.column "user_id", :integer
|
49
|
+
t.column "name", :text, :null => false
|
50
|
+
t.column "description", :text
|
51
|
+
t.column "welcome_admin_message_id", :integer, :default => 1
|
52
|
+
t.column "confirmed_admin_message_id", :integer, :default => 2
|
53
|
+
t.column "sayonara_admin_message_id", :integer, :default => 3
|
54
|
+
t.column "mailinglist_class_id", :integer
|
55
|
+
end
|
56
|
+
|
57
|
+
create_table "messages", :force => true do |t|
|
58
|
+
t.column "mailinglist_id", :integer
|
59
|
+
t.column "address_id", :integer
|
60
|
+
t.column "parent_id", :integer
|
61
|
+
t.column "subject", :string
|
62
|
+
t.column "messageid", :string
|
63
|
+
t.column "timestamp", :datetime
|
64
|
+
t.column "headers", :text
|
65
|
+
t.column "body", :text
|
66
|
+
t.column "envelope_from", :text
|
67
|
+
t.column "envelope_to", :text
|
68
|
+
end
|
69
|
+
|
70
|
+
create_table "proxy_links", :force => true do |t|
|
71
|
+
t.column "mailinglist_id", :integer, :null => false
|
72
|
+
t.column "address_id", :integer, :null => false
|
73
|
+
end
|
74
|
+
|
75
|
+
create_table "users", :force => true do |t|
|
76
|
+
t.column "login", :text, :null => false
|
77
|
+
t.column "password", :text, :null => false
|
78
|
+
t.column "mailinglist_id", :integer
|
79
|
+
t.column "domainadmin", :boolean, :default => false
|
80
|
+
t.column "domain_id", :integer
|
81
|
+
t.column "mailinglistadmin", :boolean, :default => false
|
82
|
+
t.column "virtual", :boolean, :default => false
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
-- This file is autogenerated by the Rail schema generator, using
|
2
|
+
-- the schema defined in db/migration/*.rb
|
3
|
+
--
|
4
|
+
-- Do not edit this file. Instead, add a new migration using
|
5
|
+
-- ./script/generate migration <name>, and then run
|
6
|
+
-- ./script/generate schema
|
7
|
+
|
8
|
+
-- tables
|
9
|
+
|
10
|
+
CREATE TABLE addresses (
|
11
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
12
|
+
"address" text,
|
13
|
+
"active" boolean DEFAULT 't',
|
14
|
+
"delivery_attempts" integer DEFAULT 0,
|
15
|
+
"bounces" integer DEFAULT 0
|
16
|
+
);
|
17
|
+
|
18
|
+
CREATE TABLE addresses_mailinglists (
|
19
|
+
"address_id" integer,
|
20
|
+
"mailinglist_id" integer
|
21
|
+
);
|
22
|
+
|
23
|
+
CREATE TABLE admin_messages (
|
24
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
25
|
+
"message" text NOT NULL
|
26
|
+
);
|
27
|
+
|
28
|
+
CREATE TABLE confirmationcodes (
|
29
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
30
|
+
"mailinglist_id" integer,
|
31
|
+
"address_id" integer,
|
32
|
+
"code" text NOT NULL,
|
33
|
+
"confirmed" boolean DEFAULT 'f'
|
34
|
+
);
|
35
|
+
|
36
|
+
CREATE TABLE domains (
|
37
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
38
|
+
"name" varchar(255) NOT NULL,
|
39
|
+
"password" text NOT NULL
|
40
|
+
);
|
41
|
+
|
42
|
+
CREATE TABLE mailinglist_classes (
|
43
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
44
|
+
"name" text NOT NULL,
|
45
|
+
"description" text,
|
46
|
+
"public" boolean DEFAULT 'f' NOT NULL,
|
47
|
+
"closed" boolean DEFAULT 'f' NOT NULL,
|
48
|
+
"moderated" boolean DEFAULT 'f' NOT NULL,
|
49
|
+
"confirmation" boolean DEFAULT 't' NOT NULL,
|
50
|
+
"joinable" boolean DEFAULT 't' NOT NULL,
|
51
|
+
"archived" boolean DEFAULT 'f',
|
52
|
+
"proxify" boolean DEFAULT 'f'
|
53
|
+
);
|
54
|
+
|
55
|
+
CREATE TABLE mailinglists (
|
56
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
57
|
+
"user_id" integer,
|
58
|
+
"name" text NOT NULL,
|
59
|
+
"description" text,
|
60
|
+
"welcome_admin_message_id" integer DEFAULT 1,
|
61
|
+
"confirmed_admin_message_id" integer DEFAULT 2,
|
62
|
+
"sayonara_admin_message_id" integer DEFAULT 3,
|
63
|
+
"mailinglist_class_id" integer
|
64
|
+
);
|
65
|
+
|
66
|
+
CREATE TABLE messages (
|
67
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
68
|
+
"mailinglist_id" integer,
|
69
|
+
"address_id" integer,
|
70
|
+
"parent_id" integer,
|
71
|
+
"subject" varchar(255),
|
72
|
+
"messageid" varchar(255),
|
73
|
+
"timestamp" datetime,
|
74
|
+
"headers" text,
|
75
|
+
"body" text,
|
76
|
+
"envelope_from" text,
|
77
|
+
"envelope_to" text
|
78
|
+
);
|
79
|
+
|
80
|
+
CREATE TABLE proxy_links (
|
81
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
82
|
+
"mailinglist_id" integer NOT NULL,
|
83
|
+
"address_id" integer NOT NULL
|
84
|
+
);
|
85
|
+
|
86
|
+
CREATE TABLE users (
|
87
|
+
"id" INTEGER PRIMARY KEY NOT NULL,
|
88
|
+
"login" text NOT NULL,
|
89
|
+
"password" text NOT NULL,
|
90
|
+
"mailinglist_id" integer,
|
91
|
+
"domainadmin" boolean DEFAULT 'f',
|
92
|
+
"domain_id" integer,
|
93
|
+
"mailinglistadmin" boolean DEFAULT 'f',
|
94
|
+
"virtual" boolean DEFAULT 'f'
|
95
|
+
);
|
96
|
+
|
97
|
+
|
98
|
+
-- schema version meta-info
|
99
|
+
|
100
|
+
CREATE TABLE schema_info (
|
101
|
+
"version" integer
|
102
|
+
);
|
103
|
+
|
104
|
+
insert into schema_info (version) values (25);
|
@@ -0,0 +1,113 @@
|
|
1
|
+
-- This file is autogenerated by the Rail schema generator, using
|
2
|
+
-- the schema defined in db/migration/*.rb
|
3
|
+
--
|
4
|
+
-- Do not edit this file. Instead, add a new migration using
|
5
|
+
-- ./script/generate migration <name>, and then run
|
6
|
+
-- ./script/generate schema
|
7
|
+
|
8
|
+
-- tables
|
9
|
+
|
10
|
+
CREATE TABLE addresses (
|
11
|
+
[id] int NOT NULL IDENTITY(1,
|
12
|
+
1) PRIMARY KEY,
|
13
|
+
[address] text,
|
14
|
+
[active] bit DEFAULT 1,
|
15
|
+
[delivery_attempts] int DEFAULT 0,
|
16
|
+
[bounces] int DEFAULT 0
|
17
|
+
);
|
18
|
+
|
19
|
+
CREATE TABLE addresses_mailinglists (
|
20
|
+
[address_id] int,
|
21
|
+
[mailinglist_id] int
|
22
|
+
);
|
23
|
+
|
24
|
+
CREATE TABLE admin_messages (
|
25
|
+
[id] int NOT NULL IDENTITY(1,
|
26
|
+
1) PRIMARY KEY,
|
27
|
+
[message] text NOT NULL
|
28
|
+
);
|
29
|
+
|
30
|
+
CREATE TABLE confirmationcodes (
|
31
|
+
[id] int NOT NULL IDENTITY(1,
|
32
|
+
1) PRIMARY KEY,
|
33
|
+
[mailinglist_id] int,
|
34
|
+
[address_id] int,
|
35
|
+
[code] text NOT NULL,
|
36
|
+
[confirmed] bit DEFAULT 0
|
37
|
+
);
|
38
|
+
|
39
|
+
CREATE TABLE domains (
|
40
|
+
[id] int NOT NULL IDENTITY(1,
|
41
|
+
1) PRIMARY KEY,
|
42
|
+
[name] varchar(255) NOT NULL,
|
43
|
+
[password] text NOT NULL
|
44
|
+
);
|
45
|
+
|
46
|
+
CREATE TABLE mailinglist_classes (
|
47
|
+
[id] int NOT NULL IDENTITY(1,
|
48
|
+
1) PRIMARY KEY,
|
49
|
+
[name] text NOT NULL,
|
50
|
+
[description] text,
|
51
|
+
[public] bit DEFAULT 0 NOT NULL,
|
52
|
+
[closed] bit DEFAULT 0 NOT NULL,
|
53
|
+
[moderated] bit DEFAULT 0 NOT NULL,
|
54
|
+
[confirmation] bit DEFAULT 1 NOT NULL,
|
55
|
+
[joinable] bit DEFAULT 1 NOT NULL,
|
56
|
+
[archived] bit DEFAULT 0,
|
57
|
+
[proxify] bit DEFAULT 0
|
58
|
+
);
|
59
|
+
|
60
|
+
CREATE TABLE mailinglists (
|
61
|
+
[id] int NOT NULL IDENTITY(1,
|
62
|
+
1) PRIMARY KEY,
|
63
|
+
[user_id] int,
|
64
|
+
[name] text NOT NULL,
|
65
|
+
[description] text,
|
66
|
+
[welcome_admin_message_id] int DEFAULT 1,
|
67
|
+
[confirmed_admin_message_id] int DEFAULT 2,
|
68
|
+
[sayonara_admin_message_id] int DEFAULT 3,
|
69
|
+
[mailinglist_class_id] int
|
70
|
+
);
|
71
|
+
|
72
|
+
CREATE TABLE messages (
|
73
|
+
[id] int NOT NULL IDENTITY(1,
|
74
|
+
1) PRIMARY KEY,
|
75
|
+
[mailinglist_id] int,
|
76
|
+
[address_id] int,
|
77
|
+
[parent_id] int,
|
78
|
+
[subject] varchar(255),
|
79
|
+
[messageid] varchar(255),
|
80
|
+
[timestamp] datetime,
|
81
|
+
[headers] text,
|
82
|
+
[body] text,
|
83
|
+
[envelope_from] text,
|
84
|
+
[envelope_to] text
|
85
|
+
);
|
86
|
+
|
87
|
+
CREATE TABLE proxy_links (
|
88
|
+
[id] int NOT NULL IDENTITY(1,
|
89
|
+
1) PRIMARY KEY,
|
90
|
+
[mailinglist_id] int NOT NULL,
|
91
|
+
[address_id] int NOT NULL
|
92
|
+
);
|
93
|
+
|
94
|
+
CREATE TABLE users (
|
95
|
+
[id] int NOT NULL IDENTITY(1,
|
96
|
+
1) PRIMARY KEY,
|
97
|
+
[login] text NOT NULL,
|
98
|
+
[password] text NOT NULL,
|
99
|
+
[mailinglist_id] int,
|
100
|
+
[domainadmin] bit DEFAULT 0,
|
101
|
+
[domain_id] int,
|
102
|
+
[mailinglistadmin] bit DEFAULT 0,
|
103
|
+
[virtual] bit DEFAULT 0
|
104
|
+
);
|
105
|
+
|
106
|
+
|
107
|
+
-- schema version meta-info
|
108
|
+
|
109
|
+
CREATE TABLE schema_info (
|
110
|
+
[version] int
|
111
|
+
);
|
112
|
+
|
113
|
+
insert into schema_info (version) values (25);
|
data/db/schema_version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
25
|
data/doc/README_FOR_APP
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
= Welcome to Sugoi-Mail: an introduction to mailing lists and the mail proxy
|
2
|
+
|
3
|
+
Sugoi-Mail is a new kind of mailing list manager, which combines a
|
4
|
+
whole class of different email distribution schemes into one
|
5
|
+
common thing.
|
6
|
+
|
7
|
+
= Mailing Lists
|
8
|
+
|
9
|
+
== First things first: what's a mailing list?
|
10
|
+
|
11
|
+
A mailing list is, at its most basic, a single email address that
|
12
|
+
redirects email sent to it to multiple email addresses.
|
13
|
+
|
14
|
+
Exactly how it does this can happen in a number of different ways.
|
15
|
+
There are different kinds of behaviours regarding whether it
|
16
|
+
accepts mail for delivery or not. Have a look at the
|
17
|
+
MailinglistClass class for some examples of different kinds of
|
18
|
+
behaviour.
|
19
|
+
|
20
|
+
== A couple of basic mailing list types
|
21
|
+
|
22
|
+
Let's have a look at a couple of basic kinds of mailing lists, to
|
23
|
+
illustrate.
|
24
|
+
|
25
|
+
_List type name_:: Description
|
26
|
+
Distribution list:: A personal list of addresses that one
|
27
|
+
person can send mail to.
|
28
|
+
Discussion list:: A collection of addresses where people on the
|
29
|
+
list can send email to the list address and
|
30
|
+
it's broadcast to all of them.
|
31
|
+
|
32
|
+
Those are both almost the same thing, where the only difference is
|
33
|
+
in who's allowed to send email to the list. Expressed as
|
34
|
+
MailinglistClass classes, a distribution list looks like this:
|
35
|
+
|
36
|
+
MailinglistClass.new do |distrib|
|
37
|
+
# Identification details
|
38
|
+
distrib.name = "Distribution List"
|
39
|
+
distrib.description = 'Personal distribution list'
|
40
|
+
|
41
|
+
# Mailing details
|
42
|
+
distrib.public = false
|
43
|
+
distrib.closed = true
|
44
|
+
distrib.moderated = false
|
45
|
+
distrib.archived = false
|
46
|
+
|
47
|
+
# Modification details
|
48
|
+
distrib.joinable = false
|
49
|
+
distrib.confirmation = false
|
50
|
+
end
|
51
|
+
|
52
|
+
This is a private, closed, unmoderated, non-joinable,
|
53
|
+
non-confirmation mailing list.
|
54
|
+
|
55
|
+
The key detail is "closed" here--in a closed mailing list, only
|
56
|
+
the owner is permitted to send mail to it.
|
57
|
+
|
58
|
+
Let's compare that to a discussion list, whose class may be
|
59
|
+
defined as follows:
|
60
|
+
|
61
|
+
MailinglistClass.new do |discussion|
|
62
|
+
distrib.name = "Discussion List"
|
63
|
+
distrib.description = "An unmoderated discussion list"
|
64
|
+
|
65
|
+
distrib.public = false
|
66
|
+
distrib.closed = false
|
67
|
+
distrib.moderated = false
|
68
|
+
distrib.archive = true
|
69
|
+
|
70
|
+
distrib.joinable = true
|
71
|
+
distrib.confirmation = true
|
72
|
+
end
|
73
|
+
|
74
|
+
The difference in delivery details is that where a distribution
|
75
|
+
list is closed, a discussion list is _open_--anyone on the mailing
|
76
|
+
list can send email to the mailing list's email address and it
|
77
|
+
will be delivered to everyone.
|
78
|
+
|
79
|
+
The other difference is in modification details--where a
|
80
|
+
distribution list can only be modified by the owner, the
|
81
|
+
discussion list is _joinable_. This means that people can send
|
82
|
+
email to the mailing list's "request" address asking the system to
|
83
|
+
automatically subscribe them to the mailing list.
|
84
|
+
|
85
|
+
Also, the "confirmation" parameter is set to true to prevent
|
86
|
+
abuse. When a subscription request is received, an email message
|
87
|
+
is sent to the address the subscription request was made for with
|
88
|
+
a confirmation code in it, asking the person at that email address
|
89
|
+
to verify that it's a genuine email address and that a request
|
90
|
+
really was made.
|
91
|
+
|
92
|
+
You may know of services with names like "pobox.com", which allow
|
93
|
+
you to keep a single email address which forwards your email to
|
94
|
+
whatever email address your ISP's given you this week. Anyone
|
95
|
+
who's had their ISP be bought out from underneath them and then
|
96
|
+
had their email address change from myname@smallisp.boulder.co.us to
|
97
|
+
myname27@hugeisp.com will understand how this could be handy.
|
98
|
+
|
99
|
+
== More interesting mailing list classes 1: Mail Proxy
|
100
|
+
|
101
|
+
Okay, suppose that you want to set up a service like this up? How
|
102
|
+
would you do the email forwarding? It's a kind of mailing list,
|
103
|
+
of course!
|
104
|
+
|
105
|
+
MailinglistClass.new do |forward|
|
106
|
+
forward.name = 'LTMA'
|
107
|
+
forward.description = 'Lifetime Mail Address'
|
108
|
+
|
109
|
+
forward.public = true
|
110
|
+
forward.closed = false
|
111
|
+
forward.moderated = false
|
112
|
+
forward.archive = false
|
113
|
+
|
114
|
+
forward.joinable = false
|
115
|
+
forward.confirmation = true
|
116
|
+
end
|
117
|
+
|
118
|
+
Indeed, it was for this very reason that Sugoi-Mail originally had
|
119
|
+
a User class in the first place, so be sure to check that out.
|
120
|
+
You'll notice that every User has a Mailinglist which has the same
|
121
|
+
name as the User--that's their forwarding address.
|
122
|
+
|
123
|
+
== More interesting mailing list classes 2: Web Bulletin Board
|
124
|
+
|
125
|
+
You see that +archive+ parameter in all those mailing list class
|
126
|
+
declarations? Those say whether the the mail system should save
|
127
|
+
messages that are sent to the mailing list or not. In the case of
|
128
|
+
a forwarding address, it doesn't make very much sense to archive
|
129
|
+
all messages coming through (although one could very easily set up
|
130
|
+
a webmail system simply by not letting users add any email
|
131
|
+
addresses to their mailing list--see the User section below--and
|
132
|
+
letting them access their email messages via the web).
|
133
|
+
|
134
|
+
If you have a mailing list with no subscribers, that people are
|
135
|
+
allowed to send messages to via some sort of a web interface--what
|
136
|
+
you have is a web bulletin board!
|
137
|
+
|
138
|
+
And if you add email subscribers to the bulletin board, you also
|
139
|
+
gain the ability for people to participate via email. I, for one
|
140
|
+
don't much like posting messages to the Internet via web forms (I
|
141
|
+
even update my blog offline), so the ability to participate by
|
142
|
+
email would be a nice feature. By the same token, others find
|
143
|
+
that email is a big pain to configure and get working correctly,
|
144
|
+
so they prefer to participate in online communities through a web
|
145
|
+
interface. Well, with Sugoi-Mail, you can have both at the same
|
146
|
+
time! (On my TODO list, in the distant future, is an NNTP
|
147
|
+
interface, to support people who prefer USENET clients.)
|
148
|
+
|
149
|
+
= Users
|
150
|
+
|
151
|
+
Now that we have the introduction to mailing lists out of the way,
|
152
|
+
I should talk about users. Users are the reason that this entire
|
153
|
+
project was started in the first place--I wanted to make some sort
|
154
|
+
of a replacement for pobox.com that didn't depend on a really busy
|
155
|
+
sysadmin.
|
156
|
+
|
157
|
+
This meant letting users be able to manage their own email
|
158
|
+
aliases, and if possible, their own mailing lists. Quite a lot of
|
159
|
+
the code you'll find in this project grew directly out of
|
160
|
+
real-world requirements. (Any limitations in the existing system
|
161
|
+
are most likely a direct result of the feature being outside the
|
162
|
+
scope of the problems I was trying to solve. If I overlooked
|
163
|
+
something, please contact me!)
|
164
|
+
|
165
|
+
So Users are pretty central to the whole Sugoi-Mail system--they
|
166
|
+
caused it to happen. Make sure you have a look at the
|
167
|
+
documentation for the User class, otherwise you might be confused
|
168
|
+
by the next bit.
|
169
|
+
|
170
|
+
== Proxy address
|
171
|
+
|
172
|
+
Every User has a proxy address, which is actually the name of
|
173
|
+
their Mailinglist. (A user could potentially change their
|
174
|
+
Sugoi-Mail email address without changing their userid.) If you
|
175
|
+
look at the code for User, you'll notice that the user's address
|
176
|
+
comes straight from the User's Mailinglist, and is completely
|
177
|
+
separate from his login credentials. Likewise, when you add
|
178
|
+
addresses to a User, you're actually modifying that user's
|
179
|
+
Mailinglist.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
MAILING LIST CLASSES
|
2
|
+
|
3
|
+
There are a bunch of flags that are used to describe the different attributes
|
4
|
+
of mailing lists. Since these flags are by necessity rather short (a flag
|
5
|
+
called anyone_can_send_to_the_mailing_list would certainly be clearer, but I
|
6
|
+
feel it'd clutter up the code unnecessarily), here's a list of them and what
|
7
|
+
they're for.
|
8
|
+
|
9
|
+
|
10
|
+
FLAG MEANING
|
11
|
+
public: true -> anyone can post to it (spammy!)
|
12
|
+
false -> only members can post to it <-- DEFAULT
|
13
|
+
|
14
|
+
closed: true -> only the owner can post to it
|
15
|
+
false -> other people can post to it <-- DEFAULT
|
16
|
+
|
17
|
+
moderated: true -> posted messages go to the owner first
|
18
|
+
false -> posted messages are broadcast <-- DEFAULT
|
19
|
+
|
20
|
+
confirmation: true -> subscriptions have to be confirmed <-- DEFAULT
|
21
|
+
false -> subscriptions happen automatically
|
22
|
+
|
23
|
+
joinable: true -> people can subscribe to the list at will <- DEFAULT
|
24
|
+
false -> only the owner can subscribe or unsubscribe people
|
25
|
+
|
26
|
+
archived: true -> all email sent to this address is stored
|
27
|
+
false -> all email sent to this address is discarded after being
|
28
|
+
processed
|
data/lib/daemonize.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Daemonize
|
2
|
+
VERSION = "0.1.2"
|
3
|
+
|
4
|
+
# Try to fork if at all possible retrying every 5 sec if the
|
5
|
+
# maximum process limit for the system has been reached
|
6
|
+
def safefork
|
7
|
+
tryagain = true
|
8
|
+
|
9
|
+
while tryagain
|
10
|
+
tryagain = false
|
11
|
+
begin
|
12
|
+
if pid = fork
|
13
|
+
return pid
|
14
|
+
end
|
15
|
+
rescue Errno::EWOULDBLOCK
|
16
|
+
sleep 5
|
17
|
+
tryagain = true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method causes the current running process to become a daemon
|
23
|
+
# If closefd is true, all existing file descriptors are closed
|
24
|
+
def daemonize(oldmode=0, closefd=false)
|
25
|
+
srand # Split rand streams between spawning and daemonized process
|
26
|
+
safefork and exit # Fork and exit from the parent
|
27
|
+
|
28
|
+
# Detach from the controlling terminal
|
29
|
+
unless sess_id = Process.setsid
|
30
|
+
raise 'Cannot detach from controlled terminal'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Prevent the possibility of acquiring a controlling terminal
|
34
|
+
if oldmode.zero?
|
35
|
+
trap 'SIGHUP', 'IGNORE'
|
36
|
+
exit if pid = safefork
|
37
|
+
end
|
38
|
+
|
39
|
+
Dir.chdir "/" # Release old working directory
|
40
|
+
File.umask 0000 # Insure sensible umask
|
41
|
+
|
42
|
+
if closefd
|
43
|
+
# Make sure all file descriptors are closed
|
44
|
+
ObjectSpace.each_object(IO) do |io|
|
45
|
+
unless [STDIN, STDOUT, STDERR].include?(io)
|
46
|
+
io.close rescue nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
STDIN.reopen "/dev/null" # Free file descriptors and
|
52
|
+
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible
|
53
|
+
STDERR.reopen STDOUT # STDOUT/STDERR should go to a logfile
|
54
|
+
return oldmode ? sess_id : 0 # Return value is mostly irrelevant
|
55
|
+
end
|
56
|
+
end
|