maildiode 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/maildiode +25 -3
- data/lib/maildiode-plugins/alias.rb +5 -3
- data/lib/maildiode-plugins/blacklist.rb +3 -1
- data/lib/maildiode-plugins/delay.rb +1 -0
- data/lib/maildir.rb +5 -2
- data/lib/server.rb +6 -2
- data/lib/settings.rb +41 -3
- data/maildiode.conf.sample +6 -6
- metadata +2 -2
data/bin/maildiode
CHANGED
@@ -72,7 +72,7 @@ module MailDiode
|
|
72
72
|
def self.load_plugins(settings)
|
73
73
|
plugins = []
|
74
74
|
settings.get_settings('plugin').each do | setting |
|
75
|
-
plugins << create_plugin(setting
|
75
|
+
plugins << create_plugin(setting.key, settings)
|
76
76
|
end
|
77
77
|
return plugins
|
78
78
|
end
|
@@ -119,6 +119,23 @@ def uid(user_name)
|
|
119
119
|
return Etc::getpwnam.uid
|
120
120
|
end
|
121
121
|
|
122
|
+
def apply_debug_settings(settings)
|
123
|
+
available_levels = {
|
124
|
+
'error' => Logger::ERROR,
|
125
|
+
'warn' => Logger::WARN,
|
126
|
+
'info' => Logger::INFO,
|
127
|
+
'debug' => Logger::DEBUG,
|
128
|
+
}
|
129
|
+
|
130
|
+
log_level_string = settings.get_setting('debug', 'level')
|
131
|
+
if(log_level_string)
|
132
|
+
level = available_levels[log_level_string]
|
133
|
+
if(level)
|
134
|
+
MailDiode::set_log_level(level)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
122
139
|
def drop_privileges(new_user_name)
|
123
140
|
gid = Etc::getpwnam(new_user_name).gid
|
124
141
|
Process::Sys::setresgid(gid, gid, gid)
|
@@ -132,17 +149,22 @@ def start
|
|
132
149
|
|
133
150
|
MailDiode::log_to_file($log_filename)
|
134
151
|
MailDiode::set_log_level(Logger::INFO)
|
152
|
+
MailDiode::log_info "----Starting MailDiode"
|
135
153
|
|
136
154
|
config_file = MailDiode::Settings.default_file
|
137
155
|
settings = MailDiode::Settings.new(config_file)
|
156
|
+
|
157
|
+
apply_debug_settings(settings)
|
158
|
+
MailDiode::log_debug "Debug logging enabled"
|
159
|
+
|
138
160
|
user = settings.get_setting('server', 'user')
|
139
161
|
user.untaint
|
140
162
|
|
163
|
+
|
141
164
|
plugins = MailDiode::load_plugins(settings)
|
142
165
|
factory = MailDiode::EngineFactory.new(plugins, settings)
|
143
|
-
MailDiode::log_info "Starting server..."
|
144
|
-
MailDiode::log_debug "Debug logging enabled"
|
145
166
|
server = MailDiode::Server.new(factory, settings)
|
167
|
+
MailDiode::log_info "Starting server #{server.ip}:#{server.port}..."
|
146
168
|
server.start
|
147
169
|
if(user)
|
148
170
|
drop_privileges(user)
|
@@ -28,19 +28,21 @@ module MailDiode
|
|
28
28
|
MailDiode::log_debug "alias checking: #{pattern}"
|
29
29
|
re = Regexp.new(pattern, Regexp::IGNORECASE)
|
30
30
|
if(recipient.match(re))
|
31
|
-
MailDiode::
|
31
|
+
MailDiode::log_debug "Alias #{recipient} --> #{target}"
|
32
32
|
filterable_data.recipient = target
|
33
33
|
return
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
MailDiode::
|
37
|
+
MailDiode::log_debug "No alias for #{recipient}"
|
38
38
|
end
|
39
39
|
|
40
40
|
def load_settings(settings)
|
41
41
|
settings.get_settings('alias').each do | setting |
|
42
|
-
|
42
|
+
pattern = setting.key
|
43
|
+
target = setting.value
|
43
44
|
@aliases << [pattern, target]
|
45
|
+
MailDiode::log_debug " #{pattern} -> #{target}"
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
@@ -37,10 +37,12 @@ module MailDiode
|
|
37
37
|
|
38
38
|
def load_settings(settings)
|
39
39
|
settings.get_settings('blacklist').each do | setting |
|
40
|
-
key
|
40
|
+
key = setting.key
|
41
|
+
value = setting.value
|
41
42
|
case key
|
42
43
|
when 'to'
|
43
44
|
@blacklisted_recipients << value
|
45
|
+
MailDiode::log_debug " #{key} X #{value}"
|
44
46
|
else
|
45
47
|
MailDiode::log_warning "Blacklist ignoring unknown: #{key}"
|
46
48
|
end
|
@@ -43,6 +43,7 @@ module MailDiode
|
|
43
43
|
@delay_helo = settings.get_setting('delay', 'helo').to_i
|
44
44
|
@delay_mail = settings.get_setting('delay', 'mail').to_i
|
45
45
|
@delay_rcpt = settings.get_setting('delay', 'rcpt').to_i
|
46
|
+
MailDiode::log_debug " HELO #{@delay_helo} MAIL #{@delay_mail} RCPT #{@delay_rcpt} seconds"
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|
data/lib/maildir.rb
CHANGED
@@ -55,7 +55,7 @@ module MailDiode
|
|
55
55
|
raw_dir = get_maildir(recipient)
|
56
56
|
folder = ''
|
57
57
|
dir = "#{raw_dir.chomp('/')}#{folder}/"
|
58
|
-
MailDiode::log_info "Delivering to #{dir}"
|
58
|
+
MailDiode::log_info "Delivering to #{dir} for #{recipient}"
|
59
59
|
if !File.exist?(dir)
|
60
60
|
MailDiode::log_error "ERROR: Missing maildir folder: #{dir}"
|
61
61
|
raise FolderMissingError.new(File.basename(dir))
|
@@ -100,12 +100,15 @@ module MailDiode
|
|
100
100
|
|
101
101
|
def load_settings(settings)
|
102
102
|
settings.get_settings('maildir').each do | setting |
|
103
|
-
name
|
103
|
+
name = setting.key
|
104
|
+
maildir = setting.value
|
104
105
|
if(maildir.index('/') != 0)
|
105
106
|
raise "Maildir must start with slash (/): #{maildir}"
|
106
107
|
end
|
107
108
|
maildir.untaint
|
108
109
|
@maildirs[name] = maildir
|
110
|
+
#Disabled because this is called per-connection
|
111
|
+
#MailDiode::log_debug " #{name} -> #{maildir}"
|
109
112
|
end
|
110
113
|
end
|
111
114
|
end
|
data/lib/server.rb
CHANGED
@@ -19,6 +19,10 @@ require 'io/wait'
|
|
19
19
|
|
20
20
|
module MailDiode
|
21
21
|
class Server < GServer
|
22
|
+
|
23
|
+
attr_reader :ip
|
24
|
+
attr_reader :port
|
25
|
+
|
22
26
|
def initialize(engine_factory, settings)
|
23
27
|
load_settings(settings)
|
24
28
|
|
@@ -41,7 +45,7 @@ module MailDiode
|
|
41
45
|
while !engine.terminate?
|
42
46
|
line = get_line(client, TIMEOUT_SECONDS)
|
43
47
|
if(!line)
|
44
|
-
MailDiode::log_info("
|
48
|
+
MailDiode::log_info("Client disconnected")
|
45
49
|
return
|
46
50
|
end
|
47
51
|
line.chomp!(NEWLINE)
|
@@ -52,7 +56,7 @@ module MailDiode
|
|
52
56
|
end
|
53
57
|
end
|
54
58
|
rescue Errno::ECONNRESET
|
55
|
-
MailDiode::log_info "
|
59
|
+
MailDiode::log_info "Client dropped connection"
|
56
60
|
rescue Exception => e
|
57
61
|
MailDiode::log_error("Exception #{e.class}: #{e}")
|
58
62
|
e.backtrace.each do | line |
|
data/lib/settings.rb
CHANGED
@@ -15,7 +15,41 @@
|
|
15
15
|
|
16
16
|
|
17
17
|
module MailDiode
|
18
|
+
class SingleSetting
|
19
|
+
attr_reader :key
|
20
|
+
attr_reader :value
|
21
|
+
|
22
|
+
def initialize(key, value)
|
23
|
+
@key = key
|
24
|
+
@value = value
|
25
|
+
end
|
26
|
+
end
|
18
27
|
|
28
|
+
class ComponentSettings
|
29
|
+
def initialize
|
30
|
+
@settings = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def add(new_setting)
|
34
|
+
@settings << new_setting
|
35
|
+
end
|
36
|
+
|
37
|
+
def each
|
38
|
+
@settings.each do | setting |
|
39
|
+
yield setting
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_setting(key)
|
44
|
+
each do | setting |
|
45
|
+
if(setting.key == key)
|
46
|
+
return setting
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
19
53
|
class Settings
|
20
54
|
def initialize(config_file)
|
21
55
|
@settings = {}
|
@@ -30,13 +64,13 @@ module MailDiode
|
|
30
64
|
|
31
65
|
def load_setting(component, keyword, args)
|
32
66
|
component_settings = get_settings(component)
|
33
|
-
component_settings
|
67
|
+
component_settings.add(SingleSetting.new(keyword, args))
|
34
68
|
end
|
35
69
|
|
36
70
|
def get_settings(component)
|
37
71
|
component_settings = @settings[component]
|
38
72
|
if(!component_settings)
|
39
|
-
component_settings =
|
73
|
+
component_settings = ComponentSettings.new
|
40
74
|
@settings[component] = component_settings
|
41
75
|
end
|
42
76
|
return component_settings
|
@@ -47,7 +81,11 @@ module MailDiode
|
|
47
81
|
if(!component_settings)
|
48
82
|
return nil
|
49
83
|
end
|
50
|
-
|
84
|
+
setting = component_settings.get_setting(keyword)
|
85
|
+
if(!setting)
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
return setting.value
|
51
89
|
end
|
52
90
|
|
53
91
|
def get_int(component, keyword, default_value)
|
data/maildiode.conf.sample
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#debug warn # error warn info debug
|
1
|
+
#debug level warn # error warn info debug
|
2
2
|
|
3
3
|
# Basic server info
|
4
4
|
server hostname localhost
|
@@ -12,13 +12,13 @@ maildir bob@example.com /home/bob/mail
|
|
12
12
|
maildir kevin /home/kevins/TestMail/main/
|
13
13
|
maildir catchall /home/kevins/TestMail/other/
|
14
14
|
|
15
|
-
# Aliases
|
15
|
+
# Aliases define a regexp and its corresponding maildir name
|
16
16
|
# (Stops as soon as the first match is hit, so put catchall last)
|
17
17
|
plugin alias
|
18
|
-
alias
|
19
|
-
alias
|
20
|
-
alias
|
21
|
-
alias
|
18
|
+
alias ^kevin@qualitycode.com$ kevin
|
19
|
+
alias ^kevins@qualitycode.com$ kevin
|
20
|
+
alias @qualitycode.com$ catchall
|
21
|
+
alias @example.com$ catchall
|
22
22
|
|
23
23
|
# Blacklist only supports filtering on "to" for now
|
24
24
|
# (handy to limit catchall spam)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maildiode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Smith
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-12-
|
12
|
+
date: 2008-12-13 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|