def apply(self, ui): envelope = ui.current_buffer.envelope # determine account to use sname, 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] if account.draft_box is None: ui.notify('abort: account <%s> has no draft_box set.' % saddr, priority='error') return mail = envelope.construct_mail() # store mail locally # add Date header mail['Date'] = email.Utils.formatdate(localtime=True) path = account.store_draft_mail(crypto.email_as_string(mail)) ui.notify('draft saved successfully') # add mail to index if maildir path available if path is not None: logging.debug('adding new mail to index') ui.dbman.add_message(path, account.draft_tags) ui.apply_command(globals.FlushCommand()) ui.apply_command(commands.globals.BufferCloseCommand())
def apply(self, ui): currentbuffer = ui.current_buffer # needed to close later envelope = currentbuffer.envelope if envelope.sent_time: warning = 'A modified version of ' * envelope.modified_since_sent warning += 'this message has been sent at %s.' % envelope.sent_time warning += ' Do you want to resend?' if (yield ui.choice(warning, cancel='no', msg_position='left')) == 'no': return frm = envelope.get('From') sname, saddr = email.Utils.parseaddr(frm) # determine account to use for sending account = settings.get_account_by_address(saddr) if account == None: if not settings.get_accounts(): ui.notify('no accounts set', priority='error') return else: account = settings.get_accounts()[0] clearme = ui.notify(u'constructing mail (GPG, attachments)\u2026', timeout=-1) try: mail = envelope.construct_mail() except GPGProblem, e: ui.clear_notify([clearme]) ui.notify(e.message, priority='error') return
def apply(self, ui): currentbuffer = ui.current_buffer # needed to close later envelope = currentbuffer.envelope if envelope.sent_time: warning = 'A modified version of ' * envelope.modified_since_sent warning += 'this message has been sent at %s.' % envelope.sent_time warning += ' Do you want to resend?' if (yield ui.choice(warning, cancel='no', msg_position='left')) == 'no': return frm = envelope.get('From') sname, saddr = email.Utils.parseaddr(frm) # determine account to use for sending account = settings.get_account_by_address(saddr) if account == None: if not settings.get_accounts(): ui.notify('no accounts set', priority='error') return else: account = settings.get_accounts()[0] # send clearme = ui.notify('sending..', timeout=-1) mail = envelope.construct_mail() def afterwards(returnvalue): logging.debug('mail sent successfully') ui.clear_notify([clearme]) envelope.sent_time = datetime.datetime.now() ui.apply_command(commands.globals.BufferCloseCommand()) ui.notify('mail sent successfully') # store mail locally # add Date header if 'Date' not in mail: mail['Date'] = email.Utils.formatdate(localtime=True) path = account.store_sent_mail(mail) # add mail to index if maildir path available if path is not None: logging.debug('adding new mail to index') ui.dbman.add_message(path, account.sent_tags) ui.apply_command(globals.FlushCommand()) def errb(failure): ui.clear_notify([clearme]) failure.trap(SendingMailFailed) errmsg = 'failed to send: %s' % failure.value ui.notify(errmsg, priority='error') d = account.send_mail(mail) d.addCallback(afterwards) d.addErrback(errb) logging.debug('added errbacks,callbacks')
def apply(self, ui): currentbuffer = ui.current_buffer # needed to close later envelope = currentbuffer.envelope # This is to warn the user before re-sending # an already sent message in case the envelope buffer # was not closed because it was the last remaining buffer. if envelope.sent_time: warning = 'A modified version of ' * envelope.modified_since_sent warning += 'this message has been sent at %s.' % envelope.sent_time warning += ' Do you want to resend?' if (yield ui.choice(warning, cancel='no', msg_position='left')) == 'no': return # don't do anything if another SendCommand is in the middle of sending # the message and we were triggered accidentally if envelope.sending: msg = 'sending this message already!' logging.debug(msg) return frm = envelope.get('From') sname, saddr = email.Utils.parseaddr(frm) # determine account to use for sending 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] clearme = ui.notify(u'constructing mail (GPG, attachments)\u2026', timeout=-1) try: mail = envelope.construct_mail() mail['Date'] = email.Utils.formatdate(localtime=True) mail = crypto.email_as_string(mail) except GPGProblem, e: ui.clear_notify([clearme]) ui.notify(e.message, priority='error') return
class ComposeCommand(Command): """compose a new email""" def __init__(self, envelope=None, headers={}, template=None, sender=u'', subject=u'', to=[], cc=[], bcc=[], attach=None, omit_signature=False, spawn=None, **kwargs): """ :param envelope: use existing envelope :type envelope: :class:`~alot.db.envelope.Envelope` :param headers: forced header values :type header: doct (str->str) :param template: name of template to parse into the envelope after creation. This should be the name of a file in your template_dir :type template: str :param sender: From-header value :type sender: str :param subject: Subject-header value :type subject: str :param to: To-header value :type to: str :param cc: Cc-header value :type cc: str :param bcc: Bcc-header value :type bcc: str :param attach: Path to files to be attached (globable) :type attach: str :param omit_signature: do not attach/append signature :type omit_signature: bool :param spawn: force spawning of editor in a new terminal :type spawn: bool """ Command.__init__(self, **kwargs) self.envelope = envelope self.template = template self.headers = headers self.sender = sender self.subject = subject self.to = to self.cc = cc self.bcc = bcc self.attach = attach self.omit_signature = omit_signature self.force_spawn = spawn @inlineCallbacks def apply(self, ui): if self.envelope is None: self.envelope = Envelope() if self.template is not None: #get location of tempsdir, containing msg templates tempdir = settings.get('template_dir') tempdir = os.path.expanduser(tempdir) if not tempdir: xdgdir = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')) tempdir = os.path.join(xdgdir, 'alot', 'templates') path = os.path.expanduser(self.template) if not os.path.dirname(path): # use tempsdir if not os.path.isdir(tempdir): ui.notify('no templates directory: %s' % tempdir, priority='error') return path = os.path.join(tempdir, path) if not os.path.isfile(path): ui.notify('could not find template: %s' % path, priority='error') return try: self.envelope.parse_template(open(path).read()) except Exception, e: ui.notify(str(e), priority='error') return # set forced headers for key, value in self.headers.items(): self.envelope.add(key, value) # set forced headers for separate parameters if self.sender: self.envelope.add('From', self.sender) if self.subject: self.envelope.add('Subject', self.subject) if self.to: self.envelope.add('To', ','.join(self.to)) if self.cc: self.envelope.add('Cc', ','.join(self.cc)) if self.bcc: self.envelope.add('Bcc', ','.join(self.bcc)) # get missing From header if not 'From' in self.envelope.headers: accounts = settings.get_accounts() if len(accounts) == 1: a = accounts[0] fromstring = "%s <%s>" % (a.realname, a.address) self.envelope.add('From', fromstring) else: cmpl = AccountCompleter() fromaddress = yield ui.prompt('From', completer=cmpl, tab=1) if fromaddress is None: ui.notify('canceled') return self.envelope.add('From', fromaddress) # add signature if not self.omit_signature: name, addr = email.Utils.parseaddr(self.envelope['From']) account = settings.get_account_by_address(addr) if account is not None: if account.signature: logging.debug('has signature') sig = os.path.expanduser(account.signature) if os.path.isfile(sig): logging.debug('is file') if account.signature_as_attachment: name = account.signature_filename or None self.envelope.attach(sig, filename=name) logging.debug('attached') else: sigcontent = open(sig).read() enc = helper.guess_encoding(sigcontent) mimetype = helper.guess_mimetype(sigcontent) if mimetype.startswith('text'): sigcontent = helper.string_decode( sigcontent, enc) self.envelope.body += '\n' + sigcontent else: ui.notify('could not locate signature: %s' % sig, priority='error') if (yield ui.choice('send without signature?', 'yes', 'no')) == 'no': return # Figure out whether we should GPG sign messages by default # and look up key if so sender = self.envelope.get('From') name, addr = email.Utils.parseaddr(sender) account = settings.get_account_by_address(addr) if account: self.envelope.sign = account.sign_by_default self.envelope.sign_key = account.gpg_key # get missing To header if 'To' not in self.envelope.headers: allbooks = not settings.get('complete_matching_abook_only') logging.debug(allbooks) if account is not None: abooks = settings.get_addressbooks(order=[account], append_remaining=allbooks) logging.debug(abooks) completer = ContactsCompleter(abooks) else: completer = None to = yield ui.prompt('To', completer=completer) if to is None: ui.notify('canceled') return self.envelope.add('To', to.strip(' \t\n,')) if settings.get('ask_subject') and \ not 'Subject' in self.envelope.headers: subject = yield ui.prompt('Subject') logging.debug('SUBJECT: "%s"' % subject) if subject is None: ui.notify('canceled') return self.envelope.add('Subject', subject) if settings.get('compose_ask_tags'): comp = TagsCompleter(ui.dbman) tagsstring = yield ui.prompt('Tags', completer=comp) tags = filter(lambda x: x, tagsstring.split(',')) if tags is None: ui.notify('canceled') return self.envelope.tags = tags if self.attach: for gpath in self.attach: for a in glob.glob(gpath): self.envelope.attach(a) logging.debug('attaching: ' + a) cmd = commands.envelope.EditCommand(envelope=self.envelope, spawn=self.force_spawn, refocus=False) ui.apply_command(cmd)
def apply(self, ui): if self.envelope is None: self.envelope = Envelope() if self.template is not None: # get location of tempsdir, containing msg templates tempdir = settings.get('template_dir') tempdir = os.path.expanduser(tempdir) if not tempdir: xdgdir = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')) tempdir = os.path.join(xdgdir, 'alot', 'templates') path = os.path.expanduser(self.template) if not os.path.dirname(path): # use tempsdir if not os.path.isdir(tempdir): ui.notify('no templates directory: %s' % tempdir, priority='error') return path = os.path.join(tempdir, path) if not os.path.isfile(path): ui.notify('could not find template: %s' % path, priority='error') return try: self.envelope.parse_template(open(path).read()) except Exception as e: ui.notify(str(e), priority='error') return # set forced headers for key, value in self.headers.items(): self.envelope.add(key, value) # set forced headers for separate parameters if self.sender: self.envelope.add('From', self.sender) if self.subject: self.envelope.add('Subject', self.subject) if self.to: self.envelope.add('To', ','.join(self.to)) if self.cc: self.envelope.add('Cc', ','.join(self.cc)) if self.bcc: self.envelope.add('Bcc', ','.join(self.bcc)) # get missing From header if not 'From' in self.envelope.headers: accounts = settings.get_accounts() if len(accounts) == 1: a = accounts[0] fromstring = "%s <%s>" % (a.realname, a.address) self.envelope.add('From', fromstring) else: cmpl = AccountCompleter() fromaddress = yield ui.prompt('From', completer=cmpl, tab=1) if fromaddress is None: raise CommandCanceled() self.envelope.add('From', fromaddress) # add signature if not self.omit_signature: name, addr = email.Utils.parseaddr(self.envelope['From']) account = settings.get_account_by_address(addr) if account is not None: if account.signature: logging.debug('has signature') sig = os.path.expanduser(account.signature) if os.path.isfile(sig): logging.debug('is file') if account.signature_as_attachment: name = account.signature_filename or None self.envelope.attach(sig, filename=name) logging.debug('attached') else: sigcontent = open(sig).read() enc = helper.guess_encoding(sigcontent) mimetype = helper.guess_mimetype(sigcontent) if mimetype.startswith('text'): sigcontent = helper.string_decode(sigcontent, enc) self.envelope.body += '\n' + sigcontent else: ui.notify('could not locate signature: %s' % sig, priority='error') if (yield ui.choice('send without signature?', 'yes', 'no')) == 'no': return # Figure out whether we should GPG sign messages by default # and look up key if so sender = self.envelope.get('From') name, addr = email.Utils.parseaddr(sender) account = settings.get_account_by_address(addr) if account: self.envelope.sign = account.sign_by_default self.envelope.sign_key = account.gpg_key # get missing To header if 'To' not in self.envelope.headers: allbooks = not settings.get('complete_matching_abook_only') logging.debug(allbooks) if account is not None: abooks = settings.get_addressbooks(order=[account], append_remaining=allbooks) logging.debug(abooks) completer = ContactsCompleter(abooks) else: completer = None to = yield ui.prompt('To', completer=completer) if to is None: raise CommandCanceled() self.envelope.add('To', to.strip(' \t\n,')) if settings.get('ask_subject') and \ not 'Subject' in self.envelope.headers: subject = yield ui.prompt('Subject') logging.debug('SUBJECT: "%s"' % subject) if subject is None: raise CommandCanceled() self.envelope.add('Subject', subject) if settings.get('compose_ask_tags'): comp = TagsCompleter(ui.dbman) tagsstring = yield ui.prompt('Tags', completer=comp) tags = filter(lambda x: x, tagsstring.split(',')) if tags is None: raise CommandCanceled() self.envelope.tags = tags if self.attach: for gpath in self.attach: for a in glob.glob(gpath): self.envelope.attach(a) logging.debug('attaching: ' + a) cmd = commands.envelope.EditCommand(envelope=self.envelope, spawn=self.force_spawn, refocus=False) ui.apply_command(cmd)
class SendCommand(Command): """send mail""" def __init__(self, mail=None, envelope=None, **kwargs): """ :param mail: email to send :type email: email.message.Message :param envelope: envelope to use to construct the outgoing mail. This will be ignored in case the mail parameter is set. :type envelope: alot.db.envelope.envelope """ Command.__init__(self, **kwargs) self.mail = mail self.envelope = envelope self.envelope_buffer = None @inlineCallbacks def apply(self, ui): if self.mail is None: if self.envelope is None: # needed to close later self.envelope_buffer = ui.current_buffer self.envelope = self.envelope_buffer.envelope # This is to warn the user before re-sending # an already sent message in case the envelope buffer # was not closed because it was the last remaining buffer. if self.envelope.sent_time: mod = self.envelope.modified_since_sent when = self.envelope.sent_time warning = 'A modified version of ' * mod warning += 'this message has been sent at %s.' % when warning += ' Do you want to resend?' if (yield ui.choice(warning, cancel='no', msg_position='left')) == 'no': return # don't do anything if another SendCommand is in the middle of # sending the message and we were triggered accidentally if self.envelope.sending: msg = 'sending this message already!' logging.debug(msg) return clearme = ui.notify(u'constructing mail (GPG, attachments)\u2026', timeout=-1) try: self.mail = self.envelope.construct_mail() self.mail['Date'] = email.Utils.formatdate(localtime=True) self.mail = email_as_string(self.mail) except GPGProblem, e: ui.clear_notify([clearme]) ui.notify(e.message, priority='error') return ui.clear_notify([clearme]) # determine account to use for sending msg = self.mail if not isinstance(msg, email.message.Message): msg = email.message_from_string(self.mail) sname, 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] # make sure self.mail is a string logging.debug(self.mail.__class__) if isinstance(self.mail, email.message.Message): self.mail = str(self.mail) # define callback def afterwards(returnvalue): initial_tags = [] if self.envelope is not None: self.envelope.sending = False self.envelope.sent_time = datetime.datetime.now() initial_tags = self.envelope.tags logging.debug('mail sent successfully') ui.clear_notify([clearme]) if self.envelope_buffer is not None: cmd = commands.globals.BufferCloseCommand(self.envelope_buffer) ui.apply_command(cmd) ui.notify('mail sent successfully') # store mail locally # This can raise StoreMailError path = account.store_sent_mail(self.mail) # add mail to index if maildir path available if path is not None: logging.debug('adding new mail to index') ui.dbman.add_message(path, account.sent_tags + initial_tags) ui.apply_command(globals.FlushCommand()) # define errback def send_errb(failure): if self.envelope is not None: self.envelope.sending = False ui.clear_notify([clearme]) failure.trap(SendingMailFailed) logging.error(failure.getTraceback()) errmsg = 'failed to send: %s' % failure.value ui.notify(errmsg, priority='error', block=True) def store_errb(failure): failure.trap(StoreMailError) logging.error(failure.getTraceback()) errmsg = 'could not store mail: %s' % failure.value ui.notify(errmsg, priority='error', block=True) # send out clearme = ui.notify('sending..', timeout=-1) if self.envelope is not None: self.envelope.sending = True d = account.send_mail(self.mail) d.addCallback(afterwards) d.addErrback(send_errb) d.addErrback(store_errb)
def apply(self, ui): if self.mail is None: if self.envelope is None: # needed to close later self.envelope_buffer = ui.current_buffer self.envelope = self.envelope_buffer.envelope # This is to warn the user before re-sending # an already sent message in case the envelope buffer # was not closed because it was the last remaining buffer. if self.envelope.sent_time: mod = self.envelope.modified_since_sent when = self.envelope.sent_time warning = 'A modified version of ' * mod warning += 'this message has been sent at %s.' % when warning += ' Do you want to resend?' if (yield ui.choice(warning, cancel='no', msg_position='left')) == 'no': return # don't do anything if another SendCommand is in the middle of # sending the message and we were triggered accidentally if self.envelope.sending: msg = 'sending this message already!' logging.debug(msg) return clearme = ui.notify('constructing mail (GPG, attachments)\u2026', timeout=-1) try: self.mail = self.envelope.construct_mail() self.mail['Date'] = email.Utils.formatdate(localtime=True) self.mail = email_as_string(self.mail) except GPGProblem as e: ui.clear_notify([clearme]) ui.notify(e.message, priority='error') return ui.clear_notify([clearme]) # determine account to use for sending msg = self.mail if not isinstance(msg, email.message.Message): msg = email.message_from_string(self.mail) sname, 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] # make sure self.mail is a string logging.debug(self.mail.__class__) if isinstance(self.mail, email.message.Message): self.mail = str(self.mail) # define callback def afterwards(returnvalue): initial_tags = [] if self.envelope is not None: self.envelope.sending = False self.envelope.sent_time = datetime.datetime.now() initial_tags = self.envelope.tags logging.debug('mail sent successfully') ui.clear_notify([clearme]) if self.envelope_buffer is not None: cmd = commands.globals.BufferCloseCommand(self.envelope_buffer) ui.apply_command(cmd) ui.notify('mail sent successfully') # store mail locally # This can raise StoreMailError path = account.store_sent_mail(self.mail) # add mail to index if maildir path available if path is not None: logging.debug('adding new mail to index') ui.dbman.add_message(path, account.sent_tags + initial_tags) ui.apply_command(globals.FlushCommand()) # define errback def send_errb(failure): if self.envelope is not None: self.envelope.sending = False ui.clear_notify([clearme]) failure.trap(SendingMailFailed) logging.error(failure.getTraceback()) errmsg = 'failed to send: %s' % failure.value ui.notify(errmsg, priority='error', block=True) def store_errb(failure): failure.trap(StoreMailError) logging.error(failure.getTraceback()) errmsg = 'could not store mail: %s' % failure.value ui.notify(errmsg, priority='error', block=True) # send out clearme = ui.notify('sending..', timeout=-1) if self.envelope is not None: self.envelope.sending = True d = account.send_mail(self.mail) d.addCallback(afterwards) d.addErrback(send_errb) d.addErrback(store_errb)
def apply(self, ui): if self.envelope is None: if self.rest: if self.rest.startswith('mailto'): self.envelope = mailto_to_envelope(self.rest) else: self.envelope = Envelope() self.envelope.add('To', self.rest) else: self.envelope = Envelope() if self.template is not None: # get location of tempsdir, containing msg templates tempdir = settings.get('template_dir') tempdir = os.path.expanduser(tempdir) if not tempdir: xdgdir = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')) tempdir = os.path.join(xdgdir, 'alot', 'templates') path = os.path.expanduser(self.template) if not os.path.dirname(path): # use tempsdir if not os.path.isdir(tempdir): ui.notify('no templates directory: %s' % tempdir, priority='error') return path = os.path.join(tempdir, path) if not os.path.isfile(path): ui.notify('could not find template: %s' % path, priority='error') return try: self.envelope.parse_template(open(path).read()) except Exception as e: ui.notify(str(e), priority='error') return # set forced headers for key, value in self.headers.items(): self.envelope.add(key, value) # set forced headers for separate parameters if self.sender: self.envelope.add('From', self.sender) if self.subject: self.envelope.add('Subject', self.subject) if self.to: self.envelope.add('To', ','.join(self.to)) if self.cc: self.envelope.add('Cc', ','.join(self.cc)) if self.bcc: self.envelope.add('Bcc', ','.join(self.bcc)) # get missing From header if not 'From' in self.envelope.headers: accounts = settings.get_accounts() if len(accounts) == 1: a = accounts[0] fromstring = "%s <%s>" % (a.realname, a.address) self.envelope.add('From', fromstring) else: cmpl = AccountCompleter() fromaddress = yield ui.prompt('From', completer=cmpl, tab=1) if fromaddress is None: raise CommandCanceled() self.envelope.add('From', fromaddress) # add signature if not self.omit_signature: name, addr = email.Utils.parseaddr(self.envelope['From']) account = settings.get_account_by_address(addr) if account is not None: if account.signature: logging.debug('has signature') sig = os.path.expanduser(account.signature) if os.path.isfile(sig): logging.debug('is file') if account.signature_as_attachment: name = account.signature_filename or None self.envelope.attach(sig, filename=name) logging.debug('attached') else: sigcontent = open(sig).read() enc = helper.guess_encoding(sigcontent) mimetype = helper.guess_mimetype(sigcontent) if mimetype.startswith('text'): sigcontent = helper.string_decode( sigcontent, enc) self.envelope.body += '\n' + sigcontent else: ui.notify('could not locate signature: %s' % sig, priority='error') if (yield ui.choice('send without signature?', 'yes', 'no')) == 'no': return # Figure out whether we should GPG sign messages by default # and look up key if so sender = self.envelope.get('From') name, addr = email.Utils.parseaddr(sender) account = settings.get_account_by_address(addr) if account: self.envelope.sign = account.sign_by_default self.envelope.sign_key = account.gpg_key # get missing To header if 'To' not in self.envelope.headers: allbooks = not settings.get('complete_matching_abook_only') logging.debug(allbooks) if account is not None: abooks = settings.get_addressbooks(order=[account], append_remaining=allbooks) logging.debug(abooks) completer = ContactsCompleter(abooks) else: completer = None to = yield ui.prompt('To', completer=completer) if to is None: raise CommandCanceled() self.envelope.add('To', to.strip(' \t\n,')) if settings.get('ask_subject') and \ not 'Subject' in self.envelope.headers: subject = yield ui.prompt('Subject') logging.debug('SUBJECT: "%s"' % subject) if subject is None: raise CommandCanceled() self.envelope.add('Subject', subject) if settings.get('compose_ask_tags'): comp = TagsCompleter(ui.dbman) tagsstring = yield ui.prompt('Tags', completer=comp) tags = filter(lambda x: x, tagsstring.split(',')) if tags is None: raise CommandCanceled() self.envelope.tags = tags if self.attach: for gpath in self.attach: for a in glob.glob(gpath): self.envelope.attach(a) logging.debug('attaching: ' + a) cmd = commands.envelope.EditCommand(envelope=self.envelope, spawn=self.force_spawn, refocus=False) ui.apply_command(cmd)
def apply(self, ui): if self.envelope is None: if self.rest: if self.rest.startswith("mailto"): self.envelope = mailto_to_envelope(self.rest) else: self.envelope = Envelope() self.envelope.add("To", self.rest) else: self.envelope = Envelope() if self.template is not None: # get location of tempsdir, containing msg templates tempdir = settings.get("template_dir") tempdir = os.path.expanduser(tempdir) if not tempdir: xdgdir = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")) tempdir = os.path.join(xdgdir, "alot", "templates") path = os.path.expanduser(self.template) if not os.path.dirname(path): # use tempsdir if not os.path.isdir(tempdir): ui.notify("no templates directory: %s" % tempdir, priority="error") return path = os.path.join(tempdir, path) if not os.path.isfile(path): ui.notify("could not find template: %s" % path, priority="error") return try: self.envelope.parse_template(open(path).read()) except Exception as e: ui.notify(str(e), priority="error") return # set forced headers for key, value in self.headers.items(): self.envelope.add(key, value) # set forced headers for separate parameters if self.sender: self.envelope.add("From", self.sender) if self.subject: self.envelope.add("Subject", self.subject) if self.to: self.envelope.add("To", ",".join(self.to)) if self.cc: self.envelope.add("Cc", ",".join(self.cc)) if self.bcc: self.envelope.add("Bcc", ",".join(self.bcc)) # get missing From header if not "From" in self.envelope.headers: accounts = settings.get_accounts() if len(accounts) == 1: a = accounts[0] fromstring = "%s <%s>" % (a.realname, a.address) self.envelope.add("From", fromstring) else: cmpl = AccountCompleter() fromaddress = yield ui.prompt("From", completer=cmpl, tab=1) if fromaddress is None: raise CommandCanceled() self.envelope.add("From", fromaddress) # add signature if not self.omit_signature: name, addr = email.Utils.parseaddr(self.envelope["From"]) account = settings.get_account_by_address(addr) if account is not None: if account.signature: logging.debug("has signature") sig = os.path.expanduser(account.signature) if os.path.isfile(sig): logging.debug("is file") if account.signature_as_attachment: name = account.signature_filename or None self.envelope.attach(sig, filename=name) logging.debug("attached") else: sigcontent = open(sig).read() enc = helper.guess_encoding(sigcontent) mimetype = helper.guess_mimetype(sigcontent) if mimetype.startswith("text"): sigcontent = helper.string_decode(sigcontent, enc) self.envelope.body += "\n" + sigcontent else: ui.notify("could not locate signature: %s" % sig, priority="error") if (yield ui.choice("send without signature?", "yes", "no")) == "no": return # Figure out whether we should GPG sign messages by default # and look up key if so sender = self.envelope.get("From") name, addr = email.Utils.parseaddr(sender) account = settings.get_account_by_address(addr) if account: self.envelope.sign = account.sign_by_default self.envelope.sign_key = account.gpg_key # get missing To header if "To" not in self.envelope.headers: allbooks = not settings.get("complete_matching_abook_only") logging.debug(allbooks) if account is not None: abooks = settings.get_addressbooks(order=[account], append_remaining=allbooks) logging.debug(abooks) completer = ContactsCompleter(abooks) else: completer = None to = yield ui.prompt("To", completer=completer) if to is None: raise CommandCanceled() self.envelope.add("To", to.strip(" \t\n,")) if settings.get("ask_subject") and not "Subject" in self.envelope.headers: subject = yield ui.prompt("Subject") logging.debug('SUBJECT: "%s"' % subject) if subject is None: raise CommandCanceled() self.envelope.add("Subject", subject) if settings.get("compose_ask_tags"): comp = TagsCompleter(ui.dbman) tagsstring = yield ui.prompt("Tags", completer=comp) tags = filter(lambda x: x, tagsstring.split(",")) if tags is None: raise CommandCanceled() self.envelope.tags = tags if self.attach: for gpath in self.attach: for a in glob.glob(gpath): self.envelope.attach(a) logging.debug("attaching: " + a) cmd = commands.envelope.EditCommand(envelope=self.envelope, spawn=self.force_spawn, refocus=False) ui.apply_command(cmd)