# 4.4. User Settings

Alot sets up a `SettingsManager` to access user settings defined in different places uniformly. There are four types of user settings:

what? | location | accessible via
--- | --- | ---
alot config | `~/.config/alot/config` or given by command option -c. | `SettingsManager.get()`
hooks – user provided python code | `~/.config/alot/hooks.py` or as given by the hooksfile config value | `SettingsManager.get_hook()`
notmuch config | notmuch config file as given by command option -n or its default location described in notmuch-config(1) | `SettingsManager.get_notmuch_setting()`
mailcap – defines shellcommands to handle mime types | `~/.mailcap` (`/etc/mailcap`) | `SettingsManager.mailcap_find_match()`

## 4.4.1. Settings Manager

class alot.settings.manager.SettingsManager

  Organizes user settings

  account_matching_address(address, return_default=False)

    returns `Account` for a given email address (str)

    Parameters:

      - address (str) – address to look up. A realname part will be ignored.

      - return_default (bool) – If True and no address can be found, then the default account wil be returned.

    Return type:

      `Account`

    Raises:

      NoMatchingAccount – If no account can be found. This includes if return_default is True and there are no accounts defined.

  get(key, fallback=None)

    look up global config values from alot’s config

    Parameters:

      - key (str) – key to look up

      - fallback (str) – fallback returned if key is not present

    Returns:

      config value with type as specified in the spec-file

  get_accounts()

    returns known accounts

    Return type:

      list of `Account`

  get_addressbooks(order=None, append_remaining=True)

    returns list of all defined `AddressBook` objects

  get_hook(key)

    return hook (callable) identified by key

  get_keybinding(mode, key)

    look up keybinding from MODE-maps sections

    Parameters:

      - mode (str) – mode identifier

      - key (str) – urwid-style key identifier

    Returns:

      a command line to be applied upon keypress

    Return type:

      str

  get_keybindings(mode)

    look up keybindings from MODE-maps sections

    Parameters:

      mode (str) – mode identifier

    Returns:

      dictionaries of key-cmd for global and specific mode

    Return type:

      2-tuple of dicts

  get_main_addresses()

    returns addresses of known accounts without its aliases

  get_notmuch_setting(section, key, fallback=None)

    look up config values from notmuch’s config

    Parameters:

      - section (str) – key is in

      - key (str) – key to look up

      - fallback (str) – fallback returned if key is not present

    Returns:

      the config value

    Return type:

      str

  get_tagstring_representation(tag, onebelow_normal=None, onebelow_focus=None)

    looks up user’s preferred way to represent a given tagstring.

    Parameters:

      - tag (str) – tagstring

      - onebelow_normal (urwid.AttrSpec) – attribute that shines through if unfocussed

      - onebelow_focus (urwid.AttrSpec) – attribute that shines through if focussed

    If onebelow_normal or onebelow_focus is given these attributes will be used as fallbacks for fg/bg values ‘’ and ‘default’.

    This returns a dictionary mapping
      normal:

        to `urwid.AttrSpec` used if unfocussed

      focussed:

        to `urwid.AttrSpec` used if focussed

      translated:

        to an alternative string representation

  get_theming_attribute(mode, name, part=None)

    looks up theming attribute

    Parameters:

      - mode (str) – ui-mode (e.g. search,`thread`…)

      - name (str) – identifier of the atttribute

    Return type:

      urwid.AttrSpec

  get_threadline_theming(thread)

    looks up theming info a threadline displaying a given thread. This wraps around `get_threadline_theming()`, filling in the current colour mode.

    Parameters:

      thread (alot.db.thread.Thread) – thread to theme

  mailcap_find_match(*args, **kwargs)

    Propagates `mailcap.find_match()` but caches the mailcap (first argument)

  read_config(path)

    parse alot’s config file :param path: path to alot’s config file :type path: str

  read_notmuch_config(path)

    parse notmuch’s config file :param path: path to notmuch’s config file :type path: str

  reload()

    Reload notmuch and alot config files

  represent_datetime(d)

    turns a given datetime obj into a string representation. This will:

    1. look if a fixed ‘timestamp_format’ is given in the config

    2. check if a ‘timestamp_format’ hook is defined

    3. use `pretty_datetime()` as fallback

  set(key, value)

    setter for global config values

    Parameters:

      - key (str) – config option identifies

      - value (depends on the specfile `alot.rc.spec`) – option to set

## 4.4.2. Errors

exception alot.settings.errors.ConfigError

  could not parse user config

exception alot.settings.errors.NoMatchingAccount

  No account matching requirements found.

## 4.4.3. Utils

alot.settings.utils.read_config(configpath=None, specpath=None, checks=None, report_extra=False)

  get a (validated) config object for given config file path.

  Parameters:

    - configpath (str or list(str)) – path to config-file or a list of lines as its content

    - specpath (str) – path to spec-file

    - checks (dict str->callable,) – custom checks to use for validator. see validate docs

    - report_extra (boolean) – log if a setting is not present in the spec file

  Raises:

    `ConfigError`

  Return type:

    configobj.ConfigObj

alot.settings.utils.read_notmuch_config(path)

  Read notmuch configuration.

  This function calls the command “notmuch –config {path} config list” and parses its output into a `config` dictionary, which is then returned.

  The configuration value for a key under a section can be accessed with `config[section][key]`.

  The returned value is a dict `config` with some values converted to special python types. These are the values that alot is known to use. All other values in the returned dict are just strings.

  Parameters:

    path (str) – path to the configuration file, which is passed as argument to the –config option of notmuch.

  Raises:

    `ConfigError`

  Return type:

    dict

alot.settings.utils.resolve_att(a, fallback)

  replace ‘’ and ‘default’ by fallback values

## 4.4.4. Themes

class alot.settings.theme.Theme(path)

  Colour theme

  Parameters:

    path (str) – path to theme file

  Raises:

    `ConfigError`

  get_attribute(colourmode, mode, name, part=None)

    returns requested attribute

    Parameters:

      - mode (str) – ui-mode (e.g. search,`thread`…)

      - name (str) – of the atttribute

      - colourmode (int) – colour mode; in [1, 16, 256]

    Return type:

      urwid.AttrSpec

  get_threadline_theming(thread, colourmode)

    look up how to display a Threadline widget in search mode for a given thread.

    Parameters:

      - thread (alot.db.thread.Thread) – Thread to theme Threadline for

      - colourmode (int) – colourmode to use, one of 1,16,256.

    This will return a dict mapping
      normal:

        to urwid.AttrSpec,

      focus:

        to urwid.AttrSpec,

      parts:

        to a list of strings indentifying subwidgets to be displayed in this order.

    Moreover, for every part listed this will map ‘part’ to a dict mapping
      normal:

        to urwid.AttrSpec,

      focus:

        to urwid.AttrSpec,

      width:

        to a tuple indicating the width of the subpart. This is either (‘fit’, min, max) to force the widget to be at least min and at most max characters wide, or (‘weight’, n) which makes it share remaining space with other ‘weight’ parts.

      alignment:

        where to place the content if shorter than the widget. This is either ‘right’, ‘left’ or ‘center’.

## 4.4.5. Accounts

class alot.account.Address(user, domain, case_sensitive=False)

  A class that represents an email address.

  This class implements a number of RFC requirements (as explained in detail below) specifically in the comparison of email addresses to each other.

  This class abstracts the requirements of RFC 5321 § 2.4 on the user name portion of the email:

  > local-part of a mailbox MUST BE treated as case sensitive. Therefore, SMTP implementations MUST take care to preserve the case of mailbox local-parts. In particular, for some hosts, the user “smith” is different from the user “Smith”. However, exploiting the case sensitivity of mailbox local-parts impedes interoperability and is discouraged. Mailbox domains follow normal DNS rules and are hence not case sensitive.

  This is complicated by § 2.3.11 of the same RFC:

  > The standard mailbox naming convention is defined to be “local-part@domain”; contemporary usage permits a much broader set of applications than simple “user names”. Consequently, and due to a long history of problems when intermediate hosts have attempted to optimize transport by modifying them, the local-part MUST be interpreted and assigned semantics only by the host specified in the domain part of the address.

  And also the restrictions that RFC 1035 § 3.1 places on the domain name:

  > Name servers and resolvers must compare [domains] in a case-insensitive manner

  Because of RFC 6531 § 3.2, we take special care to ensure that unicode names will work correctly:

  > An SMTP server that announces the SMTPUTF8 extension MUST be prepared to accept a UTF-8 string [RFC3629] in any position in which RFC 5321 specifies that a <mailbox> can appear. Although the characters in the <local-part> are permitted to contain non-ASCII characters, the actual parsing of the <local-part> and the delimiters used are unchanged from the base email specification [RFC5321]

  What this means is that the username can be either case-insensitive or not, but only the receiving SMTP server can know what it’s own rules are. The consensus is that the vast majority (all?) of the SMTP servers in modern usage treat user names as case-insensitve. Therefore we also, by default, treat the user name as case insenstive.

  Parameters:

    - user (str) – The “user name” portion of the address.

    - domain (str) – The domain name portion of the address.

    - case_sensitive (bool) – If False (the default) the user name portion of the address will be compared to the other user name portion without regard to case. If True then it will.

  classmethod from_string(address, case_sensitive=False)

    Alternate constructor for building from a string.

    Parameters:

      - address (str) – An email address in <user>@<domain> form

      - case_sensitive (bool) – passed directly to the constructor argument of the same name.

    Returns:

      An account from the given arguments

    Return type:

      `Account`

class alot.account.Account(address=None, aliases=None, alias_regexp=None, realname=None, gpg_key=None, signature=None, signature_filename=None, signature_as_attachment=False, sent_box=None, sent_tags=None, draft_box=None, draft_tags=None, replied_tags=None, passed_tags=None, abook=None, sign_by_default=False, encrypt_by_default='none', encrypt_to_self=None, message_id_domain=None, case_sensitive_username=False, **_)

  Datastructure that represents an email account. It manages this account’s settings, can send and store mails to maildirs (drafts/send).

  Note

  This is an abstract class that leaves `send_mail()` unspecified. See `SendmailAccount` for a subclass that uses a sendmail command to send out mails.

  matches_address(address)

    returns whether this account knows about an email address

    Parameters:

      address (str) – address to look up

    Return type:

      bool

  abstract async send_mail(mail)

    sends given mail

    Parameters:

      mail (`email.message.Message` or string) – the mail to send

    Raises:

      SendingMailFailed – if sending fails

  store_draft_mail(mail)

    stores mail (`email.message.Message` or str) as draft if `draft_box` is set.

  static store_mail(mbx, mail)

    stores given mail in mailbox. If mailbox is maildir, set the S-flag and return path to newly added mail. Oherwise this will return None.

    Parameters:

      - mbx (`mailbox.Mailbox`) – mailbox to use

      - mail (`email.message.Message` or str) – the mail to store

    Returns:

      absolute path of mail-file for Maildir or None if mail was successfully stored

    Return type:

      str or None

    Raises:

      StoreMailError

  store_sent_mail(mail)

    stores mail (`email.message.Message` or str) in send-store if `sent_box` is set.

  abook = None

    addressbook (`addressbook.AddressBook`) managing this accounts contacts

  address = None

    this accounts main email address

  alias_regexp = ''

    regex matching alternative addresses

  aliases = []

    list of alternative addresses

  encrypt_to_self = None

    encrypt outgoing encrypted emails to this account’s private key

  gpg_key = None

    gpg fingerprint for this account’s private key

  realname = None

    real name used to format from-headers

  signature = None

    signature to append to outgoing mails

  signature_as_attachment = None

    attach signature file instead of appending its content to body text

  signature_filename = None

    filename of signature file in attachment

class alot.account.SendmailAccount(cmd, **kwargs)

  `Account` that pipes a message to a sendmail shell command for sending

  Parameters:

    cmd (str) – sendmail command to use for this account

  async send_mail(mail)

    Pipe the given mail to the configured sendmail command. Display a short message on success or a notification on error. :param mail: the mail to send out :type mail: `email.message.Message` or string :raises: class:SendingMailFailed if sending failes

## 4.4.6. Addressbooks

class alot.addressbook.AddressBook(ignorecase=True)

  can look up email addresses and realnames for contacts.

  Note

  This is an abstract class that leaves `get_contacts()` unspecified. See `AbookAddressBook` and `ExternalAddressbook` for implementations.

  abstract get_contacts()

    list all contacts tuples in this abook as (name, email) tuples

  lookup(query='')

    looks up all contacts where name or address match query

class alot.addressbook.abook.AbookAddressBook(path='~/.abook/addressbook', **kwargs)

  `AddressBook` that parses abook’s config/database files

  Parameters:

    path (str) – path to abook addressbook file

  get_contacts()

    list all contacts tuples in this abook as (name, email) tuples

class alot.addressbook.external.ExternalAddressbook(commandline, regex, reflags=0, external_filtering=True, **kwargs)

  `AddressBook` that parses a shell command’s output

  Parameters:

    - commandline (str) – commandline

    - regex (str) – regular expression used to match contacts in commands output to stdout. Must define subparts named “email” and “name”.

    - reflags (str) – flags to use with regular expression. Use the constants defined in `re` here (re.IGNORECASE etc.) The default (inherited) value is set via the ignorecase config option (defaults to re.IGNORECASE) Setting a value here will replace this.

    - external_filtering (bool) – if True the command is fired with the given search string as parameter and the result is not filtered further. If set to False, the command is fired without additional parameters and the result list is filtered according to the search string.