sup 1.2 → 1.4
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.
- checksums.yaml +4 -4
- data/.github/workflows/checks.yml +19 -4
- data/.gitmodules +1 -0
- data/.rubocop.yml +1 -1
- data/History.txt +33 -0
- data/Manifest.txt +21 -2
- data/README.md +5 -3
- data/Rakefile +1 -1
- data/bin/sup +5 -3
- data/contrib/nix/Gemfile +2 -0
- data/contrib/nix/Gemfile.lock +62 -34
- data/contrib/nix/gem-install-shell.nix +2 -0
- data/contrib/nix/gemset.nix +130 -56
- data/contrib/nix/ruby2.4-Gemfile.lock +6 -2
- data/contrib/nix/ruby2.4-gemset.nix +24 -4
- data/contrib/nix/ruby2.4-shell.nix +2 -6
- data/contrib/nix/ruby2.5-Gemfile.lock +6 -2
- data/contrib/nix/ruby2.5-gemset.nix +24 -4
- data/contrib/nix/ruby2.5-shell.nix +2 -6
- data/contrib/nix/ruby2.6-Gemfile.lock +6 -2
- data/contrib/nix/ruby2.6-gemset.nix +24 -4
- data/contrib/nix/ruby2.6-shell.nix +2 -6
- data/contrib/nix/ruby2.7-Gemfile.lock +91 -0
- data/contrib/nix/ruby2.7-gemset.nix +359 -0
- data/contrib/nix/ruby2.7-shell.nix +2 -11
- data/contrib/nix/ruby3.0-Gemfile.lock +91 -0
- data/contrib/nix/ruby3.0-gemset.nix +359 -0
- data/contrib/nix/ruby3.0-shell.nix +2 -11
- data/contrib/nix/ruby3.1-Gemfile.lock +101 -0
- data/contrib/nix/ruby3.1-gemset.nix +391 -0
- data/contrib/nix/ruby3.1-shell.nix +3 -12
- data/contrib/nix/ruby3.2-Gemfile.lock +101 -0
- data/contrib/nix/ruby3.2-gemset.nix +391 -0
- data/contrib/nix/ruby3.2-shell.nix +3 -12
- data/contrib/nix/ruby3.3-shell.nix +1 -10
- data/contrib/nix/ruby3.4-shell.nix +27 -0
- data/contrib/nix/ruby4.0-shell.nix +40 -0
- data/contrib/nix/test-all-rubies.sh +1 -1
- data/lib/sup/account.rb +2 -0
- data/lib/sup/buffer.rb +1 -0
- data/lib/sup/contact.rb +3 -4
- data/lib/sup/crypto.rb +7 -5
- data/lib/sup/draft.rb +15 -11
- data/lib/sup/index.rb +8 -4
- data/lib/sup/maildir.rb +4 -0
- data/lib/sup/mbox.rb +25 -7
- data/lib/sup/message.rb +13 -10
- data/lib/sup/message_chunks.rb +0 -24
- data/lib/sup/mode.rb +1 -0
- data/lib/sup/modes/contact_list_mode.rb +0 -1
- data/lib/sup/modes/edit_message_mode.rb +6 -6
- data/lib/sup/modes/label_search_results_mode.rb +1 -2
- data/lib/sup/modes/line_cursor_mode.rb +22 -20
- data/lib/sup/modes/search_results_mode.rb +0 -1
- data/lib/sup/modes/thread_view_mode.rb +1 -2
- data/lib/sup/rfc2047.rb +5 -2
- data/lib/sup/source.rb +2 -0
- data/lib/sup/util.rb +9 -2
- data/lib/sup/version.rb +1 -1
- data/lib/sup.rb +1 -1
- data/man/sup-add.1 +18 -18
- data/man/sup-config.1 +12 -12
- data/man/sup-dump.1 +15 -14
- data/man/sup-import-dump.1 +24 -24
- data/man/sup-psych-ify-config-files.1 +11 -11
- data/man/sup-recover-sources.1 +20 -20
- data/man/sup-sync-back-maildir.1 +24 -23
- data/man/sup-sync.1 +35 -35
- data/man/sup-tweak-labels.1 +27 -26
- data/man/sup.1 +27 -27
- data/sup.gemspec +3 -1
- data/test/dummy_buffer.rb +34 -0
- data/test/dummy_source.rb +6 -0
- data/test/fixtures/contacts.txt +2 -1
- data/test/fixtures/embedded-message-rfc6532.eml +33 -0
- data/test/fixtures/invalid-date.eml +8 -0
- data/test/fixtures/rfc2047-header-encoding.eml +1 -1
- data/test/gnupg_test_home/private-keys-v1.d/26C05E44706A8E230B3255BB9532B34DC9420232.key +42 -0
- data/test/gnupg_test_home/private-keys-v1.d/D187ADC90EC4DEB7047678EAA37E33A53A465D47.key +5 -0
- data/test/gnupg_test_home/private-keys-v1.d/FB2D9BD3B1BE90B5BCF697781F8404224B0FCF5B.key +5 -0
- data/test/gnupg_test_home/pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_secring.gpg +0 -0
- data/test/gnupg_test_home/regen_keys.sh +11 -2
- data/test/gnupg_test_home/secring.gpg +0 -0
- data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -20
- data/test/integration/test_draft.rb +128 -0
- data/test/integration/test_maildir.rb +17 -1
- data/test/integration/test_mbox.rb +12 -0
- data/test/integration/test_sup-add.rb +4 -0
- data/test/test_crypto.rb +114 -72
- data/test/test_message.rb +43 -0
- data/test/unit/test_contact.rb +16 -4
- data/test/unit/test_edit_message_mode.rb +99 -0
- data/test/unit/test_index.rb +65 -0
- data/test/unit/test_line_cursor_mode.rb +208 -0
- data/test/unit/test_person.rb +3 -3
- data/test/unit/test_rmail_message.rb +36 -0
- data/test/unit/util/test_string.rb +3 -3
- metadata +64 -9
- data/shell.nix +0 -1
- data/test/gnupg_test_home/private-keys-v1.d/306D2EE90FF0014B5B9FD07E265C751791674140.key +0 -0
data/man/sup.1
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
.\" Automatically generated by Pandoc 3.
|
|
1
|
+
.\" Automatically generated by Pandoc 3.7.0.2
|
|
2
2
|
.\"
|
|
3
|
-
.TH "SUP" "1" "April 8, 2014" "Sup User Manual"
|
|
3
|
+
.TH "SUP" "1" "April 8, 2014" "Sup User Manual"
|
|
4
4
|
.SH NAME
|
|
5
|
-
sup
|
|
5
|
+
sup \- a curses\-based email client
|
|
6
6
|
.SH SYNOPSIS
|
|
7
7
|
sup [\f[I]options\f[R]]
|
|
8
8
|
.SH DESCRIPTION
|
|
9
|
-
Sup is a console
|
|
9
|
+
Sup is a console\-based email client for people with a lot of email.
|
|
10
10
|
.PP
|
|
11
11
|
It presents an interface of a list of threads, which are each
|
|
12
12
|
hierarchical collections email messages.
|
|
13
13
|
Threads can have multiple tags applied to them.
|
|
14
|
-
It supports a very fast full
|
|
14
|
+
It supports a very fast full\-text search, automatic contact\-list
|
|
15
15
|
management, custom code insertion via a Ruby hook system, and more.
|
|
16
|
-
If you\
|
|
17
|
-
|
|
16
|
+
If you\(cqre the type of person who treats email as an extension of your
|
|
17
|
+
long\-term memory, Sup is for you.
|
|
18
18
|
.SH OPTIONS
|
|
19
19
|
.TP
|
|
20
|
-
|
|
20
|
+
\-l, \-\-list\-hooks
|
|
21
21
|
List all hooks and descriptions, and quit.
|
|
22
|
-
Use \
|
|
22
|
+
Use \(enhooks\-matching to filter
|
|
23
23
|
.TP
|
|
24
|
-
|
|
24
|
+
\-m, \-\-hooks\-matching=<s>
|
|
25
25
|
If given, list all hooks and descriptions matching the given pattern.
|
|
26
|
-
Needs the \
|
|
26
|
+
Needs the \(enlist\-hooks option (default: )
|
|
27
27
|
.TP
|
|
28
|
-
|
|
28
|
+
\-n, \-\-no\-threads
|
|
29
29
|
Turn off threading.
|
|
30
30
|
Helps with debugging.
|
|
31
31
|
(Necessarily disables background polling for new messages.)
|
|
32
32
|
.TP
|
|
33
|
-
|
|
34
|
-
Don\
|
|
33
|
+
\-o, \-\-no\-initial\-poll
|
|
34
|
+
Don\(cqt poll for new messages when starting.
|
|
35
35
|
.TP
|
|
36
|
-
|
|
36
|
+
\-s \f[I]QUERY\f[R], \-\-search \f[I]QUERY\f[R]
|
|
37
37
|
Search for this query upon startup
|
|
38
38
|
.TP
|
|
39
|
-
|
|
39
|
+
\-c \f[I]STRING\f[R], \-\-compose \f[I]STRING\f[R]
|
|
40
40
|
Compose message to this recipient upon startup
|
|
41
41
|
.TP
|
|
42
|
-
|
|
42
|
+
\-j \f[I]STRING\f[R], \-\-subject \f[I]STRING\f[R]
|
|
43
43
|
When composing, use this subject
|
|
44
44
|
.TP
|
|
45
|
-
|
|
45
|
+
\-v, \-\-version
|
|
46
46
|
Print version and exit
|
|
47
47
|
.TP
|
|
48
|
-
|
|
48
|
+
\-h, \-\-help
|
|
49
49
|
Show brief help message
|
|
50
50
|
.SH ENVIRONMENT
|
|
51
51
|
.TP
|
|
@@ -54,7 +54,7 @@ Set log level verbosity.
|
|
|
54
54
|
Valid values ordered by decresing verbosity: debug info warn error.
|
|
55
55
|
Default log level is info.
|
|
56
56
|
.TP
|
|
57
|
-
SUP_BASE\
|
|
57
|
+
SUP_BASE\(rs
|
|
58
58
|
Specify home directory for configuration files and xapian index,
|
|
59
59
|
defaults to: $HOME/.sup.
|
|
60
60
|
.SH FILES
|
|
@@ -68,9 +68,9 @@ Configuration file for Sup mail sources
|
|
|
68
68
|
$HOME/.sup/colors.yaml
|
|
69
69
|
Color theme for Sup
|
|
70
70
|
.SH SEE ALSO
|
|
71
|
-
mail(1), sup
|
|
72
|
-
sup
|
|
73
|
-
sup
|
|
71
|
+
mail(1), sup\-add(1), sup\-config(1), sup\-dump(1),
|
|
72
|
+
sup\-import\-dump(1), sup\-recover\-sources(1), sup\-sync(1),
|
|
73
|
+
sup\-sync\-back\-maildir(1), sup\-tweak\-labels(1)
|
|
74
74
|
.SH REPORTING BUGS
|
|
75
75
|
You are welcome to submit bug reports to the Sup issue tracker, located
|
|
76
76
|
at
|
|
@@ -96,21 +96,21 @@ Sup Wiki:
|
|
|
96
96
|
.UE \c
|
|
97
97
|
.TP
|
|
98
98
|
Mailing list:
|
|
99
|
-
supmua\
|
|
99
|
+
supmua\(atgooglegroups.com
|
|
100
100
|
.RS
|
|
101
101
|
.PP
|
|
102
|
-
supmua+subscribe\
|
|
102
|
+
supmua+subscribe\(atgooglegroups.com
|
|
103
103
|
.PP
|
|
104
104
|
Archives: \c
|
|
105
105
|
.UR https://groups.google.com/d/forum/supmua/
|
|
106
106
|
.UE \c
|
|
107
107
|
.RE
|
|
108
108
|
.SH COPYRIGHT
|
|
109
|
-
Copyright © 2006
|
|
109
|
+
Copyright © 2006\-2009 William Morgan \c
|
|
110
110
|
.MT mworgan-sup@masanjin.net
|
|
111
111
|
.ME \c
|
|
112
112
|
.PP
|
|
113
|
-
Copyright \
|
|
113
|
+
Copyright \(at 2013\-2014 Sup developers
|
|
114
114
|
.PP
|
|
115
115
|
Permission is granted to copy and distribute this manual under the terms
|
|
116
116
|
of the GNU General Public License; either version 2 or (at your option)
|
data/sup.gemspec
CHANGED
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
|
9
9
|
s.authors = ["William Morgan", "Gaute Hope", "Hamish Downer", "Matthieu Rakotojaona"]
|
|
10
10
|
s.email = "supmua@googlegroups.com"
|
|
11
11
|
s.summary = "A console-based email client with the best features of GMail, mutt and Emacs"
|
|
12
|
-
s.homepage = "https://
|
|
12
|
+
s.homepage = "https://supmua.dev/"
|
|
13
13
|
s.license = 'GPL-2.0'
|
|
14
14
|
s.description = <<-DESC
|
|
15
15
|
Sup is a console-based email client for people with a lot of email.
|
|
@@ -61,6 +61,8 @@ SUP: please note that our old mailing lists have been shut down,
|
|
|
61
61
|
s.add_runtime_dependency "unicode", "~> 0.4.4"
|
|
62
62
|
s.add_runtime_dependency "unicode-display_width"
|
|
63
63
|
s.add_runtime_dependency "string-scrub" if /^2\.0\./ =~ RUBY_VERSION
|
|
64
|
+
s.add_runtime_dependency "benchmark"
|
|
65
|
+
s.add_runtime_dependency "fiddle"
|
|
64
66
|
|
|
65
67
|
s.add_development_dependency "bundler", ">= 1.3", "< 3"
|
|
66
68
|
s.add_development_dependency "rake"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require "sup"
|
|
2
|
+
|
|
3
|
+
module Redwood
|
|
4
|
+
|
|
5
|
+
class DummyBuffer
|
|
6
|
+
attr_reader :width, :height, :dirty_count, :commit_count
|
|
7
|
+
|
|
8
|
+
def initialize width=80, height=25
|
|
9
|
+
@width = width
|
|
10
|
+
@height = height
|
|
11
|
+
@dirty = false
|
|
12
|
+
@dirty_count = 0
|
|
13
|
+
@commit_count = 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def content_height; @height - 1; end
|
|
17
|
+
def content_width; @width; end
|
|
18
|
+
|
|
19
|
+
def mark_dirty
|
|
20
|
+
@dirty = true
|
|
21
|
+
@dirty_count += 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def dirty?; @dirty; end
|
|
25
|
+
|
|
26
|
+
def commit
|
|
27
|
+
@dirty = false
|
|
28
|
+
@commit_count += 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def write(*args); end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
data/test/dummy_source.rb
CHANGED
|
@@ -10,10 +10,12 @@ module Redwood
|
|
|
10
10
|
class DummySource < Source
|
|
11
11
|
|
|
12
12
|
attr_accessor :messages
|
|
13
|
+
attr_writer :fallback_date
|
|
13
14
|
|
|
14
15
|
def initialize uri, last_date=nil, usual=true, archived=false, id=nil, labels=[]
|
|
15
16
|
super uri, usual, archived, id
|
|
16
17
|
@messages = nil
|
|
18
|
+
@fallback_date = Time.utc 2001, 2, 3, 4, 56, 57
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def start_offset
|
|
@@ -59,6 +61,10 @@ class DummySource < Source
|
|
|
59
61
|
end
|
|
60
62
|
end
|
|
61
63
|
end
|
|
64
|
+
|
|
65
|
+
def fallback_date_for_message id
|
|
66
|
+
@fallback_date
|
|
67
|
+
end
|
|
62
68
|
end
|
|
63
69
|
|
|
64
70
|
end
|
data/test/fixtures/contacts.txt
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
RC: Random Contact <random_dude@gmail.com>
|
|
1
|
+
RC: Random Contact <random_dude@gmail.com>
|
|
2
|
+
: Unaliased Contact <unaliased@example.invalid>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Return-Path: <return@example.com>
|
|
2
|
+
From: Sender <sender@example.com>
|
|
3
|
+
To: <recipient@example.invalid>
|
|
4
|
+
Subject: Email with embedded message
|
|
5
|
+
MIME-Version: 1.0
|
|
6
|
+
Content-Type: multipart/mixed; boundary="----------=_4F506AC2.EE281DC4"
|
|
7
|
+
Message-Id: <9181f493-df49-4af5-8ad2-e1a8eb692a98>
|
|
8
|
+
Date: Wed, 15 Jul 2020 19:48:41 +0100
|
|
9
|
+
|
|
10
|
+
This is a multi-part message in MIME format.
|
|
11
|
+
|
|
12
|
+
------------=_4F506AC2.EE281DC4
|
|
13
|
+
Content-Type: text/plain; charset=iso-8859-1
|
|
14
|
+
Content-Disposition: inline
|
|
15
|
+
Content-Transfer-Encoding: 8bit
|
|
16
|
+
|
|
17
|
+
Example outer message.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
------------=_4F506AC2.EE281DC4
|
|
21
|
+
Content-Type: message/global
|
|
22
|
+
Content-Transfer-Encoding: 8bit
|
|
23
|
+
|
|
24
|
+
From: "Embed sender" <embed@example.com>
|
|
25
|
+
To: <rcpt2@example.invalid>
|
|
26
|
+
Subject: Embedded subject line with emoji ✨
|
|
27
|
+
X-heävy-mëtal-ümlaut: yes
|
|
28
|
+
Date: Sun, 12 May 2024 17:34:29 +1000
|
|
29
|
+
|
|
30
|
+
Example embedded message, with UTF-8 headers.
|
|
31
|
+
|
|
32
|
+
------------=_4F506AC2.EE281DC4--
|
|
33
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Created: 20241014T073358
|
|
2
|
+
Key: (private-key (rsa (n #00C0EF24D44D17ABD33603EDED46A2F639BDB90C9A72
|
|
3
|
+
E6AD03E83B597169BF7B8F6DEF42A5EED6F9BBDD0BDE326075969886D11D2875FB6972
|
|
4
|
+
D8D73ECC98F6A14AB083E93990567C78EEDA09260096B4B99C67824B39005DEA7D75B5
|
|
5
|
+
ECF3F03D042EEEB49E9871AA3B2DC4552FC7598B8DDAD6454EF0CCD11D8C4BAEEFEBCC
|
|
6
|
+
CF4BCDB4FBB05BCC026910D4249E24BB657BD2287E6999FD2C499C54C29CE079437CB3
|
|
7
|
+
8AE685C6D733749B046FF2235A29B22822C23EFFF38302B3A8EEC81CE9505BF8D4CCF5
|
|
8
|
+
EB958AFBDE50488F56E14B3CC116E413CE5E449D65537DDFB90F841A3B6580BEA20783
|
|
9
|
+
002699B584F53EE4C29C7381071536659E50BE9AA445068F5B2B2B0185E850DF4790FD
|
|
10
|
+
455A91135FE29A79A0E7EF73A8C6B6328603C5B46466B1A674AE205256C79B8A39E73D
|
|
11
|
+
15587A123C2FEC23C14CD2ADD2D41344408E713A10D986766F17F93011998788DEF294
|
|
12
|
+
DA6C3E86CEC1562FB574014CA2937FA7ACF7C57D80E9925994FCF8EA55102FC987FAD6
|
|
13
|
+
7393E2011515856AE9FEB6DDB9#)(e #010001#)(d
|
|
14
|
+
#1AC7D73BE4EB993D3B2D36748E2E86B12325B19B2AC1DC58437F217E3DA887B53414
|
|
15
|
+
5713036131CF22F2C7C8045DAE26C3E7F8FD29CB592AC8F0AFD5E491AF77D7A2A7D806
|
|
16
|
+
B20A9B1AC4872A90405B1BBC9B1D99E572A896A90D92D02E5835900417BC589B5E83BB
|
|
17
|
+
AD31A885764D76B29D22CB021728C70A2BF441772A2B06C745E98E5A3F93C4EDE2991F
|
|
18
|
+
F017B72F720D8CF3672329E260E1635E943A107B0EAF3963A04426910CE98BA7225C47
|
|
19
|
+
E2ABC92872001EB52585557CE8903C7B225D342894EFB6CCA4ED2397E970EAB675BE69
|
|
20
|
+
70F1009E87396923D13A6B4B1E941EA9433C386EFA94843C67C5C5D08B688BDCD3075D
|
|
21
|
+
29ACB0D3D3F156562ABB19345B547040782FA7DD199F20CA7042D8548FF72FAB96394C
|
|
22
|
+
2ADFCAFA4E38196AED778C777BA8BF4646A8E4F5DA3E44C0330AC71AFAD1FCF1C792F2
|
|
23
|
+
34C7D0BFA59E1435813695CC813C1395DDCD61BE60B1693B89DC5B8480DE5BD5065AED
|
|
24
|
+
3822B865574D55155FCACDB51807679040D6952E073982C6075E07111A205D7EBEA015
|
|
25
|
+
#)(p #00D8DF87835F964777CC15BA16559A04CD40D570084AF06117224D9B6DE56CB5
|
|
26
|
+
DCC0F5A66DEAF9DBA1542475808017B318D152FA7425376508A48E1591C75605504799
|
|
27
|
+
184C0F11059B5625C799356CC895314DD684A25CC36775DFB2270DBB1E92E7457773BB
|
|
28
|
+
9E2C1BCDB93BD7A9E4AE316F23FC06D9AC6E538A7A9A53D454B1548A80291777704EA7
|
|
29
|
+
B5D798C8378C4C7B040A4BD64875755A8CC092D4D1C340D22CA798F177F0A0A9893BC7
|
|
30
|
+
026A9023660CBF155F22CC295880965E75832AA01F#)(q
|
|
31
|
+
#00E3BDF8A4560327A98A63D6B00B7474FC0F918F043CF0A99253F41EEEF4895BFAF8
|
|
32
|
+
50AFDC107C4A741958667F7B567F280632C8B3454494CA1B253A33DD4E45ACC5194F53
|
|
33
|
+
1B67DD975D15470FA52CF2C71CEA669B1471CF1B8B76EE0E5925F5CC1103D75184D7C3
|
|
34
|
+
BB8EE7498ECC34483EEDD5516AF5F234ADA9C0BFDE2E3A15F7027B109E136C56C4779C
|
|
35
|
+
6E032DC25B5D2E68D7079C5CEBC15B25ADE6481A1E1E78305B067C452C677908BE6D16
|
|
36
|
+
EC7B1869689FC9F70FB4D45449C336D9B46727#)(u
|
|
37
|
+
#009C3200C269390035DB78F0259D81B22712470EE1FBA278564DDDE0C667EA48A511
|
|
38
|
+
7B8AB17C2DAEFD2078BF99CE548A72661E8FCA2288BE39447854F79AFDAFB4415BB60A
|
|
39
|
+
C72562E2DDB31D52DDE9D638EEDBF9636AB6BCDD2870E6C9B59AFAB04C169CF51433BE
|
|
40
|
+
C75EC697575686029F36FA2537896ACCD35EB766BB3A2EBC84DBFC24C0D049699813B1
|
|
41
|
+
1A7679D87D38B222ECD1238DCFB84AB58D5C4D8B5E90D627D9C1BEA3793AC2AEA225FC
|
|
42
|
+
7C7021EA0FA08CAF614286537134929A47097D#)))
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -67,6 +67,15 @@ gpg2 \
|
|
|
67
67
|
--passphrase '' \
|
|
68
68
|
--quick-generate-key sup-test-1@foo.bar rsa encrypt,sign 0
|
|
69
69
|
|
|
70
|
+
echo "Generating key pair for sender alternate address (email sup-fake-ecc@fake.fake)"
|
|
71
|
+
gpg2 \
|
|
72
|
+
--homedir . \
|
|
73
|
+
--batch \
|
|
74
|
+
--pinentry-mode loopback \
|
|
75
|
+
--passphrase '' \
|
|
76
|
+
--default-new-key-algo "ed25519/cert,sign+cv25519/encr" \
|
|
77
|
+
--quick-generate-key sup-fake-ecc@fake.fake default default 0
|
|
78
|
+
|
|
70
79
|
echo "Importing public key for receiver, into sender's key store"
|
|
71
80
|
gpg2 \
|
|
72
81
|
--homedir . \
|
|
@@ -80,10 +89,10 @@ gpg2 \
|
|
|
80
89
|
|
|
81
90
|
echo "Done."
|
|
82
91
|
|
|
83
|
-
echo "We now have
|
|
92
|
+
echo "We now have some non-expiring public keys:"
|
|
84
93
|
gpg2 --homedir . --list-keys
|
|
85
94
|
|
|
86
|
-
echo "And we also have
|
|
95
|
+
echo "And we also have some corresponding private keys:"
|
|
87
96
|
gpg2 --homedir . --list-secret-keys
|
|
88
97
|
|
|
89
98
|
popd
|
|
Binary file
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
+
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
=
|
|
3
|
+
mQGNBGcMyWQBDADDsDnBPhnEKSH2qSJq00/nxe1zFhwc5yiD5kwutfOCG/46Wtqs
|
|
4
|
+
vETmZfAaWOrfFectT51zLlG2/zju63NEiImt8KBxB02lI8uanLdKxNpAuN3OuNTF
|
|
5
|
+
RapqLTCwThlNZlGXM4fvC7uuFxtSV3yE5wIOQIT4IvpGc2/P7NuDg+aYoAkfNH5Y
|
|
6
|
+
1E3II/tRUYZn63t5ihmOH1b2Gc8qyD05gc7O836ZgKHL1FfCf4A8tgQEOFgkkYdH
|
|
7
|
+
fX8x57RbZAqfzpH5oxcZNa5LAC+m+3EmLF5cvNWqLh8wAnYb+krDvZ9sg8OjY5YN
|
|
8
|
+
K4SDTnKfg0zofdEHeZFqDOg1N/0Ri79EYJBINBeERj1OMPUD8uim+AeJjLbL1XiH
|
|
9
|
+
l31zEQOoTCSutGeA7sKS3YTaNcpvKfneW3MHN4y4jqLLI2g1PGGGTXYpr/t3/8uG
|
|
10
|
+
fzlkcxBDzl3IX1lvIBEhF4P1uSSc2Oa+IizzfDVPoKzy7+bLP/JvF3cTKKZHe63P
|
|
11
|
+
p/9hy34IOdKKw7sAEQEAAbQSc3VwLXRlc3QtMkBmb28uYmFyiQHRBBMBCAA7FiEE
|
|
12
|
+
IJRwaSVB2pkxecFGpaPGNeoyUYoFAmcMyWQCGw8FCwkIBwICIgIGFQoJCAsCBBYC
|
|
13
|
+
AwECHgcCF4AACgkQpaPGNeoyUYq1NwwAuurXiq3hnmTbg/Lxn1FtcwW0xKdBmUbB
|
|
14
|
+
LWg+fWZvo87wU5TxsdAu1Y8YiWqusSX9ZYg8po0/dgBKdrPREF3rCWOw6wVwWg4E
|
|
15
|
+
aydajoefUa10CPf4VeOLbVReQLsueWycp5uw3Pm8Zc78RyKL9QmY+k3ez6kspHS6
|
|
16
|
+
gWeiLv9XazBll/o1YYLQX7gI29aseBkbLS81Z1ea+a6cqvzm/MzAYiDf8ETQ3/Sm
|
|
17
|
+
Nd/HoPWJ9/aHuuBUQsX2uWCI70YgvTh/kKfaNr3up5BmCjwgQCo2zjZOGDUqnajd
|
|
18
|
+
2I5qV3uabNXTwgdjWoqN9nmBeEpW5haw+NwuhQT0H5tWfiL4wyXv01KZxPxv1tAq
|
|
19
|
+
Tu9frSOk4ziRWbUQMelIiGbIRB6VNHEIyM3F/UpboDDPn9lIVuG6ARNfPemHsErI
|
|
20
|
+
rIdC2PXMibdO5U1d+0oY5xf7YxnWWgWstsjlgyXBUnX3R5xXGm5Sf66VwR+0Vo9J
|
|
21
|
+
EFqKZ/vYa3YwJ+hfzIBVKGxBKXpXQv83
|
|
22
|
+
=kQ2o
|
|
23
23
|
-----END PGP PUBLIC KEY BLOCK-----
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require "sup"
|
|
2
|
+
require "test_helper"
|
|
3
|
+
|
|
4
|
+
class TestDraft < Minitest::Test
|
|
5
|
+
include Redwood
|
|
6
|
+
|
|
7
|
+
def setup
|
|
8
|
+
@path = Dir.mktmpdir
|
|
9
|
+
start
|
|
10
|
+
Logger.remove_sink $stderr
|
|
11
|
+
@draft_dir = File.join @path, "drafts"
|
|
12
|
+
@test_message_1 = <<EOS
|
|
13
|
+
From: Some Person <someone@example.invalid>
|
|
14
|
+
To:
|
|
15
|
+
Cc:
|
|
16
|
+
Bcc:
|
|
17
|
+
Subject: draft
|
|
18
|
+
Date: Fri, 11 Apr 2025 22:34:05 +1000
|
|
19
|
+
Message-ID: <123@example.invalid>
|
|
20
|
+
|
|
21
|
+
My incomplete message
|
|
22
|
+
EOS
|
|
23
|
+
DraftManager.instance.instance_eval "@dir = '#{@draft_dir}'"
|
|
24
|
+
Index.init @path
|
|
25
|
+
Index.load
|
|
26
|
+
SourceManager.instance.instance_eval "@sources = {}"
|
|
27
|
+
@draft_source = DraftManager.new_source
|
|
28
|
+
SourceManager.add_source @draft_source
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def teardown
|
|
32
|
+
Index.save_index
|
|
33
|
+
ObjectSpace.each_object(Class).select {|a| a < Redwood::Singleton}.each do |klass|
|
|
34
|
+
klass.deinstantiate! unless klass == Redwood::Logger
|
|
35
|
+
end
|
|
36
|
+
FileUtils.rm_r @path
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_write_draft
|
|
40
|
+
DraftManager.write_draft { |f| f.write @test_message_1 }
|
|
41
|
+
|
|
42
|
+
draft_filename = File.join @draft_dir, "0"
|
|
43
|
+
assert File.exist? draft_filename
|
|
44
|
+
assert_equal @test_message_1, (File.read draft_filename)
|
|
45
|
+
|
|
46
|
+
## Check that it is loaded back into the index successfully too.
|
|
47
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
48
|
+
assert_equal @test_message_1, messages_in_index.first.raw_message
|
|
49
|
+
assert_equal [:draft, :inbox].to_set, messages_in_index.first.labels
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_discard_draft
|
|
53
|
+
DraftManager.write_draft { |f| f.write @test_message_1 }
|
|
54
|
+
draft_filename = File.join @draft_dir, "0"
|
|
55
|
+
assert File.exist? draft_filename
|
|
56
|
+
message_in_index = Index.instance.enum_for(:each_message).to_a.first
|
|
57
|
+
|
|
58
|
+
DraftManager.discard message_in_index
|
|
59
|
+
refute File.exist? draft_filename
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_discard_already_deleted_from_disk
|
|
63
|
+
DraftManager.write_draft { |f| f.write @test_message_1 }
|
|
64
|
+
draft_filename = File.join @draft_dir, "0"
|
|
65
|
+
assert File.exist? draft_filename
|
|
66
|
+
message_in_index = Index.instance.enum_for(:each_message).to_a.first
|
|
67
|
+
|
|
68
|
+
File.delete draft_filename
|
|
69
|
+
|
|
70
|
+
DraftManager.discard message_in_index
|
|
71
|
+
refute File.exist? draft_filename
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_load_malformed_draft
|
|
75
|
+
## Sup always writes drafts by serialising a Message, meaning the draft is
|
|
76
|
+
## guaranteed to have certain headers like Date. But it's always possible
|
|
77
|
+
## for the user to edit the draft directly on the filesystem and leave it
|
|
78
|
+
## in some kind of malformed state. Sup should handle it without crashing.
|
|
79
|
+
draft_filename = File.join @draft_dir, "0"
|
|
80
|
+
fallback_date = Time.new 2025, 5, 3, 15, 47, 41
|
|
81
|
+
File.write draft_filename, <<EOS
|
|
82
|
+
Some-Header: Value
|
|
83
|
+
|
|
84
|
+
body
|
|
85
|
+
EOS
|
|
86
|
+
File.utime fallback_date, fallback_date, draft_filename
|
|
87
|
+
PollManager.poll_from @draft_source
|
|
88
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
89
|
+
assert_equal "", messages_in_index[0].subj
|
|
90
|
+
assert_equal fallback_date, messages_in_index[0].date
|
|
91
|
+
|
|
92
|
+
File.write (File.join @draft_dir, "1"), <<EOS
|
|
93
|
+
missing a header!
|
|
94
|
+
EOS
|
|
95
|
+
PollManager.poll_from @draft_source
|
|
96
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
97
|
+
assert_equal "", messages_in_index[0].subj
|
|
98
|
+
|
|
99
|
+
File.write (File.join @draft_dir, "2"), ""
|
|
100
|
+
PollManager.poll_from @draft_source
|
|
101
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
102
|
+
assert_equal "", messages_in_index[0].subj
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_draft_with_non_ascii_chars
|
|
106
|
+
message = <<EOS
|
|
107
|
+
From: Some Person <someone@example.invalid>
|
|
108
|
+
To:
|
|
109
|
+
Cc:
|
|
110
|
+
Bcc:
|
|
111
|
+
Subject: UTF-8 draft 🤐
|
|
112
|
+
Date: Fri, 11 Apr 2025 22:34:05 +1000
|
|
113
|
+
Message-ID: <123@example.invalid>
|
|
114
|
+
|
|
115
|
+
¡Buen día! Доброго ранку! おはよう!
|
|
116
|
+
EOS
|
|
117
|
+
DraftManager.write_draft { |f| f.write message }
|
|
118
|
+
draft_filename = File.join @draft_dir, "0"
|
|
119
|
+
assert_equal message, (File.read draft_filename)
|
|
120
|
+
|
|
121
|
+
PollManager.poll_from @draft_source
|
|
122
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
123
|
+
assert_equal "UTF-8 draft 🤐", messages_in_index[0].subj
|
|
124
|
+
assert_equal message, messages_in_index.first.raw_message
|
|
125
|
+
assert_equal "¡Buen día! Доброго ранку! おはよう!", \
|
|
126
|
+
messages_in_index[0].chunks[0].lines[0]
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -34,16 +34,20 @@ EOS
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def create_a_maildir_email(folder, content)
|
|
37
|
-
File.
|
|
37
|
+
filename = File.join folder, "#{Time.now.to_f}.hostname:2,S"
|
|
38
|
+
File.write filename, content
|
|
39
|
+
filename
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
def start_sup_and_add_source(source)
|
|
41
43
|
start
|
|
44
|
+
Logger.remove_sink $stderr
|
|
42
45
|
Index.init @path
|
|
43
46
|
Index.load
|
|
44
47
|
SourceManager.instance.instance_eval '@sources = {}'
|
|
45
48
|
SourceManager.instance.add_source source
|
|
46
49
|
PollManager.poll_from source
|
|
50
|
+
Index.save_index
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
# and now, let the tests begin!
|
|
@@ -74,5 +78,17 @@ EOS
|
|
|
74
78
|
|
|
75
79
|
end
|
|
76
80
|
|
|
81
|
+
def test_missing_date_header
|
|
82
|
+
## The message is missing a Date header so we should use its modtime
|
|
83
|
+
## as a fallback.
|
|
84
|
+
fallback_date = Time.new 2004, 4, 19, 11, 12, 13
|
|
85
|
+
maildir = create_a_maildir
|
|
86
|
+
filename = create_a_maildir_email(File.join(maildir, 'cur'), @test_message_1)
|
|
87
|
+
File.utime fallback_date, fallback_date, filename
|
|
88
|
+
start_sup_and_add_source Maildir.new "maildir:#{maildir}"
|
|
89
|
+
|
|
90
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
91
|
+
assert_equal fallback_date, messages_in_index.first.date
|
|
92
|
+
end
|
|
77
93
|
end
|
|
78
94
|
|
|
@@ -34,11 +34,13 @@ EOS
|
|
|
34
34
|
|
|
35
35
|
def start_sup_and_add_source(source)
|
|
36
36
|
start
|
|
37
|
+
Logger.remove_sink $stderr
|
|
37
38
|
Index.init @path
|
|
38
39
|
Index.load
|
|
39
40
|
SourceManager.instance.instance_eval '@sources = {}'
|
|
40
41
|
SourceManager.instance.add_source source
|
|
41
42
|
PollManager.poll_from source
|
|
43
|
+
Index.save_index
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
# and now, let the tests begin!
|
|
@@ -69,4 +71,14 @@ EOS
|
|
|
69
71
|
|
|
70
72
|
end
|
|
71
73
|
|
|
74
|
+
def test_missing_date_header
|
|
75
|
+
## The message is missing a Date header so we should use envelope date
|
|
76
|
+
## stored in the From line as a fallback.
|
|
77
|
+
fallback_date = Time.new 2009, 4, 27, 12, 56, 18
|
|
78
|
+
mbox = create_a_mbox
|
|
79
|
+
start_sup_and_add_source MBox.new "mbox:#{mbox}"
|
|
80
|
+
|
|
81
|
+
messages_in_index = Index.instance.enum_for(:each_message).to_a
|
|
82
|
+
assert_equal fallback_date, messages_in_index.first.date
|
|
83
|
+
end
|
|
72
84
|
end
|
|
@@ -26,6 +26,8 @@ class TestSupAdd < Minitest::Test
|
|
|
26
26
|
EOS
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
## https://github.com/sup-heliotrope/sup/issues/577
|
|
30
|
+
## https://github.com/sup-heliotrope/sup/issues/516
|
|
29
31
|
def test_fixes_old_tag_uri_syntax
|
|
30
32
|
File.write "#{@path}/sources.yaml", <<EOS
|
|
31
33
|
---
|
|
@@ -36,6 +38,7 @@ EOS
|
|
|
36
38
|
sync_back: true
|
|
37
39
|
id: 1
|
|
38
40
|
labels: []
|
|
41
|
+
- !supmua.org,2006-10-01/Redwood/SentLoader {}
|
|
39
42
|
EOS
|
|
40
43
|
_out, _err = capture_subprocess_io do
|
|
41
44
|
assert system({"SUP_BASE" => @path}, "bin/sup-add", "maildir:///other/path")
|
|
@@ -58,6 +61,7 @@ EOS
|
|
|
58
61
|
sync_back: true
|
|
59
62
|
id: 2
|
|
60
63
|
labels: []
|
|
64
|
+
- !<tag:supmua.org,2006-10-01/Redwood/SentLoader> {}
|
|
61
65
|
EOS
|
|
62
66
|
end
|
|
63
67
|
|