[DRE-commits] [schleuder] 05/52: New upstream version 3.0.0~beta8

Georg Faerber georg-alioth-guest at moszumanska.debian.org
Mon Feb 6 11:21:18 UTC 2017


This is an automated email from the git hooks/post-receive script.

georg-alioth-guest pushed a commit to branch master
in repository schleuder.

commit 8b7de6053009a3f6a8c902d442791d9d3e83f1ec
Author: Georg Faerber <georg at riseup.net>
Date:   Mon Nov 28 17:22:13 2016 +0100

    New upstream version 3.0.0~beta8
---
 .gitignore                                         |   5 +
 .rspec                                             |   2 +
 .travis.yml                                        |  11 +
 Gemfile                                            |   5 +
 Gemfile.lock                                       | 104 +++++++
 README.md                                          |  13 +-
 bin/schleuder-bundler                              |   9 +
 bin/schleuder-smtpd.rb                             |  72 +++++
 db/migrate/20140501103532_create_lists.rb          |  33 +++
 db/migrate/20140501112859_create_subscriptions.rb  |  15 ++
 db/migrate/201508092100_add_language_to_lists.rb   |   5 +
 ...12165700_change_keywords_admin_only_defaults.rb |   8 +
 ...813235800_add_forward_all_incoming_to_admins.rb |   5 +
 ...508141727_change_send_encrypted_only_default.rb |   8 +
 .../201508222143_add_logfiles_to_keep_to_lists.rb  |   5 +
 ...abled_to_delivery_enabled_and_change_default.rb |  12 +
 db/migrate/201508261815_strip_gpg_passphrase.rb    |   9 +
 db/migrate/201508261827_remove_default_mime.rb     |   9 +
 .../20160501172700_fix_headers_to_meta_defaults.rb |   8 +
 etc/schleuder-api-daemon.service                   |   1 +
 gem-public_cert.pem                                |  21 ++
 gems/schleuder-3.0.0.beta6.gem                     | Bin 0 -> 36864 bytes
 gems/schleuder-3.0.0.beta6.gem.sig                 | Bin 0 -> 94 bytes
 gems/schleuder-3.0.0.beta7.gem                     | Bin 0 -> 39424 bytes
 gems/schleuder-3.0.0.beta7.gem.sig                 | Bin 0 -> 564 bytes
 gems/schleuder-3.0.0.beta8.gem                     | Bin 0 -> 39424 bytes
 gems/schleuder-3.0.0.beta8.gem.sig                 | Bin 0 -> 564 bytes
 lib/schleuder/cli.rb                               |   2 +-
 lib/schleuder/version.rb                           |   2 +-
 man/schleuder.8                                    | 199 ++++++++++++++
 man/schleuder.8.ron                                | 136 ++++++++++
 schleuder.gemspec                                  |  97 +++----
 spec/schleuder.yml                                 |   4 +
 spec/schleuder/list_spec.rb                        | 300 +++++++++++++++++++++
 spec/schleuder/runner_spec.rb                      |   8 +
 spec/schleuder/subscription_spec.rb                | 129 +++++++++
 spec/spec_helper.rb                                |  41 +++
 37 files changed, 1209 insertions(+), 69 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..00ada9b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.bundle
+vendor
+*.swp
+db/*.sqlite3
+testmails/*
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..83e16f8
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--color
+--require spec_helper
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..7a9f875
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: ruby
+rvm:
+  - 2.3
+before_install:
+  - gem install bundler
+  - sudo apt-get -qq update
+  - sudo apt-get install -y gnupg2 libgpgme11-dev libsqlite3-dev
+before_script:
+  - SCHLEUDER_ENV=test SCHLEUDER_CONFIG=spec/schleuder.yml bundle exec rake db:create db:schema:load
+script:
+  - bundle exec rspec
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..86b5a17
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,5 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in schleuder.gemspec
+gemspec
+
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..82e288c
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,104 @@
+PATH
+  remote: .
+  specs:
+    schleuder (3.0.0.beta8)
+      activerecord (~> 4.1)
+      mail-gpg (~> 0.2.7)
+      rake (~> 10)
+      sinatra (~> 1)
+      sinatra-contrib (~> 1)
+      sqlite3 (~> 1)
+      thin (~> 1)
+      thor (~> 0)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activemodel (4.2.7.1)
+      activesupport (= 4.2.7.1)
+      builder (~> 3.1)
+    activerecord (4.2.7.1)
+      activemodel (= 4.2.7.1)
+      activesupport (= 4.2.7.1)
+      arel (~> 6.0)
+    activesupport (4.2.7.1)
+      i18n (~> 0.7)
+      json (~> 1.7, >= 1.7.7)
+      minitest (~> 5.1)
+      thread_safe (~> 0.3, >= 0.3.4)
+      tzinfo (~> 1.1)
+    arel (6.0.3)
+    backports (3.6.8)
+    builder (3.2.2)
+    daemons (1.2.3)
+    database_cleaner (1.5.3)
+    diff-lcs (1.2.5)
+    eventmachine (1.2.0.1)
+    gpgme (2.0.12)
+      mini_portile2 (~> 2.1.0)
+    hirb (0.7.3)
+    i18n (0.7.0)
+    json (1.8.3)
+    mail (2.6.4)
+      mime-types (>= 1.16, < 4)
+    mail-gpg (0.2.8)
+      gpgme (~> 2.0, >= 2.0.2)
+      mail (~> 2.5, >= 2.5.3)
+    mime-types (3.1)
+      mime-types-data (~> 3.2015)
+    mime-types-data (3.2016.0521)
+    mini_portile2 (2.1.0)
+    minitest (5.9.1)
+    multi_json (1.12.1)
+    rack (1.6.4)
+    rack-protection (1.5.3)
+      rack
+    rack-test (0.6.3)
+      rack (>= 1.0)
+    rake (10.5.0)
+    rspec (3.5.0)
+      rspec-core (~> 3.5.0)
+      rspec-expectations (~> 3.5.0)
+      rspec-mocks (~> 3.5.0)
+    rspec-core (3.5.4)
+      rspec-support (~> 3.5.0)
+    rspec-expectations (3.5.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.5.0)
+    rspec-mocks (3.5.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.5.0)
+    rspec-support (3.5.0)
+    sinatra (1.4.7)
+      rack (~> 1.5)
+      rack-protection (~> 1.4)
+      tilt (>= 1.3, < 3)
+    sinatra-contrib (1.4.7)
+      backports (>= 2.0)
+      multi_json
+      rack-protection
+      rack-test
+      sinatra (~> 1.4.0)
+      tilt (>= 1.3, < 3)
+    sqlite3 (1.3.12)
+    thin (1.6.4)
+      daemons (~> 1.0, >= 1.0.9)
+      eventmachine (~> 1.0, >= 1.0.4)
+      rack (~> 1.0)
+    thor (0.19.1)
+    thread_safe (0.3.5)
+    tilt (2.0.5)
+    tzinfo (1.2.2)
+      thread_safe (~> 0.1)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  database_cleaner
+  hirb
+  rspec (~> 3.5.0)
+  schleuder!
+
+BUNDLED WITH
+   1.13.6
diff --git a/README.md b/README.md
index 91f8561..a68a0a0 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Schleuder, version 3
 Schleuder is a gpg-enabled mailing list manager with resending-capabilities. Subscribers can communicate encrypted (and pseudonymously) among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list.
 
 Version 3 of schleuder is a complete rewrite, which aims to be more robust, flexible, and internationalized. It
-also provides an API for the optional web interface called [webschleuder](https://git.codecoop.org/schleuder/webschleuder3).
+also provides an API for the optional web interface called [schleuder-web](https://git.codecoop.org/schleuder/schleuder-web).
 
 For more details see <https://schleuder.nadir.org/docs/>.
 
@@ -33,6 +33,7 @@ Additionally these **rubygems** are required (will be installed automatically un
 * active_record
 * sqlite3
 * thor
+* thin
 * mail-gpg
 * sinatra
 * sinatra-contrib
@@ -41,15 +42,15 @@ Additionally these **rubygems** are required (will be installed automatically un
 Installing Schleuder
 ------------
 
-1. Download [the gem](https://git.codecoop.org/schleuder/schleuder3/raw/master/gems/schleuder-3.0.0.beta6.gem) and [the OpenPGP-signature](https://git.codecoop.org/schleuder/schleuder3/raw/master/gems/schleuder-3.0.0.beta6.gem.sig) and verify:
+1. Download [the gem](https://git.codecoop.org/schleuder/schleuder3/raw/master/gems/schleuder-3.0.0.beta8.gem) and [the OpenPGP-signature](https://git.codecoop.org/schleuder/schleuder3/raw/master/gems/schleuder-3.0.0.beta8.gem.sig) and verify:
    ```
    gpg --recv-key 0x75C9B62688F93AC6574BDE7ED8A6EF816E1C6F25
-   gpg --verify schleuder-3.0.0.beta6.gem.sig
+   gpg --verify schleuder-3.0.0.beta8.gem.sig
    ```
 
 2. If all went well install the gem:
    ```
-   gem install schleuder-3.0.0.beta6.gem
+   gem install schleuder-3.0.0.beta8.gem
    ```
 
 3. Set up schleuder:
@@ -77,12 +78,12 @@ List administration
 -------------------
 
 You probably want to install
-[schleuder-conf](https://git.codecoop.org/schleuder/schleuder-conf), too.
+[schleuder-cli](https://git.codecoop.org/schleuder/schleuder-cli), too.
 Otherwise you'd need to edit the database-records manually to change
 list-settings, subscribe addresses, etc.
 
 Optionally consider installing
-[webschleuder](https://git.codecoop.org/schleuder/webschleuder3), the web
+[schleuder-web](https://git.codecoop.org/schleuder/schleuder-web), the web
 interface for schleuder.
 
 
diff --git a/bin/schleuder-bundler b/bin/schleuder-bundler
new file mode 100755
index 0000000..2c7d96b
--- /dev/null
+++ b/bin/schleuder-bundler
@@ -0,0 +1,9 @@
+#!/bin/bash -l
+
+export HOME=/home/$(id -nu)
+# Little helper script to call schleuder through bundler. Useful e.g. for
+# hooking up development code into postfix.
+
+bindir="$(realpath $(dirname $0))"
+cd $bindir/..
+bundle exec ./bin/schleuder $@
diff --git a/bin/schleuder-smtpd.rb b/bin/schleuder-smtpd.rb
new file mode 100755
index 0000000..98edbd1
--- /dev/null
+++ b/bin/schleuder-smtpd.rb
@@ -0,0 +1,72 @@
+#!/usr/bin/env ruby
+require 'socket'
+require 'open3'
+
+trap ("INT") { exit 0 }
+
+def usage
+  puts "Usage: #{File.basename(__FILE__)} [-p portnum]"
+  exit 1
+end
+
+# get args
+case ARGV.first
+when '-h', '--help', 'help'
+  usage
+when '-p'
+  port = ARGV[1].to_i
+  if port == 0
+    usage
+  end
+end
+
+port ||= 25
+schleuderbin = File.join(File.dirname(__FILE__), 'schleuder')
+
+begin
+  # run the server
+  server = TCPServer.new("127.0.0.1", port)
+
+  # receive input
+  while (connection = server.accept)
+    input = ''
+    recipient = ''
+    connection.puts "220 localhost SMTP"
+    begin
+      while line = connection.gets
+        line.chomp!
+        case line[0..3].downcase
+        when 'ehlo', 'helo'
+          connection.puts "250 localhost"
+        when 'mail', 'rset'
+          connection.puts "250 ok"
+        when 'rcpt'
+          recipient = line.split(':').last.gsub(/[<>\s]*/, '')
+          connection.puts "250 ok"
+        when 'data'
+          connection.puts "354 go ahead"
+        when 'quit'
+          connection.puts "221 localhost"
+        when '.'
+          puts "New message to #{recipient}"
+          err, status = Open3.capture2e("#{schleuderbin} work #{recipient}", {stdin_data: input})
+          if status.exitstatus > 0
+            puts "Error from schleuder: #{err}."
+            connection.puts "550 #{err}"
+          else
+            connection.puts "250 ok"
+          end
+        else
+          input << line + "\n"
+        end
+      end
+    rescue IOError
+    end
+    connection.close
+  end
+
+
+rescue => exc
+  $stderr.puts exc
+  exit 1
+end
diff --git a/db/migrate/20140501103532_create_lists.rb b/db/migrate/20140501103532_create_lists.rb
new file mode 100644
index 0000000..a3329d7
--- /dev/null
+++ b/db/migrate/20140501103532_create_lists.rb
@@ -0,0 +1,33 @@
+class CreateLists < ActiveRecord::Migration
+  def change
+    create_table :lists do |t|
+      t.timestamps
+      t.string  :email
+      t.string  :fingerprint
+      t.string  :gpg_passphrase
+      t.string  :log_level, default: 'warn'
+      t.string  :default_mime, default: 'mime'
+      t.string  :subject_prefix, default: ''
+      t.string  :subject_prefix_in, default: ''
+      t.string  :subject_prefix_out, default: ''
+      t.string  :openpgp_header_preference, default: 'signencrypt'
+      t.text    :public_footer, default: ''
+      t.text    :headers_to_meta, default: '["from","to","date",":cc"]'
+      t.text    :bounces_drop_on_headers, default: '{"x-spam-flag":"yes"}'
+      t.text    :keywords_admin_only, default: '["unsubscribe", "unsubscribe", "delete-key"]'
+      t.text    :keywords_admin_notify, default: '["add-key"]'
+      t.boolean :send_encrypted_only, default: false
+      t.boolean :receive_encrypted_only, default: false
+      t.boolean :receive_signed_only, default: false
+      t.boolean :receive_authenticated_only, default: false
+      t.boolean :receive_from_subscribed_emailaddresses_only, default: false
+      t.boolean :receive_admin_only, default: false
+      t.boolean :keep_msgid, default: true
+      t.boolean :bounces_drop_all, default: false
+      t.boolean :bounces_notify_admins, default: true
+      t.boolean :include_list_headers, default: true
+      t.boolean :include_openpgp_header, default: true
+      t.integer :max_message_size_kb, default: 10240
+    end
+  end
+end
diff --git a/db/migrate/20140501112859_create_subscriptions.rb b/db/migrate/20140501112859_create_subscriptions.rb
new file mode 100644
index 0000000..dc4029f
--- /dev/null
+++ b/db/migrate/20140501112859_create_subscriptions.rb
@@ -0,0 +1,15 @@
+class CreateSubscriptions < ActiveRecord::Migration
+  def change
+    create_table :subscriptions do |t|
+      t.integer :list_id
+      t.string  :email
+      t.string  :fingerprint
+      t.boolean :admin, default: false
+      t.boolean :delivery_disabled, default: false
+      t.timestamps
+    end
+
+    add_index :subscriptions, :list_id
+    add_index :subscriptions, [:email, :list_id], unique: true
+  end
+end
diff --git a/db/migrate/201508092100_add_language_to_lists.rb b/db/migrate/201508092100_add_language_to_lists.rb
new file mode 100644
index 0000000..a7f5df6
--- /dev/null
+++ b/db/migrate/201508092100_add_language_to_lists.rb
@@ -0,0 +1,5 @@
+class AddLanguageToLists < ActiveRecord::Migration
+  def change
+    add_column :lists, :language, :string, default: 'en'
+  end
+end
diff --git a/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb b/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb
new file mode 100644
index 0000000..3e218b0
--- /dev/null
+++ b/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb
@@ -0,0 +1,8 @@
+class ChangeKeywordsAdminOnlyDefaults < ActiveRecord::Migration
+  def up
+    change_column_default :lists, :keywords_admin_only, "[\"subscribe\", \"unsubscribe\", \"delete-key\"]"
+  end
+  def down
+    change_column_default :lists, :keywords_admin_only, "[\"unsubscribe\", \"unsubscribe\", \"delete-key\"]"
+  end
+end
diff --git a/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb b/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb
new file mode 100644
index 0000000..48171c6
--- /dev/null
+++ b/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb
@@ -0,0 +1,5 @@
+class AddForwardAllIncomingToAdmins < ActiveRecord::Migration
+  def change
+    add_column :lists, :forward_all_incoming_to_admins, :boolean, default: false
+  end
+end
diff --git a/db/migrate/201508141727_change_send_encrypted_only_default.rb b/db/migrate/201508141727_change_send_encrypted_only_default.rb
new file mode 100644
index 0000000..2a4b2d8
--- /dev/null
+++ b/db/migrate/201508141727_change_send_encrypted_only_default.rb
@@ -0,0 +1,8 @@
+class ChangeSendEncryptedOnlyDefault < ActiveRecord::Migration
+  def up
+    change_column_default :lists, :send_encrypted_only, true
+  end
+  def down
+    change_column_default :lists, :send_encrypted_only, false
+  end
+end
diff --git a/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb b/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb
new file mode 100644
index 0000000..66b6bf8
--- /dev/null
+++ b/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb
@@ -0,0 +1,5 @@
+class AddLogfilesToKeepToLists < ActiveRecord::Migration
+  def change
+    add_column :lists, :logfiles_to_keep, :integer, default: 2
+  end
+end
diff --git a/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb b/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb
new file mode 100644
index 0000000..132ac14
--- /dev/null
+++ b/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb
@@ -0,0 +1,12 @@
+class RenameDeliveryDisabledToDeliveryEnabledAndChangeDefault < ActiveRecord::Migration
+  def up
+    rename_column :subscriptions, :delivery_disabled, :delivery_enabled
+    change_column_default :subscriptions, :delivery_enabled, true
+  end
+
+  def down
+    rename_column :subscriptions, :delivery_enabled, :delivery_disabled
+    change_column_default :subscriptions, :delivery_disabled, false
+  end
+end
+
diff --git a/db/migrate/201508261815_strip_gpg_passphrase.rb b/db/migrate/201508261815_strip_gpg_passphrase.rb
new file mode 100644
index 0000000..891905d
--- /dev/null
+++ b/db/migrate/201508261815_strip_gpg_passphrase.rb
@@ -0,0 +1,9 @@
+class StripGpgPassphrase < ActiveRecord::Migration
+  def up
+    remove_column :lists, :gpg_passphrase
+  end
+
+  def down
+    add_column :lists, :gpg_passphrase, :string
+  end
+end
diff --git a/db/migrate/201508261827_remove_default_mime.rb b/db/migrate/201508261827_remove_default_mime.rb
new file mode 100644
index 0000000..bec7428
--- /dev/null
+++ b/db/migrate/201508261827_remove_default_mime.rb
@@ -0,0 +1,9 @@
+class RemoveDefaultMime < ActiveRecord::Migration
+  def up
+    remove_column :lists, :default_mime
+  end
+
+  def down
+    add_column :lists, :default_mime, :string, default: 'mime'
+  end
+end
diff --git a/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb b/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb
new file mode 100644
index 0000000..7c6c4cc
--- /dev/null
+++ b/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb
@@ -0,0 +1,8 @@
+class FixHeadersToMetaDefaults < ActiveRecord::Migration
+  def up
+    change_column_default :lists, :headers_to_meta, '["from", "to", "date", "cc"]'
+  end
+
+  def down
+  end
+end
diff --git a/etc/schleuder-api-daemon.service b/etc/schleuder-api-daemon.service
index 3838e0b..7d6a68e 100644
--- a/etc/schleuder-api-daemon.service
+++ b/etc/schleuder-api-daemon.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=Schleuder API daemon
+After=local-fs.target network.target
 
 [Service]
 ExecStart=/usr/local/bin/schleuder-api-daemon
diff --git a/gem-public_cert.pem b/gem-public_cert.pem
new file mode 100644
index 0000000..ee53565
--- /dev/null
+++ b/gem-public_cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApzY2hs
+ZXVkZXIyMRUwEwYKCZImiZPyLGQBGRYFbmFkaXIxEzARBgoJkiaJk/IsZAEZFgNv
+cmcwHhcNMTMwOTI5MjAwNzQxWhcNMTQwOTI5MjAwNzQxWjBBMRMwEQYDVQQDDApz
+Y2hsZXVkZXIyMRUwEwYKCZImiZPyLGQBGRYFbmFkaXIxEzARBgoJkiaJk/IsZAEZ
+FgNvcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChGruoNnq3Ir7d
+Fd+ktG0tMZlm2ZSOkuHO5QRrgYLgbBhpTEf8i6AjzoVL0AIC+uMMVY9iE6fzaKUD
+B7SvNtccHskX6zHUVVtSqF9VpbQomWpck0iBqwQIw4vELe2iZ+/ZULKIJI/BY43y
+tX7Ora8izSyPGcu6E1fr5PJI6igFnlEgs/jCjP/JYHf/f49fnIzAJgO0Q7YNNJVr
+R0Zqm1HbYE2t+RtomT2jgCjBtF42hX8+gB4yV5nedfHKyZfD6zd7doPE/pdtpn80
+BrRQbHXlEPDCadHH013j7oL7B5fJlHejX6PFfPtepq3adDQ/O3lFvzfHuJUGjEO5
+QXp7l5+fAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
+BBSBtRuT8QNZTfwVGJKJr5bbDlgk3jAfBgNVHREEGDAWgRRzY2hsZXVkZXIyQG5h
+ZGlyLm9yZzAfBgNVHRIEGDAWgRRzY2hsZXVkZXIyQG5hZGlyLm9yZzANBgkqhkiG
+9w0BAQUFAAOCAQEAOW1oNWquxZegMjQDZF3yTDsXbDAs4JYsLEbjnD2z32nMGvat
+wDxKD0g3XIPHEoEi28/3n6C4Py2J+P7gUObr+wWF8G67nwg2tDjarOia93RcpxqW
+n4NKeyRmvEzQ+yU+X9xiwJ005mc2ME2j3QF+sjDxgd+uCN0ZT77qz2Kk4iuCGOrM
+cuTmrcZdTiHkGhK7UtDn7nk3ShgwrtyC0SqPna+PUMYkPr5FQLVwsOHGExOtVHZX
++VhPezxtXTAQ0pIYXF5NssxnhcngHV8fPs0g4gbU0RRKar9egfgZ8cVITgVauVPt
+HdW17U59V5gWNuJBqqwiV2PJubSZekUq/YMdtg==
+-----END CERTIFICATE-----
diff --git a/gems/schleuder-3.0.0.beta6.gem b/gems/schleuder-3.0.0.beta6.gem
new file mode 100644
index 0000000..1e76f62
Binary files /dev/null and b/gems/schleuder-3.0.0.beta6.gem differ
diff --git a/gems/schleuder-3.0.0.beta6.gem.sig b/gems/schleuder-3.0.0.beta6.gem.sig
new file mode 100644
index 0000000..2f0e1ab
Binary files /dev/null and b/gems/schleuder-3.0.0.beta6.gem.sig differ
diff --git a/gems/schleuder-3.0.0.beta7.gem b/gems/schleuder-3.0.0.beta7.gem
new file mode 100644
index 0000000..ef156fa
Binary files /dev/null and b/gems/schleuder-3.0.0.beta7.gem differ
diff --git a/gems/schleuder-3.0.0.beta7.gem.sig b/gems/schleuder-3.0.0.beta7.gem.sig
new file mode 100644
index 0000000..166f687
Binary files /dev/null and b/gems/schleuder-3.0.0.beta7.gem.sig differ
diff --git a/gems/schleuder-3.0.0.beta8.gem b/gems/schleuder-3.0.0.beta8.gem
new file mode 100644
index 0000000..f901cd6
Binary files /dev/null and b/gems/schleuder-3.0.0.beta8.gem differ
diff --git a/gems/schleuder-3.0.0.beta8.gem.sig b/gems/schleuder-3.0.0.beta8.gem.sig
new file mode 100644
index 0000000..0575b93
Binary files /dev/null and b/gems/schleuder-3.0.0.beta8.gem.sig differ
diff --git a/lib/schleuder/cli.rb b/lib/schleuder/cli.rb
index 6bd7346..aa55524 100644
--- a/lib/schleuder/cli.rb
+++ b/lib/schleuder/cli.rb
@@ -94,7 +94,7 @@ module Schleuder
         say "NOTE: The database was prepared using sqlite. If you prefer to use a different DBMS please edit the 'database'-section in /etc/schleuder/schleuder.yml, create the database, install the corresponding ruby-library (e.g. `gem install mysql`) and run this current command again"
       end
 
-      say "Schleuder has been set up. You can now create a new list using `schleuder-conf`.\nWe hope you enjoy!"
+      say "Schleuder has been set up. You can now create a new list using `schleuder-cli`.\nWe hope you enjoy!"
     rescue => exc
       fatal exc.message
     end
diff --git a/lib/schleuder/version.rb b/lib/schleuder/version.rb
index 296bf25..d543810 100644
--- a/lib/schleuder/version.rb
+++ b/lib/schleuder/version.rb
@@ -1,3 +1,3 @@
 module Schleuder
-  VERSION = '3.0.0.beta7'
+  VERSION = '3.0.0.beta8'
 end
diff --git a/man/schleuder.8 b/man/schleuder.8
new file mode 100644
index 0000000..c0eea90
--- /dev/null
+++ b/man/schleuder.8
@@ -0,0 +1,199 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "SCHLEUDER" "8" "November 2016" "" ""
+.
+.SH "NAME"
+\fBschleuder\fR \- an email hub for groups
+.
+.SH "SYNOPSIS"
+\fBschleuder\fR work \fIlistaddress\fR < \fIemail\fR
+.
+.P
+\fBschleuder\fR \fIother\-command\fR [<\.\.\.>]
+.
+.P
+For other commands see OPTIONS\.
+.
+.SH "DESCRIPTION"
+Schleuder is an email hub for groups\. Subscribers can communicate encryptedly and pseudonymously among themselves, receive emails from non\-subscribers and send emails to non\-subscribers via the list\.
+.
+.P
+Schleuder takes care of all de\- and encryption, stripping of headers, formatting conversions, etc\. Further Schleuder can send out its own public key and receive administrative commands by email\.
+.
+.P
+Email cryptography is handled by using GnuPG\.
+.
+.P
+schleuder(8) is usually called in delivery mode by a \fIMail Transport Agent\fR with an incoming email piped to its standard input\. For more informations on how to integrate Schleuder with your existing mail setup, please look at the Schleuder website: \fIhttp://schleuder\.nadir\.org/\fR
+.
+.SH "GETTING THE PUBLIC KEY OF A LIST"
+Each Schleuder\-list replies with its public key to any email sent to \fIlistname\-sendkey at hostname\fR\. E\.g\. to receive the key for the contact address of the Schleuder project write an email to
+.
+.br
+\fIschleuder\-sendkey at nadir\.org\fR\.
+.
+.SH "EMAIL COMMANDS"
+Schleuder knows some special keywords that trigger different behaviour\. You can e\.g\. subscribe someone, or resend an email to a non\-subscriber using keywords\. See a list of available keywords below\.
+.
+.P
+Keywords require that:
+.
+.IP "\(bu" 4
+they start the line and begin with "x\-",
+.
+.IP "\(bu" 4
+they are written into the beginning of the \fIfirst text\-part\fR of the email (usually that’s just the normal body of the email),
+.
+.IP "\(bu" 4
+possible arguments must be written \fIon the same line\fR as the keyword (exceptions are mentioned in the descriptions below),
+.
+.IP "\(bu" 4
+the email must be \fIencrypted and signed\fR by a list\-member’s key\.
+.
+.IP "" 0
+.
+.P
+Keywords can be repeated within one email at will\. Letter case doesn’t matter\.
+.
+.P
+There are two types of keywords: those to enhance messages sent over the list (“list\-keywords”), and those to request something from Schleuder (“request\-keywords”)\.
+.
+.SS "Resending"
+The resending\-keywords must be included in messages sent to the normal list\-address: \fIlistname at hostname\fR\.
+.
+.TP
+\fBx\-resend:\fR \fIsomeone at example\.org\fR
+Send the message to the given address, encrypted if possible, otherwise in the clear\.
+.
+.TP
+\fBx\-resend\-encrypted\-only:\fR \fIsomeone at example\.org\fR
+Send the message to the given address only if it could be encrypted\.
+.
+.SS "Subscription and key management"
+These keywords must be send to \fIlistname\-request at hostname\fR\. They are used to get information about the list, its subscribers and keys, or to change that information\.
+.
+.TP
+\fBx\-list\-subscriptions\fR
+List all subscriptions\.
+.
+.TP
+\fBx\-subscribe:\fR \fIperson at example\.org\fR \fI12345678DEADBEEF12345678DEADBEEF12345678\fR
+Subscribe the given address and assign it the given OpenPGP\-fingerprint\.
+.
+.TP
+\fBx\-unsubscribe:\fR \fIperson at example\.org\fR
+Unsubscribe the given address\.
+.
+.TP
+\fBx\-set\-fingerprint:\fR \fI12345678DEADBEEF12345678DEADBEEF12345678\fR
+Assign the key with the given fingerprint to your subscription\.
+.
+.TP
+\fBx\-set\-fingerprint:\fR \fIperson at example\.org\fR \fI12345678DEADBEEF12345678DEADBEEF12345678\fR
+Assign the key with the given fingerprint to the given subscription\. This variant of this command may only be used by list\-admins\.
+.
+.TP
+\fBx\-list\-keys:\fR
+Lists all public keys known to the list\.
+.
+.TP
+\fBx\-add\-key:\fR
+Import the \fIrest of the email\-body\fR into the list\'s keyring\. Write the ascii\-armored key\-block below this keyword\.
+.
+.br
+\fINote:\fR This command reads the whole body of the email\. If you want to use other keywords within the same email, \fIthis must be the last one!\fR
+.
+.TP
+\fBx\-delete\-key:\fR \fI12345678DEADBEEF12345678DEADBEEF12345678\fR
+Delete the key with the given fingerprint from the list\'s keyring\.
+.
+.TP
+\fBx\-get\-key:\fR \fI12345678DEADBEEF12345678DEADBEEF12345678\fR
+Export the key with the given fingerprint from the list\'s keyring\.
+.
+.TP
+\fBx\-fetch\-key:\fR \fI12345678DEADBEEF12345678DEADBEEF12345678\fR
+Fetch the key with the given fingerprint from a keyserver and import it into the list\'s keyring\. (This works only if a keyserver has been configured by the provider\.)
+.
+.SS "Other"
+Must also be sent to the request\-address: \fIlistname\-request at hostname\fR\.
+.
+.TP
+\fBx\-sign\-this:\fR
+Sign the remaining contents of the email body or the attachments with the list\'s key\. Use this e\.g\. to provide GnuPG\-signatures for things you are publishing\.
+.
+.br
+\fINote:\fR This command reads the whole body of the email\. If you want to use other keywords within the same email, \fIthis must be the last one!\fR
+.
+.SH "CONTACT LIST\-OWNER"
+Write to \fIlistname\-owner at hostname\fR to contact the list\-owner(s) even if you don\'t know who they are\. Use the list\'s key to encrypt the email!
+.
+.SH "OPTIONS"
+Other sub\-commands of schleuder:
+.
+.TP
+\fBschleuder help\fR
+Display usage and exit\.
+.
+.TP
+\fBschleuder version\fR
+Display version and exit\.
+.
+.TP
+\fBschleuder install\fR
+Creates neccessary directories, copies example configs, etc\. If you see errors about missing write permissions please follow the advice given\.
+.
+.TP
+\fBschleuder generate_api_key\fR
+Generate a new key to be used by clients to speak to the API\.
+.
+.SH "EXIT STATUS"
+.
+.TP
+0
+Incoming email was processed without errors\.
+.
+.TP
+1
+Internal failure in incoming email processing\.
+.
+.SH "FILES"
+.
+.TP
+\fB/etc/schleuder/schleuder\.yml\fR
+global Schleuder configuration
+.
+.TP
+\fB/etc/schleuder/list\-defaults\.yml\fR
+default list settings
+.
+.TP
+\fB/var/schleuder/lists/\fR\fIhostname\fR\fB/\fR\fIlistname\fR
+list internal data
+.
+.TP
+\fB/var/schleuder/lists/\fR\fIhostname\fR\fB/\fR\fIlistname\fR\fB/list\.log\fR
+log\-file for list
+.
+.P
+All configuration files are formatted as YAML\. See \fIhttp://www\.yaml\.org/\fR for more details\.
+.
+.SH "BUGS"
+Known bugs are listed on the Schleuder bugtracker at \fIhttps://codecoop\.org/schleuder/schleuder\fR
+.
+.SH "SEE ALSO"
+\fBschleuder\-cli\fR(8), \fBgnupg\fR(7)\.
+.
+.TP
+Website of \fBschleuder\fR
+\fIhttp://schleuder\.nadir\.org/\fR
+.
+.TP
+\fBschleuder\-cli\fR, the command line interface for list\-management
+\fIhttp://codecoop\.org/schleuder/schleuder\-cli/\fR
+.
+.TP
+\fBschleuder\-web\fR, the web interface for list\-management
+\fIhttp://codecoop\.org/schleuder/schleuder\-web/\fR
+
diff --git a/man/schleuder.8.ron b/man/schleuder.8.ron
new file mode 100644
index 0000000..af8a799
--- /dev/null
+++ b/man/schleuder.8.ron
@@ -0,0 +1,136 @@
+schleuder(8) -- an email hub for groups
+=======================================
+
+## SYNOPSIS
+
+`schleuder` work <listaddress> < <email>
+
+`schleuder` help
+
+`schleuder` <other-command> [<...>]
+
+For descriptions of the other commands see the output of the <help>-command.
+
+This manual page is written for system administrators. For other information please read the Schleuder documentation online ([SEE ALSO][]).
+
+## DESCRIPTION
+
+Schleuder is an email hub for groups. Subscribers can communicate encryptedly and pseudonymously among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list.
+
+Schleuder takes care of all de- and encryption, stripping of headers, formatting conversions, etc. Further Schleuder can send out its own public key and receive administrative commands by email.
+
+Email cryptography is handled by using GnuPG.
+
+
+## ENVIRONMENT
+
+### Configuration
+
+Schleuder reads its basic settings from a file that it by default expects at </etc/schleuder/schleuder.yml>. To make Schleuder read a different file set the environment variable <SCHLEUDER_CONFIG> to the path to your file when running schleuder. E.g.:
+
+    SCHLEUDER_CONFIG=/usr/local/etc/schleuder.yml /path/to/bin/schleuder ...
+
+For explanations of the possible settings read the default config file.
+
+The default settings for new lists are read from another config file. By default Schleuder looks at </etc/schleuder/list-defaults.yml>. To make Schleuder read a different file set the environment variable <SCHLEUDER_LIST_DEFAULTS> analogous to above. The possible settings are explained in the default config file.
+
+### Connect to MTA
+
+Schleuder behaves like an email-filter: it reads email from standard-input, and reports errors to standard-error. If all goes well Schleuder closes the initial connection to the Mail Transport Agent (MTA) only after it sent out all outgoing emails.
+
+In case of an error the MTA is expected to include Schleuder's error message into a bounce-email that is sent back to the sender (this is default behaviour of most MTAs).
+
+To connect the MTA with Schleuder it must pipe the incoming message into Schleuder's STDIN, and give it two arguments: first one: "work", second one: the full recipients email address.
+
+For more informations on how to integrate Schleuder with your existing mail
+setup, please read the Schleuder documentation online ([SEE ALSO][]).
+
+### Data storage
+
+The keyrings for each list are standard GnuPG keyrings and sit in the filesystem under $lists_dir/$hostname/$listname/ ($lists_dir is read from schleuder.yml, by default it is </var/schleuder/lists>). They can be used manually using gpg2. Please be careful to maintain proper file permissions if you touch the files.
+
+In the list-directory there’s also a list specific log-file (might be missing if the log-level is high and no error occurred yet).
+
+Other logging is sent to syslog. Where that ends up depends on the operating system and the system administration.
+
+All other list-related data is stored in the SQL-database. Most data is unserialized, only some values are JSON-encoded.
+
+
+## SPECIAL FEATURES
+
+Schleuder features some special funtionality. For more detailed information read the Schleuder documentation online ([SEE ALSO][]).
+
+### Getting the public key of a list
+
+Each Schleuder-list replies with its public key to any email sent to
+<listname-sendkey at hostname>. E.g. to receive the key for the contact address
+of the Schleuder project write an email to<br><schleuder-sendkey at nadir.org>.
+
+### Email commands
+
+Schleuder knows some special keywords that trigger different behaviour. You can e.g. subscribe someone, or resend an email to a non-subscriber using keywords.
+
+Keywords require that:
+
+ * they start the line and begin with "x-",
+ * they are written into the beginning of the *first text-part* of the email (usually that’s just the normal body of the email),
+ * possible arguments must be written *on the same line* as the keyword (exceptions are mentioned in the descriptions below),
+ * the email must be *encrypted and signed* by a list-member’s key.
+
+Keywords can be repeated within one email at will. Letter case doesn’t matter.
+
+There are two types of keywords: those to enhance messages sent over the list (“list-keywords”), and those to request something from Schleuder (“request-keywords”).
+
+Find detailed descriptions of all available keywords in the Schleuder documentation online ([SEE ALSO][]).
+
+### Contact list-owner
+
+Write to <listname-owner at hostname> to contact the list-owner(s) even if you don't know who they are. Use the list's key to encrypt the email!
+
+
+## EXIT STATUS
+
+ * 0:
+   Incoming email was processed without errors.
+
+ * 1:
+   Internal failure in incoming email processing.
+
+## FILES
+
+ * `/etc/schleuder/schleuder.yml`:
+   global Schleuder configuration
+
+ * `/etc/schleuder/list-defaults.yml`:
+   default list settings
+
+ * `/var/schleuder/lists/`<hostname>`/`<listname>:
+   list internal data
+
+ * `/var/schleuder/lists/`<hostname>`/`<listname>`/list.log`:
+   log-file for list
+
+All configuration files are formatted as YAML. See
+<http://www.yaml.org/> for more details.
+
+## BUGS
+
+Known bugs are listed on the Schleuder bugtracker at
+<https://codecoop.org/schleuder/schleuder>
+
+## SEE ALSO
+
+`schleuder-cli`(8),
+`gnupg`(7).
+
+ * Website of `schleuder`:
+   <http://schleuder.nadir.org/>
+
+ * More extensive documentation for `schleuder`:
+   <http://schleuder.nadir.org/docs/>
+
+ * `schleuder-cli`, the command line interface for list-management:
+   <http://codecoop.org/schleuder/schleuder-cli/>
+
+ * `schleuder-web`, the web interface for list-management:
+   <http://codecoop.org/schleuder/schleuder-web/>
diff --git a/schleuder.gemspec b/schleuder.gemspec
index 96b3d89..b78c430 100644
--- a/schleuder.gemspec
+++ b/schleuder.gemspec
@@ -1,67 +1,42 @@
-#########################################################
-# This file has been automatically generated by gem2tgz #
-#########################################################
-# -*- encoding: utf-8 -*-
-# stub: schleuder 3.0.0.beta7 ruby lib
+# encoding: utf-8
+
+$: << File.expand_path('../lib', __FILE__)
+require 'schleuder/version'
 
 Gem::Specification.new do |s|
-  s.name = "schleuder"
-  s.version = "3.0.0.beta7"
+  s.name         = "schleuder"
+  s.version      = Schleuder::VERSION
+  s.authors      = %w(lunar ng paz)
+  s.email        = "schleuder2 at nadir.org"
+  s.homepage     = "http://schleuder.nadir.org/"
+  s.summary      = "Schleuder is a gpg-enabled mailinglist with remailing-capabilities."
+  s.description  = "Schleuder is a group's email-gateway: subscribers can exchange encrypted emails among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list.\n\nSchleuder takes care of all decryption and (re-)encryption, stripping of headers, and more. Schleuder can also send out its own public key upon request and process administrative commands by email."
+  s.files        = `git ls-files lib locales etc db/schema.rb README.md Rakefile`.split
+  s.executables =  %w[schleuder schleuder-api-daemon]
+  s.platform     = Gem::Platform::RUBY
+  s.require_path = 'lib'
+  s.rubyforge_project = '[none]'
+  # TODO: extend/replace expired cert
+  #s.signing_key = "#{ENV['HOME']}/.gem/schleuder-gem-private_key.pem"
+  #s.cert_chain  = ['gem-public_cert.pem']
+  s.license = 'GPL-3.0'
+  s.add_runtime_dependency 'mail-gpg', '~> 0.2.7'
+  s.add_runtime_dependency 'activerecord', '~> 4.1'
+  s.add_runtime_dependency 'rake', '~> 10'
+  s.add_runtime_dependency 'sqlite3', '~> 1'
+  s.add_runtime_dependency 'sinatra', '~> 1'
+  s.add_runtime_dependency 'sinatra-contrib', '~> 1'
+  s.add_runtime_dependency 'thor', '~> 0'
+  s.add_runtime_dependency 'thin', '~> 1'
+  s.add_development_dependency 'rspec', '~> 3.5.0'
+  s.add_development_dependency 'hirb'
+  s.add_development_dependency 'database_cleaner'
+  s.post_install_message = "
 
-  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
-  s.require_paths = ["lib"]
-  s.authors = ["lunar", "ng", "paz"]
-  s.date = "2016-11-23"
-  s.description = "Schleuder is a group's email-gateway: subscribers can exchange encrypted emails among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list.\n\nSchleuder takes care of all decryption and (re-)encryption, stripping of headers, and more. Schleuder can also send out its own public key upon request and process administrative commands by email."
-  s.email = "schleuder2 at nadir.org"
-  s.executables = ["schleuder", "schleuder-api-daemon"]
-  s.files = ["README.md", "Rakefile", "bin/schleuder", "bin/schleuder-api-daemon", "db/schema.rb", "etc/list-defaults.yml", "etc/schleuder-api-daemon.service", "etc/schleuder.yml", "lib/schleuder.rb", "lib/schleuder/cli.rb", "lib/schleuder/cli/cert.rb", "lib/schleuder/cli/schleuder_cert_manager.rb", "lib/schleuder/cli/subcommand_fix.rb", "lib/schleuder/conf.rb", "lib/schleuder/errors/active_model_error.rb", "lib/schleuder/errors/base.rb", "lib/schleuder/errors/decryption_failed.rb", "lib [...]
-  s.homepage = "http://schleuder.nadir.org/"
-  s.licenses = ["GPL-3.0"]
-  s.post_install_message = "\n\n    Please consider additionallly installing schleuder-conf (allows to\n    configure lists from the command line).\n\n    To set up Schleuder on this system please run `schleuder install`.\n\n  "
-  s.rubyforge_project = "[none]"
-  s.rubygems_version = "2.5.1"
-  s.summary = "Schleuder is a gpg-enabled mailinglist with remailing-capabilities."
+    Please consider additionallly installing schleuder-cli (allows to
+    configure lists from the command line).
 
-  if s.respond_to? :specification_version then
-    s.specification_version = 4
+    To set up Schleuder on this system please run `schleuder install`.
 
-    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
-      s.add_runtime_dependency(%q<activerecord>, ["~> 4.1"])
-      s.add_development_dependency(%q<database_cleaner>, [">= 0"])
-      s.add_development_dependency(%q<hirb>, [">= 0"])
-      s.add_runtime_dependency(%q<mail-gpg>, ["~> 0.2.7"])
-      s.add_runtime_dependency(%q<rake>, ["~> 10"])
-      s.add_development_dependency(%q<rspec>, ["~> 3.5.0"])
-      s.add_runtime_dependency(%q<sinatra>, ["~> 1"])
-      s.add_runtime_dependency(%q<sinatra-contrib>, ["~> 1"])
-      s.add_runtime_dependency(%q<sqlite3>, ["~> 1"])
-      s.add_development_dependency(%q<thin>, [">= 0"])
-      s.add_runtime_dependency(%q<thor>, ["~> 0"])
-    else
-      s.add_dependency(%q<activerecord>, ["~> 4.1"])
-      s.add_dependency(%q<database_cleaner>, [">= 0"])
-      s.add_dependency(%q<hirb>, [">= 0"])
-      s.add_dependency(%q<mail-gpg>, ["~> 0.2.7"])
-      s.add_dependency(%q<rake>, ["~> 10"])
-      s.add_dependency(%q<rspec>, ["~> 3.5.0"])
-      s.add_dependency(%q<sinatra>, ["~> 1"])
-      s.add_dependency(%q<sinatra-contrib>, ["~> 1"])
-      s.add_dependency(%q<sqlite3>, ["~> 1"])
-      s.add_dependency(%q<thin>, [">= 0"])
-      s.add_dependency(%q<thor>, ["~> 0"])
-    end
-  else
-    s.add_dependency(%q<activerecord>, ["~> 4.1"])
-    s.add_dependency(%q<database_cleaner>, [">= 0"])
-    s.add_dependency(%q<hirb>, [">= 0"])
-    s.add_dependency(%q<mail-gpg>, ["~> 0.2.7"])
-    s.add_dependency(%q<rake>, ["~> 10"])
-    s.add_dependency(%q<rspec>, ["~> 3.5.0"])
-    s.add_dependency(%q<sinatra>, ["~> 1"])
-    s.add_dependency(%q<sinatra-contrib>, ["~> 1"])
-    s.add_dependency(%q<sqlite3>, ["~> 1"])
-    s.add_dependency(%q<thin>, [">= 0"])
-    s.add_dependency(%q<thor>, ["~> 0"])
-  end
+  "
 end
diff --git a/spec/schleuder.yml b/spec/schleuder.yml
new file mode 100644
index 0000000..6ddf437
--- /dev/null
+++ b/spec/schleuder.yml
@@ -0,0 +1,4 @@
+database:
+  test:
+    adapter: sqlite3
+    database: db/test.sqlite3
diff --git a/spec/schleuder/list_spec.rb b/spec/schleuder/list_spec.rb
new file mode 100644
index 0000000..52ba846
--- /dev/null
+++ b/spec/schleuder/list_spec.rb
@@ -0,0 +1,300 @@
+require "spec_helper"
+
+describe Schleuder::List do
+  BOOLEAN_LIST_ATTRIBUTES =
+    [
+      :send_encrypted_only, :receive_encrypted_only, :receive_signed_only,
+      :receive_authenticated_only, :receive_from_subscribed_emailaddresses_only,
+      :receive_admin_only, :keep_msgid, :bounces_drop_all,
+      :bounces_notify_admins, :include_list_headers, :include_list_headers,
+      :include_openpgp_header, :forward_all_incoming_to_admins
+  ].freeze
+
+  it { is_expected.to respond_to :subscriptions }
+  it { is_expected.to respond_to :email }
+  it { is_expected.to respond_to :fingerprint }
+  it { is_expected.to respond_to :log_level }
+  it { is_expected.to respond_to :subject_prefix }
+  it { is_expected.to respond_to :subject_prefix_in }
+  it { is_expected.to respond_to :subject_prefix_out }
+  it { is_expected.to respond_to :openpgp_header_preference }
+  it { is_expected.to respond_to :public_footer }
+  it { is_expected.to respond_to :headers_to_meta }
+  it { is_expected.to respond_to :bounces_drop_on_headers }
+  it { is_expected.to respond_to :keywords_admin_only }
+  it { is_expected.to respond_to :keywords_admin_notify }
+  it { is_expected.to respond_to :send_encrypted_only }
+  it { is_expected.to respond_to :receive_encrypted_only }
+  it { is_expected.to respond_to :receive_signed_only }
+  it { is_expected.to respond_to :receive_authenticated_only }
+  it { is_expected.to respond_to :receive_from_subscribed_emailaddresses_only }
+  it { is_expected.to respond_to :receive_admin_only }
+  it { is_expected.to respond_to :keep_msgid }
+  it { is_expected.to respond_to :bounces_drop_all }
+  it { is_expected.to respond_to :bounces_notify_admins }
+  it { is_expected.to respond_to :include_list_headers }
+  it { is_expected.to respond_to :include_openpgp_header }
+  it { is_expected.to respond_to :max_message_size_kb }
+  it { is_expected.to respond_to :language }
+  it { is_expected.to respond_to :forward_all_incoming_to_admins }
+  it { is_expected.to respond_to :logfiles_to_keep }
+
+  it "is invalid when email is nil" do
+    list = Schleuder::List.new(
+      email: nil,
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:email]).to include("can't be blank")
+  end
+
+   it "is invalid when email is blank" do
+    list = Schleuder::List.new(
+      email: "",
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:email]).to include("can't be blank")
+  end
+
+  it "is invalid when email does not contain an @" do
+    list = Schleuder::List.new(
+      email: "fooatbar.org",
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:email]).to include("is not a valid email address")
+  end
+
+  it "normalizes the fingerprint" do
+    fingerprint = " 99 991 1000 10"
+    list = Schleuder::List.new(fingerprint: fingerprint)
+
+    expect(list.fingerprint).to eq "99991100010"
+  end
+
+  it "is invalid when fingerprint is blank" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:fingerprint]).to include("can't be blank")
+  end
+
+  it "is invalid when fingerprint is nil" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: nil
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:fingerprint]).to include("can't be blank")
+  end
+
+  it "is invalid when fingerprint contains invalid characters" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "&$$$$67923AAA",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:fingerprint]).to include("is not a valid fingerprint")
+  end
+
+  BOOLEAN_LIST_ATTRIBUTES.each do |list_attribute|
+    it "is invalid if #{list_attribute} is nil" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": nil
+      )
+
+      expect(list).not_to be_valid
+      expect(list.errors.messages[list_attribute]).to include("must be true or false")
+    end
+
+    it "is invalid if #{list_attribute} is blank" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": ""
+      )
+
+      expect(list).not_to be_valid
+      expect(list.errors.messages[list_attribute]).to include("must be true or false")
+    end
+  end
+
+  [:headers_to_meta, :keywords_admin_only, :keywords_admin_notify].each do |list_attribute|
+    it "is invalid if #{list_attribute} contains special characters" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": ["$from", "to", "date", "cc"],
+      )
+
+      expect(list).not_to be_valid
+      expect(list.errors.messages[list_attribute]).to include("contains invalid characters")
+    end
+
+    it "is valid if #{list_attribute} does not contain special characters" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": ["foobar"],
+      )
+
+      expect(list).to be_valid
+    end
+  end
+
+  it "is invalid if bounces_drop_on_headers contains special characters" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "aaaadddd0000999",
+      bounces_drop_on_headers: {"$": "%"},
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:bounces_drop_on_headers]).to include("contains invalid characters")
+  end
+
+  [:subject_prefix, :subject_prefix_in, :subject_prefix_out].each do |list_attribute|
+    it "is invalid if #{list_attribute} contains a linebreak" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": "Foo\nbar",
+      )
+
+      expect(list).not_to be_valid
+      expect(list.errors.messages[list_attribute]).to include("must not include line-breaks")
+    end
+
+    it "is valid if #{list_attribute} is nil" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": nil,
+      )
+
+      expect(list).to be_valid
+    end
+  end
+
+  it "is invalid if openpgp_header_preference is foobar" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "aaaadddd0000999",
+      openpgp_header_preference: "foobar",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:openpgp_header_preference]).to include("must be one of: sign, encrypt, signencrypt, unprotected, none")
+  end
+
+  [:max_message_size_kb, :logfiles_to_keep].each do |list_attribute|
+    it "is invalid if #{list_attribute} is 0" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+        "#{list_attribute}": 0,
+      )
+
+      expect(list).not_to be_valid
+      expect(list.errors.messages[list_attribute]).to include("must be a number greater than zero")
+    end
+  end
+
+  it "is invalid if log_level is foobar" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "aaaadddd0000999",
+      log_level: "foobar",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:log_level]).to include("must be one of: debug, info, warn, error")
+  end
+
+  it "is invalid if language is jp" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "aaaadddd0000999",
+      language: "jp",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:language]).to include("must be one of: en, de")
+  end
+
+  it "is invalid if public footer include a non-printable characters" do
+    list = Schleuder::List.new(
+      email: "foo at bar.org",
+      fingerprint: "aaaadddd0000999",
+      public_footer: "\a",
+    )
+
+    expect(list).not_to be_valid
+    expect(list.errors.messages[:public_footer]).to include("includes non-printable characters")
+  end
+
+  describe ".configurable_attributes" do
+    it "returns an array that contains the configurable attributes" do
+      expect(Schleuder::List.configurable_attributes).to eq [
+       :bounces_drop_all, :bounces_drop_on_headers, :bounces_notify_admins,
+       :forward_all_incoming_to_admins, :headers_to_meta, :include_list_headers,
+       :include_openpgp_header, :keep_msgid, :keywords_admin_notify, :keywords_admin_only,
+       :language, :log_level, :logfiles_to_keep, :max_message_size_kb, :openpgp_header_preference,
+       :public_footer, :receive_admin_only, :receive_authenticated_only, :receive_encrypted_only,
+       :receive_from_subscribed_emailaddresses_only, :receive_signed_only, :send_encrypted_only,
+       :subject_prefix, :subject_prefix_in, :subject_prefix_out,
+      ]
+    end
+
+    it "does not contain the attributes email and fingerprint" do
+      expect(Schleuder::List.configurable_attributes).to_not include(:email)
+      expect(Schleuder::List.configurable_attributes).to_not include(:fingerprint)
+    end
+  end
+
+  describe "#logfile" do
+    it "returns the logfile path" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+      )
+
+      expect(list.logfile).to eq "/var/schleuder/lists/bar.org/foo/list.log"
+    end
+  end
+
+  describe "#logger" do
+    it "calls the ListLogger" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+      )
+
+      expect(Listlogger).to receive(:new).with(list)
+
+      list.logger
+    end
+  end
+
+  describe "#to_s" do
+    it "returns the email" do
+      list = Schleuder::List.new(
+        email: "foo at bar.org",
+        fingerprint: "aaaadddd0000999",
+      )
+
+      expect(list.email).to eq "foo at bar.org"
+    end
+  end
+end
diff --git a/spec/schleuder/runner_spec.rb b/spec/schleuder/runner_spec.rb
new file mode 100644
index 0000000..09c3adf
--- /dev/null
+++ b/spec/schleuder/runner_spec.rb
@@ -0,0 +1,8 @@
+require 'spec_helper'
+
+describe Schleuder::Runner do
+
+  describe '#run' do
+    it 'should parses mail'
+  end
+end
diff --git a/spec/schleuder/subscription_spec.rb b/spec/schleuder/subscription_spec.rb
new file mode 100644
index 0000000..9a2f4be
--- /dev/null
+++ b/spec/schleuder/subscription_spec.rb
@@ -0,0 +1,129 @@
+require "spec_helper"
+
+describe Schleuder::Subscription do
+  BOOLEAN_SUBSCRIPTION_ATTRIBUTES =
+    [
+      :delivery_enabled,
+      :admin
+  ].freeze
+
+  before(:example) do
+    @list = Schleuder::List.first || Schleuder::List.create(email: 'test at whatever', fingerprint: 'aaaadddd0000999')
+  end
+
+  it { is_expected.to respond_to :list_id }
+  it { is_expected.to respond_to :email }
+  it { is_expected.to respond_to :fingerprint }
+  it { is_expected.to respond_to :admin }
+  it { is_expected.to respond_to :delivery_enabled }
+
+  it "is invalid when list_id is blank" do
+    subscription = Schleuder::Subscription.new(
+      email: "foo at bar.org",
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(subscription).not_to be_valid
+    expect(subscription.errors.messages[:list_id]).to be_present
+  end
+
+  it "is invalid when email is nil" do
+    subscription = Schleuder::Subscription.new(
+      list_id: @list.id,
+      email: nil,
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(subscription).not_to be_valid
+    expect(subscription.errors.messages[:email]).to include("can't be blank")
+  end
+
+   it "is invalid when email is blank" do
+    subscription = Schleuder::Subscription.new(
+      list_id: @list.id,
+      email: "",
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(subscription).not_to be_valid
+    expect(subscription.errors.messages[:email]).to include("can't be blank")
+  end
+
+  it "is invalid when email does not contain an @" do
+    subscription = Schleuder::Subscription.new(
+      list_id: @list.id,
+      email: "fooatbar.org",
+      fingerprint: "aaaadddd0000999",
+    )
+
+    expect(subscription).not_to be_valid
+    expect(subscription.errors.messages[:email]).to include("is not a valid email address")
+  end
+
+  it "normalizes the fingerprint" do
+    fingerprint = " 99 991 1000 10"
+    subscription = Schleuder::Subscription.new(fingerprint: fingerprint)
+
+    expect(subscription.fingerprint).to eq "99991100010"
+  end
+
+  it "is valid when fingerprint is empty" do
+    subscription = Schleuder::Subscription.new(
+      list_id: @list.id,
+      email: "foo at bar.org",
+      fingerprint: "",
+    )
+
+    expect(subscription).to be_valid
+    expect(subscription.errors.messages[:fingerprint]).to be_blank
+  end
+
+  it "is valid when fingerprint is nil" do
+    subscription = Schleuder::Subscription.new(
+      list_id: @list.id,
+      email: "foo at bar.org",
+      fingerprint: nil
+    )
+
+    expect(subscription).to be_valid
+    expect(subscription.errors.messages[:fingerprint]).to be_blank
+  end
+
+  it "is invalid when fingerprint contains invalid characters" do
+    subscription = Schleuder::Subscription.new(
+      list_id: @list.id,
+      email: "foo at bar.org",
+      fingerprint: "&$$$$123AAA",
+    )
+
+    expect(subscription).not_to be_valid
+    expect(subscription.errors.messages[:fingerprint]).to include("is not a valid fingerprint")
+  end
+
+  BOOLEAN_SUBSCRIPTION_ATTRIBUTES.each do |subscription_attribute|
+    it "is invalid if #{subscription_attribute} is nil" do
+      subscription = Schleuder::Subscription.new(
+        list_id: @list.id,
+        email: "foo at bar.org",
+        fingerprint: nil,
+        "#{subscription_attribute}": nil
+      )
+
+      expect(subscription).not_to be_valid
+      expect(subscription.errors.messages[subscription_attribute]).to include("must be true or false")
+    end
+
+    it "is invalid if #{subscription_attribute} is blank" do
+      subscription = Schleuder::Subscription.new(
+        list_id: @list.id,
+        email: "foo at bar.org",
+        fingerprint: nil,
+        "#{subscription_attribute}": ""
+      )
+
+      expect(subscription).not_to be_valid
+      expect(subscription.errors.messages[subscription_attribute]).to include("must be true or false")
+    end
+  end
+end
+
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..79f8972
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,41 @@
+ENV['SCHLEUDER_ENV'] ||= 'test'
+ENV['SCHLEUDER_CONFIG'] = 'spec/schleuder.yml'
+require 'bundler/setup'
+Bundler.setup
+require 'schleuder'
+require 'database_cleaner'
+
+RSpec.configure do |config|
+  config.expect_with :rspec do |expectations|
+    # This option will default to `true` in RSpec 4. It makes the `description`
+    # and `failure_message` of custom matchers include text for helper methods
+    # defined using `chain`, e.g.:
+    # be_bigger_than(2).and_smaller_than(4).description
+    #   # => "be bigger than 2 and smaller than 4"
+    # ...rather than:
+    #   # => "be bigger than 2"
+    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+  end
+
+  config.order = :random
+
+  config.before(:suite) do
+    DatabaseCleaner.strategy = :transaction
+    DatabaseCleaner.clean_with(:truncation)
+  end
+
+  config.around(:each) do |example|
+    DatabaseCleaner.cleaning do
+      example.run
+    end
+  end
+
+  # rspec-mocks config goes here. You can use an alternate test double
+  # library (such as bogus or mocha) by changing the `mock_with` option here.
+  config.mock_with :rspec do |mocks|
+    # Prevents you from mocking or stubbing a method that does not exist on
+    # a real object. This is generally recommended, and will default to
+    # `true` in RSpec 4.
+    mocks.verify_partial_doubles = true
+  end
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/schleuder.git



More information about the Pkg-ruby-extras-commits mailing list