...
 
Commits (21)
......@@ -3,12 +3,25 @@ Change Log
This project adheres to [Semantic Versioning](http://semver.org/).
## [3.5.9] / 2019-12-??
## [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)
* Add visual separator (78 dashes) to the end of the 'pseudoheaders' block: This should help users of Apple Mail, which jams this block and the body together. Hopefully, this change makes it easier to dinstiguish both parts from each other. (#348)
* `deliver_selfsent` per-list option to control whether subscribers get a copy of mail they sent themselves. (#365)
### Fixed
* Allow Jenkins job notifications to reach lists. Before, such mails were rejected due to being "auto-submitted".
* Do not recognize sudo messages as automated message (#248)
* Fixed using x-attach-listkey with emails from Thunderbird that include protected headers.
* Ensure ASCII-8BIT as external encoding, this should ensure that plain text emails in different charsets can be parsed (#409)
* Handle incoming mails encrypted to an absent key, using symmetric encryption or containing PGP-garbage in a more graceful manner: Don't throw an exception, don't notify (and annoy) the admins, instead inform the sender of the mail how to do better. (#337)
* Add missing List-Id header to notification mails sent to admins. This should help with filtering such messages, which is currently not easy to do in a reliable way.
>>>>>>> CHANGELOG.md
## [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"
......@@ -45,6 +45,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
......
# default to ASCII-8BIT encoding as early as possible for external
# data.
#
# this should ensure we are able to parse most incoming
# plain text mails in different charsets.
Encoding.default_external = Encoding::ASCII_8BIT
# Stdlib
require 'fileutils'
require 'singleton'
......
......@@ -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
......
......@@ -147,6 +147,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
......
......@@ -42,6 +42,8 @@ module Schleuder
gpg_opts.merge!(encrypt: true, keys: { address => key.fingerprint })
end
mail.gpg gpg_opts
mail.header['List-Id'] = "<#{@list.email.gsub('@', '.')}>"
end
mail.deliver
end
......
......@@ -206,11 +206,15 @@ module Mail
@recipient.match(/-bounce@/).present? ||
# Empty Return-Path
self.return_path.to_s == '<>' ||
# Auto-Submitted exists and does not equal 'no' and no cron header
# present, as cron emails have the auto-submitted header.
# Auto-Submitted exists and does not equal 'no' and:
# - no cron header is present
# - no Jenkins job notification header is present
# as these emails have the auto-submitted header.
( self['Auto-Submitted'].present? && \
self['Auto-Submitted'].to_s.downcase != 'no' && \
!self['X-Cron-Env'].present?)
!self['X-Cron-Env'].present? && \
!self['X-Jenkins-Job'].present? && \
self.subject.to_s !~ /\A\*\*\* SECURITY information.*\*\*\*\Z/)
end
def keywords
......@@ -330,7 +334,8 @@ module Mail
end
def pseudoheaders(list)
(standard_pseudoheaders(list) + dynamic_pseudoheaders).flatten.join("\n") + "\n"
separator = '------------------------------------------------------------------------------'
(standard_pseudoheaders(list) + dynamic_pseudoheaders).flatten.join("\n") + "\n" + separator + "\n"
end
def add_msgids(list, orig)
......@@ -345,6 +350,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)"
......
module Schleuder
module ListPlugins
def self.attach_listkey(arguments, list, mail)
filename = "#{list.fingerprint}.pgpkey"
# "Mail" only really converts to multipart if the content-type is blank.
mail.content_type = nil
mail.add_file({
filename: filename,
content: list.export_key
})
mail.attachments[filename].content_type = 'application/pgp-keys'
mail.attachments[filename].content_description = "OpenPGP public key of #{list.email}"
mail.attachments[filename].content_disposition = "attachment; filename=#{filename}"
new_part = Mail::Part.new
new_part.body = list.export_key
new_part.content_type = 'application/pgp-keys'
new_part.content_description = "OpenPGP public key of #{list.email}"
new_part.content_disposition = "attachment; filename=#{list.fingerprint}.pgpkey"
mail.add_part new_part
nil
end
end
......
......@@ -13,7 +13,12 @@ module Schleuder
begin
# This decrypts, verifies, etc.
@mail = @mail.setup
rescue GPGME::Error::DecryptFailed
rescue GPGME::Error::BadPassphrase,
GPGME::Error::DecryptFailed,
GPGME::Error::NoData,
GPGME::Error::NoSecretKey
logger.warn "Decryption of incoming message failed."
return Errors::DecryptionFailed.new(list)
end
......
......@@ -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'
......
......@@ -23,6 +23,7 @@ FactoryBot.define do
bounces_drop_all { false }
bounces_notify_admins { true }
deliver_selfsent { true }
include_autocrypt_header { true }
include_list_headers { true }
include_openpgp_header { true }
max_message_size_kb { 10240 }
......
From: user <user@example.net>
To: testlist@example.net
Message-ID: <6ce92946-85f0-075a-3577-ab5f6420d389@example.net>
Date: Sat, 4 Jan 2020 19:43:54 +0100
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.3.1
MIME-Version: 1.0
Subject: ...
Content-Type: multipart/encrypted;
protocol="application/pgp-encrypted";
boundary="1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c"
This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)
--1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c
Content-Type: application/pgp-encrypted
Content-Description: PGP/MIME version identification
Version: 1
--1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c
Content-Type: application/octet-stream; name="encrypted.asc"
Content-Description: OpenPGP encrypted message
Content-Disposition: inline; filename="encrypted.asc"
-----BEGIN PGP MESSAGE-----
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
725O30U=
=2AyW
-----END PGP MESSAGE-----
--1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c--
MIME-Version: 1.0
Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?=
From: sender@example.com
To: =?UTF-8?B?44G/44GR44KL?= <schleuder@example.org>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
44GL44GN44GP44GI44GTCgotLSAKaHR0cDovL2xpbmRzYWFyLm5ldC8KUmFpbHMsIFJTcGVjIGFu
ZCBMaWZlIGJsb2cuLi4uCg==
\ No newline at end of file
MIME-Version: 1.0
Received: by 10.231.35.72 with HTTP; Fri, 16 Oct 2009 05:39:34 -0700 (PDT)
Date: Fri, 16 Oct 2009 23:39:34 +1100
Delivered-To: schleuder@example.org
Message-ID: <57a815bf0910160539m64240421gb35ea52e101aedbc@mail.gmail.com>
Subject: testing
From: sender@example.com
To: Schleuder <schleuder@example.org>
Content-Type: multipart/mixed; boundary=00032557395e3572cf04760cb060
--00032557395e3572cf04760cb060
Content-Type: text/plain; charset=UTF-8
testing
--
http://lindsaar.net/
Rails, RSpec and Life blog....
--00032557395e3572cf04760cb060
Content-Type: text/plain; charset=UTF-8; name="=?UTF-8?B?44Gm44GZ44GoLnR4dA==?="
Content-Disposition: attachment; filename="=?UTF-8?B?44Gm44GZ44GoLnR4dA==?="
Content-Transfer-Encoding: base64
X-Attachment-Id: f_g0uxfl510
dGhpcyBpcyBhIHRlc3QK44GT44KM44KP44Gm44GZ44Go
--00032557395e3572cf04760cb060--
\ No newline at end of file
Delivered-To: schleuder@example.org
Received: by 10.231.12.67 with SMTP id w3cs164325ibw;
Fri, 30 Oct 2009 01:11:12 -0700 (PDT)
Received: by 10.150.44.2 with SMTP id r2mr2367210ybr.77.1256890271939;
Fri, 30 Oct 2009 01:11:11 -0700 (PDT)
Return-Path: <mikel@test.lindsaar.net>
Received: from mx1.test.lindsaar.net.au (mx1.test.lindsaar.net.au [210.14.110.240])
by mx.google.com with ESMTP id 25si7923673gxk.34.2009.10.30.01.11.11;
Fri, 30 Oct 2009 01:11:11 -0700 (PDT)
Received-SPF: neutral (google.com: 210.14.110.240 is neither permitted nor denied by domain of mikel@test.lindsaar.net) client-ip=210.14.110.240;
Authentication-Results: mx.google.com; spf=neutral (google.com: 210.14.110.240 is neither permitted nor denied by domain of mikel@test.lindsaar.net) smtp.mail=mikel@test.lindsaar.net
Received: from [192.168.4.253] (60-241-138-146.static.tpgi.com.au [60.241.138.146])
(using TLSv1 with cipher AES128-SHA (128/128 bits))
(No client certificate requested)
(Authenticated sender: mikel)
by mx1.test.lindsaar.net.au (Postfix) with ESMTPSA id 5C0186DD4CD
for <schleuder@example.org>; Fri, 30 Oct 2009 19:11:08 +1100 (EST)
Subject: =?utf-8?B?44G+44G/44KA44KB44KC44G+44G/44KA44KB44KC44G+44G/44KA?=
=?utf-8?B?44KB44KC44G+44G/44KA44KB44KC44G+44G/44KA44KB44KC44G+?=
=?utf-8?B?44G/44KA44KB44KC44G+44G/44KA44KB44KC44G+44G/44KA44KB?=
=?utf-8?B?44KC44G+44G/44KA44KB44KC44G+44G/44KA44KB44KC?=
From: sender@example.com
Content-Type: multipart/mixed; boundary=Apple-Mail-6--589811753
Message-Id: <60A112A8-F26C-4E23-95B8-4EB9F139D6A0@test.lindsaar.net>
Date: Fri, 30 Oct 2009 19:11:02 +1100
To: Schleuder <schleuder@example.org>
Mime-Version: 1.0 (Apple Message framework v1076)
X-Mailer: Apple Mail (2.1076)
--Apple-Mail-6--589811753
Content-Disposition: attachment;
filename*0*=utf-8''%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B;
filename*1*=%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93.txt
Content-Type: text/plain;
x-unix-mode=0644;
name="=?utf-8?B?44GL44GN44GP44GR44GT44GL44GN44GP44GR44GT44GL44GN44GP?=
=?utf-8?B?44GR44GT44GL44GN44GP44GR44GT44GL44GN44GP44GR44GTLnR4?=
=?utf-8?B?dA==?="
Content-Transfer-Encoding: 7bit
this is the data
--Apple-Mail-6--589811753--
\ No newline at end of file
MIME-Version: 1.0
Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?=
From: sender@example.com
To: =?UTF-8?B?44G/44GR44KL?= <schleuder@example.org>
Content-Type: text/plain;
charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
$B$9$_$^$;$s!#(B
Delivered-To: schleuder@example.org
Date: Wed, 28 May 2014 17:18:19 +0900 (JST)
From: sender@example.com
To: schleuder@example.org
Subject: test
Message-ID: <xxxxx@docomo.ne.jp>
MIME-Version: 1.0
Content-Type: text/plain; charset="Shift_JIS"
Content-Transfer-Encoding: 8bit
あいうえお
このメールはテスト用のメールです。
今後ともよろしくお願い申し上げます!
Delivered-To: schleuder@example.org
Date: Wed, 28 May 2014 17:18:19 +0900 (JST)
From: sender@example.com
To: schleuder@example.org
Subject: test
Message-ID: <from@example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="ks_c_5601-1987"
Content-Transfer-Encoding: 8bit
Ƽ
Date: Wed, 28 May 2014 17:18:19 +0900 (JST)
From: sender@example.com
To: schleuder@example.org
Subject: test
Message-ID: <xxxxx@docomo.ne.jp>
MIME-Version: 1.0
Content-Type: text/plain; charset="Shift_JIS"
Content-Transfer-Encoding: 8bit
あいうえお
このメールはテスト用のメールです。
今後ともよろしくお願い申し上げます!
MIME-Version: 1.0
Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?=
From: Mikel Lindsaar <raasdnil@gmail.com>
To: =?UTF-8?B?44G/44GR44KL?= <raasdnil@gmail.com>
Content-Type: text/plain;
charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
$B$9$_$^$;$s!#(B
Subject: test
To: schleuder@example.org
From: sender@example.com
Date: Wed, 6 Nov 2019 22:04:23 -0200
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859
Content-Language: en-US
Content-Transfer-Encoding: 8bit
é
Subject: test
To: schleuder@example.org
From: sender@example.com
Date: Wed, 6 Nov 2019 22:04:23 -0200
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Language: en-US
Content-Transfer-Encoding: 8bit
é
Date: Sat, 4 Jan 2020 23:42:49 +0000
From: <schleuder@example.org>
To: schleuder@example.org
Subject: Test
Message-ID: <20200104234249.GB9231@example.org>
MIME-Version: 1.0
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
boundary="eAbsdosE1cNLO4uF"
Content-Disposition: inline
--eAbsdosE1cNLO4uF
Content-Type: application/pgp-encrypted
Content-Disposition: attachment
Version: 1
--eAbsdosE1cNLO4uF
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="msg.asc"
-----BEGIN PGP MESSAGE-----
hF4DTO8GH8gtgSMSAQdAjiYMTVwKw70Z3H8NwyZeHpPopnE1BB2L8Cs0MF95AXYw
=xJbn
-----END PGP MESSAGE-----
--eAbsdosE1cNLO4uF--
Date: Sat, 4 Jan 2020 23:42:49 +0000
From: <schleuder@example.org>
To: schleuder@example.org
Subject: Test
Message-ID: <20200104234249.GB9231@example.org>
MIME-Version: 1.0
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
boundary="eAbsdosE1cNLO4uF"
Content-Disposition: inline
--eAbsdosE1cNLO4uF
Content-Type: application/pgp-encrypted
Content-Disposition: attachment
Version: 1
--eAbsdosE1cNLO4uF
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="msg.asc"
-----BEGIN PGP MESSAGE-----
hQGMA+8L5wLeonReAQv/ch+gZBhnP0ikFnkmEXB50e3oWlP7/Gc0hRetb6s5I8u4
dJOt9FUpaWiKg/OryBafJ889VtE7ujO2d8T+D0xwqiE9JRNzP3DiWiXgNpKw5pmN
L6R4+skZ9UK009AzxWSivgg6fJIpk8i022n9c5DPK4sMOE2jUYV7C2BMzXcSq8jf
vr5Wet3lf2yzfU+Pb62s8N1y/qg0PZrJb/0ddnaY4DDMPb4db3H2fuOEzuHnyxOK
WiphCGWSKqKUUWt/x/01GABWBDCy/5HB5ow1o43u8KDriTVB765dd0aS2QGqhLD8
yvhEnzjb1DRz5Bml7NOXKeueFL80S0vge1AKT1YOf1bW1YfTEpn0jiLr8zasd41c
c7cM6SGX6PFV6xGTqMgHLBZaN7Xj4ijgqZfPslYJp4iqjyQ18y1S3zMBDLc3s+9T
iihTi2Ve2D2nI7Xb1Cl/UAgRDin7pQT39UBsHtrKHbpf0NTKYQKzHk+0K+VZn1Bq
a89bFZrfiT+iMXovAzx20loBzk6GUrmSRSgngW7ai0se4nEQ7Vj8xJV/awmBq8Oz
O8UtXiQlIoqOXH07aLxZm819BRNy66XiRUsW0bxN/pzSbOlhivIXYm5ypy5UWEsl
hGHDxswJibLDdpc=
=pSCD
-----END PGP MESSAGE-----
--eAbsdosE1cNLO4uF--
Date: Sat, 4 Jan 2020 23:42:49 +0000
From: <schleuder@example.org>
To: schleuder@example.org
Subject: Test
Message-ID: <20200104234249.GB9231@example.org>
MIME-Version: 1.0
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
boundary="eAbsdosE1cNLO4uF"
Content-Disposition: inline
--eAbsdosE1cNLO4uF
Content-Type: application/pgp-encrypted
Content-Disposition: attachment
Version: 1
--eAbsdosE1cNLO4uF
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="msg.asc"
-----BEGIN PGP MESSAGE-----
jA0ECQMCk858png0tIj/0lQBvHbaDcW9nElJfL0tgFhEnZv3847kDXaRpYAaQhAY
TmHzD51Z7uUbalJSxgmLnBVFRFop2sKSmba1sqtlhszYFjTRerlWAJsb5vNZ1KIB
1kyOuBU=
=42m3
-----END PGP MESSAGE-----
--eAbsdosE1cNLO4uF--
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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)
......
......@@ -2752,6 +2752,30 @@ EOS
teardown_list_and_mailer(list)
end
it 'x-attach-listkey from Thunderbird with protected headers' do
list = create(:list, email: 'testlist@example.net')
list.subscribe('schleuder@example.org', '59C71FB38AEE22E091C78259D06350440F759BD3', true)
encrypted_mail = File.read('spec/fixtures/mails/attach-list-key-thunderbird.eml')
res = nil
begin
res = Schleuder::Runner.new().run(encrypted_mail.to_s, list.email)
rescue SystemExit
end
raw = Mail::TestMailer.deliveries.first
message = Mail.create_message_to_list(raw.to_s, list.email, list).setup
expect(message.parts.length).to eql(2)
expect(message.parts.last.parts.length).to eql(2)
expect(message.parts.last.parts.first.decoded).to eql("Hallo\r\n\r\nkurz mal testen, wie ein resend mail, wo zusätzlich der listkey attached\r\nist bei euch so ankommt.\r\n\r\nich habe das gefühl hier ist as broken.\r\n\r\n\r\n\r\n\r\n")
expect(message.parts.last.parts.last.content_type.to_s).to eql('application/pgp-keys')
expect(message.parts.last.parts.last.body.decoded).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/)
expect(message.parts.last.parts.last.body.decoded).to include('-----BEGIN PGP PUBLIC KEY BLOCK-----')
expect(message.parts.last.parts.last.body.decoded).to include('mQINBFhGvz0BEADXbbTWo/PStyTznAo/f1UobY0EiVPNKNERvYua2Pnq8BwOQ5bS')
teardown_list_and_mailer(list)
end
it "x-get-version" do
list = create(:list)
list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true)
......
require "spec_helper"
describe "user sends emails with different charsets" do
Dir["spec/fixtures/mails/charset_mails/*.eml"].each do |f|
it "works with #{File.basename(f,'.eml')}" do
start_smtp_daemon
list = create(:list)
list.subscribe("admin@example.org", nil, true)
# Clean any LANG from env as this is usually the case for MUAs
# https://0xacab.org/schleuder/schleuder/issues/409
with_env(ENV.delete_if {|key, value| key =~ /LANG/ || key =~ /LC/ }) do
error = run_schleuder(:work, list.email, f)
mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*")
expect(error).to be_empty
expect(mails.size).to eq 1
end
stop_smtp_daemon
end
end
end
......@@ -39,7 +39,8 @@ describe Schleuder::Runner do
Schleuder::Runner.new().run(mail, list.email)
message = Mail::TestMailer.deliveries.first
content_part = message.parts.first
pseudoheaders = "From: Nina Siessegger <schleuder@example.org>\nSig: Unsigned"
separator = '------------------------------------------------------------------------------'
pseudoheaders = "From: Nina Siessegger <schleuder@example.org>\nSig: Unsigned\n#{separator}\n"
expect(content_part.parts.first.body).to include(pseudoheaders)
expect(content_part.parts.first.body).not_to include('To:')
......@@ -92,6 +93,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,
......@@ -182,6 +218,54 @@ describe Schleuder::Runner do
end
end
context 'mails not encrypted to the list key' do
it 'handles a mail which was encrypted to an absent key and returns DecryptionFailed error' do
list = create(
:list,
send_encrypted_only: false
)
list.subscribe("schleuder@example.org", nil, true)
mail = File.read('spec/fixtures/mails/encrypted-to-absent-key.txt')
result = Schleuder::Runner.new().run(mail, list.email)
expect(result.class).to eql(Schleuder::Errors::DecryptionFailed)
teardown_list_and_mailer(list)
end
it 'handles a mail which was encrypted to a passphrase and returns DecryptionFailed error' do
list = create(
:list,
send_encrypted_only: false
)
list.subscribe("schleuder@example.org", nil, true)
mail = File.read('spec/fixtures/mails/encrypted-to-passphrase.txt')
result = Schleuder::Runner.new().run(mail, list.email)
expect(result.class).to eql(Schleuder::Errors::DecryptionFailed)
teardown_list_and_mailer(list)
end
it 'handles a mail containing PGP-garbage and returns DecryptionFailed error' do
list = create(
:list,
send_encrypted_only: false
)
list.subscribe("schleuder@example.org", nil, true)
mail = File.read('spec/fixtures/mails/containing-pgp-garbage.txt')
result = Schleuder::Runner.new().run(mail, list.email)
expect(result.class).to eql(Schleuder::Errors::DecryptionFailed)
teardown_list_and_mailer(list)
end
end
it "delivers a signed error message if a subscription's key is expired on a encrypted-only list" do
list = create(:list, send_encrypted_only: true)
list.subscribe("admin@example.org", nil, true, false)
......
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)
......
......@@ -372,6 +372,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")
......
......@@ -97,4 +97,16 @@ describe Schleuder::LoggerNotifications do
expect(message.parts.size).to be(2)
expect(message.parts.first.parts.first.body.to_s).to eql('Something')
end
it 'includes a List-Id header in notification mails sent to admins' do
list = create(:list, send_encrypted_only: false)
list.subscribe("schleuder@example.org", nil, true)
mail = Mail.new
list.logger.notify_admin("Something", mail.to_s, I18n.t('notice'))
message = Mail::TestMailer.deliveries.first
expect(message.header['List-Id'].to_s).to eql("<#{list.email.gsub('@', '.')}>")
end
end
......@@ -54,6 +54,31 @@ describe Mail::Message do
expect(mail.automated_message?).to be(false)
end
it "recognizes a Jenkins message with 'Auto-Submitted'-header NOT as automated message" do
list = create(:list)
mail = Mail.new
mail.header['Auto-submitted'] = 'auto-generated'
mail.header['X-Jenkins-Job'] = 'test_Tails_ISO_stable'
# Trigger the setting of mandatory headers.
mail.to_s
mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup
expect(mail.automated_message?).to be(false)
end
# https://0xacab.org/schleuder/schleuder/issues/248
it "recognizes a sudo message with 'Auto-Submitted'-header NOT as automated message" do
list = create(:list)
mail = Mail.new
mail.header['Auto-submitted'] = 'auto-generated'
mail.subject = '*** SECURITY information for host.example.com ***'
# Trigger the setting of mandatory headers.
mail.to_s
mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup
expect(mail.automated_message?).to be(false)
end
context '#add_subject_prefix!' do
it 'adds a configured subject prefix' do
list = create(:list)
......
......@@ -136,6 +136,14 @@ RSpec.configure do |config|
`SCHLEUDER_ENV=test SCHLEUDER_CONFIG=spec/schleuder.yml bin/schleuder #{command} 2>&1`
end
def with_env(env)
backup = ENV.to_hash
ENV.replace(env)
yield
ensure
ENV.replace(backup)
end
def process_mail(msg, recipient)
output = nil
begin
......
......@@ -6,3 +6,5 @@ nto
keyserver
keyservers
fpr
files'
ist