---
title: meli mail client - alpha release 0.4.1
ogTitle: meli mail client - alpha release 0.4.1
author: epilys
date: 2019-12-09 00:00:00
date_iso_8601: 2019-12-09T00:00:00+02:00
bees: What if bees could see the abyss of deep knees in a sea
left:
right:
updates:
---

>> **update**: _0.4.1 is supported for rust >= 1.39_ Checkout current master or latest release tag for bug fixes since 0.4.1.

## Summary
- New mail stores available: **IMAP**, **notmuch** join **Maildir** and **mbox**. _JMAP_ is partially supported but not shipped with the master branch release.
- **Tagging** (on IMAP & notmuch) with 
  - custom colours
  - hiding unwanted tags
  - use as search keyword
- **Embed your editor** in the composing tab without ever leaving <code class="Nm">meli</code>. The editor runs in an embedded terminal emulator.
- **vCard support**, read-only from local storage.
- **Search**
  - Full text search if _sqlite3_ cache selected
  - _SEARCH_ in _IMAP_ without a cache
  - _notmuch queries_ in _notmuch_ without a cache
- **GPG signatures**, signing and verifying
- **mailcap** support
- **format=flowed** support

and other smaller additions. Consult the [manpages](/documentation.html) for up-to-date information.

[Download](/download.html)

<figure><img src="/images/posts/2019-12-09-alpha-release/tags.png" style="height: min-content;width: min-content;margin: auto;" /></figure>
## stability
I use <code class="Nm">meli</code> as my main client and though at times buggy, it is mostly stable enough to be usable. Data is treated immutably everywhere _except_ for when you explicitly ask for mutation, meaning I don't think data corruption is generally possible. I'd appreciate bug reports at this stage in order to start polishing it for a proper release.

## IMAP, notmuch and... JMAP?
>> _See example configuration files in [meli.conf.5](/documentation.html#meli.conf.5)_

_IMAP_ accounts are retrieved on startup without any local caching. It is easy to implement though and I expect to do it soonish.

_notmuch_ accounts don't support new mail notifications yet. I have to check if I should use _inotify_ just like in _Maildir_ or poll the database's _mtime_. notmuch search queries are passed to _libnotmuch_ unchanged, though the app's search syntax is quite similar.

_JMAP_ is at an early stage still and unless you are a dev in pertinent projects or just really want to try it you shouldn't care about it yet. I've written code using [jmap-proxy](https://github.com/jmapio/jmap-perl) for _IMAP_ written in _Perl_. Authentication is still an unclear subject in _JMAP_ and I haven't a way to implement how fastmail, the company behind _JMAP_, does it without an account.

_JMAP_ translates really well to Rust thanks to _serde\_json_. By modeling _JMAP Objects_ and methods as traits we can have some type safety in our queries:

```rust
trait Object {
   const NAME: &'static str;
}

trait Response<OBJ: Object> {
   const NAME: &'static str;
}

trait Method<OBJ: Object>: Serialize {
   const NAME: &'static str;
}

struct Request {
   using: &'static [&'static str],
   /* Why is this Value instead of Box<dyn Method<_>>? The Method trait cannot
      be made into a Trait object because its serialize() will be generic.
      Bummer! */
   method_calls: Vec<serde_json::Value>,

   #[serde(skip)]
   request_no: Arc<Mutex<usize>>,
}

#[serde(rename_all = "camelCase")]
struct Get<OBJ: Object>
where
    OBJ: std::fmt::Debug + Serialize,
{
   account_id: String,
   #[serde(flatten)]
   ids: Option<JmapArgument<Vec<String>>>,
   properties: Option<Vec<String>>,
   #[serde(skip)]
   _ph: PhantomData<*const OBJ>,
}
#[serde(rename_all = "camelCase")]
struct EmailGet {
   #[serde(flatten)]
   get_call: Get<EmailObject>,
   body_properties: Vec<String>,
   fetch_text_body_values: bool,
   fetch_html_body_values: bool,
   fetch_all_body_values: bool,
   max_body_value_bytes: u64,
}

impl Method<EmailObject> for EmailGet {
   const NAME: &'static str = "Email/get";
}
```

One of _JMAP_'s features is the ability to reference the results of previous calls in the same request, thus preventing the need for round-trips:
```rust
#[serde(rename_all = "camelCase")]
enum JmapArgument<T> {
   Value(T),
   ResultReference {
       result_of: String,
       name: String,
       path: String,
   },
}
```


## vCard
vCard is [haphazardly](https://git.meli.delivery/meli/meli/src/branch/master/melib/src/addressbook/vcard.rs#L75) parsed and available along with <code class="Nm">meli</code> contacts. They are read-only for now, until a more standard-compliant parser and serializer is written.

<figure><img src="/images/posts/2019-12-09-alpha-release/contacts.png" style="height: min-content;width: min-content;margin: auto;" /></figure>

## sqlite3
sqlite3 searching uses a simple query language based on the Gmail webclient one: 

> ((from:unrealistic and (to:complex or not "query")) or flags:seen,draft)

You can also explore your data with SQL by loading the database (_$XDG_DATA\_HOME/meli/_) with the sqlite3 cli tool. 
_IMAP_ searches are converted from this language to _SEARCH_ queries. _notmuch_ queries are not tampered with at all.

## quick unsubscribe

<figure><img src="/images/posts/2019-12-09-alpha-release/list_actions.png" style="height: min-content;width: min-content;margin: auto;"/></figure>
If a newsletter has a _List-Unsubscribe_ header, <code class="Nm">meli</code> can send an unsubscribe request with the command _list-unsubscribe_. Other _List-*_ headers are also usable.

## mailcap
You can now open attachments using mailcap files. You can still open them with _xdg-open_ as well.

## account info
View supported mailstore features in the _status_ tab:

<figure><img src="/images/posts/2019-12-09-alpha-release/imap_status.png" style="height: min-content;width: min-content;margin: auto;" /></figure>
<figure><img src="/images/posts/2019-12-09-alpha-release/maildir_status.png" style="height: min-content;width: min-content;margin: auto;"/></figure>

## vim-like motions
Prepend any move motion with a number _n_ to repeat it _n_ times.

