summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alot/commands/envelope.py47
-rw-r--r--alot/commands/utils.py1
-rw-r--r--alot/settings/errors.py5
-rw-r--r--alot/settings/manager.py26
-rw-r--r--tests/settings/manager_test.py53
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)