Skip to content

Commit

Permalink
release v0.5.5 (pimalaya#290)
Browse files Browse the repository at this point in the history
* update main screenshot readme

* add contributing file

* update changelog

* doc: remove roadmap from reame

* improve main comments

* improve arg and handler logs

* fix multiple recipients issue (pimalaya#288)

* add notify-query config option (pimalaya#289)

* set up end-to-end encryption (pimalaya#287)

* init basic pgp encrypt/decrypt

* add small rpgp poc for (pimalaya#286)

* improve decrypt parts logs

* add pgp-decrypt-cmd to config

* add pgp-encrypt-cmd to config

* init pgp signature

* improve decrypt part readability

* improve encrypt multipart, remove sign

* remove unused md5 lib

* add encrypt arg to reply and forward commands

* fix typos

* prepare v0.5.5
  • Loading branch information
soywod authored Feb 8, 2022
1 parent e33a9a7 commit 585fa77
Show file tree
Hide file tree
Showing 29 changed files with 762 additions and 274 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.5.5] - 2022-02-08

### Added

- [Contributing guide](https://github.com/soywod/himalaya/blob/master/CONTRIBUTING.md) [#256]
- Notify query config option [#289]
- End-to-end encryption *(EXPERIMENTAL)* [#54]

### Fixed

- Multiple recipients issue [#288]

## [0.5.4] - 2022-02-05

### Fixed
Expand Down Expand Up @@ -280,7 +292,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Password from command [#22]
- Set up README [#20]

[unreleased]: https://github.com/soywod/himalaya/compare/v0.5.4...HEAD
[unreleased]: https://github.com/soywod/himalaya/compare/v0.5.5...HEAD
[0.5.5]: https://github.com/soywod/himalaya/compare/v0.5.4...v0.5.5
[0.5.4]: https://github.com/soywod/himalaya/compare/v0.5.3...v0.5.4
[0.5.3]: https://github.com/soywod/himalaya/compare/v0.5.2...v0.5.3
[0.5.2]: https://github.com/soywod/himalaya/compare/v0.5.1...v0.5.2
Expand Down Expand Up @@ -336,6 +349,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#47]: https://github.com/soywod/himalaya/issues/47
[#48]: https://github.com/soywod/himalaya/issues/48
[#50]: https://github.com/soywod/himalaya/issues/50
[#54]: https://github.com/soywod/himalaya/issues/54
[#58]: https://github.com/soywod/himalaya/issues/58
[#59]: https://github.com/soywod/himalaya/issues/59
[#61]: https://github.com/soywod/himalaya/issues/61
Expand Down Expand Up @@ -392,6 +406,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#228]: https://github.com/soywod/himalaya/issues/228
[#229]: https://github.com/soywod/himalaya/issues/229
[#249]: https://github.com/soywod/himalaya/issues/249
[#256]: https://github.com/soywod/himalaya/issues/256
[#259]: https://github.com/soywod/himalaya/issues/259
[#268]: https://github.com/soywod/himalaya/issues/268
[#272]: https://github.com/soywod/himalaya/issues/272
Expand All @@ -400,3 +415,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#271]: https://github.com/soywod/himalaya/issues/271
[#276]: https://github.com/soywod/himalaya/issues/276
[#280]: https://github.com/soywod/himalaya/issues/280
[#288]: https://github.com/soywod/himalaya/issues/288
[#289]: https://github.com/soywod/himalaya/issues/289
42 changes: 42 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Himalaya contributing guide

Thank you for investing your time in contributing to Himalaya!

In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.

## New contributor guide

To get an overview of the project, read the [README](README.md). To get more information about the project, read the [wiki](https://github.com/soywod/himalaya/wiki).

## Getting started

### Issues

#### Create a new issue

If you spot a problem with the docs, [search if an issue already exists](https://github.com/soywod/himalaya/issues). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/soywod/himalaya/issues/new/choose).

#### Solve an issue

Scan through our [existing issues](https://github.com/soywod/himalaya/issues) to find one that interests you. You can narrow down the search using `labels` as filters. If you find an issue to work on, you are welcome to open a PR with a fix.

### Make Changes

#### Make changes in the UI

Click **Make a contribution** at the bottom of any docs page to make small changes such as a typo, sentence fix, or a broken link. This takes you to the `.md` file where you can make your changes and [create a pull request](#pull-request) for a review.

#### Make changes locally

First, follow the instructions on [how to install Himalaya from sources](https://github.com/soywod/himalaya/wiki/Installation:sources). Then, create a working branch and start with your changes!

### Commit your update

Commit the changes once you are happy with them. Commit messages follow the [Angular Convention](https://gist.github.com/stephenparish/9941e89d80e2bc58a153), but contain only a subject. The subject can be prefixed with a custom context like `msg: `, `mbox: `, `imap: ` etc.

> Use imperative, present tense: “change” not “changed” nor
> “changes”<br>Don't capitalize first letter<br>No dot (.) at the end
### Pull Request

When you're finished with the changes, create a pull request, also known as a PR.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "himalaya"
description = "Command-line interface for email management"
version = "0.5.4"
version = "0.5.5"
authors = ["soywod <[email protected]>"]
edition = "2018"
license-file = "LICENSE"
Expand Down
26 changes: 7 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,15 @@

Command-line interface for email management

*The project is under active development. Do not use in production before the
`v1.0.0` (see the [roadmap](https://github.com/soywod/himalaya/milestone/5)).*
*The project is under active development. Do not use in production before the `v1.0.0`.*

![image](https://user-images.githubusercontent.com/10437171/115144003-8a1b4880-a04a-11eb-80d2-245027e28591.png)
![image](https://user-images.githubusercontent.com/10437171/138774902-7b9de5a3-93eb-44b0-8cfb-6d2e11e3b1aa.png)

## Motivation

Bringing emails to the terminal is a *pain*. First, because they are sensitive
data. Secondly, the existing TUIs ([Mutt](http://www.mutt.org/),
[NeoMutt](https://neomutt.org/), [Alpine](https://alpine.x10host.com/),
[aerc](https://aerc-mail.org/)…) are really hard to configure. They require time
and patience.
Bringing emails to the terminal is a *pain*. First, because they are sensitive data. Secondly, the existing TUIs ([Mutt](http://www.mutt.org/), [NeoMutt](https://neomutt.org/), [Alpine](https://alpine.x10host.com/), [aerc](https://aerc-mail.org/)…) are really hard to configure. They require time and patience.

The aim of Himalaya is to extract the email logic into a simple (yet solid) CLI
API that can be used directly from the terminal, from scripts, from UIs…
Possibilities are endless!
The aim of Himalaya is to extract the email logic into a simple (yet solid) CLI API that can be used directly from the terminal, from scripts, from UIs… Possibilities are endless!

## Installation

Expand All @@ -28,9 +21,7 @@ Possibilities are endless!
curl -sSL https://raw.githubusercontent.com/soywod/himalaya/master/install.sh | PREFIX=~/.local sh
```

*See the
[wiki](https://github.com/soywod/himalaya/wiki/Installation:from-binary) for
other installation methods.*
*See the [wiki](https://github.com/soywod/himalaya/wiki/Installation:from-binary) for other installation methods.*

## Configuration

Expand Down Expand Up @@ -59,9 +50,7 @@ smtp-login = "[email protected]"
smtp-passwd-cmd = "security find-internet-password -gs gmail -w"
```

*See the
[wiki](https://github.com/soywod/himalaya/wiki/Configuration:config-file) for
all the options.*
*See the [wiki](https://github.com/soywod/himalaya/wiki/Configuration:config-file) for all the options.*

## Features

Expand All @@ -76,8 +65,7 @@ all the options.*
- JSON output
-

*See the [wiki](https://github.com/soywod/himalaya/wiki/Usage:msg:list) for all
the features.*
*See the [wiki](https://github.com/soywod/himalaya/wiki/Usage:msg:list) for all the features.*

## Sponsoring

Expand Down
8 changes: 5 additions & 3 deletions src/compl/compl_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use anyhow::Result;
use clap::{self, App, Arg, ArgMatches, Shell, SubCommand};
use log::debug;
use log::{debug, info};

type OptionShell<'a> = Option<&'a str>;

Expand All @@ -16,10 +16,12 @@ pub enum Command<'a> {

/// Completion command matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
info!("entering completion command matcher");

if let Some(m) = m.subcommand_matches("completion") {
debug!("completion command matched");
info!("completion command matched");
let shell = m.value_of("shell");
debug!("shell: `{:?}`", shell);
debug!("shell: {:?}", shell);
return Ok(Some(Command::Generate(shell)));
};

Expand Down
7 changes: 6 additions & 1 deletion src/compl/compl_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
use anyhow::{anyhow, Context, Result};
use clap::{App, Shell};
use log::{debug, info};
use std::{io, str::FromStr};

/// Generate completion script from the given [`clap::App`] for the given shell slice.
/// Generates completion script from the given [`clap::App`] for the given shell slice.
pub fn generate<'a>(mut app: App<'a, 'a>, shell: Option<&'a str>) -> Result<()> {
info!("entering generate completion handler");

let shell = Shell::from_str(shell.unwrap_or_default())
.map_err(|err| anyhow!(err))
.context("cannot parse shell")?;
debug!("shell: {}", shell);

app.gen_completions_to("himalaya", shell, &mut io::stdout());
Ok(())
}
40 changes: 39 additions & 1 deletion src/config/account_entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub struct Account {
pub sent_folder: String,
/// Defines the draft folder name for this account
pub draft_folder: String,
/// Defines the IMAP query used to fetch new messages.
pub notify_query: String,
pub watch_cmds: Vec<String>,
pub default: bool,
pub email: String,
Expand All @@ -43,6 +45,9 @@ pub struct Account {
pub smtp_insecure: bool,
pub smtp_login: String,
pub smtp_passwd_cmd: String,

pub pgp_encrypt_cmd: Option<String>,
pub pgp_decrypt_cmd: Option<String>,
}

impl Account {
Expand Down Expand Up @@ -77,6 +82,30 @@ impl Account {

Ok(SmtpCredentials::new(self.smtp_login.to_owned(), passwd))
}

pub fn pgp_encrypt_file(&self, addr: &str, path: PathBuf) -> Result<Option<String>> {
if let Some(cmd) = self.pgp_encrypt_cmd.as_ref() {
let encrypt_file_cmd = format!("{} {} {:?}", cmd, addr, path);
run_cmd(&encrypt_file_cmd).map(Some).context(format!(
"cannot run pgp encrypt command {:?}",
encrypt_file_cmd
))
} else {
Ok(None)
}
}

pub fn pgp_decrypt_file(&self, path: PathBuf) -> Result<Option<String>> {
if let Some(cmd) = self.pgp_decrypt_cmd.as_ref() {
let decrypt_file_cmd = format!("{} {:?}", cmd, path);
run_cmd(&decrypt_file_cmd).map(Some).context(format!(
"cannot run pgp decrypt command {:?}",
decrypt_file_cmd
))
} else {
Ok(None)
}
}
}

impl<'a> TryFrom<(&'a Config, Option<&str>)> for Account {
Expand Down Expand Up @@ -162,6 +191,12 @@ impl<'a> TryFrom<(&'a Config, Option<&str>)> for Account {
.or_else(|| config.draft_folder.as_deref())
.unwrap_or(DEFAULT_DRAFT_FOLDER)
.to_string(),
notify_query: account
.notify_query
.as_ref()
.or_else(|| config.notify_query.as_ref())
.unwrap_or(&String::from("NEW"))
.to_owned(),
watch_cmds: account
.watch_cmds
.as_ref()
Expand All @@ -184,9 +219,12 @@ impl<'a> TryFrom<(&'a Config, Option<&str>)> for Account {
smtp_insecure: account.smtp_insecure.unwrap_or_default(),
smtp_login: account.smtp_login.to_owned(),
smtp_passwd_cmd: account.smtp_passwd_cmd.to_owned(),

pgp_encrypt_cmd: account.pgp_encrypt_cmd.to_owned(),
pgp_decrypt_cmd: account.pgp_decrypt_cmd.to_owned(),
};

trace!("{:#?}", account);
trace!("account: {:?}", account);
Ok(account)
}
}
7 changes: 7 additions & 0 deletions src/config/config_entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub struct Config {
pub draft_folder: Option<String>,
/// Defines the notify command.
pub notify_cmd: Option<String>,
/// Customizes the IMAP query used to fetch new messages.
pub notify_query: Option<String>,
/// Defines the watch commands.
pub watch_cmds: Option<Vec<String>>,

Expand All @@ -56,6 +58,8 @@ pub struct ConfigAccountEntry {
pub sent_folder: Option<String>,
/// Defines a specific draft folder name for this account.
pub draft_folder: Option<String>,
/// Customizes the IMAP query used to fetch new messages.
pub notify_query: Option<String>,
pub watch_cmds: Option<Vec<String>>,
pub default: Option<bool>,
pub email: String,
Expand All @@ -73,6 +77,9 @@ pub struct ConfigAccountEntry {
pub smtp_insecure: Option<bool>,
pub smtp_login: String,
pub smtp_passwd_cmd: String,

pub pgp_encrypt_cmd: Option<String>,
pub pgp_decrypt_cmd: Option<String>,
}

impl Config {
Expand Down
8 changes: 5 additions & 3 deletions src/domain/imap/imap_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use anyhow::Result;
use clap::{App, ArgMatches};
use log::debug;
use log::{debug, info};

type Keepalive = u64;

Expand All @@ -19,15 +19,17 @@ pub enum Command {

/// IMAP command matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Command>> {
info!("entering imap command matcher");

if let Some(m) = m.subcommand_matches("notify") {
debug!("notify command matched");
info!("notify command matched");
let keepalive = clap::value_t_or_exit!(m.value_of("keepalive"), u64);
debug!("keepalive: {}", keepalive);
return Ok(Some(Command::Notify(keepalive)));
}

if let Some(m) = m.subcommand_matches("watch") {
debug!("watch command matched");
info!("watch command matched");
let keepalive = clap::value_t_or_exit!(m.value_of("keepalive"), u64);
debug!("keepalive: {}", keepalive);
return Ok(Some(Command::Watch(keepalive)));
Expand Down
5 changes: 2 additions & 3 deletions src/domain/imap/imap_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ use crate::{
domain::imap::ImapServiceInterface,
};

/// Notify handler.
pub fn notify<'a, ImapService: ImapServiceInterface<'a>>(
keepalive: u64,
config: &Config,
account: &Account,
imap: &mut ImapService,
) -> Result<()> {
imap.notify(config, keepalive)
imap.notify(config, account, keepalive)
}

/// Watch handler.
pub fn watch<'a, ImapService: ImapServiceInterface<'a>>(
keepalive: u64,
account: &Account,
Expand Down
Loading

0 comments on commit 585fa77

Please sign in to comment.