diff options
-rw-r--r-- | alot/commands/envelope.py | 47 | ||||
-rw-r--r-- | alot/commands/utils.py | 1 | ||||
-rw-r--r-- | alot/settings/errors.py | 5 | ||||
-rw-r--r-- | alot/settings/manager.py | 26 | ||||
-rw-r--r-- | tests/settings/manager_test.py | 53 |
5 files changed, 98 insertions, 34 deletions
diff --git a/alot/commands/envelope.py b/alot/commands/envelope.py index 0e479f87..4a1482b6 100644 --- a/alot/commands/envelope.py +++ b/alot/commands/envelope.py @@ -16,7 +16,7 @@ from twisted.internet.defer import inlineCallbacks from . import Command, registerCommand from . import globals -from .utils import set_encrypt +from . import utils from .. import buffers from .. import commands from .. import crypto @@ -26,6 +26,7 @@ from ..errors import GPGProblem from ..helper import email_as_string from ..helper import string_decode from ..settings import settings +from ..settings.errors import NoMatchingAccount from ..utils import argparse as cargparse @@ -114,18 +115,17 @@ class SaveCommand(Command): envelope = ui.current_buffer.envelope # determine account to use - _, saddr = email.Utils.parseaddr(envelope.get('From')) - account = settings.get_account_by_address(saddr) - if account is None: - if not settings.get_accounts(): - ui.notify('no accounts set.', priority='error') - return - else: - account = settings.get_accounts()[0] + try: + account = settings.get_account_by_address( + envelope.get('From'), return_default=True) + except NoMatchingAccount: + ui.notify('no accounts set.', priority='error') + return if account.draft_box is None: - ui.notify('abort: account <%s> has no draft_box set.' % saddr, - priority='error') + ui.notify( + 'abort: account <%s> has no draft_box set.' % envelope.get('From'), + priority='error') return mail = envelope.construct_mail() @@ -214,14 +214,12 @@ class SendCommand(Command): msg = self.mail if not isinstance(msg, email.message.Message): msg = email.message_from_string(self.mail) - _, saddr = email.Utils.parseaddr(msg.get('From', '')) - account = settings.get_account_by_address(saddr) - if account is None: - if not settings.get_accounts(): - ui.notify('no accounts set', priority='error') - return - else: - account = settings.get_accounts()[0] + try: + account = settings.get_account_by_address( + msg.get('From', ''), return_default=True) + except NoMatchingAccount: + ui.notify('no accounts set', priority='error') + return # make sure self.mail is a string logging.debug(self.mail.__class__) @@ -494,14 +492,15 @@ class SignCommand(Command): ui.notify(e.message, priority='error') return else: - _, addr = email.utils.parseaddr(envelope.headers['From'][0]) - acc = settings.get_account_by_address(addr) - if not acc: + try: + acc = settings.get_account_by_address( + envelope.headers['From'][0]) + except NoMatchingAccount: envelope.sign = False ui.notify('Unable to find a matching account', priority='error') return - elif not acc.gpg_key: + if not acc.gpg_key: envelope.sign = False ui.notify('Account for {} has no gpg key'.format(acc.address), priority='error') @@ -575,7 +574,7 @@ class EncryptCommand(Command): elif self.action == 'toggleencrypt': encrypt = not envelope.encrypt if encrypt: - yield set_encrypt(ui, envelope, signed_only=self.trusted) + yield utils.set_encrypt(ui, envelope, signed_only=self.trusted) envelope.encrypt = encrypt if not envelope.encrypt: # This is an extra conditional as it can even happen if encrypt is diff --git a/alot/commands/utils.py b/alot/commands/utils.py index f54d4f09..f8e5067d 100644 --- a/alot/commands/utils.py +++ b/alot/commands/utils.py @@ -5,6 +5,7 @@ from __future__ import absolute_import import re import logging + from twisted.internet.defer import inlineCallbacks, returnValue from ..errors import GPGProblem, GPGCode diff --git a/alot/settings/errors.py b/alot/settings/errors.py index 606f78e1..baf794ff 100644 --- a/alot/settings/errors.py +++ b/alot/settings/errors.py @@ -6,3 +6,8 @@ class ConfigError(Exception): """could not parse user config""" pass + + +class NoMatchingAccount(ConfigError): + """No account matching requirements found.""" + pass diff --git a/alot/settings/manager.py b/alot/settings/manager.py index 5e86ecec..5aec9078 100644 --- a/alot/settings/manager.py +++ b/alot/settings/manager.py @@ -16,7 +16,7 @@ from ..addressbook.external import ExternalAddressbook from ..helper import pretty_datetime, string_decode from ..utils import configobj as checks -from .errors import ConfigError +from .errors import ConfigError, NoMatchingAccount from .utils import read_config from .utils import resolve_att from .theme import Theme @@ -414,19 +414,27 @@ class SettingsManager(object): """ return self._accounts - def get_account_by_address(self, address): - """ - returns :class:`Account` for a given email address (str) + def get_account_by_address(self, address, return_default=False): + """returns :class:`Account` for a given email address (str) - :param address: address to look up - :type address: string - :rtype: :class:`Account` or None + :param str address: address to look up + :param bool return_default: If True and no address can be found, then + the default account wil be returned + :rtype: :class:`Account` + :raises ~alot.settings.errors.NoMatchingAccount: If no account can be + found. Thsi includes if return_default is True and there are no + accounts defined. """ - for myad in self.get_addresses(): if myad == address: return self._accountmap[myad] - return None + if return_default: + try: + return self.get_accounts()[0] + except IndexError: + # Fall through + pass + raise NoMatchingAccount def get_main_addresses(self): """returns addresses of known accounts without its aliases""" diff --git a/tests/settings/manager_test.py b/tests/settings/manager_test.py index 17a228a2..3201ad41 100644 --- a/tests/settings/manager_test.py +++ b/tests/settings/manager_test.py @@ -12,7 +12,9 @@ import textwrap import unittest from alot.settings.manager import SettingsManager -from alot.settings.errors import ConfigError +from alot.settings.errors import ConfigError, NoMatchingAccount + +from .. import utilities class TestSettingsManager(unittest.TestCase): @@ -60,3 +62,52 @@ class TestSettingsManager(unittest.TestCase): manager.reload() actual = manager.get_notmuch_setting('maildir', 'synchronize_flags') self.assertTrue(actual) + + +class TestSettingsManagerGetAccountByAddress(utilities.TestCaseClassCleanup): + """Test the get_account_by_address helper.""" + + @classmethod + def setUpClass(cls): + config = textwrap.dedent("""\ + [accounts] + [[default]] + realname = That Guy + address = that_guy@example.com + sendmail_commnd = /bin/true + + [[other]] + realname = A Dude + address = a_dude@example.com + sendmail_command = /bin/true + """) + + # Allow settings.reload to work by not deleting the file until the end + with tempfile.NamedTemporaryFile(delete=False) as f: + f.write(config) + cls.addClassCleanup(os.unlink, f.name) + + # Replace the actual settings object with our own using mock, but + # ensure it's put back afterwards + cls.manager = SettingsManager(alot_rc=f.name) + + def test_exists_addr(self): + acc = self.manager.get_account_by_address('that_guy@example.com') + self.assertEqual(acc.realname, 'That Guy') + + def test_doesnt_exist_return_default(self): + acc = self.manager.get_account_by_address('doesntexist@example.com', + return_default=True) + self.assertEqual(acc.realname, 'That Guy') + + def test_doesnt_exist_raise(self): + with self.assertRaises(NoMatchingAccount): + self.manager.get_account_by_address('doesntexist@example.com') + + def test_doesnt_exist_no_default(self): + with tempfile.NamedTemporaryFile() as f: + f.write('') + settings = SettingsManager(alot_rc=f.name) + with self.assertRaises(NoMatchingAccount): + settings.get_account_by_address('that_guy@example.com', + return_default=True) |