Пример #1
0
    def __init__(self, path, spawn=None, thread=None, **kwargs):
        """
        :param path: path to the file to be edited
        :type path: str
        :param spawn: force running edtor in a new terminal
        :type spawn: bool
        :param thread: run asynchronously, don't block alot
        :type thread: bool
        """
        self.spawn = spawn
        if spawn is None:
            self.spawn = settings.get('editor_spawn')
        self.thread = thread
        if thread is None:
            self.thread = settings.get('editor_in_thread')

        editor_cmdstring = None
        if os.path.isfile('/usr/bin/editor'):
            editor_cmdstring = '/usr/bin/editor'
        editor_cmdstring = os.environ.get('EDITOR', editor_cmdstring)
        editor_cmdstring = settings.get('editor_cmd') or editor_cmdstring
        logging.debug('using editor_cmd: %s' % editor_cmdstring)

        self.cmdlist = None
        if '%s' in editor_cmdstring:
            cmdstring = editor_cmdstring.replace('%s',
                                                 helper.shell_quote(path))
            self.cmdlist = split_commandstring(cmdstring)
        else:
            self.cmdlist = split_commandstring(editor_cmdstring) + [path]

        logging.debug({'spawn: ': self.spawn, 'in_thread': self.thread})
        ExternalCommand.__init__(self, self.cmdlist,
                                 spawn=self.spawn, thread=self.thread,
                                 **kwargs)
Пример #2
0
    def __init__(self, path, spawn=None, thread=None, **kwargs):
        """
        :param path: path to the file to be edited
        :type path: str
        :param spawn: force running edtor in a new terminal
        :type spawn: bool
        :param thread: run asynchronously, don't block alot
        :type thread: bool
        """
        self.spawn = spawn
        if spawn is None:
            self.spawn = settings.get('editor_spawn')
        self.thread = thread
        if thread is None:
            self.thread = settings.get('editor_in_thread')

        editor_cmdstring = None
        if os.path.isfile('/usr/bin/editor'):
            editor_cmdstring = '/usr/bin/editor'
        editor_cmdstring = os.environ.get('EDITOR', editor_cmdstring)
        editor_cmdstring = settings.get('editor_cmd') or editor_cmdstring
        logging.debug('using editor_cmd: %s' % editor_cmdstring)

        self.cmdlist = None
        if '%s' in editor_cmdstring:
            cmdstring = editor_cmdstring.replace('%s',
                                                 helper.shell_quote(path))
            self.cmdlist = split_commandstring(cmdstring)
        else:
            self.cmdlist = split_commandstring(editor_cmdstring) + [path]

        logging.debug({'spawn: ': self.spawn, 'in_thread': self.thread})
        ExternalCommand.__init__(self, self.cmdlist,
                                 spawn=self.spawn, thread=self.thread,
                                 **kwargs)
Пример #3
0
    def __init__(self,
                 cmd,
                 stdin=None,
                 shell=False,
                 spawn=False,
                 refocus=True,
                 thread=False,
                 on_success=None,
                 **kwargs):
        """
        :param cmd: the command to call
        :type cmd: list or str
        :param stdin: input to pipe to the process
        :type stdin: file or str
        :param spawn: run command in a new terminal
        :type spawn: bool
        :param shell: let shell interpret command string
        :type shell: bool
        :param thread: run asynchronously, don't block alot
        :type thread: bool
        :param refocus: refocus calling buffer after cmd termination
        :type refocus: bool
        :param on_success: code to execute after command successfully exited
        :type on_success: callable
        """
        logging.debug({'spawn': spawn})
        # make sure cmd is a list of str
        if isinstance(cmd, unicode):
            # convert cmdstring to list: in case shell==True,
            # Popen passes only the first item in the list to $SHELL
            cmd = [cmd] if shell else split_commandstring(cmd)

        # determine complete command list to pass
        touchhook = settings.get_hook('touch_external_cmdlist')
        # filter cmd, shell and thread through hook if defined
        if touchhook is not None:
            logging.debug('calling hook: touch_external_cmdlist')
            res = touchhook(cmd, shell=shell, spawn=spawn, thread=thread)
            logging.debug('got: %s' % res)
            cmd, shell, self.in_thread = res
        # otherwise if spawn requested and X11 is running
        elif spawn:
            if 'DISPLAY' in os.environ:
                term_cmd = settings.get('terminal_cmd', '')
                logging.info('spawn in terminal: %s' % term_cmd)
                termcmdlist = split_commandstring(term_cmd)
                cmd = termcmdlist + cmd
            else:
                thread = False

        self.cmdlist = cmd
        self.stdin = stdin
        self.shell = shell
        self.refocus = refocus
        self.in_thread = thread
        self.on_success = on_success
        Command.__init__(self, **kwargs)
Пример #4
0
    def __init__(
        self, cmd, stdin=None, shell=False, spawn=False, refocus=True, thread=False, on_success=None, **kwargs
    ):
        """
        :param cmd: the command to call
        :type cmd: list or str
        :param stdin: input to pipe to the process
        :type stdin: file or str
        :param spawn: run command in a new terminal
        :type spawn: bool
        :param shell: let shell interpret command string
        :type shell: bool
        :param thread: run asynchronously, don't block alot
        :type thread: bool
        :param refocus: refocus calling buffer after cmd termination
        :type refocus: bool
        :param on_success: code to execute after command successfully exited
        :type on_success: callable
        """
        logging.debug({"spawn": spawn})
        # make sure cmd is a list of str
        if isinstance(cmd, unicode):
            # convert cmdstring to list: in case shell==True,
            # Popen passes only the first item in the list to $SHELL
            cmd = [cmd] if shell else split_commandstring(cmd)

        # determine complete command list to pass
        touchhook = settings.get_hook("touch_external_cmdlist")
        # filter cmd, shell and thread through hook if defined
        if touchhook is not None:
            logging.debug("calling hook: touch_external_cmdlist")
            res = touchhook(cmd, shell=shell, spawn=spawn, thread=thread)
            logging.debug("got: %s" % res)
            cmd, shell, self.in_thread = res
        # otherwise if spawn requested and X11 is running
        elif spawn:
            if "DISPLAY" in os.environ:
                term_cmd = settings.get("terminal_cmd", "")
                logging.info("spawn in terminal: %s" % term_cmd)
                termcmdlist = split_commandstring(term_cmd)
                cmd = termcmdlist + cmd
            else:
                thread = False

        self.cmdlist = cmd
        self.stdin = stdin
        self.shell = shell
        self.refocus = refocus
        self.in_thread = thread
        self.on_success = on_success
        Command.__init__(self, **kwargs)
Пример #5
0
def commandfactory(cmdline, mode='global'):
    """
    parses `cmdline` and constructs a :class:`Command`.

    :param cmdline: command line to interpret
    :type cmdline: str
    :param mode: mode identifier
    :type mode: str

    >>> cmd = alot.commands.commandfactory('save --all /foo', mode='thread')
    >>> cmd
    <alot.commands.thread.SaveAttachmentCommand object at 0x272cf10
    >>> cmd.all
    True
    >>> cmd.path
    u'/foo'
    """
    # split commandname and parameters
    if not cmdline:
        return None
    logging.debug('mode:%s got commandline "%s"' % (mode, cmdline))
    # allow to shellescape without a space after '!'
    if cmdline.startswith('!'):
        cmdline = 'shellescape \'%s\'' % cmdline[1:]
    cmdline = re.sub(r'"(.*)"', r'"\\"\1\\""', cmdline)
    try:
        args = split_commandstring(cmdline)
    except ValueError, e:
        raise CommandParseError(e.message)
Пример #6
0
def commandfactory(cmdline, mode='global'):
    """
    parses `cmdline` and constructs a :class:`Command`.

    :param cmdline: command line to interpret
    :type cmdline: str
    :param mode: mode identifier
    :type mode: str

    >>> cmd = alot.commands.commandfactory('save --all /foo', mode='thread')
    >>> cmd
    <alot.commands.thread.SaveAttachmentCommand object at 0x272cf10
    >>> cmd.all
    True
    >>> cmd.path
    u'/foo'
    """
    # split commandname and parameters
    if not cmdline:
        return None
    logging.debug('mode:%s got commandline "%s"' % (mode, cmdline))
    # allow to shellescape without a space after '!'
    if cmdline.startswith('!'):
        cmdline = 'shellescape \'%s\'' % cmdline[1:]
    cmdline = re.sub(r'"(.*)"', r'"\\"\1\\""', cmdline)
    try:
        args = split_commandstring(cmdline)
    except ValueError, e:
        raise CommandParseError(e.message)
Пример #7
0
def commandfactory(cmdline, mode='global'):
    """
    parses `cmdline` and constructs a :class:`Command`.

    :param cmdline: command line to interpret
    :type cmdline: str
    :param mode: mode identifier
    :type mode: str

    >>> cmd = alot.commands.commandfactory('save --all /foo', mode='thread')
    >>> cmd
    <alot.commands.thread.SaveAttachmentCommand object at 0x272cf10
    >>> cmd.all
    True
    >>> cmd.path
    u'/foo'
    """
    # split commandname and parameters
    if not cmdline:
        return None
    logging.debug('mode:%s got commandline "%s"' % (mode, cmdline))
    # allow to shellescape without a space after '!'
    if cmdline.startswith('!'):
        cmdline = 'shellescape \'%s\'' % cmdline[1:]
    cmdline = re.sub(r'"(.*)"', r'"\\"\1\\""', cmdline)
    try:
        args = split_commandstring(cmdline)
    except ValueError as e:
        raise CommandParseError(e.message)
    args = map(lambda x: alot.helper.string_decode(x, 'utf-8'), args)
    logging.debug('ARGS: %s' % args)
    cmdname = args[0]
    args = args[1:]

    # unfold aliases
    # TODO: read from settingsmanager

    # get class, argparser and forced parameter
    (cmdclass, parser, forcedparms) = lookup_command(cmdname, mode)
    if cmdclass is None:
        msg = 'unknown command: %s' % cmdname
        logging.debug(msg)
        raise CommandParseError(msg)

    parms = vars(parser.parse_args(args))
    parms.update(forcedparms)

    logging.debug('cmd parms %s' % parms)

    # create Command
    cmd = cmdclass(**parms)

    # set pre and post command hooks
    get_hook = settings.get_hook
    cmd.prehook = get_hook('pre_%s_%s' % (mode, cmdname)) or \
        get_hook('pre_global_%s' % cmdname)
    cmd.posthook = get_hook('post_%s_%s' % (mode, cmdname)) or \
        get_hook('post_global_%s' % cmdname)

    return cmd
Пример #8
0
def commandfactory(cmdline, mode='global'):
    """
    parses `cmdline` and constructs a :class:`Command`.

    :param cmdline: command line to interpret
    :type cmdline: str
    :param mode: mode identifier
    :type mode: str

    >>> cmd = alot.commands.commandfactory('save --all /foo', mode='thread')
    >>> cmd
    <alot.commands.thread.SaveAttachmentCommand object at 0x272cf10
    >>> cmd.all
    True
    >>> cmd.path
    u'/foo'
    """
    # split commandname and parameters
    if not cmdline:
        return None
    logging.debug('mode:%s got commandline "%s"' % (mode, cmdline))
    # allow to shellescape without a space after '!'
    if cmdline.startswith('!'):
        cmdline = 'shellescape \'%s\'' % cmdline[1:]
    cmdline = re.sub(r'"(.*)"', r'"\\"\1\\""', cmdline)
    try:
        args = split_commandstring(cmdline)
    except ValueError as e:
        raise CommandParseError(e.message)
    args = map(lambda x: alot.helper.string_decode(x, 'utf-8'), args)
    logging.debug('ARGS: %s' % args)
    cmdname = args[0]
    args = args[1:]

    # unfold aliases
    # TODO: read from settingsmanager

    # get class, argparser and forced parameter
    (cmdclass, parser, forcedparms) = lookup_command(cmdname, mode)
    if cmdclass is None:
        msg = 'unknown command: %s' % cmdname
        logging.debug(msg)
        raise CommandParseError(msg)

    parms = vars(parser.parse_args(args))
    parms.update(forcedparms)

    logging.debug('cmd parms %s' % parms)

    # create Command
    cmd = cmdclass(**parms)

    # set pre and post command hooks
    get_hook = settings.get_hook
    cmd.prehook = get_hook('pre_%s_%s' % (mode, cmdname)) or \
        get_hook('pre_global_%s' % cmdname)
    cmd.posthook = get_hook('post_%s_%s' % (mode, cmdname)) or \
        get_hook('post_global_%s' % cmdname)

    return cmd
Пример #9
0
    def apply(self, ui):
        logging.info('open attachment')
        mimetype = self.attachment.get_content_type()

        # returns pair of preliminary command string and entry dict containing
        # more info. We only use the dict and construct the command ourselves
        _, entry = settings.mailcap_find_match(mimetype)
        if entry:
            afterwards = None  # callback, will rm tempfile if used
            handler_stdin = None
            tempfile_name = None
            handler_raw_commandstring = entry['view']
            # read parameter
            part = self.attachment.get_mime_representation()
            parms = tuple(map('='.join, part.get_params()))

            # in case the mailcap defined command contains no '%s',
            # we pipe the files content to the handling command via stdin
            if '%s' in handler_raw_commandstring:
                nametemplate = entry.get('nametemplate', '%s')
                prefix, suffix = parse_mailcap_nametemplate(nametemplate)

                fn_hook = settings.get_hook('sanitize_attachment_filename')
                if fn_hook:
                    # get filename
                    filename = self.attachment.get_filename()
                    prefix, suffix = fn_hook(filename, prefix, suffix)

                tmpfile = tempfile.NamedTemporaryFile(delete=False,
                                                      prefix=prefix,
                                                      suffix=suffix)

                tempfile_name = tmpfile.name
                self.attachment.write(tmpfile)
                tmpfile.close()

                def afterwards():
                    os.unlink(tempfile_name)
            else:
                handler_stdin = StringIO()
                self.attachment.write(handler_stdin)

            # create handler command list
            handler_cmd = mailcap.subst(handler_raw_commandstring, mimetype,
                                        filename=tempfile_name, plist=parms)

            handler_cmdlist = split_commandstring(handler_cmd)

            # 'needsterminal' makes handler overtake the terminal
            nt = entry.get('needsterminal', None)
            overtakes = (nt is None)

            ui.apply_command(ExternalCommand(handler_cmdlist,
                                             stdin=handler_stdin,
                                             on_success=afterwards,
                                             thread=overtakes))
        else:
            ui.notify('unknown mime type')
Пример #10
0
 def __init__(self,
              cmd,
              all=False,
              separately=False,
              background=False,
              shell=False,
              notify_stdout=False,
              format='raw',
              add_tags=False,
              noop_msg='no command specified',
              confirm_msg='',
              done_msg='done',
              **kwargs):
     """
     :param cmd: shellcommand to open
     :type cmd: str or list of str
     :param all: pipe all, not only selected message
     :type all: bool
     :param separately: call command once per message
     :type separately: bool
     :param background: do not suspend the interface
     :type background: bool
     :param notify_stdout: display command\'s stdout as notification message
     :type notify_stdout: bool
     :param shell: let the shell interpret the command
     :type shell: bool
     :param format: what to pipe to the processes stdin. one of:
                    'raw': message content as is,
                    'decoded': message content, decoded quoted printable,
                    'id': message ids, separated by newlines,
                    'filepath': paths to message files on disk
     :type format: str
     :param add_tags: add 'Tags' header to the message
     :type add_tags: bool
     :param noop_msg: error notification to show if `cmd` is empty
     :type noop_msg: str
     :param confirm_msg: confirmation question to ask (continues directly if
                         unset)
     :type confirm_msg: str
     :param done_msg: notification message to show upon success
     :type done_msg: str
     """
     Command.__init__(self, **kwargs)
     if isinstance(cmd, unicode):
         cmd = split_commandstring(cmd)
     self.cmd = cmd
     self.whole_thread = all
     self.separately = separately
     self.background = background
     self.shell = shell
     self.notify_stdout = notify_stdout
     self.output_format = format
     self.add_tags = add_tags
     self.noop_msg = noop_msg
     self.confirm_msg = confirm_msg
     self.done_msg = done_msg
Пример #11
0
 def lookup(self, prefix):
     cmdlist = split_commandstring(self.command)
     resultstring, errmsg, retval = call_cmd(cmdlist + [prefix])
     if not resultstring:
         return []
     lines = resultstring.splitlines()
     res = []
     for l in lines:
         m = re.match(self.match, l)
         if m:
             info = m.groupdict()
             email = info['email'].strip()
             name = info['name']
             res.append((name, email))
     return res
Пример #12
0
 def lookup(self, prefix):
     cmdlist = split_commandstring(self.command)
     resultstring, errmsg, retval = call_cmd(cmdlist + [prefix])
     if not resultstring:
         return []
     lines = resultstring.splitlines()
     res = []
     for l in lines:
         m = re.match(self.match, l, self.reflags)
         if m:
             info = m.groupdict()
             email = info['email'].strip()
             name = info['name']
             res.append((name, email))
     return res
Пример #13
0
    def __init__(self, cmd, all=False, separately=False, background=False,
                 shell=False, notify_stdout=False, format='raw',
                 add_tags=False, noop_msg='no command specified',
                 confirm_msg='', done_msg=None, **kwargs):
        """
        :param cmd: shellcommand to open
        :type cmd: str or list of str
        :param all: pipe all, not only selected message
        :type all: bool
        :param separately: call command once per message
        :type separately: bool
        :param background: do not suspend the interface
        :type background: bool
        :param notify_stdout: display command\'s stdout as notification message
        :type notify_stdout: bool
        :param shell: let the shell interpret the command
        :type shell: bool

                       'raw': message content as is,
                       'decoded': message content, decoded quoted printable,
                       'id': message ids, separated by newlines,
                       'filepath': paths to message files on disk
        :type format: str
        :param add_tags: add 'Tags' header to the message
        :type add_tags: bool
        :param noop_msg: error notification to show if `cmd` is empty
        :type noop_msg: str
        :param confirm_msg: confirmation question to ask (continues directly if
                            unset)
        :type confirm_msg: str
        :param done_msg: notification message to show upon success
        :type done_msg: str
        """
        Command.__init__(self, **kwargs)
        if isinstance(cmd, unicode):
            cmd = split_commandstring(cmd)
        self.cmd = cmd
        self.whole_thread = all
        self.separately = separately
        self.background = background
        self.shell = shell
        self.notify_stdout = notify_stdout
        self.output_format = format
        self.add_tags = add_tags
        self.noop_msg = noop_msg
        self.confirm_msg = confirm_msg
        self.done_msg = done_msg
Пример #14
0
    def send_mail(self, mail):
        cmdlist = split_commandstring(self.cmd)

        def cb(out):
            logging.info('sent mail successfully')
            logging.info(out)

        def errb(failure):
            termobj = failure.value
            errmsg = '%s\nsendmail_cmd set to: %s' % (str(termobj), self.cmd)
            logging.error(errmsg)
            logging.error(failure.getTraceback())
            logging.error(failure.value.stderr)
            raise SendingMailFailed(errmsg)

        d = call_cmd_async(cmdlist, stdin=mail)
        d.addCallback(cb)
        d.addErrback(errb)
        return d
Пример #15
0
    def send_mail(self, mail):
        cmdlist = split_commandstring(self.cmd)

        def cb(out):
            logging.info("sent mail successfully")
            logging.info(out)

        def errb(failure):
            termobj = failure.value
            errmsg = "%s failed with code %s:\n%s" % (self.cmd, termobj.exitCode, str(failure.value))
            logging.error(errmsg)
            logging.error(failure.getTraceback())
            logging.error(failure.value.stderr)
            raise SendingMailFailed(errmsg)

        d = call_cmd_async(cmdlist, stdin=mail)
        d.addCallback(cb)
        d.addErrback(errb)
        return d
Пример #16
0
    def send_mail(self, mail):
        mail['Date'] = email.utils.formatdate(time.time(), True)
        cmdlist = split_commandstring(self.cmd)

        def cb(out):
            logging.info('sent mail successfully')
            logging.info(out)

        def errb(failure):
            termobj = failure.value
            errmsg = '%s\nsendmail_cmd set to: %s' % (str(termobj), self.cmd)
            logging.error(errmsg)
            logging.error(failure.getTraceback())
            logging.error(failure.value.stderr)
            raise SendingMailFailed(errmsg)

        d = call_cmd_async(cmdlist, stdin=crypto.email_as_string(mail))
        d.addCallback(cb)
        d.addErrback(errb)
        return d
Пример #17
0
    def send_mail(self, mail):
        mail['Date'] = email.utils.formatdate(time.time(), True)
        cmdlist = split_commandstring(self.cmd)

        def cb(out):
            logging.info('sent mail successfully')
            logging.info(out)

        def errb(failure):
            termobj = failure.value
            errmsg = '%s\nsendmail_cmd set to: %s' % (str(termobj), self.cmd)
            logging.error(errmsg)
            logging.error(failure.getTraceback())
            logging.error(failure.value.stderr)
            raise SendingMailFailed(errmsg)

        d = call_cmd_async(cmdlist, stdin=crypto.email_as_string(mail))
        d.addCallback(cb)
        d.addErrback(errb)
        return d
Пример #18
0
    def send_mail(self, mail):
        cmdlist = split_commandstring(self.cmd)

        def cb(out):
            logging.info('sent mail successfully')
            logging.info(out)

        def errb(failure):
            termobj = failure.value
            errmsg = '%s failed with code %s:\n%s' % \
                (self.cmd, termobj.exitCode, failure.value.stderr.rstrip())
            logging.error(errmsg)
            logging.error(failure.getTraceback())
            logging.error(failure.value.stderr)
            raise SendingMailFailed(errmsg)

        d = call_cmd_async(cmdlist, stdin=mail)
        d.addCallback(cb)
        d.addErrback(errb)
        return d
Пример #19
0
def dimapseminar(ui):
    """interprets DIMAP seminar mails"""
    msg = ui.current_buffer.get_selected_message()
    msgtext = msg.accumulate_body()
    r = r"Title:\s*(?P<title>((.*)(\n\s*.*)*))\n\nSpeaker:\s*(?P<speaker>.*)\nTime:\s*(?P<time>.*)\nLocation:\s*(?P<location>.*)\n\s*Abstract:\s*(?P<abstract>((.*)\n)*)"
    info = re.search(r, msgtext).groupdict()
    info['title'] = ' '.join(info['title'].split())
    #ui.notify('info: %s' % str(info.items()))
    cmd = "gcalcli add " \
          "--calendar uni " \
          "--title \"DIMAP: {speaker}:{title}\" " \
          "--where \"{location}\" " \
          "--when \"{time}\" "\
          "--description \"{abstract}\" "\
          "--duration 60 "\
          "--reminder 30"
    cmdlist = split_commandstring(cmd.format(**info))
    msg = ui.notify('info: %s' % cmdlist)
    if (yield ui.choice("commit?", select='yes', cancel='no')) == 'no':
        return
    ui.clear_notify([msg])
    ui.notify('info: %s' % str(call_cmd(cmdlist)))
Пример #20
0
    def lookup(self, prefix):
        cmdlist = split_commandstring(self.command)
        resultstring, errmsg, retval = call_cmd(cmdlist + [prefix])
        if retval != 0:
            msg = 'abook command "%s" returned with ' % self.command
            msg += 'return code %d' % retval
            if errmsg:
                msg += ':\n%s' % errmsg
            raise AddressbookError(msg)

        if not resultstring:
            return []
        lines = resultstring.splitlines()
        res = []
        for l in lines:
            m = re.match(self.match, l, self.reflags)
            if m:
                info = m.groupdict()
                if 'email' and 'name' in info:
                    email = info['email'].strip()
                    name = info['name']
                    res.append((name, email))
        return res
Пример #21
0
def dimapseminar(ui):
    """interprets DIMAP seminar mails"""
    msg = ui.current_buffer.get_selected_message()
    msgtext = msg.accumulate_body()
    r = r"Title:\s*(?P<title>((.*)(\n\s*.*)*))\n\nSpeaker:\s*(?P<speaker>.*)\nTime:\s*(?P<time>.*)\nLocation:\s*(?P<location>.*)\n\s*Abstract:\s*(?P<abstract>((.*)\n)*)"
    info = re.search(r, msgtext).groupdict()
    info["title"] = " ".join(info["title"].split())
    # ui.notify('info: %s' % str(info.items()))
    cmd = (
        "gcalcli add "
        "--calendar uni "
        '--title "DIMAP: {speaker}:{title}" '
        '--where "{location}" '
        '--when "{time}" '
        '--description "{abstract}" '
        "--duration 60 "
        "--reminder 30"
    )
    cmdlist = split_commandstring(cmd.format(**info))
    msg = ui.notify("info: %s" % cmdlist)
    if (yield ui.choice("commit?", select="yes", cancel="no")) == "no":
        return
    ui.clear_notify([msg])
    ui.notify("info: %s" % str(call_cmd(cmdlist)))
Пример #22
0
def extract_body(mail, types=None):
    """
    returns a body text string for given mail.
    If types is `None`, `text/*` is used:
    The exact preferred type is specified by the prefer_plaintext config option
    which defaults to text/html.

    :param mail: the mail to use
    :type mail: :class:`email.Message`
    :param types: mime content types to use for body string
    :type types: list of str
    """

    preferred = 'text/plain' if settings.get('prefer_plaintext') else 'text/html'
    has_preferred = False

    # see if the mail has our preferred type
    if types == None:
        has_preferred = list(typed_subpart_iterator(mail, *preferred.split('/')))

    body_parts = []
    for part in mail.walk():
        ctype = part.get_content_type()

        if types is not None:
            if ctype not in types:
                continue
        cd = part.get('Content-Disposition', '')
        if cd.startswith('attachment'):
            continue
        # if the mail has our preferred type, we only keep this type
        # note that if types != None, has_preferred always stays False
        if has_preferred and ctype != preferred:
            continue

        enc = part.get_content_charset() or 'ascii'
        raw_payload = part.get_payload(decode=True)
        if ctype == 'text/plain':
            raw_payload = string_decode(raw_payload, enc)
            body_parts.append(string_sanitize(raw_payload))
        else:
            #get mime handler
            key = 'copiousoutput'
            handler, entry = settings.mailcap_find_match(ctype, key=key)
            tempfile_name = None
            stdin = None

            if entry:
                handler_raw_commandstring = entry['view']
                # in case the mailcap defined command contains no '%s',
                # we pipe the files content to the handling command via stdin
                if '%s' in handler_raw_commandstring:
                    # open tempfile, respect mailcaps nametemplate
                    nametemplate = entry.get('nametemplate', '%s')
                    prefix, suffix = parse_mailcap_nametemplate(nametemplate)
                    tmpfile = tempfile.NamedTemporaryFile(delete=False,
                                                        prefix=prefix,
                                                        suffix=suffix)
                    # write payload to tmpfile
                    tmpfile.write(raw_payload)
                    tmpfile.close()
                    tempfile_name = tmpfile.name
                else:
                    stdin = raw_payload

                # read parameter, create handler command
                parms = tuple(map('='.join, part.get_params()))

                # create and call external command
                cmd = mailcap.subst(entry['view'], ctype,
                                    filename=tempfile_name, plist=parms)
                logging.debug('command: %s' % cmd)
                logging.debug('parms: %s' % str(parms))
                cmdlist = split_commandstring(cmd)
                # call handler
                rendered_payload, errmsg, retval = helper.call_cmd(cmdlist, stdin=stdin)

                # remove tempfile
                if tempfile_name:
                    os.unlink(tempfile_name)

                if rendered_payload:  # handler had output
                    body_parts.append(string_sanitize(rendered_payload))
    return u'\n\n'.join(body_parts)
Пример #23
0
 def _test(self, base, expected):
     """Shared helper to reduce some boilerplate."""
     actual = helper.split_commandstring(base)
     self.assertListEqual(actual, expected)
Пример #24
0
Файл: utils.py Проект: a3nm/alot
def extract_body(mail, types=None):
    """
    returns a body text string for given mail.
    If types is `None`, `text/*` is used:
    In case mail has a `text/html` part, it is prefered over
    `text/plain` parts.

    :param mail: the mail to use
    :type mail: :class:`email.Message`
    :param types: mime content types to use for body string
    :type types: list of str
    """
    html = list(typed_subpart_iterator(mail, 'text', 'html'))

    # if no specific types are given, we favor text/html over text/plain
    drop_plaintext = False
    if html and not types:
        drop_plaintext = True

    body_parts = []
    for part in mail.walk():
        ctype = part.get_content_type()

        if types is not None:
            if ctype not in types:
                continue
        cd = part.get('Content-Disposition', '')
        if cd.startswith('attachment'):
            continue

        enc = part.get_content_charset() or 'ascii'
        raw_payload = part.get_payload(decode=True)
        if ctype == 'text/plain' and not drop_plaintext:
            raw_payload = string_decode(raw_payload, enc)
            body_parts.append(string_sanitize(raw_payload))
        else:
            #get mime handler
            key = 'copiousoutput'
            handler, entry = settings.mailcap_find_match(ctype, key=key)

            if entry:
                # open tempfile, respect mailcaps nametemplate
                nametemplate = entry.get('nametemplate', '%s')
                prefix, suffix = parse_mailcap_nametemplate(nametemplate)
                tmpfile = tempfile.NamedTemporaryFile(delete=False,
                                                      prefix=prefix,
                                                      suffix=suffix)
                # write payload to tmpfile
                tmpfile.write(raw_payload)
                tmpfile.close()

                # read parameter, create handler command
                parms = tuple(map('='.join, part.get_params()))

                # create and call external command
                cmd = mailcap.subst(entry['view'], ctype,
                                    filename=tmpfile.name, plist=parms)
                logging.debug('command: %s' % cmd)
                logging.debug('parms: %s' % str(parms))
                cmdlist = split_commandstring(cmd)
                # call handler
                rendered_payload, errmsg, retval = helper.call_cmd(cmdlist)
                # remove tempfile
                os.unlink(tmpfile.name)
                if rendered_payload:  # handler had output
                    body_parts.append(string_sanitize(rendered_payload))
    return u'\n\n'.join(body_parts)
Пример #25
0
 def _test(self, base, expected):
     """Shared helper to reduce some boilerplate."""
     actual = helper.split_commandstring(base)
     self.assertListEqual(actual, expected)
Пример #26
0
def extract_body(mail, types=None):
    """
    returns a body text string for given mail.
    If types is `None`, `text/*` is used:
    In case mail has a `text/html` part, it is prefered over
    `text/plain` parts.

    :param mail: the mail to use
    :type mail: :class:`email.Message`
    :param types: mime content types to use for body string
    :type types: list of str
    """
    html = list(typed_subpart_iterator(mail, 'text', 'html'))

    # if no specific types are given, we favor text/html over text/plain
    drop_plaintext = False
    if html and not types:
        drop_plaintext = True

    body_parts = []
    for part in mail.walk():
        ctype = part.get_content_type()
        logging.debug(ctype)

        if types is not None:
            if ctype not in types:
                continue
        cd = part.get('Content-Disposition', '')
        if cd.startswith('attachment'):
            continue

        enc = part.get_content_charset() or 'ascii'
        raw_payload = part.get_payload(decode=True)
        if ctype == 'text/plain' and not drop_plaintext:
            raw_payload = string_decode(raw_payload, enc)
            body_parts.append(string_sanitize(raw_payload))
        else:
            #get mime handler
            key = 'copiousoutput'
            handler, entry = settings.mailcap_find_match(ctype, key=key)

            if entry:
                # open tempfile, respect mailcaps nametemplate
                nametemplate = entry.get('nametemplate', '%s')
                prefix, suffix = parse_mailcap_nametemplate(nametemplate)
                tmpfile = tempfile.NamedTemporaryFile(delete=False,
                                                      prefix=prefix,
                                                      suffix=suffix)
                # write payload to tmpfile
                tmpfile.write(raw_payload)
                tmpfile.close()

                # read parameter, create handler command
                parms = tuple(map('='.join, part.get_params()))

                # create and call external command
                cmd = mailcap.subst(entry['view'],
                                    ctype,
                                    filename=tmpfile.name,
                                    plist=parms)
                logging.debug('command: %s' % cmd)
                logging.debug('parms: %s' % str(parms))
                cmdlist = split_commandstring(cmd)
                # call handler
                rendered_payload, errmsg, retval = helper.call_cmd(cmdlist)
                # remove tempfile
                os.unlink(tmpfile.name)
                if rendered_payload:  # handler had output
                    body_parts.append(string_sanitize(rendered_payload))
    return u'\n\n'.join(body_parts)
Пример #27
0
def extract_body(mail, types=None):
    """
    returns a body text string for given mail.
    If types is `None`, `text/*` is used:
    The exact preferred type is specified by the prefer_plaintext config option
    which defaults to text/html.

    :param mail: the mail to use
    :type mail: :class:`email.Message`
    :param types: mime content types to use for body string
    :type types: list of str
    """

    preferred = 'text/plain' if settings.get(
        'prefer_plaintext') else 'text/html'
    has_preferred = False

    # see if the mail has our preferred type
    if types is None:
        has_preferred = list(
            typed_subpart_iterator(mail, *preferred.split('/')))

    body_parts = []
    for part in mail.walk():
        ctype = part.get_content_type()

        if types is not None:
            if ctype not in types:
                continue
        cd = part.get('Content-Disposition', '')
        if cd.startswith('attachment'):
            continue
        # if the mail has our preferred type, we only keep this type
        # note that if types != None, has_preferred always stays False
        if has_preferred and ctype != preferred:
            continue

        enc = part.get_content_charset() or 'ascii'
        raw_payload = part.get_payload(decode=True)
        if ctype == 'text/plain':
            raw_payload = string_decode(raw_payload, enc)
            body_parts.append(string_sanitize(raw_payload))
        else:
            # get mime handler
            key = 'copiousoutput'
            handler, entry = settings.mailcap_find_match(ctype, key=key)
            tempfile_name = None
            stdin = None

            if entry:
                handler_raw_commandstring = entry['view']
                # in case the mailcap defined command contains no '%s',
                # we pipe the files content to the handling command via stdin
                if '%s' in handler_raw_commandstring:
                    # open tempfile, respect mailcaps nametemplate
                    nametemplate = entry.get('nametemplate', '%s')
                    prefix, suffix = parse_mailcap_nametemplate(nametemplate)
                    tmpfile = tempfile.NamedTemporaryFile(delete=False,
                                                          prefix=prefix,
                                                          suffix=suffix)
                    # write payload to tmpfile
                    tmpfile.write(raw_payload)
                    tmpfile.close()
                    tempfile_name = tmpfile.name
                else:
                    stdin = raw_payload

                # read parameter, create handler command
                parms = tuple(map('='.join, part.get_params()))

                # create and call external command
                cmd = mailcap.subst(entry['view'],
                                    ctype,
                                    filename=tempfile_name,
                                    plist=parms)
                logging.debug('command: %s' % cmd)
                logging.debug('parms: %s' % str(parms))
                cmdlist = split_commandstring(cmd)
                # call handler
                rendered_payload, errmsg, retval = helper.call_cmd(cmdlist,
                                                                   stdin=stdin)

                # remove tempfile
                if tempfile_name:
                    os.unlink(tempfile_name)

                if rendered_payload:  # handler had output
                    body_parts.append(string_sanitize(rendered_payload))
    return u'\n\n'.join(body_parts)