secret_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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Rune Myrland
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,24 @@
1
+ = secret_mail
2
+
3
+ **Still under heavy developmnet**
4
+
5
+ Maintains a table of secret mail addresses, with a crypted version of the address
6
+ which may send to it, and an action which is to performed on the mails. The actions
7
+ are handled in an controller class which is meant to be overridden and extended
8
+ by applications.
9
+
10
+ Typical usage will be posting to blogs via an email interface.
11
+
12
+ == Note on Patches/Pull Requests
13
+
14
+ * Fork the project.
15
+ * Make your feature addition or bug fix.
16
+ * Add tests for it. This is important so I don't break it in a
17
+ future version unintentionally.
18
+ * Commit, do not mess with rakefile, version, or history.
19
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
20
+ * Send me a pull request. Bonus points for topic branches.
21
+
22
+ == Copyright
23
+
24
+ Copyright (c) 2010 Rune Myrland. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "secret_mail"
8
+ gem.summary = %Q{Maintan a database of secret mail adresses.}
9
+ gem.description = %Q{The secret mail address is mapped to a sender address and a forwarding address or action}
10
+ gem.email = "rune@epubify.com"
11
+ gem.homepage = "http://github.com/wrimle/secret_mail"
12
+ gem.authors = ["Rune Myrland"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "secret_mail #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,19 @@
1
+ class CreateTables < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :mail_actions do |t|
4
+ t.string :secret_mail
5
+ t.string :crypted_from
6
+ t.string :salt
7
+ t.string :packed_action
8
+ t.string :packed_params
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :mail_actions, :secret_mail
14
+ end
15
+
16
+ def self.down
17
+ drop_table :mail_actions
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ require 'mail'
2
+
3
+
4
+ class UnkownAction < StandardError
5
+ end
6
+
7
+
8
+ module SecretMail
9
+ class Controller
10
+ def self.process message, &block
11
+ record = MailAction.find_valid(message.to, message.from)
12
+ if record
13
+ Controller.new record, message, &block
14
+ end
15
+ end
16
+
17
+
18
+ def create
19
+ s = MailAction.create(@message.from[0], @record.params, @message.subject)
20
+ s.save
21
+ @created = s
22
+ end
23
+
24
+
25
+ def destroy
26
+ s = MailAction.find_valid(@message.subject.strip, @message.from[0])
27
+ s.destroy
28
+ s.save
29
+ end
30
+
31
+
32
+ private
33
+ def initialize record, message, &block
34
+ @record = record
35
+ @message = message
36
+
37
+ action = record.action
38
+ if respond_to?(action)
39
+ send(action.to_s)
40
+ if(@created && block_given?)
41
+ yield :created, @created, message
42
+ end
43
+ else
44
+ if block_given?
45
+ yield action.to_sym, record, message
46
+ else
47
+ raise UnkownAction, "Action: #{action} not implemented in the controller"
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,81 @@
1
+ require 'rubygems'
2
+ require 'base32_pure'
3
+ require 'json'
4
+ require 'uuidtools'
5
+ require 'active_record'
6
+
7
+
8
+ module SecretMail
9
+ class MailAction < ActiveRecord::Base
10
+ def self.create from, action, params = {}
11
+ # Create a secret mail address
12
+ r = SecureRandom.random_bytes(5)
13
+ secret = Base32::Crockford.encode(r).downcase
14
+
15
+ # Create object with sender
16
+ record = MailAction.new({
17
+ :secret_mail => "#{secret}@#{self.mail_domain}",
18
+ :from => from,
19
+ :action => action,
20
+ :params => params,
21
+ })
22
+ end
23
+
24
+
25
+ def self.find_valid secret_mail, from
26
+ s = find_by_secret_mail(secret_mail)
27
+ if s && s.crypted_from
28
+ s.valid_sender?(from) ? s : nil
29
+ else
30
+ s
31
+ end
32
+ end
33
+
34
+ def from= v
35
+ self.salt = UUIDTools::UUID::random_create.to_s
36
+ self.crypted_from = MailAction.sign(salt, v)
37
+ end
38
+
39
+
40
+ def valid_sender? v
41
+ crypted_from == MailAction.sign(salt, v)
42
+ end
43
+
44
+
45
+ def action= v
46
+ self.packed_action = [v].to_json
47
+ end
48
+
49
+
50
+ def action
51
+ (self.packed_action && JSON.parse(self.packed_action)[0]) || nil
52
+ end
53
+
54
+
55
+ def params= v
56
+ self.packed_params = [v].to_json
57
+ end
58
+
59
+
60
+ def params
61
+ (self.packed_params && JSON.parse(self.packed_params)[0]) || nil
62
+ end
63
+
64
+
65
+ protected
66
+ def self.mail_domain v = nil
67
+ if v
68
+ @mail_domain = v
69
+ else
70
+ @mail_domain
71
+ end
72
+ end
73
+
74
+
75
+ def self.sign salt, v
76
+ namespace = UUIDTools::UUID.parse(salt)
77
+ UUIDTools::UUID.sha1_create(namespace, v).hexdigest
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+
2
+ require 'secret_mail/record'
3
+ require 'secret_mail/controller'
@@ -0,0 +1,27 @@
1
+ #!/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'active_record'
5
+ require 'yaml'
6
+ require 'db/create_tables'
7
+
8
+ db_yaml = case
9
+ when File.exists?(f = "config/database.yml") then
10
+ f
11
+ when File.exists?(f = "#{ENV['HOME']}/.secret_mail/config/database.yml") then
12
+ f
13
+ when File.exists?(f = "/etc/secret_mail/database.yml") then
14
+ f
15
+ else
16
+ nil
17
+ end
18
+
19
+ dbconfig = YAML::load(File.open(db_yaml))
20
+ ActiveRecord::Base.establish_connection(dbconfig)
21
+ ActiveRecord::Base.connection
22
+
23
+ begin
24
+ CreateTables.up
25
+ rescue ActiveRecord::StatementInvalid
26
+ puts "Creation failed. Tables already up?"
27
+ end
data/script/db_drop.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'active_record'
5
+ require 'yaml'
6
+ require 'db/create_tables'
7
+
8
+ db_yaml = case
9
+ when File.exists?(f = "config/database.yml") then
10
+ f
11
+ when File.exists?(f = "#{ENV['HOME']}/.secret_mail/config/database.yml") then
12
+ f
13
+ when File.exists?(f = "/etc/secret_mail/database.yml") then
14
+ f
15
+ else
16
+ nil
17
+ end
18
+
19
+ dbconfig = YAML::load(File.open(db_yaml))
20
+ ActiveRecord::Base.establish_connection(dbconfig)
21
+ ActiveRecord::Base.connection
22
+
23
+ begin
24
+ CreateTables.down
25
+ rescue ActiveRecord::StatementInvalid
26
+ puts "Dropping failed. Tables already down?"
27
+ end
@@ -0,0 +1,65 @@
1
+
2
+ describe SecretMail::Controller do
3
+ begin
4
+ end
5
+
6
+ it "takes a mail message and translates it to a controller action" do
7
+ @mail = Mail.new do
8
+ to "blog@example.com"
9
+ from "from@example.com"
10
+ subject "user@example.com"
11
+ body "A body"
12
+ end
13
+
14
+ controller = SecretMail::Controller::process(@mail)
15
+ end
16
+
17
+
18
+ it "creates a new secret mail address if email address has action create" do
19
+ @mail = Mail.new do
20
+ to "blog@example.com"
21
+ from "from@example.com"
22
+ subject "user@example.com"
23
+ body "A body"
24
+ end
25
+
26
+ controller = SecretMail::Controller::process(@mail)
27
+ controller.instance_eval do
28
+ secret_mail = @created.secret_mail
29
+ r = SecretMail::MailAction.find_valid(secret_mail, "from@example.com")
30
+ r.should_not == nil
31
+
32
+ r.action.should_not == nil
33
+ r.params.should_not == nil
34
+ r.salt.should_not == nil
35
+ r.crypted_from.should_not == nil
36
+ end
37
+ end
38
+
39
+
40
+ it "destroys a secret mail address if email address has action destroy" do
41
+ create_mail = Mail.new do
42
+ to "blog@example.com"
43
+ from "from@example.com"
44
+ subject "user@example.com"
45
+ body "A body"
46
+ end
47
+
48
+ controller = SecretMail::Controller::process(create_mail)
49
+
50
+ destroy_mail = Mail.new do
51
+ to "destroy@example.com"
52
+ from "from@example.com"
53
+ body "A body"
54
+ end
55
+ controller.instance_eval do
56
+ destroy_mail.subject @created.secret_mail
57
+ end
58
+ secret_mail = destroy_mail.subject
59
+ controller = SecretMail::Controller::process(destroy_mail)
60
+
61
+ record = SecretMail::MailAction.find_valid(secret_mail, "from@example.com")
62
+ record.should == nil
63
+ end
64
+
65
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ include SecretMail
4
+
5
+ describe "MailAction" do
6
+ begin
7
+ salt = UUIDTools::UUID::random_create.to_s
8
+ attributes = {
9
+ :secret_mail => "secret@example.com",
10
+ :from => "from@example.com",
11
+ :action => "mail_to",
12
+ :params => {}
13
+ }
14
+ MailAction.new(attributes).save
15
+ end
16
+
17
+
18
+ it "creates a secret mail address for a sender email and an action" do
19
+ mail_from = "from@example.com"
20
+ action = "mail_to"
21
+ params = { :to => "secret@example.com" }
22
+ record = MailAction::create(mail_from, action, params)
23
+
24
+ record.secret_mail.should be_a(String)
25
+ record.secret_mail.length.should be > 0
26
+ record.secret_mail.should include("@#{MailAction.mail_domain}")
27
+
28
+ record.action.should_not == nil
29
+ record.params.should_not == nil
30
+
31
+ record.should be_valid_sender(mail_from)
32
+ record.save
33
+ end
34
+
35
+
36
+ it "checks that the sender is valid" do
37
+ secret_mail = "secret@example.com"
38
+ from = "wrong@example.com"
39
+ record = MailAction::find_valid(secret_mail, from)
40
+ record.should be(nil)
41
+ end
42
+
43
+
44
+ it "finds an action based on secret_mail and sender" do
45
+ from = "from@example.com"
46
+ # The secret is in the mails to field
47
+ secret_mail = "secret@example.com"
48
+ record = MailAction::find_valid(secret_mail, from)
49
+ record.should_not be(nil)
50
+ record.action.should_not == nil
51
+ end
52
+
53
+
54
+ it "destroys a secret_mail when asked to" do
55
+ from = "from@example.com"
56
+ secret_mail = "secret@example.com"
57
+ record = MailAction::find_valid(secret_mail, from)
58
+ record.should_not be(nil)
59
+ record.destroy
60
+ end
61
+
62
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,44 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'secret_mail'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'fileutils'
7
+ require 'db/create_tables'
8
+
9
+ Spec::Runner.configure do |config|
10
+ SecretMail::MailAction.mail_domain "example.com"
11
+
12
+ ActiveRecord::Base.establish_connection(
13
+ :adapter => "sqlite3",
14
+ :database => "db/test.sqlite3"
15
+ )
16
+ ActiveRecord::Base.connection
17
+ ActiveRecord::Migrator.migrate("db/migrate")
18
+ begin
19
+ CreateTables.down
20
+ rescue
21
+ end
22
+ CreateTables.up
23
+
24
+ attributes = {
25
+ :secret_mail => "blog@example.com",
26
+ :action => "create",
27
+ :params => "mail_to"
28
+ }
29
+ record = SecretMail::MailAction.new(attributes)
30
+ record.save
31
+
32
+ attributes = {
33
+ :secret_mail => "destroy@example.com",
34
+ :action => "destroy",
35
+ :params => {}
36
+ }
37
+ record = SecretMail::MailAction.new(attributes)
38
+ record.save
39
+
40
+
41
+ Mail.defaults do
42
+ delivery_method :test
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: secret_mail
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Rune Myrland
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-22 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 1
32
+ - 2
33
+ - 9
34
+ version: 1.2.9
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: The secret mail address is mapped to a sender address and a forwarding address or action
38
+ email: rune@epubify.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - LICENSE
45
+ - README.rdoc
46
+ files:
47
+ - .document
48
+ - .gitignore
49
+ - LICENSE
50
+ - README.rdoc
51
+ - Rakefile
52
+ - VERSION
53
+ - db/create_tables.rb
54
+ - lib/secret_mail.rb
55
+ - lib/secret_mail/controller.rb
56
+ - lib/secret_mail/record.rb
57
+ - script/db_create.rb
58
+ - script/db_drop.rb
59
+ - spec/controller_spec.rb
60
+ - spec/record_spec.rb
61
+ - spec/spec.opts
62
+ - spec/spec_helper.rb
63
+ has_rdoc: true
64
+ homepage: http://github.com/wrimle/secret_mail
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --charset=UTF-8
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.3.7
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Maintan a database of secret mail adresses.
97
+ test_files:
98
+ - spec/record_spec.rb
99
+ - spec/spec_helper.rb
100
+ - spec/controller_spec.rb