Dodo - A graphical, hackable email client based on notmuch

Overview

Dodo

Documentation Status

Dodo is a graphical email client written in Python/PyQt5, based on the command line email swiss-army-knife notmuch. It's main goals are to:

  • offer efficient, keyboard-oriented mail reading, sorting, and composing
  • give a mostly text-based email experience by default, but with HTML support a few keystrokes away
  • offload as much work as possible on existing, excellent command-line tools (UNIX philosphy-style)
  • be simple enough to customise and hack on yourself

This README has instructions on installation, usage, and basic configuration. For API documentation (which is also useful for configuration), check out the Read the Docs page.

As an email client, Dodo is pretty much feature-complete, but not yet extensively tested. Since it's based on notmuch, all of its features are non-destructive, so you shouldn't ever lose any email due to bugs. That being said, you might see some strange behaviour, so use at your own risk.

A lot of Dodo's design is inspired by two existing notmuch-based clients: alot and astroid.

Prerequisites

If you have already used notmuch for email, there's not much to do here :). If not, you'll need to set up some other programs first:

  • something to check mail and sync with a local Maildir (offlineimap is the default, but others like mbsync should work fine)
  • a sendmail-compatible SMTP client to send mail (msmtp is the default)
  • notmuch for email searching and tagging
  • w3m for translating HTML messages into plaintext

All of this is pretty standard stuff, and should be installable via your package manager on Linux/Mac/etc. If you don't know how to set these things up already, see the respective websites or the "Setting up the prerequisites" section below for a quick reference.

Install and run

Make sure you have Python 3.7+ and PyQt5. Clone Dodo with:

% git clone https://github.com/akissinger/dodo.git

Then, add the bin/ subdirectory to your PATH and run with:

% dodo

An optional Python dependency is lxml for some limited HTML sanitization, which is off by default (see the next section for switching it on).

Configuration

Dodo is configured via ~/.config/dodo/config.py. This is just a Python file that gets eval-ed right before the main window is shown.

Most settings have reasonable defaults (assuming your are using offlineimap/msmtp), which can be found in settings.py. The only two things that must be set for Dodo to work properly are your email address and the location of your sent mail folder. Some things you probably also want to set up are the text editor (for composing messages) and the file browser (for viewing attachments).

Here is an example config.py, with some settings similar to the ones I use:

import dodo

# required
dodo.settings.email_address = 'First Last <[email protected]>'
dodo.settings.sent_dir = '/home/user/mail/Work/Sent'

# optional
dodo.settings.theme = dodo.themes.nord
dodo.settings.editor_command = ['kitty', 'nvim', '-c', 'set tw=0']
dodo.settings.file_browser_command = ['fman', '/home/user/Documents/']

A theme is just a Python dictionary mapping some fixed color names to HTML color codes. Currently, the themes implemented in themes.py are nord, solarized_light and solarized_dark. If you want more, feel free to roll your own, or (better) send me a pull request!

All of the settings of the form ..._command are given as a list consisting of the command and its arguments. Additional arguments, such as the relevant folder or file are appended to this list.

The settings above replace the default text editor (xterm -e vim) with neovim run inside a new kitty terminal. I am also using Michael Herrmann's excellent dual-pane file manager fman instead of the default (nautilus). With these settings, showing attachments will open fman with a fixed directory in the left pane (/home/user/Documents) and a directory containing the attachments on the right. A similar effect can be obtained with ranger using the multipane view mode.

While Javascript is disabled in the HTML email viewer, you may want to set up a custom HTML sanitizer function as follows:

dodo.util.html2html = dodo.util.clean_html2html

The above function passes the HTML through the Cleaner object of the lxml library. Note this still allows some dodgy stuff, such as calling home via embedded img tags. Fully safe and private HTML email from untrusted sources should be considered a work-in-progress.

Key mapping

Key mappings can be customised by changing the dictionaries defined in keymap.py. These map a key to a pair consisting of a description string and a Python function. For the global_keymap, this function takes the Dodo object defined in app.py as its argument. The other maps take the relevant "local" widget (SearchView, ThreadView, ComposeView, or CommandBar).

To bind a single key, you can write something like this in config.py:

dodo.keymap.search_keymap['t'] = (
  'toggle todo',
  lambda p: p.toggle_thread_tag('todo'))

or you can replace the keymap completely from config.py, e.g.:

dodo.keymap.search_keymap = {
  'C-n': ('next thread', lambda p: p.next_thread()),
  'C-p': ('previous thread', lambda p: p.previous_thread()),
  # ...
}

The keymaps used by Dodo are global_keymap, search_keymap, thread_keymap, and command_bar_keymap. All the keymaps except command_bar_keymap also support keychords, which are represented as space-separated sequences of keypresses, e.g.

dodo.keymap.global_keymap['C-x C-c'] = (
  'exit emacs ... erm, I mean Dodo',
  lambda a: a.quit())

You can unmap a single key by deleting it from the dictionary:

del dodo.keymap.global_keymap["Q"]

Basic use

Most functionality in Dodo comes from keyboard shortcuts. Press ? to get a full list of the key mappings at any time.

Dodo has 3 different kinds of view: search views, thread views, and compose views. It opens initially with a search view with the query tag:inbox. Pressing enter or double-clicking a thread with open that thread in the thread view. Pressing c at any time or r while looking at a message in the thread view will open the compose view.

In the compose view, press <enter> to edit the message on your chosen editor. Once you save and exit, the message will be updated. Press a to add attachments (or use the special A: header). Press S to send.

Setting up the prerequisites

Since there's a lot of little bits to configure, I've also included some minimal configurations for offlineimap, msmtp, and notmuch, just to have it all in one place.

Note the offlineimap and msmtp configurations below simply read the password from a plaintext file. More secure options are available, which are explained in the respective docs.

Incoming mail

Assuming your system configuration directory is ~/.config/, the configuration file for offlineimap is located in ~/.config/offlineimap/config. Here is a template for syncing one IMAP account named "Work":

[general]
accounts = Work

[Account Work]
localrepository = WorkLocal
remoterepository = WorkRemote

[Repository WorkLocal]
type = Maildir
localfolders = ~/mail/Work

[Repository WorkRemote]
type = IMAP
remotehost = (IMAP SERVER)
remoteuser = (USER NAME)
remotepassfile = (PASSWORD FILE)
sslcacertfile = OS-DEFAULT

If you want to set up multiple IMAP accounts, just put them all in the ~/mail folder and set ~/mail as your database path for notmuch.

Outgoing mail

Here is a sample ~/.config/msmtp/config, setting up a single SMTP server (also named "Work") with TLS:

defaults
auth           on
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log
account        Work
host           (SMTP SERVER)
port           587
from           (EMAIL ADRESS)
user           (USER NAME)
passwordeval   cat (PASSWORD FILE)
account        default : Work

You may need to change the 4th line if your system stores CA certificates in a different location.

Mail indexing

Once offlineimap is set up, just run notmuch from the command line to do some initial setup, which gets saved in ~/.notmuch-config by default. You can set ~/mail as your database path. notmuch has lots of options, the ability to set up various hooks and filters, and to sync certain IMAP markers with notmuch tags.

Here's a ~/.notmuch-config which is roughly like the one I use:

[database]
path=/home/user/mail

[user]
name=First Last
[email protected]

[new]
tags=new
ignore=

[search]
exclude_tags=deleted;killed;spam;

[maildir]
synchronize_flags=true
Owner
Aleks Kissinger
Aleks Kissinger
Zaid Vc Player Allows u to steam Songs/music on vc chat

ᴢᴀɪᴅ ᴠᴄ ᴘʟᴀʏᴇʀ 🔥 SORRY FOR OUR PROJECTS DELETED BY GITHUB FLAGGED ᴢᴀɪᴅ ᴠᴄ ᴘʟᴀᴇʀ ɪꜱ ᴀ ᴛᴇʟᴇɢʀᴀᴍ ᴘʀᴏᴊᴇᴄᴛ ʙᴀꜱᴇᴅ ᴏɴ ᴘʏʀᴏɢʀᴀᴍ ꜰᴏʀ ᴘʟᴀʏ ᴍᴜꜱɪᴄꜱ ɪɴ ᴠᴄ ᴄʜᴀᴛꜱ..

Zaid 117 Dec 29, 2022
AWS CloudSaga - Simulate security events in AWS

AWS CloudSaga - Simulate security events in AWS AWS CloudSaga is for customers to test security controls and alerts within their Amazon Web Services (

Amazon Web Services - Labs 325 Dec 01, 2022
A python script that can send notifications to your phone via SMS text

Discord SMS Notification A python script that help you send text message to your phone one of your desire discord channel have a new message. The proj

2 Apr 25, 2022
A simple API Wrapper for Guilded.

Guildr A simple API Wrapper for Guilded. Frequently updated! I am not a user of Guilded, meaning I do not keep track of new Guilded updates or patches

2 Mar 07, 2022
A synchronous, object oriented API wrapper for thecatapi

cats.py A synchronous, object oriented API wrapper for thecatapi Table Of Content cats.py Table Of Content Installation Usage Contributing FAQ License

Marcus 2 Feb 04, 2022
Python wrapper for Coinex APIs

coinexpy - Python wrapper for Coinex APIs Through coinexpy you can simply buy or sell crypto in your Coinex account Features place limit order place m

Iman Mousaei 16 Jan 02, 2023
Aplicação dos metodos de classificação em 3 diferentes banco de dados. Usando...

Machine Learning - Métodos de classificação Base de Dados utilizadas: Dados de crédito Dados do Census Métodos de classificação aplicados: Naive Bayes

1 Jan 18, 2022
Decryption utility for PGP Whole Disk Encryption

wdepy: Decryption and Inspection for PGP WDE Disks This is a small python tool to inspect and decrypt disk images encrypted with PGP Whole Disk Encryp

Brendan Dolan-Gavitt 17 Oct 07, 2022
Discord-Mass-Mention - Yup the title says it all

Protocol - Mass Mention (i havent tested this with any token other than my own t

Mallowies 14 Nov 06, 2022
A Simple Voice Music Player

📀 𝐕𝐂𝐔𝐬𝐞𝐫𝐁𝐨𝐭 √𝙏𝙚𝙖𝙢✘𝙊𝙘𝙩𝙖𝙫𝙚 NOTE JUST AN ENGLISH VERSION OF OUR PRIVATE SOURCE WAIT FOR LATEST UPDATES JOIN @𝐒𝐔𝐏𝐏𝐎𝐑𝐓 JOIN @𝐂?

TeamOctave 8 May 08, 2022
My homeserver setup. Everything managed securely using Portainer.

homeserver-traefik-portainer Features: access all services with free TLS from letsencrypt using your own domain running a side project is super simple

Tomasz Wójcik 44 Jan 03, 2023
A Telegram Bot written in Python for mirroring files on the Internet to your Google Drive or Telegram

Original Repo mirror-leech-telegram-bot This is a Telegram Bot written in Python for mirroring files on the Internet to your Google Drive or Telegram.

0 Jan 03, 2022
Telegram Radio - A User-bot who continuously play random audio files (from the famous telegram music channel @mveargasm) in the intended voice chat.

MvEargasmDJ: This is my submission for the Telegram Radio Project of Baivaru. Which required a userbot to continiously play random audio files from th

eyaadh 24 Nov 12, 2022
radiant discord anti nuke src leaked lol.

radiant-anti-wizz-leaked radiant discord anti nuke src leaked lol, the whole anti sucks but idc. sucks to suck thats tuff bro LMAOOOOOO join my server

ok 15 Aug 06, 2022
The official Discord Python framework for thenewboston blockchain.

Project Setup Follow the steps below to set up the project on your environment. Mac Setup Homebrew requires the Xcode command-line tools from Apple's

Bucky Roberts 18 Jul 15, 2022
LimitatiBot - A simple telegram bot to establish a conversation with a user without having to use private chats

🤖 LimitatiBot [0.2] LimitatiBot is a simple telegram bot to establish a convers

xMrPente 9 Dec 27, 2022
Market calendar RESTful API with holiday, late open, and early close. Over 50+ unique exchange calendars for global equity and futures markets.

Trading Calendar Market calendar RESTful API with holiday, late open, and early close. Over 50+ unique exchange calendars for global equity and future

Apptastic Software 1 Feb 03, 2022
A simple Discord bot that notifies users of new Abitti versions

A simple Discord bot that notifies users of new Abitti versions. New features might be added later on. If you have good ideas, feel free to do a PR.

1 Feb 11, 2022
Amanda-A next gen powerful telegram group manager bot for manage your groups and have fun with other cool modules.

Amanda-A next gen powerful telegram group manager bot for manage your groups and have fun with other cool modules.

Team Amanda 4 Oct 21, 2022
KiKi bare dogs can share your joys and sorrows with you.

Kiki-FangLee-DiscordBot KiKi bare dogs can share your joys and sorrows with you. $help: Kiki will show you my talent, aw-aw. $list: Show Kiki's knowle

Fang Lee 0 Feb 12, 2022