ruml 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +9 -1
- data/README.md +31 -1
- data/Rakefile +11 -0
- data/bin/ruml +21 -3
- data/lib/ruml/broadcaster.rb +6 -16
- data/lib/ruml/list.rb +3 -3
- data/lib/ruml/version.rb +1 -1
- data/ruml.gemspec +3 -2
- data/test/fixtures/example_ml/bounce_to +1 -0
- data/test/fixtures/example_ml/members +7 -0
- data/test/fixtures/example_ml/name +1 -0
- data/test/fixtures/example_ml/to +1 -0
- data/test/helper.rb +55 -0
- data/test/integration_test.rb +80 -0
- metadata +26 -6
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ruml (0.0.1)
|
5
|
+
mail (~> 2.3.0)
|
6
|
+
|
1
7
|
GEM
|
2
8
|
remote: http://rubygems.org/
|
3
9
|
specs:
|
@@ -7,6 +13,7 @@ GEM
|
|
7
13
|
mime-types (~> 1.16)
|
8
14
|
treetop (~> 1.4.8)
|
9
15
|
mime-types (1.17.2)
|
16
|
+
minitest (2.7.0)
|
10
17
|
polyglot (0.3.2)
|
11
18
|
treetop (1.4.10)
|
12
19
|
polyglot
|
@@ -16,4 +23,5 @@ PLATFORMS
|
|
16
23
|
ruby
|
17
24
|
|
18
25
|
DEPENDENCIES
|
19
|
-
|
26
|
+
minitest
|
27
|
+
ruml!
|
data/README.md
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
Ruby mailing list software
|
4
4
|
|
5
|
-
|
5
|
+
|
6
|
+
## Configration (ruml)
|
7
|
+
|
8
|
+
### File based
|
6
9
|
|
7
10
|
<pre>
|
8
11
|
testml/
|
@@ -17,6 +20,33 @@ testml/
|
|
17
20
|
* member - List of member's addresses
|
18
21
|
* bounce_to - Bounce mails go to this email (optional)
|
19
22
|
|
23
|
+
|
24
|
+
## Configuration (Postfix)
|
25
|
+
|
26
|
+
### Postfix
|
27
|
+
|
28
|
+
#### /etc/postfix/ml-maps
|
29
|
+
|
30
|
+
<pre>
|
31
|
+
/^testml@example.com$/ ml-testml
|
32
|
+
/^testml-bounce@mail.info$/ testml-bounce@mail.info
|
33
|
+
</pre>
|
34
|
+
|
35
|
+
#### /etc/postfix/ml-aliases
|
36
|
+
|
37
|
+
<pre>
|
38
|
+
ml-testml: "|/path/to/bin/ruml /var/spool/ruml/lists/testml"
|
39
|
+
</pre>
|
40
|
+
|
41
|
+
#### /etc/postfix/main.cf
|
42
|
+
|
43
|
+
<pre>
|
44
|
+
virtual_alias_maps = regexp:/etc/postfix/ml-maps
|
45
|
+
alias_maps = hash:/etc/postfix/ml-aliases
|
46
|
+
alias_database = hash:/etc/postfix/ml-aliases
|
47
|
+
</pre>
|
48
|
+
|
49
|
+
|
20
50
|
## TODO
|
21
51
|
|
22
52
|
* Write tests!
|
data/Rakefile
CHANGED
@@ -1 +1,12 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
# Test
|
4
|
+
require 'rake/testtask'
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
Rake::TestTask.new(:test) do |test|
|
9
|
+
test.test_files = FileList.new('test/*_test.rb')
|
10
|
+
test.libs << 'test'
|
11
|
+
test.verbose = true
|
12
|
+
end
|
data/bin/ruml
CHANGED
@@ -1,8 +1,26 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$debug = ENV['DEBUG']
|
4
|
-
|
5
3
|
require 'ruml'
|
6
4
|
|
5
|
+
# TODO test!
|
6
|
+
if %w[true 1 on].include?(ENV['DEBUG'])
|
7
|
+
Mail.defaults do
|
8
|
+
spitter = Class.new do
|
9
|
+
def initialize(settings)
|
10
|
+
end
|
11
|
+
|
12
|
+
def deliver!(mail)
|
13
|
+
puts mail
|
14
|
+
puts "=" * 80
|
15
|
+
end
|
16
|
+
end
|
17
|
+
delivery_method spitter
|
18
|
+
end
|
19
|
+
else
|
20
|
+
Mail.defaults do
|
21
|
+
delivery_method :sendmail
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
7
25
|
ml = Ruml.new(ARGV[0])
|
8
|
-
ml.broadcast!(
|
26
|
+
ml.broadcast!($stdin.read)
|
data/lib/ruml/broadcaster.rb
CHANGED
@@ -47,6 +47,10 @@ module Ruml
|
|
47
47
|
@ml.to
|
48
48
|
end
|
49
49
|
|
50
|
+
def recipients
|
51
|
+
@ml.members
|
52
|
+
end
|
53
|
+
|
50
54
|
def subject
|
51
55
|
if @ml.name && !@message.subject.include?(@ml.name)
|
52
56
|
"#{@ml.name} #{@message.subject}"
|
@@ -56,30 +60,16 @@ module Ruml
|
|
56
60
|
end
|
57
61
|
|
58
62
|
def send!
|
59
|
-
@ml.members.each do |recipient|
|
60
|
-
send_to(recipient)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def send_to(recipient)
|
65
63
|
mail = Mail.new
|
66
64
|
mail.subject subject
|
67
65
|
mail.from from
|
68
66
|
mail.to to
|
69
|
-
mail.bcc
|
67
|
+
mail.bcc recipients
|
70
68
|
|
71
69
|
add_headers! mail
|
72
70
|
add_body! mail
|
73
|
-
deliver! mail
|
74
|
-
end
|
75
71
|
|
76
|
-
|
77
|
-
if $debug
|
78
|
-
puts mail.to_s
|
79
|
-
else
|
80
|
-
mail.delivery_method :sendmail
|
81
|
-
mail.deliver
|
82
|
-
end
|
72
|
+
mail.deliver
|
83
73
|
end
|
84
74
|
end
|
85
75
|
end
|
data/lib/ruml/list.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Ruml
|
2
2
|
class List
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :dir
|
4
4
|
|
5
5
|
def initialize(dir)
|
6
|
+
raise ArgumentError, "Couldn't find mailing list in #{dir.inspect}" unless File.directory?(dir)
|
6
7
|
@dir = dir
|
7
|
-
raise "Unknown ml #{name} (#{@dir})" unless File.directory?(@dir)
|
8
8
|
end
|
9
9
|
|
10
10
|
def id
|
@@ -16,7 +16,7 @@ module Ruml
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def members
|
19
|
-
@members ||= readlines("members").reject { |member| member =~ /^#|^$/ }
|
19
|
+
@members ||= readlines("members").map(&:downcase).uniq.reject { |member| member =~ /^#|^$/ }
|
20
20
|
end
|
21
21
|
|
22
22
|
def to
|
data/lib/ruml/version.rb
CHANGED
data/ruml.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "ruml"
|
3
|
+
require "ruml/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "ruml"
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
|
19
|
+
s.add_development_dependency "minitest"
|
20
|
+
|
20
21
|
s.add_runtime_dependency "mail", "~> 2.3.0"
|
21
22
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
test-ml-bounce@example.com
|
@@ -0,0 +1 @@
|
|
1
|
+
[Test ML]
|
@@ -0,0 +1 @@
|
|
1
|
+
test-ml@example.com
|
data/test/helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'minitest/spec'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
|
7
|
+
require 'ruml'
|
8
|
+
|
9
|
+
Mail.defaults do
|
10
|
+
delivery_method :test
|
11
|
+
end
|
12
|
+
|
13
|
+
module RumlTestSupport
|
14
|
+
def exec_ruml(arg, input)
|
15
|
+
# TODO execute "bin/ruml" directly
|
16
|
+
begin
|
17
|
+
ml = Ruml.new(arg)
|
18
|
+
ml.broadcast!(input)
|
19
|
+
"" # empty output
|
20
|
+
rescue => e
|
21
|
+
"#{e.message} (#{e.class})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def fixture_path(*name)
|
26
|
+
File.join(File.dirname(__FILE__), "fixtures", *name.map(&:to_s))
|
27
|
+
end
|
28
|
+
|
29
|
+
def deliveries
|
30
|
+
Mail::TestMailer.deliveries
|
31
|
+
end
|
32
|
+
|
33
|
+
def example_ml_path
|
34
|
+
fixture_path "example_ml"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
MiniTest::Unit::TestCase.send :include, RumlTestSupport
|
39
|
+
|
40
|
+
MiniTest::Unit::TestCase.add_setup_hook do
|
41
|
+
Mail::TestMailer.deliveries.clear
|
42
|
+
end
|
43
|
+
|
44
|
+
module Kernel
|
45
|
+
def capture_output
|
46
|
+
out = StringIO.new
|
47
|
+
$stdout = out
|
48
|
+
$stderr = out
|
49
|
+
yield
|
50
|
+
return out.string
|
51
|
+
ensure
|
52
|
+
$stdout = STDOUT
|
53
|
+
$stdout = STDERR
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe "Ruml binary" do
|
4
|
+
it "fails with TypeError w/o arguments" do
|
5
|
+
output = exec_ruml nil, nil
|
6
|
+
output.must_match "can't convert nil into String (TypeError)"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "fails with ArgumentError using invalid list path" do
|
10
|
+
output = exec_ruml "invalid path", nil
|
11
|
+
output.must_match "Couldn't find mailing list in \"invalid path\" (ArgumentError)"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "fails with NoMethodError on empty input" do
|
15
|
+
output = exec_ruml example_ml_path, nil
|
16
|
+
output.must_match "undefined method `size' for nil:NilClass (NoMethodError)"
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "with example_ml" do
|
20
|
+
let(:mailing_list) { Ruml::List.new(example_ml_path) }
|
21
|
+
|
22
|
+
it "refuse email from unknown member" do
|
23
|
+
mail = compose_mail(mailing_list, :from => "unknown@member.com")
|
24
|
+
output = exec_ruml mailing_list.dir, mail.to_s
|
25
|
+
output.must_be_empty
|
26
|
+
deliveries.must_be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "from valid member" do
|
30
|
+
let(:mail) { compose_mail(mailing_list) }
|
31
|
+
let(:output) { exec_ruml mailing_list.dir, mail.to_s }
|
32
|
+
let(:delivery) { output; deliveries.first }
|
33
|
+
|
34
|
+
it "output is empty" do
|
35
|
+
output.must_be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it "delivers to mailing list & its members" do
|
39
|
+
k = (mailing_list.members + [ mailing_list.to ]).sort
|
40
|
+
delivery.destinations.sort.must_equal k
|
41
|
+
deliveries.size.must_equal 1
|
42
|
+
end
|
43
|
+
|
44
|
+
it "contains valid headers" do
|
45
|
+
delivery.subject.must_include mailing_list.name
|
46
|
+
delivery.subject.must_include mail.subject
|
47
|
+
delivery.from.must_equal mail.from
|
48
|
+
delivery.to.must_equal [ mailing_list.to ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "contains valid extra headers" do
|
52
|
+
delivery['X-BeenThere'].value.must_equal mailing_list.to
|
53
|
+
delivery['List-Id'].value.must_include mailing_list.id
|
54
|
+
delivery['List-Post'].value.must_include "mailto:"
|
55
|
+
delivery['List-Post'].value.must_include mailing_list.to
|
56
|
+
delivery['Sender'].value.must_equal mailing_list.bounce_to
|
57
|
+
delivery['Errors-To'].value.must_equal mailing_list.bounce_to
|
58
|
+
end
|
59
|
+
|
60
|
+
#it "contains users agent" do
|
61
|
+
#end
|
62
|
+
|
63
|
+
it "contains correct body" do
|
64
|
+
delivery.body.encoded.must_equal mail.body.encoded
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def compose_mail(ml, options={}, &block)
|
72
|
+
defaults = {
|
73
|
+
:from => ml.members.first,
|
74
|
+
:to => ml.to,
|
75
|
+
:subject => "Some subject",
|
76
|
+
:body => "some body"
|
77
|
+
}
|
78
|
+
Mail.new(defaults.merge(options), &block)
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Peter Suschlik
|
@@ -15,12 +15,26 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-10-
|
18
|
+
date: 2011-10-29 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: minitest
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: mail
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
24
38
|
none: false
|
25
39
|
requirements:
|
26
40
|
- - ~>
|
@@ -32,7 +46,7 @@ dependencies:
|
|
32
46
|
- 0
|
33
47
|
version: 2.3.0
|
34
48
|
type: :runtime
|
35
|
-
version_requirements: *
|
49
|
+
version_requirements: *id002
|
36
50
|
description: ""
|
37
51
|
email:
|
38
52
|
- peter@suschlik.de
|
@@ -59,6 +73,12 @@ files:
|
|
59
73
|
- lib/ruml/list.rb
|
60
74
|
- lib/ruml/version.rb
|
61
75
|
- ruml.gemspec
|
76
|
+
- test/fixtures/example_ml/bounce_to
|
77
|
+
- test/fixtures/example_ml/members
|
78
|
+
- test/fixtures/example_ml/name
|
79
|
+
- test/fixtures/example_ml/to
|
80
|
+
- test/helper.rb
|
81
|
+
- test/integration_test.rb
|
62
82
|
homepage: https://github.com/splattael/ruml
|
63
83
|
licenses: []
|
64
84
|
|