From dcd397f776d938a772b9c904d55b7808ec7a80f9 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Tue, 30 Aug 2022 19:25:31 -0500 Subject: [PATCH] pgp: enable quoted replies of encrypted messages When quoting an encrypted message for reply, the quoted text is shown as "Version: 1.0". This is due to this being the first non-multipart text portion of the message, which is what the quoted reply logic looks for. Properly quote replies to encrypted messages by decrypting the message, and quoting the content. The message must be open in a message view in order to quote it (it must be decrypted, which is handled by the message viewer). Suggested-by: Moritz Poldrack Signed-off-by: Tim Culverhouse Tested-by: Jens Grassel --- commands/msg/reply.go | 26 ++++++++++++++++++++++++++ lib/crypto/crypto.go | 15 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/commands/msg/reply.go b/commands/msg/reply.go index 8365172..e5f8d47 100644 --- a/commands/msg/reply.go +++ b/commands/msg/reply.go @@ -11,6 +11,7 @@ import ( "git.sr.ht/~sircmpwn/getopt" "git.sr.ht/~rjarry/aerc/lib" + "git.sr.ht/~rjarry/aerc/lib/crypto" "git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/models" @@ -210,6 +211,31 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error { template = aerc.Config().Templates.QuotedReply } + if crypto.IsEncrypted(msg.BodyStructure) { + provider := aerc.SelectedTabContent().(widgets.ProvidesMessage) + mv, ok := provider.(*widgets.MessageViewer) + if !ok { + return fmt.Errorf("message is encrypted. can only quote reply while message is open") + } + p := provider.SelectedMessagePart() + if p == nil { + return fmt.Errorf("could not fetch message part") + } + mv.MessageView().FetchBodyPart(p.Index, func(reader io.Reader) { + buf := new(bytes.Buffer) + _, err := buf.ReadFrom(reader) + if err != nil { + logging.Warnf("failed to fetch bodypart: %v", err) + } + original.Text = buf.String() + err = addTab() + if err != nil { + logging.Warnf("failed to add tab: %v", err) + } + }) + return nil + } + part := lib.FindPlaintext(msg.BodyStructure, nil) if part == nil { // mkey... let's get the first thing that isn't a container diff --git a/lib/crypto/crypto.go b/lib/crypto/crypto.go index 8f895b4..b7afe63 100644 --- a/lib/crypto/crypto.go +++ b/lib/crypto/crypto.go @@ -31,3 +31,18 @@ func New(s string) Provider { return &pgp.Mail{} } } + +func IsEncrypted(bs *models.BodyStructure) bool { + if bs == nil { + return false + } + if bs.MIMEType == "application" && bs.MIMESubType == "pgp-encrypted" { + return true + } + for _, part := range bs.Parts { + if IsEncrypted(part) { + return true + } + } + return false +}