add pgp support

This commit is contained in:
Clément DOUIN
2023-08-02 18:03:47 +02:00
parent 183aa2f306
commit 99ec7c6d97
9 changed files with 141 additions and 98 deletions
+37 -1
View File
@@ -5,7 +5,9 @@ use pimalaya_email::backend::{ImapAuthConfig, ImapConfig};
#[cfg(feature = "smtp-sender")]
use pimalaya_email::sender::{SmtpAuthConfig, SmtpConfig};
use pimalaya_email::{
account::{OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig},
account::{
OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig, PgpConfig, PgpKey, PgpNativeConfig,
},
backend::{BackendConfig, MaildirConfig},
email::{EmailHooks, EmailTextPlainFormat},
folder::sync::FolderSyncStrategy,
@@ -387,3 +389,37 @@ pub enum FolderSyncStrategyDef {
#[serde(alias = "ignore")]
Exclude(HashSet<String>),
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
#[serde(remote = "PgpConfig", tag = "backend", rename_all = "kebab-case")]
pub enum PgpConfigDef {
#[default]
None,
#[serde(with = "PgpNativeConfigDef")]
Native(PgpNativeConfig),
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
#[serde(remote = "PgpNativeConfig", rename_all = "kebab-case")]
pub struct PgpNativeConfigDef {
#[serde(default, with = "PgpKeyDef")]
secret_key: PgpKey,
#[serde(default, with = "SecretDef")]
secret_key_passwd: Secret,
#[serde(default, with = "PgpKeyDef")]
public_key: PgpKey,
#[serde(default = "PgpNativeConfig::default_wkd")]
wkd: bool,
#[serde(default = "PgpNativeConfig::default_key_servers")]
key_servers: Vec<String>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
#[serde(remote = "PgpKey", rename_all = "kebab-case")]
pub enum PgpKeyDef {
#[default]
None,
Path(PathBuf),
#[serde(with = "EntryDef")]
Keyring(Entry),
}
+5 -42
View File
@@ -8,7 +8,7 @@ use pimalaya_email::backend::ImapAuthConfig;
#[cfg(feature = "smtp-sender")]
use pimalaya_email::sender::SmtpAuthConfig;
use pimalaya_email::{
account::AccountConfig,
account::{AccountConfig, PgpConfig},
backend::BackendConfig,
email::{EmailHooks, EmailTextPlainFormat},
folder::sync::FolderSyncStrategy,
@@ -90,6 +90,9 @@ pub struct DeserializedAccountConfig {
pub backend: BackendConfig,
#[serde(flatten, with = "SenderConfigDef")]
pub sender: SenderConfig,
#[serde(default, with = "PgpConfigDef")]
pub pgp: PgpConfig,
}
impl DeserializedAccountConfig {
@@ -155,46 +158,6 @@ impl DeserializedAccountConfig {
.map(ToOwned::to_owned)
.or_else(|| config.email_reading_headers.as_ref().map(ToOwned::to_owned)),
email_reading_format: self.email_reading_format.clone(),
email_reading_verify_cmd: self
.email_reading_verify_cmd
.as_ref()
.map(ToOwned::to_owned)
.or_else(|| {
config
.email_reading_verify_cmd
.as_ref()
.map(ToOwned::to_owned)
}),
email_reading_decrypt_cmd: self
.email_reading_decrypt_cmd
.as_ref()
.map(ToOwned::to_owned)
.or_else(|| {
config
.email_reading_decrypt_cmd
.as_ref()
.map(ToOwned::to_owned)
}),
email_writing_sign_cmd: self
.email_writing_sign_cmd
.as_ref()
.map(ToOwned::to_owned)
.or_else(|| {
config
.email_writing_sign_cmd
.as_ref()
.map(ToOwned::to_owned)
}),
email_writing_encrypt_cmd: self
.email_writing_encrypt_cmd
.as_ref()
.map(ToOwned::to_owned)
.or_else(|| {
config
.email_writing_encrypt_cmd
.as_ref()
.map(ToOwned::to_owned)
}),
email_writing_headers: self
.email_writing_headers
.as_ref()
@@ -258,7 +221,7 @@ impl DeserializedAccountConfig {
sender
},
pgp: Default::default(),
pgp: self.pgp.clone(),
}
}
}
+7
View File
@@ -72,6 +72,8 @@ pub async fn configure(config: &AccountConfig, reset: bool) -> Result<()> {
warn!("{err}");
}
}
config.pgp.reset().await?;
}
#[cfg(feature = "imap-backend")]
@@ -102,6 +104,11 @@ pub async fn configure(config: &AccountConfig, reset: bool) -> Result<()> {
}?;
}
config
.pgp
.configure(&config.email, || prompt_passwd("PGP secret key password"))
.await?;
println!(
"Account successfully {}configured!",
if reset { "re" } else { "" }
+4 -4
View File
@@ -185,7 +185,7 @@ pub async fn mailto<P: Printer>(
let tpl = config
.generate_tpl_interpreter()
.show_only_headers(config.email_writing_headers())
.with_show_only_headers(config.email_writing_headers())
.interpret_msg_builder(builder)
.await?;
@@ -235,9 +235,9 @@ pub async fn read<P: Printer>(
let tpl: String = email
.to_read_tpl(&config, |tpl| match text_mime {
"html" => tpl
.hide_all_headers()
.filter_parts(FilterParts::Only("text/html".into())),
_ => tpl.show_additional_headers(&headers),
.with_hide_all_headers()
.with_filter_parts(FilterParts::Only("text/html".into())),
_ => tpl.with_show_additional_headers(&headers),
})
.await?
.into();
+9 -7
View File
@@ -3,7 +3,7 @@ use atty::Stream;
use pimalaya_email::{
account::AccountConfig,
backend::Backend,
email::{Flags, Message, Tpl},
email::{Flag, Flags, Message, Tpl},
sender::Sender,
};
use std::io::{stdin, BufRead};
@@ -86,8 +86,8 @@ pub async fn save<P: Printer>(
.collect::<Vec<String>>()
.join("\n")
})
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
.with_pgp_encrypt(config.pgp.clone())
.with_pgp_sign(config.pgp.clone())
.compile()
.await?
.write_to_vec()?;
@@ -103,9 +103,9 @@ pub async fn send<P: Printer>(
printer: &mut P,
backend: &mut dyn Backend,
sender: &mut dyn Sender,
folder: &str,
tpl: String,
) -> Result<()> {
let folder = config.sent_folder_alias()?;
let email = Tpl::from(if atty::is(Stream::Stdin) || printer.is_json() {
tpl.replace("\r", "")
} else {
@@ -116,8 +116,8 @@ pub async fn send<P: Printer>(
.collect::<Vec<String>>()
.join("\n")
})
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
.with_pgp_encrypt(config.pgp.clone())
.with_pgp_sign(config.pgp.clone())
.compile()
.await?
.write_to_vec()?;
@@ -125,7 +125,9 @@ pub async fn send<P: Printer>(
sender.send(&email).await?;
if config.email_sending_save_copy {
backend.add_email(folder, &email, &Flags::default()).await?;
backend
.add_email(&folder, &email, &Flags::from_iter([Flag::Seen]))
.await?;
}
printer.print("Template successfully sent!")?;
-2
View File
@@ -513,7 +513,6 @@ async fn main() -> Result<()> {
return Ok(());
}
Some(tpl::args::Cmd::Send(tpl)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let mut backend = backend_builder.clone().into_build().await?;
let mut sender = sender_builder.build().await?;
tpl::handlers::send(
@@ -521,7 +520,6 @@ async fn main() -> Result<()> {
&mut printer,
backend.as_mut(),
sender.as_mut(),
&folder,
tpl,
)
.await?;
+4 -4
View File
@@ -76,8 +76,8 @@ pub async fn edit_tpl_with_editor<P: Printer>(
Ok(PostEditChoice::Send) => {
printer.print_log("Sending email…")?;
let email = tpl
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
.with_pgp_encrypt(config.pgp.clone())
.with_pgp_sign(config.pgp.clone())
.compile()
.await?
.write_to_vec()?;
@@ -103,8 +103,8 @@ pub async fn edit_tpl_with_editor<P: Printer>(
}
Ok(PostEditChoice::RemoteDraft) => {
let email = tpl
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
.with_pgp_encrypt(config.pgp.clone())
.with_pgp_sign(config.pgp.clone())
.compile()
.await?
.write_to_vec()?;