Commit 77687f29 authored by georg's avatar georg

Merge branch 'autocrypt-outgoing-header' into 'master'

Add new option to send outgoing Autocrypt header, defaults to true

Closes #335

See merge request !299
parents ffa4ab30 b068379e
Pipeline #32719 passed with stages
in 19 minutes and 13 seconds
......@@ -3,12 +3,17 @@ Change Log
This project adheres to [Semantic Versioning](http://semver.org/).
## [3.4.x]
## [3.5.0] / 2020-01-XX
### Added
* New option for lists to include their public keys in the headers of outgoing emails (conforming with Autocrypt, https://autocrypt.org/). Defaults to true. (#335)
### Fixed
* Allow Jenkins job notifications to reach lists. Before, such mails were rejected due to being "auto-submitted".
## [3.4.1] / 2019-09-16
### Fixed
......
class AddAutocryptHeaderToList < ActiveRecord::Migration
def up
if ! column_exists?(:lists, :include_autocrypt_header)
add_column :lists, :include_autocrypt_header, :boolean, default: true
end
end
def down
remove_column(:lists, :include_autocrypt_header)
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180110203100) do
ActiveRecord::Schema.define(version: 20190906194820) do
create_table "lists", force: :cascade do |t|
t.datetime "created_at"
......@@ -44,6 +44,7 @@ ActiveRecord::Schema.define(version: 20180110203100) do
t.boolean "forward_all_incoming_to_admins", default: false
t.integer "logfiles_to_keep", default: 2
t.text "internal_footer", default: ""
t.boolean "include_autocrypt_header", default: true
end
create_table "subscriptions", force: :cascade do |t|
......
......@@ -93,6 +93,9 @@ bounces_drop_on_headers:
# Send a notice to the list-admins whenever an email is bounced or dropped?
bounces_notify_admins: true
# Include Autocrypt header into emails?
include_autocrypt_header: true
# Include RFC-compliant List-* Headers into emails?
include_list_headers: true
......
......@@ -57,6 +57,10 @@ module GPGME
"#{self.to_s}\n\n#{export(armor: true).read}"
end
def minimal
export(minimal: true).to_s
end
# Force encoding, some databases save "ASCII-8BIT" as binary data.
alias_method :orig_fingerprint, :fingerprint
def fingerprint
......
......@@ -146,6 +146,16 @@ module Schleuder
key.armored
end
def key_minimal_base64_encoded(fingerprint=self.fingerprint)
key = keys(fingerprint).first
if key.blank?
return false
end
Base64.strict_encode64(key.minimal)
end
def check_keys
now = Time.now
checkdate = now + (60 * 60 * 24 * 14) # two weeks
......
......@@ -348,6 +348,14 @@ module Mail
end
def add_list_headers(list)
if list.include_autocrypt_header
# Inject whitespaces, to let Mail break the string at these points
# leading to correct wrapping.
keydata = list.key_minimal_base64_encoded.gsub(/(.{78})/, '\1 ')
self['Autocrypt'] = "addr=#{list.email}; prefer-encrypt=mutual; keydata=#{keydata}"
end
if list.include_list_headers
self['List-Id'] = "<#{list.email.gsub('@', '.')}>"
self['List-Owner'] = "<mailto:#{list.owner_address}> (Use list's public key)"
......
......@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
"mailing_list_uri" => "https://lists.nadir.org/mailman/listinfo/schleuder-announce/",
}
s.required_ruby_version = ">= 2.1.0"
s.add_runtime_dependency 'gpgme', '~> 2.0', '>= 2.0.13' # Explicitly include to force a version.
s.add_runtime_dependency 'gpgme', '~> 2.0', '>= 2.0.19' # Explicitly include to force a version.
s.add_runtime_dependency 'mail', '~> 2.7.1'
s.add_runtime_dependency 'mail-gpg', '~> 0.3', '>= 0.3.3'
s.add_runtime_dependency 'activerecord', '~> 4.2'
......
......@@ -22,6 +22,7 @@ FactoryBot.define do
keep_msgid { true }
bounces_drop_all { false }
bounces_notify_admins { true }
include_autocrypt_header { true }
include_list_headers { true }
include_openpgp_header { true }
max_message_size_kb { 10240 }
......
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
\ No newline at end of file
......@@ -5,6 +5,10 @@ describe 'AddSigEncToHeadersToMetaDefaults' do
let(:migration_under_test) { 20180110203100 }
let(:previous_migration) { 20170713215059 }
after(:each) do
ActiveRecord::Migrator.migrate(migrations_paths)
end
describe 'up' do
it 'sets the column defaults' do
ActiveRecord::Migrator.migrate(migrations_paths, previous_migration)
......
......@@ -92,6 +92,41 @@ describe Schleuder::Runner do
teardown_list_and_mailer(list)
end
it 'contains the Autocrypt header if include_autocrypt_header is set to true' do
list = create(
:list,
send_encrypted_only: false,
include_autocrypt_header: true,
)
list.subscribe('admin@example.org', nil, true)
mail = File.read('spec/fixtures/mails/plain/thunderbird.eml')
Schleuder::Runner.new().run(mail, list.email)
message = Mail::TestMailer.deliveries.first
keydata = list.key_minimal_base64_encoded.gsub(/(.{78})/, '\1 ')
expect(message.header['Autocrypt'].to_s).to eq("addr=#{list.email}; prefer-encrypt=mutual; keydata=#{keydata}")
teardown_list_and_mailer(list)
end
it 'does not contain the Autocrypt header if include_autocrypt_header is set to false' do
list = create(
:list,
send_encrypted_only: false,
include_autocrypt_header: false,
)
list.subscribe('admin@example.org', nil, true)
mail = File.read('spec/fixtures/mails/plain/thunderbird.eml')
Schleuder::Runner.new().run(mail, list.email)
message = Mail::TestMailer.deliveries.first
expect(message.header.to_s).to_not include('Autocrypt')
teardown_list_and_mailer(list)
end
it "contains the list headers if include_list_headers is set to true" do
list = create(
:list,
......
require "spec_helper"
describe GPGME::Key do
describe '#minimal' do
it 'returns a minimal key' do
list = create(:list)
list.import_key(File.read('spec/fixtures/schleuder_at_example_public_key.txt'))
expect(list.key.minimal()).to eq(File.read('spec/fixtures/schleuder_at_example_public_key_minimal.gpg', mode: 'rb'))
end
end
describe "#oneline" do
it "displays the expected basic attributes" do
list = create(:list)
......
......@@ -371,6 +371,20 @@ describe Schleuder::List do
expect(list.export_key()).to include expected_public_key
end
end
describe '#key_minimal_base64_encoded' do
it 'returns the key with the fingerprint of the list if no argument is given in an Autocrypt-compatible format' do
list = create(:list)
expect(list.key_minimal_base64_encoded()).to eq(File.read('spec/fixtures/schleuder_at_example_public_key_minimal_base64.txt'))
end
it 'does not return the key with the fingerprint in an Autocrypt-compatible format if the argument given does not correspond to a key' do
list = create(:list)
expect(list.key_minimal_base64_encoded('this fpr does not exist')).to be(false)
end
end
it "exports the key with the given fingerprint" do
list = create(:list, email: "schleuder@example.org")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment