diff --git a/CHANGELOG.md b/CHANGELOG.md index f62f4bd..891d90d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,41 +7,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.7.1] - 2023-02-14 + +### Added + +- Added command `folders expunge` that deletes all emails marked for + deletion. + +### Changed + +- Changed the location of the + [documentation](https://pimalaya.org/himalaya/docs/). + +### Fixed + +- Fixed broken links in README.md. + +### Removed + +- Removed the `maildir-backend` cargo feature, it is now included by + default. +- Removed issues section on GitHub, now issues need to be opened by + sending an email at + [~soywod/pimalaya@todo.sr.ht](mailto:~soywod/pimalaya@todo.sr.ht). + ## [0.7.0] - 2023-02-08 ### Added -* Added offline support with the `account sync` command to synchronize +- Added offline support with the `account sync` command to synchronize a backend to a local Maildir backend [#342]. -* Added the flag `--disable-cache` to not use the local Maildir +- Added the flag `--disable-cache` to not use the local Maildir backend. -* Added the email composer (from its own +- Added the email composer (from its own [repository](https://git.sr.ht/~soywod/mime-msg-builder)) [#341]. -* Added Musl builds to releases [#356]. -* Added `himalaya man` command to generate man page [#419]. +- Added Musl builds to releases [#356]. +- Added `himalaya man` command to generate man page [#419]. ### Changed -* Made commands `read`, `attachments`, `flags`, `copy`, `move`, +- Made commands `read`, `attachments`, `flags`, `copy`, `move`, `delete` accept multiple ids. -* Flipped arguments `ids` and `folder` for commands `copy` and `move` +- Flipped arguments `ids` and `folder` for commands `copy` and `move` in order the folder not to be considered as an id. ### Fixed -* Fixed missing folder aliases [#430]. +- Fixed missing folder aliases [#430]. ### Removed -* Removed the `-a|--attachment` argument from `write`, `reply` and +- Removed the `-a|--attachment` argument from `write`, `reply` and `forward` commands. Instead you can attach documents directly from the template using the syntax `<#part filename=/path/to/you/document.ext>`. -* Removed the `-e|--encrypt` flag from `write`, `reply` and `forward` +- Removed the `-e|--encrypt` flag from `write`, `reply` and `forward` commands. Instead you can encrypt and sign parts directly from the template using the syntax `<#part type=text/plain encrypt=command sign=command>Hello!<#/part>`. -* Removed the `-l|--log-level` option, use instead the `RUST_LOG` +- Removed the `-l|--log-level` option, use instead the `RUST_LOG` environment variable (see the [wiki](https://github.com/soywod/himalaya/wiki/Tips:debug-and-logs)) @@ -49,434 +73,434 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -* Added `-s|--sanitize` flag for the `read` command. +- Added `-s|--sanitize` flag for the `read` command. ### Changed -* Changed the behaviour of the `-t|--mime-type` argument of the `read` +- Changed the behaviour of the `-t|--mime-type` argument of the `read` command. It is less strict now: if no part is found for the given MIME type, it will fallback to the other one. For example, giving `-t html` will show in priority HTML parts, but if none of them are found it will show plain parts instead (and vice versa). -* Sanitization is not done by default when using the `read` command, +- Sanitization is not done by default when using the `read` command, the flag `-s|--sanitize` needs to be explicitly provided. ### Fixed -* Fixed empty text bodies when reading html part on plain text email +- Fixed empty text bodies when reading html part on plain text email [#352]. ## [0.6.0] - 2022-10-10 ### Changed -* Separated the CLI from the lib module [#340]. +- Separated the CLI from the lib module [#340]. The source code has been splitted into subrepositories: - * The email logic has been extracted from the CLI and placed in a + - The email logic has been extracted from the CLI and placed in a lib on [sourcehut](https://git.sr.ht/~soywod/himalaya-lib) - * The vim plugin is now in a dedicated repository on + - The vim plugin is now in a dedicated repository on [sourcehut](https://git.sr.ht/~soywod/himalaya-vim) as well - * This repository only contains the CLI source code (it was not + - This repository only contains the CLI source code (it was not possible to move it to sourcehut because of cross platform builds) -* [**BREAKING**] Renamed `-m|--mailbox` to `-f|--folder` +- [**BREAKING**] Renamed `-m|--mailbox` to `-f|--folder` -* [**BREAKING**] Refactored config system [#344]. +- [**BREAKING**] Refactored config system [#344]. The configuration has been rethought in order to be more intuitive and structured. Here are the breaking changes for the global config: - * `name` becomes `display-name` and is not mandatory anymore - * `signature-delimiter` becomes `signature-delim` - * `default-page-size` has been moved to `folder-listing-page-size` + - `name` becomes `display-name` and is not mandatory anymore + - `signature-delimiter` becomes `signature-delim` + - `default-page-size` has been moved to `folder-listing-page-size` and `email-listing-page-size` - * `notify-cmd`, `notify-query` and `watch-cmds` have been removed + - `notify-cmd`, `notify-query` and `watch-cmds` have been removed from the global config (available in account config only) - * `folder-aliases` has been added to the global config (previously + - `folder-aliases` has been added to the global config (previously known as `mailboxes` from the account config) - * `email-reading-headers`, `email-reading-format`, + - `email-reading-headers`, `email-reading-format`, `email-reading-decrypt-cmd`, `email-writing-encrypt-cmd` and `email-hooks` have been added The account config inherits the same breaking changes from the global config, plus: - * `imap-*` requires `backend = "imap"` - * `maildir-*` requires `backend = "maildir"` - * `notmuch-*` requires `backend = "notmuch"` - * `smtp-*` requires `sender = "smtp"` - * `sendmail-*` requires `sender = "sendmail"` - * `pgp-encrypt-cmd` becomes `email-writing-encrypt-cmd` - * `pgp-decrypt-cmd` becomes `email-reading-decrypt-cmd` - * `mailboxes` becomes `folder-aliases` - * `hooks` becomes `email-hooks` - * `maildir-dir` becomes `maildir-root-dir` - * `notmuch-database-dir` becomes `notmuch-db-path` + - `imap-*` requires `backend = "imap"` + - `maildir-*` requires `backend = "maildir"` + - `notmuch-*` requires `backend = "notmuch"` + - `smtp-*` requires `sender = "smtp"` + - `sendmail-*` requires `sender = "sendmail"` + - `pgp-encrypt-cmd` becomes `email-writing-encrypt-cmd` + - `pgp-decrypt-cmd` becomes `email-reading-decrypt-cmd` + - `mailboxes` becomes `folder-aliases` + - `hooks` becomes `email-hooks` + - `maildir-dir` becomes `maildir-root-dir` + - `notmuch-database-dir` becomes `notmuch-db-path` ## [0.5.10] - 2022-03-20 ### Fixed -* Flag commands [#334] -* Windows build [#346] +- Flag commands [#334] +- Windows build [#346] ## [0.5.9] - 2022-03-12 ### Added -* SMTP pre-send hook [#178] -* Customize headers to show at the top of a read message [#338] +- SMTP pre-send hook [#178] +- Customize headers to show at the top of a read message [#338] ### Changed -* Improve `attachments` command [#281] +- Improve `attachments` command [#281] ### Fixed -* `In-Reply-To` not set properly when replying to a message [#323] -* `Cc` missing or invalid when replying to a message [#324] -* Notmuch backend hangs [#329] -* Maildir e2e tests [#335] -* JSON API for listings [#331] +- `In-Reply-To` not set properly when replying to a message [#323] +- `Cc` missing or invalid when replying to a message [#324] +- Notmuch backend hangs [#329] +- Maildir e2e tests [#335] +- JSON API for listings [#331] ## [0.5.8] - 2022-03-04 ### Added -* Flowed format support [#206] -* List accounts command [#244] -* One cargo feature per backend [#318] +- Flowed format support [#206] +- List accounts command [#244] +- One cargo feature per backend [#318] ### Changed -* Vim doc about mailbox pickers [#298] +- Vim doc about mailbox pickers [#298] ### Fixed -* Some emojis break the table layout [#300] -* Bad sender and date in reply and forward template [#321] +- Some emojis break the table layout [#300] +- Bad sender and date in reply and forward template [#321] ## [0.5.7] - 2022-03-01 ### Added -* Notmuch support [#57] +- Notmuch support [#57] ### Fixed -* Build failure due to `imap` version [#303] -* No tilde expansion in `maildir-dir` [#305] -* Unknown command SORT [#308] +- Build failure due to `imap` version [#303] +- No tilde expansion in `maildir-dir` [#305] +- Unknown command SORT [#308] ### Changed -* [**BREAKING**] Replace `inbox-folder`, `sent-folder` and `draft-folder` by a generic hashmap `mailboxes` -* Display short envelopes id for `maildir` and `notmuch` backends [#309] +- [**BREAKING**] Replace `inbox-folder`, `sent-folder` and `draft-folder` by a generic hashmap `mailboxes` +- Display short envelopes id for `maildir` and `notmuch` backends [#309] ## [0.5.6] - 2022-02-22 ### Added -* Sort command [#34] -* Maildir support [#43] +- Sort command [#34] +- Maildir support [#43] ### Fixed -* Suffix to downloaded attachments with same name [#204] +- Suffix to downloaded attachments with same name [#204] ## [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 [#54] +- [Contributing guide](https://github.com/soywod/himalaya/blob/master/CONTRIBUTING.md) [#256] +- Notify query config option [#289] +- End-to-end encryption [#54] ### Fixed -* Multiple recipients issue [#288] -* Cannot parse address [#227] +- Multiple recipients issue [#288] +- Cannot parse address [#227] ## [0.5.4] - 2022-02-05 ### Fixed -* Add attachments with save and send commands [#47] [#259] -* Invalid sequence set [#276] +- Add attachments with save and send commands [#47] [#259] +- Invalid sequence set [#276] ## [0.5.3] - 2022-02-03 ### Added -* Activate rust-imap logs when trace mode is enabled -* Set up cargo deployment +- Activate rust-imap logs when trace mode is enabled +- Set up cargo deployment ## [0.5.2] - 2022-02-02 ### Fixed -* Blur in list msg screenshot [#181] -* Make inbox, sent and drafts folders customizable [#172] -* Vim plugin get focused msg id [#268] -* Nix run issue [#272] -* Range not displayed when fetch fails [#276] -* Blank lines and spaces in `text/plain` parts [#280] -* Watch command [#271] -* Mailbox telescope.nvim preview [#249] +- Blur in list msg screenshot [#181] +- Make inbox, sent and drafts folders customizable [#172] +- Vim plugin get focused msg id [#268] +- Nix run issue [#272] +- Range not displayed when fetch fails [#276] +- Blank lines and spaces in `text/plain` parts [#280] +- Watch command [#271] +- Mailbox telescope.nvim preview [#249] ### Removed -* The wiki git submodule [#273] +- The wiki git submodule [#273] ## [0.5.1] - 2021-10-24 ### Added -* Disable color feature [#185] -* `--max-width|-w` argument to restrict listing table width [#220] +- Disable color feature [#185] +- `--max-width|-w` argument to restrict listing table width [#220] ### Fixed -* Error when receiving notification from `notify` command [#228] +- Error when receiving notification from `notify` command [#228] ### Changed -* Remove error when empty subject [#229] -* Vim plugin does not render anymore the msg by itself, it uses the one available from the CLI [#220] +- Remove error when empty subject [#229] +- Vim plugin does not render anymore the msg by itself, it uses the one available from the CLI [#220] ## [0.5.0] - 2021-10-10 ### Added -* Mailto support [#162] -* Remove previous signature when replying/forwarding a message [#193] -* Config option `signature-delimiter` to customize the signature delimiter (default to `-- \n`) [[#114](https://github.com/soywod/himalaya/pull/114)] -* Expand tilde and env vars for `downloads-dir` and `signature` [#102] +- Mailto support [#162] +- Remove previous signature when replying/forwarding a message [#193] +- Config option `signature-delimiter` to customize the signature delimiter (default to `-- \n`) [[#114](https://github.com/soywod/himalaya/pull/114)] +- Expand tilde and env vars for `downloads-dir` and `signature` [#102] ### Changed -* [**BREAKING**] Folder structure, message management, JSON API and Vim plugin [#199] -* Pagination for list and search cmd starts from 1 instead of 0 [#186] -* Errors management with `anyhow` [#152] +- [**BREAKING**] Folder structure, message management, JSON API and Vim plugin [#199] +- Pagination for list and search cmd starts from 1 instead of 0 [#186] +- Errors management with `anyhow` [#152] ### Fixed -* Panic on flags command [#190] -* Make more use of serde [#153] -* Write message vim plugin [#196] -* Invalid encoding when sending message [#205] -* Pagination reset current account [#215] -* New/reply/forward from Vim plugin since Tpl refactor [#176] +- Panic on flags command [#190] +- Make more use of serde [#153] +- Write message vim plugin [#196] +- Invalid encoding when sending message [#205] +- Pagination reset current account [#215] +- New/reply/forward from Vim plugin since Tpl refactor [#176] ## [0.4.0] - 2021-06-03 ### Added -* Add ability to change account in with the Vim plugin [#91] -* Add possibility to make Himalaya default email app [#160] [[#161](https://github.com/soywod/himalaya/pull/161)] +- Add ability to change account in with the Vim plugin [#91] +- Add possibility to make Himalaya default email app [#160] [[#161](https://github.com/soywod/himalaya/pull/161)] ### Changed -* [**BREAKING**] Short version of reply `--all` arg is now `-A` to +- [**BREAKING**] Short version of reply `--all` arg is now `-A` to avoid conflicts with `--attachment|-a` -* Template management [#80] +- Template management [#80] ### Fixed -* `\Seen` flag when moving a message -* Attachments arg for reply and forward commands [#109] -* Vim doc [#117] +- `\Seen` flag when moving a message +- Attachments arg for reply and forward commands [#109] +- Vim doc [#117] ### Removed -* `Content-Type` from templates [#146] +- `Content-Type` from templates [#146] ## [0.3.2] - 2021-05-08 ### Added -* Mailbox attributes [#134] -* Wiki entry about new messages counter [#121] -* Copy/move/delete a message in vim [#95] +- Mailbox attributes [#134] +- Wiki entry about new messages counter [#121] +- Copy/move/delete a message in vim [#95] ### Changed -* Get signature from file [#135] -* [**BREAKING**] Split `idle` command into two commands: - * `notify`: Runs `notify-cmd` when a new message arrives to the server - * `watch`: Runs `watch-cmds` when any change occurs on the server +- Get signature from file [#135] +- [**BREAKING**] Split `idle` command into two commands: + - `notify`: Runs `notify-cmd` when a new message arrives to the server + - `watch`: Runs `watch-cmds` when any change occurs on the server ### Removed -* `.exe` extension from release binaries [#144] +- `.exe` extension from release binaries [#144] ## [0.3.1] - 2021-05-04 ### Added -* Send message via stdin [#78] +- Send message via stdin [#78] ### Fixed -* Table with subject containing `\r`, `\n` or `\t` [#141] -* Overflow panic when shrink column [#138] -* Vim plugin empty mailbox message [#136] +- Table with subject containing `\r`, `\n` or `\t` [#141] +- Overflow panic when shrink column [#138] +- Vim plugin empty mailbox message [#136] ## [0.3.0] - 2021-04-28 ### Fixed -* IDLE mode after network interruption [#123] -* Output redirected to `stderr` [#130] -* Refactor table system [#132] -* Editon file format on Linux [#133] -* Show email address when name not available [#131] +- IDLE mode after network interruption [#123] +- Output redirected to `stderr` [#130] +- Refactor table system [#132] +- Editon file format on Linux [#133] +- Show email address when name not available [#131] ### Removed -* `--log-level|-l` arg (replaced by default `RUST_LOG` env var from `env_logger`) [#130] +- `--log-level|-l` arg (replaced by default `RUST_LOG` env var from `env_logger`) [#130] ## [0.2.7] - 2021-04-24 ### Added -* Default page size to config [#96] -* Custom config path [#86] -* Setting idle-hook-cmds +- Default page size to config [#96] +- Custom config path [#86] +- Setting idle-hook-cmds ### Changed -* Plain logger with `env_logger` [#126] -* Refresh email list on load buffer [#125] +- Plain logger with `env_logger` [#126] +- Refresh email list on load buffer [#125] ### Fixed -* Improve config compatibility on Windows [[#111](https://github.com/soywod/himalaya/pull/111)] -* Vim table containing emoji [#122] +- Improve config compatibility on Windows [[#111](https://github.com/soywod/himalaya/pull/111)] +- Vim table containing emoji [#122] ## [0.2.6] - 2021-04-17 ### Added -* Insecure TLS option [#84] [#103](https://github.com/soywod/himalaya/pull/103) [[#105](https://github.com/soywod/himalaya/pull/105)] -* Completion subcommands [[#99](https://github.com/soywod/himalaya/pull/99)] -* Vim flags to enable telescope preview and to choose picker [[#97](https://github.com/soywod/himalaya/pull/97)] +- Insecure TLS option [#84] [#103](https://github.com/soywod/himalaya/pull/103) [[#105](https://github.com/soywod/himalaya/pull/105)] +- Completion subcommands [[#99](https://github.com/soywod/himalaya/pull/99)] +- Vim flags to enable telescope preview and to choose picker [[#97](https://github.com/soywod/himalaya/pull/97)] ### Changed -* Make `install.sh` POSIX compliant [[#53](https://github.com/soywod/himalaya/pull/53)] +- Make `install.sh` POSIX compliant [[#53](https://github.com/soywod/himalaya/pull/53)] ### Fixed -* SMTP port [#87] -* Save msg upon error [#59] -* Answered flag not set [#50] -* Panic when downloads-dir does not exist [#100] -* Idle mode incorrect new message notification [#48] +- SMTP port [#87] +- Save msg upon error [#59] +- Answered flag not set [#50] +- Panic when downloads-dir does not exist [#100] +- Idle mode incorrect new message notification [#48] ## [0.2.5] - 2021-04-12 ### Fixed -* Expunge mbox after `move` and `delete` cmd [#83] -* JSON output [#89] +- Expunge mbox after `move` and `delete` cmd [#83] +- JSON output [#89] ## [0.2.4] - 2021-04-09 ### Added -* Wiki entry for Gmail users [#58] -* Info logs for copy/move/delete cmd + silent mode [#74] -* `--raw` arg for `read` cmd [#79] +- Wiki entry for Gmail users [#58] +- Info logs for copy/move/delete cmd + silent mode [#74] +- `--raw` arg for `read` cmd [#79] ### Changed -* Refactor output system + log levels [#74] +- Refactor output system + log levels [#74] ## [0.2.3] - 2021-04-08 ### Added -* Telescope support [#61] +- Telescope support [#61] ### Fixed -* Unicode chars breaks the view [#71] -* Copy/move incomplete (missing parts) [#75] +- Unicode chars breaks the view [#71] +- Copy/move incomplete (missing parts) [#75] ## [0.2.2] - 2021-04-04 ### Added -* `w` alias for `write` cmd +- `w` alias for `write` cmd ### Fixed -* `attachments` cmd logs -* Page size arg `search` cmd +- `attachments` cmd logs +- Page size arg `search` cmd ## [0.2.1] - 2021-04-04 ### Added -* IDLE support [#29] -* Improve choice after editing msg [#30] -* Flags management [#41] -* Copy feature [#35] -* Move feature [#31] -* Delete feature [#36] -* Signature support [#33] -* Add attachment(s) to a message (CLI) [#37] +- IDLE support [#29] +- Improve choice after editing msg [#30] +- Flags management [#41] +- Copy feature [#35] +- Move feature [#31] +- Delete feature [#36] +- Signature support [#33] +- Add attachment(s) to a message (CLI) [#37] ### Changed -* Errors management with `error_chain` [#39] +- Errors management with `error_chain` [#39] ### Fixed -* Missing `FLAGS` column in messages table [#40] -* Subtract with overflow if next page empty [#38] +- Missing `FLAGS` column in messages table [#40] +- Subtract with overflow if next page empty [#38] ## [0.2.0] - 2021-03-10 ### Added -* STARTTLS support [#32] -* Flags [#25] +- STARTTLS support [#32] +- Flags [#25] ### Changed -* JSON support [#18] +- JSON support [#18] ## [0.1.0] - 2021-01-17 ### Added -* Parse TOML config [#1] -* Populate Config struct from TOML [#2] -* Set up IMAP connection [#3] -* List new emails [#6] -* Set up CLI arg parser [#15] -* List mailboxes command [#5] -* Text and HTML previews [#12] [#13] -* Set up SMTP connection [#4] -* Write new email [#8] -* Write new email [#8] -* Reply, reply all and forward [#9] [#10] [#11] -* Download attachments [#14] -* Merge `Email` with `Msg` [#21] -* List command with pagination [#19] -* Icon in table when attachment is present [#16] -* Multi-account [#17] -* Password from command [#22] -* Set up README [#20] +- Parse TOML config [#1] +- Populate Config struct from TOML [#2] +- Set up IMAP connection [#3] +- List new emails [#6] +- Set up CLI arg parser [#15] +- List mailboxes command [#5] +- Text and HTML previews [#12] [#13] +- Set up SMTP connection [#4] +- Write new email [#8] +- Write new email [#8] +- Reply, reply all and forward [#9] [#10] [#11] +- Download attachments [#14] +- Merge `Email` with `Msg` [#21] +- List command with pagination [#19] +- Icon in table when attachment is present [#16] +- Multi-account [#17] +- Password from command [#22] +- Set up README [#20] -[Unreleased]: https://github.com/soywod/himalaya/compare/v0.7.0...HEAD -[0.7.0]: https://github.com/soywod/himalaya/compare/v0.6.2...v0.7.0 -[0.6.2]: https://github.com/soywod/himalaya/compare/v0.6.1...v0.6.2 +[Unreleased]: https://github.com/soywod/himalaya/compare/v0.7.1...develop +[0.7.1]: https://github.com/soywod/himalaya/compare/v0.7.0...v0.7.1 +[0.7.0]: https://github.com/soywod/himalaya/compare/v0.6.1...v0.7.0 [0.6.1]: https://github.com/soywod/himalaya/compare/v0.6.0...v0.6.1 [0.6.0]: https://github.com/soywod/himalaya/compare/v0.5.10...v0.6.0 [0.5.10]: https://github.com/soywod/himalaya/compare/v0.5.9...v0.5.10 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index edf467d..79187ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,5 +44,6 @@ email at If you want to **discuss** about the project, feel free to join the [Matrix](https://matrix.org/) workspace -[#pimalaya](https://matrix.to/#/#pimalaya:matrix.org) or contact me -directly [@soywod](https://matrix.to/#/@soywod:matrix.org). +[#pimalaya.himalaya](https://matrix.to/#/#pimalaya.himalaya:matrix.org) +or contact me directly +[@soywod](https://matrix.to/#/@soywod:matrix.org). diff --git a/Cargo.lock b/Cargo.lock index 4e4e908..ded212d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -765,7 +765,7 @@ dependencies = [ [[package]] name = "himalaya" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "atty", @@ -796,9 +796,9 @@ dependencies = [ [[package]] name = "himalaya-lib" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96448bba297a565c27dc18404da17d465e79df2feffa632b249281c8c0b5b68" +checksum = "d6aa84cdd1cec7bd25e319f0decd7d6ec5d765fb983da7a0dea10d797f7e73a8" dependencies = [ "ammonia", "chrono", @@ -1124,6 +1124,7 @@ checksum = "5d2d08d52a925272eda99f8fe9e91237b1cb958804ee0628cc398ebd1bbc426f" dependencies = [ "gethostname", "mailparse", + "memmap2", ] [[package]] @@ -1190,6 +1191,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memmap2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index 25b3b89..bd282e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "himalaya" description = "Command-line interface for email management." -version = "0.7.0" +version = "0.7.1" authors = ["soywod "] edition = "2021" license = "MIT" @@ -17,9 +17,9 @@ section = "mail" [features] imap-backend = ["himalaya-lib/imap-backend"] -maildir-backend = ["himalaya-lib/maildir-backend"] +smtp-sender = ["himalaya-lib/smtp-sender"] notmuch-backend = ["himalaya-lib/notmuch-backend"] -default = ["imap-backend", "maildir-backend"] +default = ["imap-backend", "smtp-sender"] [dev-dependencies] tempfile = "3.3" @@ -36,7 +36,7 @@ dialoguer = "0.10.2" email_address = "0.2.4" env_logger = "0.8" erased-serde = "0.3" -himalaya-lib = "0.5" +himalaya-lib = "0.6.0" indicatif = "0.17" log = "0.4" once_cell = "1.16.0" diff --git a/README.md b/README.md index 0305985..ebc9690 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,43 @@ -# 📫 Himalaya [![GitHub release](https://img.shields.io/github/v/release/soywod/himalaya?color=success&style=flat-square)](https://github.com/soywod/himalaya/releases/latest) [![Matrix](https://img.shields.io/matrix/himalaya.email.client:matrix.org?color=success&label=chat&style=flat-square)](https://matrix.to/#/#himalaya.email.client:matrix.org) +# 📫 Himalaya [![GitHub release](https://img.shields.io/github/v/release/soywod/himalaya?color=success)](https://github.com/soywod/himalaya/releases/latest) [![Matrix](https://img.shields.io/matrix/pimalaya.himalaya:matrix.org?color=success&label=chat)](https://matrix.to/#/#pimalaya.himalaya:matrix.org) -Command-line interface for email management based on the -[himalaya-lib](https://git.sr.ht/~soywod/himalaya-lib). +Himalaya is a CLI based on the +[himalaya-lib](https://git.sr.ht/~soywod/himalaya-lib) that allows you +to manipulate your emails using commands in your console. ![image](https://user-images.githubusercontent.com/10437171/138774902-7b9de5a3-93eb-44b0-8cfb-6d2e11e3b1aa.png) -*Warning: the project is under active development, do not use in +*Disclaimer: the project is under active development, do not use in production before the `v1.0.0`.* ## Features -- Folder listing -- Email listing and searching -- Email composition based on `$EDITOR` -- Email manipulation (copy/move/delete) -- Multi-accounting -- Account listing +- [Folder listing] +- [Envelopes listing], [searching] and [sorting] +- [Email composition] based on `$EDITOR` +- Email manipulation ([copy]/[move]/[delete]) +- [Multi-accounting] +- [Account listing] +- [Account synchronization] for offline usage - IMAP, Maildir and Notmuch support -- IMAP IDLE mode for real-time notifications +- IMAP IDLE mode for [real-time notifications] - PGP end-to-end encryption -- Completions for various shells +- [Completions] for various shells - JSON output - … -*Note: see the [wiki](https://github.com/soywod/himalaya/wiki) for all -the features.* +[Folder listing]: https://pimalaya.org/himalaya/docs/cli/usage/folders/list.html +[Envelopes listing]: https://pimalaya.org/himalaya/docs/cli/usage/envelopes/list.html +[searching]: https://pimalaya.org/himalaya/docs/cli/usage/envelopes/search.html +[sorting]: https://pimalaya.org/himalaya/docs/cli/usage/envelopes/sort.html +[Email composition]: https://pimalaya.org/himalaya/docs/cli/usage/emails/write.html +[copy]: https://pimalaya.org/himalaya/docs/cli/usage/emails/copy.html +[move]: https://pimalaya.org/himalaya/docs/cli/usage/emails/move.html +[delete]: https://pimalaya.org/himalaya/docs/cli/usage/emails/delete.html +[Multi-accounting]: https://pimalaya.org/himalaya/docs/cli/configuration.html +[Account listing]: https://pimalaya.org/himalaya/docs/cli/usage/accounts/list.html +[Account synchronization]: https://pimalaya.org/himalaya/docs/cli/usage/accounts/synchronize.html +[real-time notifications]: https://pimalaya.org/himalaya/docs/cli/usage/notifications.html +[Completions]: https://pimalaya.org/himalaya/docs/cli/tips/completion.html ## Installation @@ -37,7 +50,7 @@ the features.* -```shell +```bash # Arch Linux (official) $ pacman -S himalaya @@ -54,9 +67,9 @@ $ cargo install himalaya $ nix-env -i himalaya ``` -*Note: see the -[wiki](https://github.com/soywod/himalaya/wiki/Installation) for other -installation methods.* +*See the +[documentation](https://pimalaya.org/himalaya/docs/cli/installation.html) +for other installation methods.* @@ -64,49 +77,8 @@ installation methods.* ## Configuration -```toml -# ~/.config/himalaya/config.toml - -display-name = "Test" -downloads-dir = "~/downloads" -signature = "Regards," - -[gmail] -default = true -email = "test@gmail.com" - -backend = "imap" -imap-host = "imap.gmail.com" -imap-port = 993 -imap-login = "test@gmail.com" -imap-passwd-cmd = "security find-internet-password -gs gmail -w" - -sender = "smtp" -smtp-host = "smtp.gmail.com" -smtp-port = 465 -smtp-login = "test@gmail.com" -smtp-passwd-cmd = "security find-internet-password -gs gmail -w" - -[gmail.folder-aliases] -inbox = "INBOX" -sent = "[Gmail]/Sent" -drafts = "[Gmail]/Drafts" - -[local] -email = "test@localhost" -signature-delim = "~~\n" -signature = "Regards," - -backend = "maildir" -maildir-root-dir = "~/emails" - -sender = "sendmail" -sendmail-cmd = "msmtp --read-envelope-from --read-recipients" -``` - -*Note: see the -[wiki](https://github.com/soywod/himalaya/wiki/Configuration) for all -the options.* +Please read the +[documentation](https://pimalaya.org/himalaya/docs/cli/configuration.html). ## Contributing @@ -132,7 +104,7 @@ email at If you want to **discuss** about the project, feel free to join the [Matrix](https://matrix.org/) workspace -[#pimalaya](https://matrix.to/#/#pimalaya:matrix.org) or contact me +[#pimalaya.himalaya](https://matrix.to/#/#pimalaya.himalaya:matrix.org) or contact me directly [@soywod](https://matrix.to/#/@soywod:matrix.org). ## Credits @@ -163,8 +135,8 @@ European Commission in September, 2022. ## Sponsoring -[![GitHub](https://img.shields.io/badge/-GitHub%20Sponsors-fafbfc?logo=GitHub%20Sponsors&style=flat-square)](https://github.com/sponsors/soywod) -[![PayPal](https://img.shields.io/badge/-PayPal-0079c1?logo=PayPal&logoColor=ffffff&style=flat-square)](https://www.paypal.com/paypalme/soywod) -[![Ko-fi](https://img.shields.io/badge/-Ko--fi-ff5e5a?logo=Ko-fi&logoColor=ffffff&style=flat-square)](https://ko-fi.com/soywod) -[![Buy Me a Coffee](https://img.shields.io/badge/-Buy%20Me%20a%20Coffee-ffdd00?logo=Buy%20Me%20A%20Coffee&logoColor=000000&style=flat-square)](https://www.buymeacoffee.com/soywod) -[![Liberapay](https://img.shields.io/badge/-Liberapay-f6c915?logo=Liberapay&logoColor=222222&style=flat-square)](https://liberapay.com/soywod) +[![GitHub](https://img.shields.io/badge/-GitHub%20Sponsors-fafbfc?logo=GitHub%20Sponsors)](https://github.com/sponsors/soywod) +[![PayPal](https://img.shields.io/badge/-PayPal-0079c1?logo=PayPal&logoColor=ffffff)](https://www.paypal.com/paypalme/soywod) +[![Ko-fi](https://img.shields.io/badge/-Ko--fi-ff5e5a?logo=Ko-fi&logoColor=ffffff)](https://ko-fi.com/soywod) +[![Buy Me a Coffee](https://img.shields.io/badge/-Buy%20Me%20a%20Coffee-ffdd00?logo=Buy%20Me%20A%20Coffee&logoColor=000000)](https://www.buymeacoffee.com/soywod) +[![Liberapay](https://img.shields.io/badge/-Liberapay-f6c915?logo=Liberapay&logoColor=222222)](https://liberapay.com/soywod) diff --git a/src/config/config.rs b/src/config/config.rs index 42ba72f..dbb96d3 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -31,14 +31,22 @@ pub struct DeserializedConfig { pub email_listing_page_size: Option, pub email_reading_headers: Option>, - #[serde(default, with = "EmailTextPlainFormatOptionDef", skip_serializing_if = "Option::is_none")] + #[serde( + default, + with = "EmailTextPlainFormatOptionDef", + skip_serializing_if = "Option::is_none" + )] pub email_reading_format: Option, pub email_reading_verify_cmd: Option, pub email_reading_decrypt_cmd: Option, pub email_writing_headers: Option>, pub email_writing_sign_cmd: Option, pub email_writing_encrypt_cmd: Option, - #[serde(default, with = "EmailHooksOptionDef", skip_serializing_if = "Option::is_none")] + #[serde( + default, + with = "EmailHooksOptionDef", + skip_serializing_if = "Option::is_none" + )] pub email_hooks: Option, #[serde(flatten)] @@ -115,12 +123,10 @@ impl DeserializedConfig { #[cfg(test)] mod tests { - use himalaya_lib::{EmailSender, SendmailConfig, SmtpConfig}; + use himalaya_lib::{EmailSender, MaildirConfig, SendmailConfig, SmtpConfig}; #[cfg(feature = "imap-backend")] use himalaya_lib::ImapConfig; - #[cfg(feature = "maildir-backend")] - use himalaya_lib::MaildirConfig; #[cfg(feature = "notmuch-backend")] use himalaya_lib::NotmuchConfig; @@ -131,7 +137,6 @@ mod tests { #[cfg(feature = "imap-backend")] use crate::account::DeserializedImapAccountConfig; - #[cfg(feature = "maildir-backend")] use crate::account::DeserializedMaildirAccountConfig; #[cfg(feature = "notmuch-backend")] use crate::account::DeserializedNotmuchAccountConfig; diff --git a/src/config/prelude.rs b/src/config/prelude.rs index 6b37fe5..9f30f97 100644 --- a/src/config/prelude.rs +++ b/src/config/prelude.rs @@ -1,13 +1,13 @@ -use himalaya_lib::{EmailHooks, EmailSender, EmailTextPlainFormat, SendmailConfig, SmtpConfig}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; +use himalaya_lib::{ + EmailHooks, EmailSender, EmailTextPlainFormat, MaildirConfig, SendmailConfig, SmtpConfig, +}; + #[cfg(feature = "imap-backend")] use himalaya_lib::ImapConfig; -#[cfg(feature = "maildir-backend")] -use himalaya_lib::MaildirConfig; - #[cfg(feature = "notmuch-backend")] use himalaya_lib::NotmuchConfig; @@ -56,7 +56,6 @@ pub struct ImapConfigDef { pub watch_cmds: Option>, } -#[cfg(feature = "maildir-backend")] #[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(remote = "MaildirConfig")] pub struct MaildirConfigDef { diff --git a/src/config/wizard/maildir.rs b/src/config/wizard/maildir.rs index 8041791..2670301 100644 --- a/src/config/wizard/maildir.rs +++ b/src/config/wizard/maildir.rs @@ -7,7 +7,6 @@ use dialoguer::Input; use dirs::home_dir; use himalaya_lib::MaildirConfig; -#[cfg(feature = "maildir-backend")] pub(crate) fn configure(base: DeserializedBaseAccountConfig) -> Result { let input = if let Some(home) = home_dir() { Input::with_theme(&*THEME) diff --git a/src/config/wizard/mod.rs b/src/config/wizard/mod.rs index fcbe681..2282af8 100644 --- a/src/config/wizard/mod.rs +++ b/src/config/wizard/mod.rs @@ -1,6 +1,5 @@ #[cfg(feature = "imap-backend")] mod imap; -#[cfg(feature = "maildir-backend")] mod maildir; #[cfg(feature = "notmuch-backend")] mod notmuch; @@ -18,10 +17,9 @@ use once_cell::sync::Lazy; use std::{fs, process}; const BACKENDS: &[&str] = &[ + "Maildir", #[cfg(feature = "imap-backend")] "IMAP", - #[cfg(feature = "maildir-backend")] - "Maildir", #[cfg(feature = "notmuch-backend")] "Notmuch", ]; @@ -102,10 +100,9 @@ pub(crate) fn wizard() -> Result { match default { Some(DeserializedAccountConfig::None(default)) => default.default = Some(true), + Some(DeserializedAccountConfig::Maildir(default)) => default.base.default = Some(true), #[cfg(feature = "imap-backend")] Some(DeserializedAccountConfig::Imap(default)) => default.base.default = Some(true), - #[cfg(feature = "maildir-backend")] - Some(DeserializedAccountConfig::Maildir(default)) => default.base.default = Some(true), #[cfg(feature = "notmuch-backend")] Some(DeserializedAccountConfig::Notmuch(default)) => default.base.default = Some(true), _ => {} @@ -141,10 +138,9 @@ fn configure_account() -> Result> { .interact_opt()?; match backend { + Some(idx) if BACKENDS[idx] == "Maildir" => Ok(Some(maildir::configure(base)?)), #[cfg(feature = "imap-backend")] Some(idx) if BACKENDS[idx] == "IMAP" => Ok(Some(imap::configure(base)?)), - #[cfg(feature = "maildir-backend")] - Some(idx) if BACKENDS[idx] == "Maildir" => Ok(Some(maildir::configure(base)?)), #[cfg(feature = "notmuch-backend")] Some(idx) if BACKENDS[idx] == "Notmuch" => Ok(Some(notmuch::configure(base)?)), _ => Ok(None), diff --git a/src/domain/account/accounts.rs b/src/domain/account/accounts.rs index b948ac8..2ede0dc 100644 --- a/src/domain/account/accounts.rs +++ b/src/domain/account/accounts.rs @@ -40,14 +40,13 @@ impl From> for Accounts { fn from(map: Iter<'_, String, DeserializedAccountConfig>) -> Self { let mut accounts: Vec<_> = map .map(|(name, account)| match account { + DeserializedAccountConfig::Maildir(config) => { + Account::new(name, "maildir", config.base.default.unwrap_or_default()) + } #[cfg(feature = "imap-backend")] DeserializedAccountConfig::Imap(config) => { Account::new(name, "imap", config.base.default.unwrap_or_default()) } - #[cfg(feature = "maildir-backend")] - DeserializedAccountConfig::Maildir(config) => { - Account::new(name, "maildir", config.base.default.unwrap_or_default()) - } #[cfg(feature = "notmuch-backend")] DeserializedAccountConfig::Notmuch(config) => { Account::new(name, "notmuch", config.base.default.unwrap_or_default()) diff --git a/src/domain/account/config.rs b/src/domain/account/config.rs index 972ea79..fa76224 100644 --- a/src/domain/account/config.rs +++ b/src/domain/account/config.rs @@ -3,14 +3,13 @@ //! This module contains the raw deserialized representation of an //! account in the accounts section of the user configuration file. -use himalaya_lib::{AccountConfig, BackendConfig, EmailHooks, EmailSender, EmailTextPlainFormat}; +use himalaya_lib::{ + AccountConfig, BackendConfig, EmailHooks, EmailSender, EmailTextPlainFormat, MaildirConfig, +}; #[cfg(feature = "imap-backend")] use himalaya_lib::ImapConfig; -#[cfg(feature = "maildir-backend")] -use himalaya_lib::MaildirConfig; - #[cfg(feature = "notmuch-backend")] use himalaya_lib::NotmuchConfig; @@ -24,10 +23,9 @@ use crate::config::{prelude::*, DeserializedConfig}; #[serde(tag = "backend", rename_all = "snake_case")] pub enum DeserializedAccountConfig { None(DeserializedBaseAccountConfig), + Maildir(DeserializedMaildirAccountConfig), #[cfg(feature = "imap-backend")] Imap(DeserializedImapAccountConfig), - #[cfg(feature = "maildir-backend")] - Maildir(DeserializedMaildirAccountConfig), #[cfg(feature = "notmuch-backend")] Notmuch(DeserializedNotmuchAccountConfig), } @@ -43,16 +41,15 @@ impl DeserializedAccountConfig { config.to_account_config(name, global_config), BackendConfig::None, ), + DeserializedAccountConfig::Maildir(config) => ( + config.base.to_account_config(name, global_config), + BackendConfig::Maildir(config.backend.clone()), + ), #[cfg(feature = "imap-backend")] DeserializedAccountConfig::Imap(config) => ( config.base.to_account_config(name, global_config), BackendConfig::Imap(config.backend.clone()), ), - #[cfg(feature = "maildir-backend")] - DeserializedAccountConfig::Maildir(config) => ( - config.base.to_account_config(name, global_config), - BackendConfig::Maildir(config.backend.clone()), - ), #[cfg(feature = "notmuch-backend")] DeserializedAccountConfig::Notmuch(config) => ( config.base.to_account_config(name, global_config), @@ -64,10 +61,9 @@ impl DeserializedAccountConfig { pub fn is_default(&self) -> bool { match self { DeserializedAccountConfig::None(config) => config.default.unwrap_or_default(), + DeserializedAccountConfig::Maildir(config) => config.base.default.unwrap_or_default(), #[cfg(feature = "imap-backend")] DeserializedAccountConfig::Imap(config) => config.base.default.unwrap_or_default(), - #[cfg(feature = "maildir-backend")] - DeserializedAccountConfig::Maildir(config) => config.base.default.unwrap_or_default(), #[cfg(feature = "notmuch-backend")] DeserializedAccountConfig::Notmuch(config) => config.base.default.unwrap_or_default(), } @@ -89,7 +85,11 @@ pub struct DeserializedBaseAccountConfig { pub email_listing_page_size: Option, pub email_reading_headers: Option>, - #[serde(default, with = "EmailTextPlainFormatOptionDef", skip_serializing_if = "Option::is_none")] + #[serde( + default, + with = "EmailTextPlainFormatOptionDef", + skip_serializing_if = "Option::is_none" + )] pub email_reading_format: Option, pub email_reading_verify_cmd: Option, pub email_reading_decrypt_cmd: Option, @@ -98,7 +98,11 @@ pub struct DeserializedBaseAccountConfig { pub email_writing_encrypt_cmd: Option, #[serde(flatten, with = "EmailSenderDef")] pub email_sender: EmailSender, - #[serde(default, with = "EmailHooksOptionDef", skip_serializing_if = "Option::is_none")] + #[serde( + default, + with = "EmailHooksOptionDef", + skip_serializing_if = "Option::is_none" + )] pub email_hooks: Option, #[serde(default)] @@ -237,7 +241,6 @@ pub struct DeserializedImapAccountConfig { } #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] -#[cfg(feature = "maildir-backend")] pub struct DeserializedMaildirAccountConfig { #[serde(flatten)] pub base: DeserializedBaseAccountConfig, diff --git a/src/domain/account/handlers.rs b/src/domain/account/handlers.rs index cde1c80..0f5aeca 100644 --- a/src/domain/account/handlers.rs +++ b/src/domain/account/handlers.rs @@ -43,12 +43,16 @@ pub fn sync( account_config: &AccountConfig, printer: &mut P, backend: &dyn Backend, + folder: &Option, dry_run: bool, ) -> Result<()> { info!("entering the sync accounts handler"); trace!("dry run: {}", dry_run); - let sync_builder = BackendSyncBuilder::new(account_config); + let mut sync_builder = BackendSyncBuilder::new(account_config); + if let Some(folder) = folder { + sync_builder = sync_builder.only_folder(folder); + } if dry_run { let report = sync_builder.dry_run(true).sync(backend)?; diff --git a/src/domain/folder/args.rs b/src/domain/folder/args.rs index 97f00fe..4ddf949 100644 --- a/src/domain/folder/args.rs +++ b/src/domain/folder/args.rs @@ -5,26 +5,37 @@ use anyhow::Result; use clap::{self, Arg, ArgMatches, Command}; -use log::debug; +use log::{debug, info}; use crate::ui::table; const ARG_SOURCE: &str = "source"; const ARG_TARGET: &str = "target"; +const CMD_EXPUNGE: &str = "expunge"; const CMD_FOLDERS: &str = "folders"; +const CMD_LIST: &str = "list"; /// Represents the folder commands. #[derive(Debug, PartialEq, Eq)] pub enum Cmd { List(table::args::MaxTableWidth), + Expunge, } /// Represents the folder command matcher. pub fn matches(m: &ArgMatches) -> Result> { let cmd = if let Some(m) = m.subcommand_matches(CMD_FOLDERS) { - debug!("folders command matched"); - let max_table_width = table::args::parse_max_width(m); - Some(Cmd::List(max_table_width)) + if let Some(_) = m.subcommand_matches(CMD_EXPUNGE) { + info!("expunge folder subcommand matched"); + Some(Cmd::Expunge) + } else if let Some(m) = m.subcommand_matches(CMD_LIST) { + debug!("list folders command matched"); + let max_table_width = table::args::parse_max_width(m); + Some(Cmd::List(max_table_width)) + } else { + info!("no folder subcommand matched, falling back to subcommand list"); + Some(Cmd::List(None)) + } } else { None }; @@ -35,8 +46,13 @@ pub fn matches(m: &ArgMatches) -> Result> { /// Represents the folder subcommand. pub fn subcmd() -> Command { Command::new(CMD_FOLDERS) - .about("Lists folders") - .arg(table::args::max_width()) + .about("Manage folders") + .subcommands([ + Command::new(CMD_EXPUNGE).about("Delete emails marked for deletion"), + Command::new(CMD_LIST) + .about("List folders") + .arg(table::args::max_width()), + ]) } /// Represents the source folder argument. @@ -46,12 +62,11 @@ pub fn source_arg() -> Arg { .short('f') .help("Specifies the source folder") .value_name("SOURCE") - .default_value("inbox") } /// Represents the source folder argument parser. -pub fn parse_source_arg(matches: &ArgMatches) -> &str { - matches.get_one::(ARG_SOURCE).unwrap().as_str() +pub fn parse_source_arg(matches: &ArgMatches) -> Option<&str> { + matches.get_one::(ARG_SOURCE).map(String::as_str) } /// Represents the target folder argument. @@ -82,7 +97,7 @@ mod tests { let arg = Command::new("himalaya") .subcommand(subcmd()) - .get_matches_from(&["himalaya", "folders", "--max-width", "20"]); + .get_matches_from(&["himalaya", "folders", "list", "--max-width", "20"]); assert_eq!(Some(Cmd::List(Some(20))), matches(&arg).unwrap()); } @@ -97,10 +112,7 @@ mod tests { } let app = get_matches_from![]; - assert_eq!( - Some("inbox"), - app.get_one::(ARG_SOURCE).map(String::as_str) - ); + assert_eq!(None, app.get_one::(ARG_SOURCE).map(String::as_str)); let app = get_matches_from!["-f", "SOURCE"]; assert_eq!( diff --git a/src/domain/folder/handlers.rs b/src/domain/folder/handlers.rs index fb70f9f..85c1516 100644 --- a/src/domain/folder/handlers.rs +++ b/src/domain/folder/handlers.rs @@ -7,6 +7,15 @@ use himalaya_lib::{AccountConfig, Backend}; use crate::printer::{PrintTableOpts, Printer}; +pub fn expunge( + folder: &str, + printer: &mut P, + backend: &mut B, +) -> Result<()> { + backend.expunge_folder(folder)?; + printer.print(format!("Folder {folder} successfully expunged!")) +} + pub fn list( max_width: Option, config: &AccountConfig, @@ -123,6 +132,9 @@ mod tests { }, ])) } + fn expunge_folder(&self, _: &str) -> backend::Result<()> { + unimplemented!(); + } fn purge_folder(&self, _: &str) -> backend::Result<()> { unimplemented!(); } diff --git a/src/main.rs b/src/main.rs index b9de5bc..797af9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,9 @@ use himalaya::{ printer::StdoutPrinter, tpl, }; -use himalaya_lib::{BackendBuilder, BackendConfig, ImapBackend, SenderBuilder}; +use himalaya_lib::{ + BackendBuilder, BackendConfig, ImapBackend, SenderBuilder, DEFAULT_INBOX_FOLDER, +}; #[cfg(feature = "imap-backend")] use himalaya::imap; @@ -87,11 +89,13 @@ fn main() -> Result<()> { // inits config let config = DeserializedConfig::from_opt_path(config::args::parse_arg(&m))?; let (account_config, backend_config) = config.to_configs(account::args::parse_arg(&m))?; - let folder = account_config.folder_alias(folder::args::parse_source_arg(&m))?; + let folder = folder::args::parse_source_arg(&m); // checks IMAP commands #[cfg(feature = "imap-backend")] if let BackendConfig::Imap(imap_config) = &backend_config { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + // FIXME: find a way to downcast `backend` instead of // recreating an instance. match imap::args::matches(&m)? { @@ -120,11 +124,21 @@ fn main() -> Result<()> { return account::handlers::list(max_width, &account_config, &config, &mut printer); } Some(account::args::Cmd::Sync(dry_run)) => { + let folder = match folder { + Some(folder) => Some(account_config.folder_alias(folder)?), + None => None, + }; let backend = BackendBuilder::new() - .sessions_pool_size(16) + .sessions_pool_size(8) .disable_cache(true) .build(&account_config, &backend_config)?; - account::handlers::sync(&account_config, &mut printer, backend.as_ref(), dry_run)?; + account::handlers::sync( + &account_config, + &mut printer, + backend.as_ref(), + &folder, + dry_run, + )?; backend.close()?; return Ok(()); } @@ -133,6 +147,13 @@ fn main() -> Result<()> { // checks folder commands match folder::args::matches(&m)? { + Some(folder::args::Cmd::Expunge) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let mut backend = BackendBuilder::new() + .disable_cache(disable_cache) + .build(&account_config, &backend_config)?; + return folder::handlers::expunge(&folder, &mut printer, backend.as_mut()); + } Some(folder::args::Cmd::List(max_width)) => { let mut backend = BackendBuilder::new() .disable_cache(disable_cache) @@ -150,6 +171,7 @@ fn main() -> Result<()> { // checks email commands match email::args::matches(&m)? { Some(email::args::Cmd::Attachments(ids)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -162,6 +184,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Copy(ids, to_folder)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -175,6 +198,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Delete(ids)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -187,6 +211,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Forward(id, headers, body)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -202,6 +227,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::List(max_width, page_size, page)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -216,6 +242,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Move(ids, to_folder)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -229,6 +256,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Read(ids, text_mime, sanitize, raw, headers)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -245,6 +273,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Reply(id, all, headers, body)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -261,6 +290,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Save(raw_email)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -273,6 +303,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Search(query, max_width, page_size, page)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -288,6 +319,7 @@ fn main() -> Result<()> { ); } Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -317,18 +349,21 @@ fn main() -> Result<()> { } Some(email::args::Cmd::Flag(m)) => match m { Some(flag::args::Cmd::Set(ids, ref flags)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; return flag::handlers::set(&mut printer, backend.as_mut(), &folder, ids, flags); } Some(flag::args::Cmd::Add(ids, ref flags)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; return flag::handlers::add(&mut printer, backend.as_mut(), &folder, ids, flags); } Some(flag::args::Cmd::Remove(ids, ref flags)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -338,6 +373,7 @@ fn main() -> Result<()> { }, Some(email::args::Cmd::Tpl(m)) => match m { Some(tpl::args::Cmd::Forward(id, headers, body)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -355,6 +391,7 @@ fn main() -> Result<()> { return tpl::handlers::write(&account_config, &mut printer, headers, body); } Some(tpl::args::Cmd::Reply(id, all, headers, body)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -370,6 +407,7 @@ fn main() -> Result<()> { ); } Some(tpl::args::Cmd::Save(tpl)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?; @@ -382,6 +420,7 @@ fn main() -> Result<()> { ); } Some(tpl::args::Cmd::Send(tpl)) => { + let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; let mut backend = BackendBuilder::new() .disable_cache(disable_cache) .build(&account_config, &backend_config)?;