API reference
dodo.app
dodo.commandbar
dodo.compose
dodo.helpwindow
dodo.keymap
- command_bar_keymap = {'<down>': ('history next', <function <lambda>>), '<enter>': ('accept', <function <lambda>>), '<escape>': ('close', <function <lambda>>), '<up>': ('history previous', <function <lambda>>), 'C-n': ('history next', <function <lambda>>), 'C-p': ('history previous', <function <lambda>>)}
The keymap active when the command bar is visible
A dictionary from key strings to pairs consisting of a short docstring and a function taking
CommandBaras input. Unlike the other keymaps, the command bar keymap doesn’t accept keychords. Also, you should avoid mapping alphanumeric keys to commands, as this will interfere with typing.
- compose_keymap = {'<enter>': ('edit message', <function <lambda>>), 'S': ('send', <function <lambda>>), '[': ('previous SMTP account', <function <lambda>>), ']': ('next SMTP account', <function <lambda>>), 'a': ('attach file', <function <lambda>>), 'e': ('toggle PGP-encrypt', <function <lambda>>), 's': ('toggle PGP-sign', <function <lambda>>), 'w': ('toggle word wrap', <function <lambda>>)}
The local keymap for compose panels
A dictionary from key strings to pairs consisting of a short docstring and a function taking
ComposePanelas input.
- global_keymap = {'/': ('search', <function <lambda>>), '?': ('show help', <function <lambda>>), 'F': ('show flagged', <function <lambda>>), 'I': ('show inbox', <function <lambda>>), 'Q': ('quit', <function <lambda>>), 'T': ('show tags', <function <lambda>>), 'U': ('show unread', <function <lambda>>), 'X': ('close all', <function <lambda>>), '`': ('sync mail', <function <lambda>>), 'c': ('compose', <function <lambda>>), 'h': ('previous panel', <function <lambda>>), 'l': ('next panel', <function <lambda>>), 't m': ('tag marked', <function <lambda>>), 't t': ('tag', <function <lambda>>), 'x': ('close panel', <function <lambda>>)}
The global keymap
A dictionary from key strings to pairs consisting of a short docstring and a function taking
Dodoas input. This commands can be superseded by the various local keymaps.
- search_keymap = {'<down>': ('next thread', <function <lambda>>), '<enter>': ('open thread', <function <lambda>>), '<pagedown>': ('page down', <function <lambda>>), '<pageup>': ('page up', <function <lambda>>), '<space>': ('toggle marked', <function <lambda>>), '<tab>': ('next unread', <function <lambda>>), '<up>': ('previous thread', <function <lambda>>), 'C-d': ('down 20', <function <lambda>>), 'C-u': ('up 20', <function <lambda>>), 'G': ('last thread', <function <lambda>>), 'S-<tab>': ('previous unread', <function <lambda>>), 'a': ('tag -inbox -unread', <function <lambda>>), 'f': ('toggle flagged', <function <lambda>>), 'g g': ('first thread', <function <lambda>>), 'j': ('next thread', <function <lambda>>), 'k': ('previous thread', <function <lambda>>), 'u': ('toggle unread', <function <lambda>>)}
The local keymap for search panels
A dictionary from key strings to pairs consisting of a short docstring and a function taking
SearchPanelas input.
- tag_keymap = {'<down>': ('next tag', <function <lambda>>), '<enter>': ('search tag', <function <lambda>>), '<up>': ('previous tag', <function <lambda>>), 'C-d': ('down 20', <function <lambda>>), 'C-u': ('up 20', <function <lambda>>), 'G': ('last tag', <function <lambda>>), 'g g': ('first tag', <function <lambda>>), 'j': ('next tag', <function <lambda>>), 'k': ('previous tag', <function <lambda>>)}
The local keymap for the tag panel
A dictionary from key strings to pairs consisting of a short docstring and a function taking
TagPanelas input.
- thread_keymap = {'-': ('page up', <function <lambda>>), '<pagedown>': ('page down', <function <lambda>>), '<pageup>': ('page up', <function <lambda>>), '<space>': ('page down', <function <lambda>>), 'A': ('show attachments in file browser', <function <lambda>>), 'C-d': ('scroll down more', <function <lambda>>), 'C-f': ('forward', <function <lambda>>), 'C-u': ('scroll up more', <function <lambda>>), 'G': ('bottom of message', <function <lambda>>), 'H': ('toggle HTML', <function <lambda>>), 'J': ('next message', <function <lambda>>), 'K': ('previous message', <function <lambda>>), 'M': ('toggle thread list mode', <function <lambda>>), 'R': ('reply', <function <lambda>>), 'U': ('next matching unread message', <function <lambda>>), 'f': ('toggle flagged', <function <lambda>>), 'g g': ('top of message', <function <lambda>>), 'j': ('scroll down', <function <lambda>>), 'k': ('scroll up', <function <lambda>>), 'r': ('reply to all', <function <lambda>>), 'u': ('toggle unread', <function <lambda>>)}
The local keymap for thread panels
A dictionary from key strings to pairs consisting of a short docstring and a function taking
ThreadPanelas input.
dodo.panel
dodo.search
dodo.settings
This module holds settings and sets their default values. The values set here should be overridden by the user in ~/.config/dodo/config.py. This can be done as follows:
import dodo
dodo.settings.email_address = 'First Last <me@domain.com>''
dodo.settings.sent_dir = '~/mail/work/Sent'
The settings email_address and
sent_dir are required. Dodo may not work correctly
unless you set them properly. The rest of the settings have reasonable
defaults, as detailed below.
- default_thread_list_mode: Literal['conversation', 'thread'] = 'conversation'
Set the way your thread should be listed.
- Possible values are:
‘conversation’: flat list, chronologically sorted
‘thread’: tree view, following the various subthreads
- default_to_html = False
Open messages in HTML mode by default, rather than plaintext
- editor_command = "xterm -e vim '{file}'"
Command used to launch external text editor
This is a shell command, which additionally takes the {file} placeholder, which is passed the name of a temp file being edited while composing an email.
- email_address: str | Dict[str, str] = ''
Your email address (REQUIRED)
This is used both to populate the ‘From’ field of emails and to (mostly) avoid CC’ing yourself when replying to all. It can be given as ‘NAME <ADDRESS@DOMAIN>’ format. For just one email address, this can be given as a string. From multiple emails, use a dictionary mapping the account names in
smtp_accountsto the associated email addresses.
- file_browser_command = "nautilus '{dir}'"
Command used to launch external file browser
This is a shell command, which additionally takes the {dir} placeholder. This command is used when viewing attachments, which first dumps the attachments to a temp directory given by {dir}, then opens that directory in a file browser.
- file_picker_command = None
Command used to launch external file picker
This is an optional shell command, which additionally takes the {tempfile} placeholder. This command is used when picking files to attach to an email. The command should write out the chosen files to {tempfile}, which will then be read and deleted, if it exists.
By default, this is set to None, in which case the built-in file picker will be used.
- gnupg_home = None
Directory containg GnuPG keys
If set to None, GnuPG will use whatever directory is the default (consult the GnuPG documentation for more information on what this might be).
- gnupg_keyid = None
The id of the key to be used for GnuPG-signing mail messages.
If set to the id of a valid GnuPG private signing key, sent messages will be cryptographically signed according to rfc3156 using the GnuPG sotware, which should be installed and configured. Requires python-gnupg (https://pypi.org/project/python-gnupg/)
- hide_tags = ['unread', 'sent']
Tags to hide in search panel
- html_block_remote_requests = True
Block remote requests for HTML messages
HTML messages, especially from dodgy senders, can display remote content or ‘call home’ from embedded image tags or iframes. If set to True, Dodo will not allow these requests.
- html_confirm_open_links = True
Display a confirmation dialog before opening a link in browser
If this is True, Dodo will display a confirmation dialog showing the actual URL that the web browser will request before opening. This is an extra measure against phishing or emails opening your web browser without your permission.
- html_confirm_open_links_trusted_hosts = []
A list of trusted hosts for HTML links.
If a link is to a host in this list, it will be opened without confirmation, even if
html_confirm_open_linksis True.
- init_queries = ['tag:inbox']
List of non closable queries open at startup
You can save query with notmuch config set query:inbox “tag:inbox and not tag:trash” and use query:inbox as a search term.
- message2html_filters = []
A list of functions to extract text from a mail message JSON.
Every item in this list should be a function, which either returns a HTML string (which gets formatted inside a
<pre>tag), or returnsNone. The first function to return a non-Nonevalue is used to render the message. If all functions returnNone, the default rendering is used.The default rendering runs the following functions in order, which might also be useful when writing your own filters:
body_text(to get a body string from the JSON)simple_escape(to make the string HTML-safe)colorize_text(to colorize quoted text)linkify(to detect URLs)
Example configuration using this feature to highlight markdown syntax:
import pygments.formatters from dodo import util def render_github(msg): # Double imports needed due to how dodo runs config.py import pygments.lexers import pygments.formatters # If you use some sort of auto-tagging, you might want to match on # tags instead of headers. if "headers" not in msg or "From" not in msg["headers"]: return None if not msg["headers"]["From"].endswith("<notifications@github.com>"): return None text = util.body_text(msg) lexer = pygments.lexers.MarkdownLexer() formatter = pygments.formatters.HtmlFormatter(nowrap=True) highlighted = pygments.highlight(text, lexer, formatter) return util.linkify(highlighted) dodo.settings.message2html_filters = [render_github] # Available styles: https://pygments.org/styles/ pygments_css = pygments.formatters.HtmlFormatter(style="gruvbox-dark").get_style_defs() dodo.settings.message_css += pygments_css.replace("{", "{{").replace("}", "}}")
- message_css = '\npre {{\n font-family: {message_font};\n font-size: {message_font_size}pt;\n}}\n\npre .quoted {{\n color: {fg_dim};\n}}\n\npre .headername {{\n color: {fg_bright};\n font-weight: bold;\n}}\n\npre .headertext {{\n color: {fg_bright};\n}}\n\nbody {{\n background-color: {bg};\n color: {fg};\n}}\n\n::-webkit-scrollbar {{\n background: {bg};\n}}\n\n::-webkit-scrollbar-thumb {{\n background: {bg_button};\n}}\n\n::selection {{\n color: {bg};\n background: {fg};\n}}\n\na {{\n color: {fg_bright};\n}}\n'
CSS used in view and compose window
Placeholders may be included in curly brackets for any color named in the current theme, as well as {message_font} and {message_font_size}. Literal curly braces should be doubled, i.e. ‘{’ should be ‘{{’ and ‘}’ should be ‘}}’.
- message_font = 'DejaVu Sans Mono'
The font used for plaintext messages
- message_font_size = 12
The font size used for plaintext messages
- no_hooks_on_send = True
disable/enable calling notmuch hooks when sending email
When True, ‘notmuch new’ is called with –no-hooks when a message is sent. One may not wanting to wait for the hooks on each sent email, for example when calling mbsync on their notmuch hooks. Other users may set this to False, for example when notmuch hooks are used to archive sent mail.
- remove_temp_dirs = 'ask'
Set whether to remove temporary directories when closing a panel
Thread panels create temporary directories to open attachments. These can be cleaned up automatically when a panel (or Dodo) is closed. Possible values are: ‘always’, ‘never’, or ‘ask’.
- search_color_overrides = {}
A dictionary mapping tags to color dictionaries.
The color dictionaries map columns to override colors. The available columns are:
date
from
subject
tags
For example, to show a red subject for messages tagged ‘urgent’, using the built-in Gruvbox palette:
dodo.settings.search_color_overrides = { 'urgent': { 'subject': dodo.themes.gruvbox_p['neutral_red'], } }
- search_font = 'DejaVu Sans Mono'
The font used for search output and various other list-boxes
- search_font_size = 13
The font size used for search output and various other list-boxes
- search_title_format = '{query} [{num_threads}]'
A Python format string for the tab title of search panels
The following placeholders can be used:
{query}: the current search query
{num_threads}: the number of threads returned by the search
- search_view_padding = 1
A bit of spacing around each line in the search panel
- send_mail_command: str | dict[str, str] = 'msmtp -a "{account}" -t'
Command used to send mail via SMTP
Either a plain command or a mapping of account names to command.
The command must be a shell command that expects a (sendmail-compatible) email message to be written to STDIN. Note that it should read the destination from the From: header of the message and not a command-line argument. Use the {account} placeholder to read the currently selected account.
- sent_dir = ''
Where to store sent messages (REQUIRED)
This will usually be a subdirectory of the Maildir sync’ed with
sync_mail_command. This setting can be given either as a string to use one global sent directory, or as a dictionary mapping account names insmtp_accountsto their own sent dirs.A value of None, either standalone or as one of the dict value, can be used to indicate the email should be discarded. This can be useful if the sendmail command already has a mechanism for that feature.
- smtp_accounts = ['default']
A list of SMTP account names recognised by send_mail_command
This setting allows switching SMTP accounts in the Compose panel. The first account in the list is selected by default.
- sync_mail_command = 'offlineimap'
Command used to sync IMAP with local Maildir
- sync_mail_interval = 300
Interval to run
sync_mail_commandautomatically, in secondsSet this to -1 to disable automatic syncing.
- tag_font = 'DejaVu Sans Mono'
The font used for tags and tag icons
- tag_font_size = 13
The font size used for tags and tag icons
- tag_icons = {'attachment': '\uf565', 'flagged': '\uf73a', 'inbox': '\uf01c', 'marked': '\uf111', 'replied': '\uf4a8', 'sent': '>', 'signed': '\uf040', 'unread': '\uf0e0'}
Tag icons
This is a dictionary of substitutions used to abbreviate common tag names as unicode icons in the search and thread panels.
- theme = {'bg': '#2e3440', 'bg_alt': '#3b4252', 'bg_button': '#4c566a', 'bg_highlight': '#a3be8c', 'fg': '#d8dee9', 'fg_bad': '#bf616a', 'fg_bright': '#b48ead', 'fg_button': '#eceff4', 'fg_date': '#4c566a', 'fg_dim': '#4c566a', 'fg_from': '#5e81ac', 'fg_good': '#a3be8c', 'fg_highlight': '#2e3440', 'fg_link': '#81a1c1', 'fg_subject': '#d8dee9', 'fg_subject_flagged': '#ebcb8b', 'fg_subject_irrelevant': '#4c566a', 'fg_subject_unread': '#b48ead', 'fg_tags': '#81a1c1'}
The GUI theme
A theme is a dictionary mapping a dozen or so named colors to HEX values. Several themes are defined in dodo.themes, based on the popular Nord, Solarized and Gruvbox color palettes.
- web_browser_command = ''
Web browser to use when clicking links in emails
This should be a single command which expects a URL as its first argument. If this is an empty string, Dodo will attempt to use the default web browser supplied by the desktop environment, if it exists.
- wrap_column = 78
Wrap text to this column when composing emails
- wrap_message = True
Hard-wrap message text by default
You may wish to disable this if you don’t want hard wraps in your email messages or your text editor does hard wrapping already.
dodo.themes
- apply_theme(theme)
“Apply the given theme to GUI components
This is called when
Dodois initialised.- Return type:
None
- catppuccin_macchiato = {'bg': '#24273a', 'bg_alt': '#181926', 'bg_button': '#363a4f', 'bg_highlight': '#8aadf4', 'fg': '#cad3f5', 'fg_bad': '#ed8796', 'fg_bright': '#b7bdf8', 'fg_button': '#f4dbd6', 'fg_date': '#f0c6c6', 'fg_dim': '#8087a2', 'fg_from': '#8aadf4', 'fg_good': '#a6da95', 'fg_highlight': '#181926', 'fg_link': '#8aadf4', 'fg_subject': '#cad3f5', 'fg_subject_flagged': '#eed49f', 'fg_subject_irrelevant': '#939ab7', 'fg_subject_unread': '#c6a0f6', 'fg_tags': '#f5a97f'}
Theme based on the Catppuchin palette (macchiatto version).
- gruvbox_dark = {'bg': '#282828', 'bg_alt': '#3c3836', 'bg_button': '#3c3836', 'bg_highlight': '#282828', 'fg': '#ebdbb2', 'fg_bad': '#cc241d', 'fg_bright': '#fbf1c7', 'fg_button': '#d5c4a1', 'fg_date': '#689d6a', 'fg_dim': '#a89984', 'fg_from': '#458588', 'fg_good': '#98971a', 'fg_highlight': '#d79921', 'fg_link': '#b16286', 'fg_subject': '#bdae93', 'fg_subject_flagged': '#d65d0e', 'fg_subject_irrelevant': '#928374', 'fg_subject_unread': '#98971a', 'fg_tags': '#b16286'}
Theme based on the Gruvbox palette (dark background)
- gruvbox_dark_hard = {'bg': '#1d2021', 'bg_alt': '#3c3836', 'bg_button': '#3c3836', 'bg_highlight': '#282828', 'fg': '#ebdbb2', 'fg_bad': '#cc241d', 'fg_bright': '#fbf1c7', 'fg_button': '#d5c4a1', 'fg_date': '#689d6a', 'fg_dim': '#a89984', 'fg_from': '#458588', 'fg_good': '#98971a', 'fg_highlight': '#d79921', 'fg_link': '#b16286', 'fg_subject': '#bdae93', 'fg_subject_flagged': '#d65d0e', 'fg_subject_irrelevant': '#928374', 'fg_subject_unread': '#98971a', 'fg_tags': '#b16286'}
Theme based on the Gruvbox palette (dark background, hard contrast)
- gruvbox_dark_soft = {'bg': '#32302f', 'bg_alt': '#3c3836', 'bg_button': '#3c3836', 'bg_highlight': '#282828', 'fg': '#ebdbb2', 'fg_bad': '#cc241d', 'fg_bright': '#fbf1c7', 'fg_button': '#d5c4a1', 'fg_date': '#689d6a', 'fg_dim': '#a89984', 'fg_from': '#458588', 'fg_good': '#98971a', 'fg_highlight': '#d79921', 'fg_link': '#b16286', 'fg_subject': '#bdae93', 'fg_subject_flagged': '#d65d0e', 'fg_subject_irrelevant': '#928374', 'fg_subject_unread': '#98971a', 'fg_tags': '#b16286'}
Theme based on the Gruvbox palette (dark background, soft contrast)
- gruvbox_light = {'bg': '#fbf1c7', 'bg_alt': '#ebdbb2', 'bg_button': '#ebdbb2', 'bg_highlight': '#fbf1c7', 'fg': '#3c3836', 'fg_bad': '#cc241d', 'fg_bright': '#282828', 'fg_button': '#504945', 'fg_date': '#689d6a', 'fg_dim': '#504945', 'fg_from': '#458588', 'fg_good': '#98971a', 'fg_highlight': '#d79921', 'fg_link': '#b16286', 'fg_subject': '#665c54', 'fg_subject_flagged': '#d65d0e', 'fg_subject_irrelevant': '#928374', 'fg_subject_unread': '#98971a', 'fg_tags': '#b16286'}
Theme based on the Gruvbox palette (light background)
- gruvbox_light_hard = {'bg': '#f9f5d7', 'bg_alt': '#ebdbb2', 'bg_button': '#ebdbb2', 'bg_highlight': '#fbf1c7', 'fg': '#3c3836', 'fg_bad': '#cc241d', 'fg_bright': '#282828', 'fg_button': '#504945', 'fg_date': '#689d6a', 'fg_dim': '#504945', 'fg_from': '#458588', 'fg_good': '#98971a', 'fg_highlight': '#d79921', 'fg_link': '#b16286', 'fg_subject': '#665c54', 'fg_subject_flagged': '#d65d0e', 'fg_subject_irrelevant': '#928374', 'fg_subject_unread': '#98971a', 'fg_tags': '#b16286'}
Theme based on the Gruvbox palette (light background, hard contrast)
- gruvbox_light_soft = {'bg': '#f2e5bc', 'bg_alt': '#ebdbb2', 'bg_button': '#ebdbb2', 'bg_highlight': '#fbf1c7', 'fg': '#3c3836', 'fg_bad': '#cc241d', 'fg_bright': '#282828', 'fg_button': '#504945', 'fg_date': '#689d6a', 'fg_dim': '#504945', 'fg_from': '#458588', 'fg_good': '#98971a', 'fg_highlight': '#d79921', 'fg_link': '#b16286', 'fg_subject': '#665c54', 'fg_subject_flagged': '#d65d0e', 'fg_subject_irrelevant': '#928374', 'fg_subject_unread': '#98971a', 'fg_tags': '#b16286'}
Theme based on the Gruvbox palette (light background, soft contrast)
- nord = {'bg': '#2e3440', 'bg_alt': '#3b4252', 'bg_button': '#4c566a', 'bg_highlight': '#a3be8c', 'fg': '#d8dee9', 'fg_bad': '#bf616a', 'fg_bright': '#b48ead', 'fg_button': '#eceff4', 'fg_date': '#4c566a', 'fg_dim': '#4c566a', 'fg_from': '#5e81ac', 'fg_good': '#a3be8c', 'fg_highlight': '#2e3440', 'fg_link': '#81a1c1', 'fg_subject': '#d8dee9', 'fg_subject_flagged': '#ebcb8b', 'fg_subject_irrelevant': '#4c566a', 'fg_subject_unread': '#b48ead', 'fg_tags': '#81a1c1'}
Theme based on the Nord palette
- solarized_dark = {'bg': '#073642', 'bg_alt': '#002b36', 'bg_button': '#002b36', 'bg_highlight': '#eee8d5', 'fg': '#93a1a1', 'fg_bad': '#dc322f', 'fg_bright': '#6c71c4', 'fg_button': '#586e75', 'fg_date': '#2aa198', 'fg_dim': '#586e75', 'fg_from': '#268bd2', 'fg_good': '#859900', 'fg_highlight': '#586e75', 'fg_link': '#6c71c4', 'fg_subject': '#839496', 'fg_subject_flagged': '#6c71c4', 'fg_subject_irrelevant': '#586e75', 'fg_subject_unread': '#eee8d5', 'fg_tags': '#6c71c4'}
Theme based on the Solarized palette (dark background).
- solarized_light = {'bg': '#fdf6e3', 'bg_alt': '#fdf6e3', 'bg_button': '#fdf6e3', 'bg_highlight': '#073642', 'fg': '#586e75', 'fg_bad': '#dc322f', 'fg_bright': '#6c71c4', 'fg_button': '#93a1a1', 'fg_date': '#2aa198', 'fg_dim': '#93a1a1', 'fg_from': '#268bd2', 'fg_good': '#859900', 'fg_highlight': '#93a1a1', 'fg_link': '#6c71c4', 'fg_subject': '#839496', 'fg_subject_flagged': '#6c71c4', 'fg_subject_irrelevant': '#586e75', 'fg_subject_unread': '#073642', 'fg_tags': '#6c71c4'}
Theme based on the Solarized palette (light background).
dodo.thread
dodo.util
- add_header_line(s, h)
Add the given string to the headers, i.e. before the first blank line, in the provided string.
- Return type:
str
- body_html(m)
Get the body HTML of a message
Search a message recursively for the first part with content-type equal to “text/html” and return it.
- Parameters:
m (
dict) – a JSON message- Return type:
str
- body_text(m)
Get the body text of a message
Search a message recursively for the first part with content-type equal to “text/plain” and return it.
- Parameters:
m (
dict) – a JSON message- Return type:
str
- clean_html2html(s)
Sanitize the given HTML string
This cleans the input string using
Cleanerwith the default settings. Set the global util.html2html to this function to enable.- Parameters:
s (
str) – an HTML input string- Return type:
str
- colorize_text(s, has_headers=False)
Add some colors to HTML-escaped plaintext, for use inside <pre> tag
- Return type:
str
- decode_header(s)
Decode any charset-encoded parts of an email header
- Return type:
str
- email_is_me(e)
Check whether the provided email is me
This compares settings.email_address with the provided email, after calling
strip_email_addresson both. This method is used e.g. bydodo.compose.Composeto filter out the user’s own email when forming a “reply-to-all” message.- Return type:
bool
- email_smtp_account_index(e)
Index in settings.smtp_accounts of account having the provided email address
This method is used e.g. by
dodo.compose.Composeto autmatically select the account to be used when replying to a mail. It returns the index of first matching account or None if provided email does not match any smtp account.- Return type:
Optional[int]
- find_content(m, content_type)
Return a flat list consisting of the ‘content’ field of each message part with the given content-type.
- Return type:
List[str]
- get_header_addresses(headers, header_keys)
Extract realnames and email addresses from message headers.
The given header_keys are considered, e.g. [‘From’, ‘Reply-To’] to get senders, or [‘To’, ‘Cc’] to get recipients.
- Return type:
List[Tuple[str,str]]
- html2html(s)
Function used to process HTML messages
This is the identity by default, but can be set to another function to do HTML sanitization, (de)formatting, etc.
- html2text(s)
Function used to convert HTML to plain text
This is set to
w3m_html2textby default, but can be changed by the user in “config.py”.- Return type:
str
- is_attachment(part)
Check whether a message part should be shown an attachment.
All parts with content-disposition equal to “attachment” are considered attachments, except for PGP signatures and parts without a filename.
Some clients also send attachments without a Content-Disposition header. We consider any unknown binary part an attachment.
- Return type:
bool
- key_string(e)
Convert a Qt keycode plus modifiers into a human readable/writable string
- Parameters:
e (
QKeyEvent) – a QKeyEvent- Return type:
str- Returns:
a string representing e.key() and its modifiers
- linkify(s)
Link URLs and email addresses
- Parameters:
s (
str) – a plaintext input string- Return type:
str- Returns:
HTML with URLs and emails linked
- make_message_css()
Fill placeholders in settings.message_css using the current theme and font settings.
- Return type:
str
- message_parts(m)
Iterate over JSON message parts recursively, in depth-first order
This is method roughly emulates the behavior of
walk, but for JSON representations of an email message rather thanMessageobjects.Note that if parts are nested, their data will be returned multiple times, first as a sub-object of their parent, then as the part itself.
- Parameters:
m (
dict) – a JSON message- Return type:
Iterator[dict]- Returns:
an iterator which returns each JSON-subobject corresponding to a message part.
- quote_body_text(m)
Return the body text of the message, with ‘>’ prepended to each line
- Return type:
str
- replace_header(s, h, new_value)
Replace a single header without doing full message parsing
Note this ONLY works for short (i.e. unwrapped) headers.
- Return type:
str
- sanitize_filename(name)
Replace invalid filename characters.
Note: This should be used for the basename, as it also removes the path separator.
- Return type:
str
- separate_headers(s)
Split a message into its header part and body part
- Return type:
Tuple[str,str]
- simple_escape(s)
Provide (limited) HTML escaping
This function only escapes &, <, and >.
- Return type:
str
- strip_email_address(e)
Strip the display name, leaving just the email address
E.g. “First Last <me@domain.com>” -> “me@domain.com”
- Return type:
str
- w3m_html2text(s)
Convert HTML to plain text using “w3m -dump”
- Parameters:
s (
str) – an HTML input string- Return type:
str- Returns:
plain text representation of the HTML
- wrap_message(s)
Hard wrap message body using
wrap_columnWrap the body part of the message. Headers and quoted text are not affected.
- Return type:
str
- write_attachments(m)
Write attachments out into temp directory and open with settings.file_browser_command
Currently, this exports a new copy of the attachments every time it is called. Maybe it should do something smarter?
- Parameters:
m (
dict) – message JSON- Return type:
Tuple[str,List[str]]- Returns:
Return a tuple consisting of the temp dir and a list of files. If no attachments, returns an empty string and empty list.