Skip to content

Commit 2339549

Browse files
committed
compose/pgp: add encrypt_for_self flag
Signed-off-by: Manos Pitsidianakis <[email protected]>
1 parent c82341f commit 2339549

File tree

5 files changed

+120
-76
lines changed

5 files changed

+120
-76
lines changed

meli/src/conf/overrides.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@ use crate::conf::{*, data_types::*};
4242

4343
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct TagsSettingsOverride { # [serde (deserialize_with = "tag_color_de")] # [serde (default)] pub colors : Option < IndexMap < TagHash , Color > > , # [serde (deserialize_with = "tag_set_de" , alias = "ignore-tags")] # [serde (default)] pub ignore_tags : Option < IndexSet < TagHash > > } impl Default for TagsSettingsOverride { fn default () -> Self { Self { colors : None , ignore_tags : None } } }
4444

45-
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct PGPSettingsOverride { # [doc = " auto verify signed e-mail according to RFC3156"] # [doc = " Default: true"] # [serde (alias = "auto-verify-signatures")] # [serde (default)] pub auto_verify_signatures : Option < ActionFlag > , # [doc = " auto decrypt encrypted e-mail"] # [doc = " Default: true"] # [serde (alias = "auto-decrypt")] # [serde (default)] pub auto_decrypt : Option < ActionFlag > , # [doc = " always sign sent e-mail"] # [doc = " Default: false"] # [serde (alias = "auto-sign")] # [serde (default)] pub auto_sign : Option < ActionFlag > , # [doc = " Auto encrypt sent e-mail"] # [doc = " Default: false"] # [serde (alias = "auto-encrypt")] # [serde (default)] pub auto_encrypt : Option < ActionFlag > , # [doc = " Default: None"] # [serde (alias = "sign-key")] # [serde (default)] pub sign_key : Option < Option < String > > , # [doc = " Default: None"] # [serde (alias = "decrypt-key")] # [serde (default)] pub decrypt_key : Option < Option < String > > , # [doc = " Default: None"] # [serde (alias = "encrypt-key")] # [serde (default)] pub encrypt_key : Option < Option < String > > , # [doc = " Allow remote lookups"] # [doc = " Default: False"] # [serde (alias = "allow-remote-lookups")] # [serde (default)] pub allow_remote_lookup : Option < ActionFlag > , # [doc = " Remote lookup mechanisms."] # [doc = " Default: \"local,wkd\""] # [cfg_attr (feature = "gpgme" , serde (alias = "remote-lookup-mechanisms"))] # [cfg (feature = "gpgme")] # [serde (default)] pub remote_lookup_mechanisms : Option < melib :: gpgme :: LocateKey > , # [cfg (not (feature = "gpgme"))] # [cfg_attr (not (feature = "gpgme") , serde (alias = "remote-lookup-mechanisms"))] # [serde (default)] pub remote_lookup_mechanisms : Option < String > } impl Default for PGPSettingsOverride { fn default () -> Self { Self { auto_verify_signatures : None , auto_decrypt : None , auto_sign : None , auto_encrypt : None , sign_key : None , decrypt_key : None , encrypt_key : None , allow_remote_lookup : None , remote_lookup_mechanisms : None } } }
45+
# [derive (Debug , Serialize , Deserialize , Clone)] # [serde (deny_unknown_fields)] pub struct PGPSettingsOverride { # [doc = " auto verify signed e-mail according to RFC3156"] # [doc = " Default: true"] # [serde (alias = "auto-verify-signatures")] # [serde (default)] pub auto_verify_signatures : Option < ActionFlag > , # [doc = " auto decrypt encrypted e-mail"] # [doc = " Default: true"] # [serde (alias = "auto-decrypt")] # [serde (default)] pub auto_decrypt : Option < ActionFlag > , # [doc = " always sign sent e-mail"] # [doc = " Default: false"] # [serde (alias = "auto-sign")] # [serde (default)] pub auto_sign : Option < ActionFlag > , # [doc = " Auto encrypt sent e-mail"] # [doc = " Default: false"] # [serde (alias = "auto-encrypt")] # [serde (default)] pub auto_encrypt : Option < ActionFlag > , # [doc = " Default: None"] # [serde (alias = "sign-key")] # [serde (default)] pub sign_key : Option < Option < String > > , # [doc = " Default: None"] # [serde (alias = "decrypt-key")] # [serde (default)] pub decrypt_key : Option < Option < String > > , # [doc = " Default: None"] # [serde (alias = "encrypt-key")] # [serde (default)] pub encrypt_key : Option < Option < String > > , # [doc = " Default: true"] # [serde (alias = "encrypt-for-self")] # [serde (default)] pub encrypt_for_self : Option < bool > , # [doc = " Allow remote lookups"] # [doc = " Default: False"] # [serde (alias = "allow-remote-lookups")] # [serde (default)] pub allow_remote_lookup : Option < ActionFlag > , # [doc = " Remote lookup mechanisms."] # [doc = " Default: \"local,wkd\""] # [cfg_attr (feature = "gpgme" , serde (alias = "remote-lookup-mechanisms"))] # [cfg (feature = "gpgme")] # [serde (default)] pub remote_lookup_mechanisms : Option < melib :: gpgme :: LocateKey > , # [cfg (not (feature = "gpgme"))] # [cfg_attr (not (feature = "gpgme") , serde (alias = "remote-lookup-mechanisms"))] # [serde (default)] pub remote_lookup_mechanisms : Option < String > } impl Default for PGPSettingsOverride { fn default () -> Self { Self { auto_verify_signatures : None , auto_decrypt : None , auto_sign : None , auto_encrypt : None , sign_key : None , decrypt_key : None , encrypt_key : None , encrypt_for_self : None , allow_remote_lookup : None , remote_lookup_mechanisms : None } } }
4646

meli/src/conf/pgp.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ pub struct PGPSettings {
6060
#[serde(default = "none", alias = "encrypt-key")]
6161
pub encrypt_key: Option<String>,
6262

63+
/// Default: true
64+
#[serde(default = "true_val", alias = "encrypt-for-self")]
65+
pub encrypt_for_self: bool,
66+
6367
/// Allow remote lookups
6468
/// Default: False
6569
#[serde(
@@ -99,6 +103,7 @@ impl Default for PGPSettings {
99103
auto_decrypt: true.into(),
100104
auto_sign: false.into(),
101105
auto_encrypt: false.into(),
106+
encrypt_for_self: true,
102107
sign_key: None,
103108
decrypt_key: None,
104109
encrypt_key: None,

meli/src/mail.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,21 @@
2121

2222
//! Entities that handle Mail specific functions.
2323
24+
use std::{future::Future, pin::Pin};
25+
2426
use indexmap::IndexMap;
2527
use melib::{
2628
backends::{AccountHash, Mailbox, MailboxHash},
2729
email::{attachment_types::*, attachments::*},
30+
text::{TextProcessing, Truncate},
2831
thread::ThreadNodeHash,
2932
};
33+
use uuid::Uuid;
3034

3135
use super::*;
32-
use crate::{
33-
melib::text::{TextProcessing, Truncate},
34-
uuid::Uuid,
35-
};
36+
37+
pub type AttachmentBoxFuture = Pin<Box<dyn Future<Output = Result<AttachmentBuilder>> + Send>>;
38+
pub type AttachmentFilterBox = Box<dyn FnOnce(AttachmentBuilder) -> AttachmentBoxFuture + Send>;
3639

3740
pub mod listing;
3841
pub use crate::listing::*;

meli/src/mail/compose.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,8 @@ impl Component for Composer {
888888
self.gpg_state.sign_mail =
889889
Some(*account_settings!(context[self.account_hash].pgp.auto_sign));
890890
}
891+
self.gpg_state.encrypt_for_self =
892+
*account_settings!(context[self.account_hash].pgp.encrypt_for_self);
891893
if !self.draft.headers().contains_key(HeaderName::FROM)
892894
|| self.draft.headers()[HeaderName::FROM].is_empty()
893895
{
@@ -2564,16 +2566,7 @@ pub fn send_draft_async(
25642566
let format_flowed = *account_settings!(context[account_hash].composing.format_flowed);
25652567
let event_sender = context.main_loop_handler.sender.clone();
25662568
#[cfg(feature = "gpgme")]
2567-
#[allow(clippy::type_complexity)]
2568-
let mut filters_stack: Vec<
2569-
Box<
2570-
dyn FnOnce(
2571-
AttachmentBuilder,
2572-
)
2573-
-> Pin<Box<dyn Future<Output = Result<AttachmentBuilder>> + Send>>
2574-
+ Send,
2575-
>,
2576-
> = vec![];
2569+
let mut filters_stack: Vec<AttachmentFilterBox> = vec![];
25772570
#[cfg(feature = "gpgme")]
25782571
if gpg_state.sign_mail.unwrap_or(ActionFlag::False).is_true()
25792572
&& !gpg_state
@@ -2623,13 +2616,14 @@ pub fn send_draft_async(
26232616
let send_mail = account_settings!(context[account_hash].send_mail).clone();
26242617
let send_cb = context.accounts[&account_hash].send_async(send_mail);
26252618
let mut content_type = ContentType::default();
2626-
if format_flowed {
2627-
if let ContentType::Text {
2619+
if let (
2620+
true,
2621+
ContentType::Text {
26282622
ref mut parameters, ..
2629-
} = content_type
2630-
{
2631-
parameters.push((b"format".to_vec(), b"flowed".to_vec()));
2632-
}
2623+
},
2624+
) = (format_flowed, &mut content_type)
2625+
{
2626+
parameters.push((b"format".to_vec(), b"flowed".to_vec()));
26332627
}
26342628
let mut body: AttachmentBuilder = Attachment::new(
26352629
content_type,

meli/src/mail/pgp.rs

Lines changed: 97 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use std::{
2323
collections::{hash_map::DefaultHasher, BTreeMap},
2424
future::Future,
2525
hash::{Hash, Hasher},
26-
pin::Pin,
2726
sync::{Arc, Mutex},
2827
};
2928

@@ -38,6 +37,8 @@ use melib::{
3837
parser::BytesExt,
3938
};
4039

40+
use super::AttachmentBoxFuture;
41+
4142
pub async fn decrypt(raw: Vec<u8>) -> Result<(melib_pgp::DecryptionMetadata, Vec<u8>)> {
4243
let mut ctx = Context::new()?;
4344
let cipher = ctx.new_data_mem(&raw)?;
@@ -88,31 +89,47 @@ pub fn sign_filter(
8889
Box::pin(async move {
8990
if let Some(default_key) = default_key {
9091
let mut ctx = Context::new()?;
91-
let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec(
92-
a.into_raw().as_bytes(),
93-
))?;
94-
let sig_attachment = Attachment::new(
95-
ContentType::PGPSignature,
96-
Default::default(),
97-
ctx.sign(sign_keys, data)?.await?,
98-
);
99-
let a: AttachmentBuilder = a.into();
100-
let parts = vec![a, sig_attachment.into()];
101-
let boundary = ContentType::make_boundary(&parts);
102-
Ok(Attachment::new(
103-
ContentType::Multipart {
104-
boundary: boundary.into_bytes(),
105-
kind: MultipartType::Signed,
106-
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
107-
parameters: vec![],
108-
},
109-
Default::default(),
110-
vec![],
111-
)
112-
.into())
113-
})
114-
},
115-
)
92+
ctx.set_auto_key_locate(LocateKey::LOCAL)?;
93+
let keys = ctx.keylist(false, Some(default_key.clone()))?.await?;
94+
if keys.is_empty() {
95+
return Err(Error::new(format!(
96+
"Could not locate sign key with ID `{}`",
97+
default_key
98+
)));
99+
}
100+
sign_keys.extend(keys);
101+
}
102+
if sign_keys.is_empty() {
103+
return Err(Error::new(
104+
"No key was selected for signing; please select one.",
105+
));
106+
}
107+
let a: Attachment = a.into();
108+
let mut ctx = Context::new()?;
109+
let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec(
110+
a.into_raw().as_bytes(),
111+
))?;
112+
let sig_attachment = Attachment::new(
113+
ContentType::PGPSignature,
114+
Default::default(),
115+
ctx.sign(sign_keys, data)?.await?,
116+
);
117+
let a: AttachmentBuilder = a.into();
118+
let parts = vec![a, sig_attachment.into()];
119+
let boundary = ContentType::make_boundary(&parts);
120+
Ok(Attachment::new(
121+
ContentType::Multipart {
122+
boundary: boundary.into_bytes(),
123+
kind: MultipartType::Signed,
124+
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
125+
parameters: vec![],
126+
},
127+
Default::default(),
128+
vec![],
129+
)
130+
.into())
131+
})
132+
})
116133
}
117134

118135
pub fn encrypt_filter(
@@ -166,37 +183,62 @@ pub fn encrypt_filter(
166183
}
167184
if let Some(encrypt_for_self) = encrypt_for_self {
168185
let mut ctx = Context::new()?;
169-
let data = ctx.new_data_mem(
170-
a.into_raw().as_bytes()
171-
)?;
172-
173-
let sig_attachment = {
174-
let mut a = Attachment::new(
175-
ContentType::OctetStream { name: None, parameters: vec![] },
176-
Default::default(),
177-
ctx.encrypt(sign_keys, encrypt_keys, data)?.await?,
178-
);
179-
a.content_disposition = ContentDisposition::from(br#"attachment; filename="msg.asc""#);
180-
a
181-
};
182-
let mut a: AttachmentBuilder = AttachmentBuilder::new(b"Version: 1\n");
186+
ctx.set_auto_key_locate(LocateKey::LOCAL)?;
187+
let keys = ctx
188+
.keylist(false, Some(encrypt_for_self.to_string()))?
189+
.await?;
190+
if keys.is_empty() {
191+
return Err(Error::new(format!(
192+
"Could not locate personal encryption key for address `{}`",
193+
encrypt_for_self
194+
)));
195+
}
196+
for key in keys {
197+
if !encrypt_keys.contains(&key) {
198+
encrypt_keys.push(key);
199+
}
200+
}
201+
}
202+
let a: Attachment = a.into();
203+
log::trace!(
204+
"main attachment is {:?} sign_keys = {:?} encrypt_keys = {:?}",
205+
&a,
206+
&sign_keys,
207+
&encrypt_keys
208+
);
209+
let mut ctx = Context::new()?;
210+
let data = ctx.new_data_mem(a.into_raw().as_bytes())?;
183211

184-
a.set_content_type_from_bytes(b"application/pgp-encrypted");
185-
a.set_content_disposition(ContentDisposition::from(b"attachment"));
186-
let parts = vec![a, sig_attachment.into()];
187-
let boundary = ContentType::make_boundary(&parts);
188-
Ok(Attachment::new(
189-
ContentType::Multipart {
190-
boundary: boundary.into_bytes(),
191-
kind: MultipartType::Encrypted,
192-
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
212+
let enc_attachment = {
213+
let mut a = Attachment::new(
214+
ContentType::OctetStream {
215+
name: None,
193216
parameters: vec![],
194217
},
195218
Default::default(),
196-
vec![],
197-
)
198-
.into())
199-
})
200-
},
201-
)
219+
ctx.encrypt(sign_keys, encrypt_keys, data)?.await?,
220+
);
221+
a.content_disposition =
222+
ContentDisposition::from(br#"attachment; filename="msg.asc""#);
223+
a
224+
};
225+
let mut a: AttachmentBuilder = AttachmentBuilder::new(b"Version: 1\n");
226+
227+
a.set_content_type_from_bytes(b"application/pgp-encrypted");
228+
a.set_content_disposition(ContentDisposition::from(b"attachment"));
229+
let parts = vec![a, enc_attachment.into()];
230+
let boundary = ContentType::make_boundary(&parts);
231+
Ok(Attachment::new(
232+
ContentType::Multipart {
233+
boundary: boundary.into_bytes(),
234+
kind: MultipartType::Encrypted,
235+
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
236+
parameters: vec![],
237+
},
238+
Default::default(),
239+
vec![],
240+
)
241+
.into())
242+
})
243+
})
202244
}

0 commit comments

Comments
 (0)