diff --git a/alot/commands/envelope.py b/alot/commands/envelope.py index 9293d66f6..ed6602f76 100644 --- a/alot/commands/envelope.py +++ b/alot/commands/envelope.py @@ -112,6 +112,48 @@ async def apply(self, ui): await ui.apply_command(globals.PromptCommand(cmdstring)) +async def delete_previous_draft(envelope, ui): + try: + if envelope.previous_draft is None: + return + except AttributeError: + return + if settings.get('envelope_always_delete_old_drafts'): + del_old_draft = True + else: + msg = 'Do you want to delete the old draft?' + del_old_draft = (await ui.choice(msg, cancel='no', + msg_position='left')) + del_old_draft = (del_old_draft == 'yes') + if del_old_draft: + try: + message_path = envelope.previous_draft.get_filename() + except Exception as e: + logging.error(e) + ui.notify('could not get draft path:\n%s' % e, + priority='error', block=True) + return + + try: + ui.dbman.remove_message(envelope.previous_draft) + await ui.apply_command(globals.FlushCommand()) + except DatabaseError as e: + logging.error(e) + ui.notify('could not remove draft from db:\n%s' % e, + priority='error', block=True) + return + + try: + os.unlink(message_path) + except OSError as e: + logging.error(e) + ui.notify('could not delete draft file:\n%s' % e, + priority='error', block=True) + return + + envelope.previous_draft = None + + @registerCommand(MODE, 'save') class SaveCommand(Command): """save draft""" @@ -138,23 +180,26 @@ async def apply(self, ui): path = account.store_draft_mail( mail.as_string(policy=email.policy.SMTP, maxheaderlen=sys.maxsize)) - msg = 'draft saved successfully' - # add mail to index if maildir path available if path is not None: - ui.notify(msg + ' to %s' % path) + ui.notify('draft saved successfully to %s' % path) logging.debug('adding new mail to index') try: ui.dbman.add_message(path, account.draft_tags + envelope.tags) await ui.apply_command(globals.FlushCommand()) - await ui.apply_command(commands.globals.BufferCloseCommand()) except DatabaseError as e: logging.error(str(e)) ui.notify('could not index message:\n%s' % str(e), priority='error', block=True) - else: - await ui.apply_command(commands.globals.BufferCloseCommand()) + return + + await delete_previous_draft(envelope, ui) + + # strip the outside '<' and '>' characters from the id + mid = mail['Message-ID'][1:-1] + envelope.previous_draft = ui.dbman.get_message(mid) + await ui.apply_command(commands.globals.BufferCloseCommand()) @registerCommand(MODE, 'send') @@ -315,6 +360,8 @@ async def apply(self, ui): ui.dbman.add_message(path, account.sent_tags + initial_tags) await ui.apply_command(globals.FlushCommand()) + await delete_previous_draft(self.envelope, ui) + @registerCommand(MODE, 'edit', arguments=[ (['--spawn'], {'action': cargparse.BooleanAction, 'default': None, diff --git a/alot/commands/thread.py b/alot/commands/thread.py index ad3839991..cd28a2f1a 100644 --- a/alot/commands/thread.py +++ b/alot/commands/thread.py @@ -465,9 +465,15 @@ async def apply(self, ui): tags.difference_update({'inbox', 'sent', 'draft', 'killed', 'replied', 'signed', 'encrypted', 'unread', 'attachment'}) tags = list(tags) + + draft = None + if 'draft' in self.message.get_tags(): + draft = self.message + # set body text mailcontent = self.message.get_body_text() - envelope = Envelope(bodytext=mailcontent, tags=tags) + envelope = Envelope(bodytext=mailcontent, tags=tags, + previous_draft=draft) # copy selected headers to_copy = ['Subject', 'From', 'To', 'Cc', 'Bcc', 'In-Reply-To', diff --git a/alot/db/envelope.py b/alot/db/envelope.py index 1e850855d..d69b262f6 100644 --- a/alot/db/envelope.py +++ b/alot/db/envelope.py @@ -54,7 +54,7 @@ class Envelope: def __init__( self, template=None, bodytext=None, headers=None, attachments=None, sign=False, sign_key=None, encrypt=False, tags=None, replied=None, - passed=None, account=None): + passed=None, account=None, previous_draft=None): """ :param template: if not None, the envelope will be initialised by :meth:`parsing ` this string before @@ -92,6 +92,7 @@ def __init__( self.tags = tags or [] # tags to add after successful sendout self.replied = replied # message being replied to self.passed = passed # message being passed on + self.previous_draft = previous_draft self.sent_time = None self.modified_since_sent = False self.sending = False # semaphore to avoid accidental double sendout diff --git a/alot/db/manager.py b/alot/db/manager.py index 6d950ef74..d3f3c9585 100644 --- a/alot/db/manager.py +++ b/alot/db/manager.py @@ -292,7 +292,7 @@ def _with_notmuch_message(self, mid): mode = Database.MODE.READ_ONLY with Database(path=self.path, mode=mode) as db: try: - yield db.find_message(mid) + yield db.find(mid) except: errmsg = 'no message with id %s exists!' % mid raise NonexistantObjectError(errmsg) diff --git a/alot/defaults/alot.rc.spec b/alot/defaults/alot.rc.spec index 07432846f..1b3125e20 100644 --- a/alot/defaults/alot.rc.spec +++ b/alot/defaults/alot.rc.spec @@ -268,6 +268,10 @@ auto_replyto_mailinglist = boolean(default=False) # prefer plaintext alternatives over html content in multipart/alternative prefer_plaintext = boolean(default=False) +# When sending an email or saving a new draft, always delete the old draft. +# If set to False, the user will be prompted every time. +envelope_always_delete_old_drafts = boolean(default=False) + # always edit the given body text alternative when editing outgoing messages in envelope mode. # alternative, and not the html source, even if that is currently displayed. # If unset, html content will be edited unless the current envelope shows the plaintext alternative.