compose/pgp: add encrypt_for_self flag

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/490/head
Manos Pitsidianakis 4 weeks ago
parent c82341f3af
commit 23395491db
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -42,5 +42,5 @@ use crate::conf::{*, data_types::*};
# [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 } } } # [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 } } }
# [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 } } } # [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 } } }

@ -60,6 +60,10 @@ pub struct PGPSettings {
#[serde(default = "none", alias = "encrypt-key")] #[serde(default = "none", alias = "encrypt-key")]
pub encrypt_key: Option<String>, pub encrypt_key: Option<String>,
/// Default: true
#[serde(default = "true_val", alias = "encrypt-for-self")]
pub encrypt_for_self: bool,
/// Allow remote lookups /// Allow remote lookups
/// Default: False /// Default: False
#[serde( #[serde(
@ -99,6 +103,7 @@ impl Default for PGPSettings {
auto_decrypt: true.into(), auto_decrypt: true.into(),
auto_sign: false.into(), auto_sign: false.into(),
auto_encrypt: false.into(), auto_encrypt: false.into(),
encrypt_for_self: true,
sign_key: None, sign_key: None,
decrypt_key: None, decrypt_key: None,
encrypt_key: None, encrypt_key: None,

@ -21,18 +21,21 @@
//! Entities that handle Mail specific functions. //! Entities that handle Mail specific functions.
use std::{future::Future, pin::Pin};
use indexmap::IndexMap; use indexmap::IndexMap;
use melib::{ use melib::{
backends::{AccountHash, Mailbox, MailboxHash}, backends::{AccountHash, Mailbox, MailboxHash},
email::{attachment_types::*, attachments::*}, email::{attachment_types::*, attachments::*},
text::{TextProcessing, Truncate},
thread::ThreadNodeHash, thread::ThreadNodeHash,
}; };
use uuid::Uuid;
use super::*; use super::*;
use crate::{
melib::text::{TextProcessing, Truncate}, pub type AttachmentBoxFuture = Pin<Box<dyn Future<Output = Result<AttachmentBuilder>> + Send>>;
uuid::Uuid, pub type AttachmentFilterBox = Box<dyn FnOnce(AttachmentBuilder) -> AttachmentBoxFuture + Send>;
};
pub mod listing; pub mod listing;
pub use crate::listing::*; pub use crate::listing::*;

@ -888,6 +888,8 @@ impl Component for Composer {
self.gpg_state.sign_mail = self.gpg_state.sign_mail =
Some(*account_settings!(context[self.account_hash].pgp.auto_sign)); Some(*account_settings!(context[self.account_hash].pgp.auto_sign));
} }
self.gpg_state.encrypt_for_self =
*account_settings!(context[self.account_hash].pgp.encrypt_for_self);
if !self.draft.headers().contains_key(HeaderName::FROM) if !self.draft.headers().contains_key(HeaderName::FROM)
|| self.draft.headers()[HeaderName::FROM].is_empty() || self.draft.headers()[HeaderName::FROM].is_empty()
{ {
@ -2564,16 +2566,7 @@ pub fn send_draft_async(
let format_flowed = *account_settings!(context[account_hash].composing.format_flowed); let format_flowed = *account_settings!(context[account_hash].composing.format_flowed);
let event_sender = context.main_loop_handler.sender.clone(); let event_sender = context.main_loop_handler.sender.clone();
#[cfg(feature = "gpgme")] #[cfg(feature = "gpgme")]
#[allow(clippy::type_complexity)] let mut filters_stack: Vec<AttachmentFilterBox> = vec![];
let mut filters_stack: Vec<
Box<
dyn FnOnce(
AttachmentBuilder,
)
-> Pin<Box<dyn Future<Output = Result<AttachmentBuilder>> + Send>>
+ Send,
>,
> = vec![];
#[cfg(feature = "gpgme")] #[cfg(feature = "gpgme")]
if gpg_state.sign_mail.unwrap_or(ActionFlag::False).is_true() if gpg_state.sign_mail.unwrap_or(ActionFlag::False).is_true()
&& !gpg_state && !gpg_state
@ -2623,14 +2616,15 @@ pub fn send_draft_async(
let send_mail = account_settings!(context[account_hash].send_mail).clone(); let send_mail = account_settings!(context[account_hash].send_mail).clone();
let send_cb = context.accounts[&account_hash].send_async(send_mail); let send_cb = context.accounts[&account_hash].send_async(send_mail);
let mut content_type = ContentType::default(); let mut content_type = ContentType::default();
if format_flowed { if let (
if let ContentType::Text { true,
ContentType::Text {
ref mut parameters, .. ref mut parameters, ..
} = content_type },
) = (format_flowed, &mut content_type)
{ {
parameters.push((b"format".to_vec(), b"flowed".to_vec())); parameters.push((b"format".to_vec(), b"flowed".to_vec()));
} }
}
let mut body: AttachmentBuilder = Attachment::new( let mut body: AttachmentBuilder = Attachment::new(
content_type, content_type,
Default::default(), Default::default(),

@ -23,7 +23,6 @@ use std::{
collections::{hash_map::DefaultHasher, BTreeMap}, collections::{hash_map::DefaultHasher, BTreeMap},
future::Future, future::Future,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
pin::Pin,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -38,6 +37,8 @@ use melib::{
parser::BytesExt, parser::BytesExt,
}; };
use super::AttachmentBoxFuture;
pub async fn decrypt(raw: Vec<u8>) -> Result<(melib_pgp::DecryptionMetadata, Vec<u8>)> { pub async fn decrypt(raw: Vec<u8>) -> Result<(melib_pgp::DecryptionMetadata, Vec<u8>)> {
let mut ctx = Context::new()?; let mut ctx = Context::new()?;
let cipher = ctx.new_data_mem(&raw)?; let cipher = ctx.new_data_mem(&raw)?;
@ -87,6 +88,23 @@ pub fn sign_filter(
Ok(move |a: AttachmentBuilder| -> AttachmentBoxFuture { Ok(move |a: AttachmentBuilder| -> AttachmentBoxFuture {
Box::pin(async move { Box::pin(async move {
if let Some(default_key) = default_key { if let Some(default_key) = default_key {
let mut ctx = Context::new()?;
ctx.set_auto_key_locate(LocateKey::LOCAL)?;
let keys = ctx.keylist(false, Some(default_key.clone()))?.await?;
if keys.is_empty() {
return Err(Error::new(format!(
"Could not locate sign key with ID `{}`",
default_key
)));
}
sign_keys.extend(keys);
}
if sign_keys.is_empty() {
return Err(Error::new(
"No key was selected for signing; please select one.",
));
}
let a: Attachment = a.into();
let mut ctx = Context::new()?; let mut ctx = Context::new()?;
let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec( let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec(
a.into_raw().as_bytes(), a.into_raw().as_bytes(),
@ -111,8 +129,7 @@ pub fn sign_filter(
) )
.into()) .into())
}) })
}, })
)
} }
pub fn encrypt_filter( pub fn encrypt_filter(
@ -166,24 +183,50 @@ pub fn encrypt_filter(
} }
if let Some(encrypt_for_self) = encrypt_for_self { if let Some(encrypt_for_self) = encrypt_for_self {
let mut ctx = Context::new()?; let mut ctx = Context::new()?;
let data = ctx.new_data_mem( ctx.set_auto_key_locate(LocateKey::LOCAL)?;
a.into_raw().as_bytes() let keys = ctx
)?; .keylist(false, Some(encrypt_for_self.to_string()))?
.await?;
if keys.is_empty() {
return Err(Error::new(format!(
"Could not locate personal encryption key for address `{}`",
encrypt_for_self
)));
}
for key in keys {
if !encrypt_keys.contains(&key) {
encrypt_keys.push(key);
}
}
}
let a: Attachment = a.into();
log::trace!(
"main attachment is {:?} sign_keys = {:?} encrypt_keys = {:?}",
&a,
&sign_keys,
&encrypt_keys
);
let mut ctx = Context::new()?;
let data = ctx.new_data_mem(a.into_raw().as_bytes())?;
let sig_attachment = { let enc_attachment = {
let mut a = Attachment::new( let mut a = Attachment::new(
ContentType::OctetStream { name: None, parameters: vec![] }, ContentType::OctetStream {
name: None,
parameters: vec![],
},
Default::default(), Default::default(),
ctx.encrypt(sign_keys, encrypt_keys, data)?.await?, ctx.encrypt(sign_keys, encrypt_keys, data)?.await?,
); );
a.content_disposition = ContentDisposition::from(br#"attachment; filename="msg.asc""#); a.content_disposition =
ContentDisposition::from(br#"attachment; filename="msg.asc""#);
a a
}; };
let mut a: AttachmentBuilder = AttachmentBuilder::new(b"Version: 1\n"); let mut a: AttachmentBuilder = AttachmentBuilder::new(b"Version: 1\n");
a.set_content_type_from_bytes(b"application/pgp-encrypted"); a.set_content_type_from_bytes(b"application/pgp-encrypted");
a.set_content_disposition(ContentDisposition::from(b"attachment")); a.set_content_disposition(ContentDisposition::from(b"attachment"));
let parts = vec![a, sig_attachment.into()]; let parts = vec![a, enc_attachment.into()];
let boundary = ContentType::make_boundary(&parts); let boundary = ContentType::make_boundary(&parts);
Ok(Attachment::new( Ok(Attachment::new(
ContentType::Multipart { ContentType::Multipart {
@ -197,6 +240,5 @@ pub fn encrypt_filter(
) )
.into()) .into())
}) })
}, })
)
} }

Loading…
Cancel
Save