예제 #1
0
def exec_and_parse_bugscript(handler, bugscript):
    """Execute and parse the output of the package bugscript, in particular
    identifying the headers and pseudo-headers blocks, if present"""

    fh, filename = TempFile()
    fh.close()
    rc = os.system('LC_ALL=C %s %s %s' % (handler, commands.mkarg(bugscript),
                                          commands.mkarg(filename)))

    isheaders = False
    ispseudoheaders = False
    headers = pseudoheaders = text = ''
    fp = open(filename)
    for line in fp.readlines():
        # we identify the blocks for headers and pseudo-h
        if line == '-- BEGIN HEADERS --\n':
            isheaders = True
        elif line == '-- END HEADERS --\n':
            isheaders = False
        elif line == '-- BEGIN PSEUDOHEADERS --\n':
            ispseudoheaders = True
        elif line == '-- END PSEUDOHEADERS --\n':
            ispseudoheaders = False
        else:
            if isheaders:
                headers += line
            elif ispseudoheaders:
                pseudoheaders += line
            else:
                text += line
    fp.close()
    cleanup_temp_file(filename)

    text = text.decode('utf-8', 'replace')
    return (rc, headers, pseudoheaders, text)
예제 #2
0
def sign_message(body, fromaddr, package='x', pgp_addr=None, sign='gpg', draftpath=None):
    '''Sign message with pgp key.'''
    ''' Return: a signed body.
        On failure, return None.
        kw need to have the following keys
    '''
    if not pgp_addr:
        pgp_addr = get_email_addr(fromaddr)[1]

    # Make the unsigned file first
    (unsigned, file1) = TempFile(prefix=tempfile_prefix(package, 'unsigned'), dir=draftpath)
    unsigned.write(body)
    unsigned.close()

    # Now make the signed file
    (signed, file2) = TempFile(prefix=tempfile_prefix(package, 'signed'), dir=draftpath)
    signed.close()

    if sign == 'gpg':
        os.unlink(file2)
        if 'GPG_AGENT_INFO' not in os.environ:
            signcmd = "gpg --local-user '%s' --clearsign " % pgp_addr
        else:
            signcmd = "gpg --local-user '%s' --use-agent --clearsign " % pgp_addr
        signcmd += '--output '+commands.mkarg(file2)+ ' ' + commands.mkarg(file1)
    else:
        signcmd = "pgp -u '%s' -fast" % pgp_addr
        signcmd += '<'+commands.mkarg(file1)+' >'+commands.mkarg(file2)

    try:
        os.system(signcmd)
        x = file(file2, 'r')
        signedbody = x.read()
        x.close()

        if os.path.exists(file1):
            os.unlink(file1)
        if os.path.exists(file2):
            os.unlink(file2)

        if not signedbody:
            raise NoMessage
        body = signedbody
    except (NoMessage, IOError, OSError):
        fh, tmpfile2 = TempFile(prefix=tempfile_prefix(package), dir=draftpath)
        fh.write(body)
        fh.close()
        ewrite('gpg/pgp failed; input file in %s\n', tmpfile2)
        body = None
    return body
예제 #3
0
def sign_message(body,
                 fromaddr,
                 package='x',
                 pgp_addr=None,
                 sign='gpg',
                 draftpath=None):
    '''Sign message with pgp key.'''
    ''' Return: a signed body.
        On failure, return None.
        kw need to have the following keys
    '''
    if not pgp_addr:
        pgp_addr = get_email_addr(fromaddr)[1]

    # Make the unsigned file first
    (unsigned, file1) = TempFile(prefix=tempfile_prefix(package, 'unsigned'),
                                 dir=draftpath)
    unsigned.write(body)
    unsigned.close()

    # Now make the signed file
    (signed, file2) = TempFile(prefix=tempfile_prefix(package, 'signed'),
                               dir=draftpath)
    signed.close()

    if sign == 'gpg':
        os.unlink(file2)
        if 'GPG_AGENT_INFO' not in os.environ:
            signcmd = "gpg --local-user '%s' --clearsign " % pgp_addr
        else:
            signcmd = "gpg --local-user '%s' --use-agent --clearsign " % pgp_addr
        signcmd += '--output ' + commands.mkarg(file2) + ' ' + commands.mkarg(
            file1)
    else:
        signcmd = "pgp -u '%s' -fast" % pgp_addr
        signcmd += '<' + commands.mkarg(file1) + ' >' + commands.mkarg(file2)

    try:
        os.system(signcmd)
        x = file(file2, 'r')
        signedbody = x.read()
        x.close()

        if os.path.exists(file1):
            os.unlink(file1)
        if os.path.exists(file2):
            os.unlink(file2)

        if not signedbody:
            raise NoMessage
        body = signedbody
    except (NoMessage, IOError, OSError):
        fh, tmpfile2 = TempFile(prefix=tempfile_prefix(package), dir=draftpath)
        fh.write(body)
        fh.close()
        ewrite('gpg/pgp failed; input file in %s\n', tmpfile2)
        body = None
    return body
예제 #4
0
def exec_and_parse_bugscript(handler, bugscript):
    """Execute and parse the output of the package bugscript, in particular
    identifying the headers and pseudo-headers blocks, if present"""

    fh, filename = TempFile()
    fh.close()
    rc = os.system(
        'LC_ALL=C %s %s %s' %
        (handler, commands.mkarg(bugscript), commands.mkarg(filename)))

    isheaders = False
    ispseudoheaders = False
    isattachments = False
    headers = pseudoheaders = text = ''
    attachments = []
    fp = open(filename)
    for line in fp.readlines():
        # we identify the blocks for headers and pseudo-h
        if line == '-- BEGIN HEADERS --\n':
            isheaders = True
        elif line == '-- END HEADERS --\n':
            isheaders = False
        elif line == '-- BEGIN PSEUDOHEADERS --\n':
            ispseudoheaders = True
        elif line == '-- END PSEUDOHEADERS --\n':
            ispseudoheaders = False
        elif line == '-- BEGIN ATTACHMENTS --\n':
            isattachments = True
        elif line == '-- END ATTACHMENTS --\n':
            isattachments = False
        else:
            if isheaders:
                headers += line
            elif ispseudoheaders:
                pseudoheaders += line
            elif isattachments:
                attachments.append(line.strip())
            else:
                text += line
    fp.close()
    cleanup_temp_file(filename)

    text = text.decode('utf-8', 'replace')
    return (rc, headers, pseudoheaders, text, attachments)
예제 #5
0
def launch_mbox_reader(cmd, url, http_proxy, timeout):
    """Runs the command specified by cmd passing the mbox file
    downloaded from url as a parameter. If cmd is None or fails, then
    fallback to mail program."""
    mbox = open_url(url, http_proxy, timeout)
    if mbox is None:
        return
    (fd, fname) = TempFile()
    try:
        for line in mbox:
            fd.write(line)
        fd.close()
        if cmd is not None:
            try:
                cmd = cmd % fname
            except TypeError:
                cmd = "%s %s" % (cmd, fname)
            error = os.system(cmd)
            if not error:
                return
        #fallback
        os.system('mail -f ' + fname)
    finally:
        os.unlink(fname)
예제 #6
0
def send_report(body, attachments, mua, fromaddr, sendto, ccaddr, bccaddr,
                headers, package='x', charset="us-ascii", mailing=True,
                sysinfo=None,
                rtype='debbugs', exinfo=None, replyto=None, printonly=False,
                template=False, outfile=None, mta='', kudos=False,
                smtptls=False, smtphost='localhost',
                smtpuser=None, smtppasswd=None, paranoid=False, draftpath=None):
    '''Send a report.'''

    failed = using_sendmail = False
    msgname = ''
    # Disable smtphost if mua is set
    if mua and smtphost:
        smtphost = ''

    # No, I'm not going to do a full MX lookup on every address... get a
    # real MTA!
    if kudos and smtphost == 'reportbug.debian.org':
        smtphost = 'packages.debian.org'

    body_charset = charset
    if isinstance(body, unicode):
        # Since the body is Unicode, utf-8 seems like a sensible body encoding
        # to choose pretty much all the time.
        body = body.encode('utf-8', 'replace')
        body_charset = 'utf-8'

    tfprefix = tempfile_prefix(package)
    if attachments and not mua:
        (message, failed) = mime_attach(body, attachments, charset, body_charset)
        if failed:
            ewrite("Error: Message creation failed, not sending\n")
            mua = mta = smtphost = None
    else:
        message = BetterMIMEText(body, _charset=body_charset)

    # Standard headers
    message['From'] = rfc2047_encode_address(fromaddr, 'utf-8', mua)
    message['To'] = rfc2047_encode_address(sendto, charset, mua)

    for (header, value) in headers:
        if header in ['From', 'To', 'Cc', 'Bcc', 'X-Debbugs-CC', 'Reply-To',
                      'Mail-Followup-To']:
            message[header] = rfc2047_encode_address(value, charset, mua)
        else:
            message[header] = rfc2047_encode_header(value, charset, mua)

    if ccaddr:
        message['Cc'] = rfc2047_encode_address(ccaddr, charset, mua)

    if bccaddr:
        message['Bcc'] = rfc2047_encode_address(bccaddr, charset, mua)

    replyto = os.environ.get("REPLYTO", replyto)
    if replyto:
        message['Reply-To'] = rfc2047_encode_address(replyto, charset, mua)

    if mailing:
        message['Message-ID'] = email.Utils.make_msgid('reportbug')
        message['X-Mailer'] = VERSION
        message['Date'] = email.Utils.formatdate(localtime=True)
    elif mua and not (printonly or template):
        message['X-Reportbug-Version'] = VERSION_NUMBER

    addrs = [str(x) for x in (message.get_all('To', []) +
                              message.get_all('Cc', []) +
                              message.get_all('Bcc', []))]
    alist = email.Utils.getaddresses(addrs)

    cclist = [str(x) for x in message.get_all('X-Debbugs-Cc', [])]
    debbugs_cc = email.Utils.getaddresses(cclist)
    if cclist:
        del message['X-Debbugs-Cc']
        addrlist = ', '.join(cclist)
        message['X-Debbugs-Cc'] = rfc2047_encode_address(addrlist, charset, mua)

    # Drop any Bcc headers from the message to be sent
    if not outfile and not mua:
        try:
            del message['Bcc']
        except:
            pass

    message = message.as_string()
    if paranoid and not (template or printonly):
        pager = os.environ.get('PAGER', 'sensible-pager')
        os.popen(pager, 'w').write(message)
        if not ui.yes_no('Does your report seem satisfactory', 'Yes, send it.',
                         'No, don\'t send it.'):
            smtphost = mta = None

    filename = None
    if template or printonly:
        pipe = sys.stdout
    elif mua:
        pipe, filename = TempFile(prefix=tfprefix, dir=draftpath)
    elif outfile or not mta or not os.path.exists(mta):
        msgname = outfile or ('/var/tmp/%s.bug' % package)
        if os.path.exists(msgname):
            try:
                os.rename(msgname, msgname+'~')
            except OSError:
                ewrite('Unable to rename existing %s as %s~\n',
                       msgname, msgname)
        try:
            pipe = open_write_safe(msgname, 'w')
        except OSError:
            fh, newmsgname = TempFile(prefix=tfprefix, dir=draftpath)
            fh.write(message.as_string())
            fh.close()
            ewrite('Writing to %s failed; '
                   'wrote bug report to %s\n', msgname, newmsgname)
            msgname = newmsgname
    elif mta and not smtphost:
        try:
            x = os.getcwd()
        except OSError:
            os.chdir('/')

        malist = [commands.mkarg(a[1]) for a in alist]
        jalist = ' '.join(malist)

        faddr = rfc822.parseaddr(fromaddr)[1]
        ewrite("Sending message via %s...\n", mta)
        pipe = os.popen('%s -f %s -oi -oem %s' % (
            mta, commands.mkarg(faddr), jalist), 'w')
        using_sendmail = True

    if smtphost:
        toaddrs = [x[1] for x in alist]
        smtp_message = re.sub(r'(?m)^[.]', '..', message)

        tryagain = True
        refused = None
        retry = 0
        while tryagain:
            tryagain = False
            ewrite("Connecting to %s via SMTP...\n", smtphost)
            try:
                conn = None
                # if we're using reportbug.debian.org, send mail to
                # submit
                if smtphost.lower() == 'reportbug.debian.org':
                    conn = smtplib.SMTP(smtphost,587)
                else: 
                    conn = smtplib.SMTP(smtphost)
                response = conn.ehlo()
                if not (200 <= response[0] <= 299):
                    conn.helo()
                if smtptls:
                    conn.starttls()
                    response = conn.ehlo()
                    if not (200 <= response[0] <= 299):
                        conn.helo()
                if smtpuser:
                    if not smtppasswd:
                        smtppasswd = ui.get_password(
                            'Enter SMTP password for %s@%s: ' %
                            (smtpuser, smtphost))
                    conn.login(smtpuser, smtppasswd)
                refused = conn.sendmail(fromaddr, toaddrs, smtp_message)
                conn.quit()
            except (socket.error, smtplib.SMTPException), x:
                # If wrong password, try again...
                if isinstance(x, smtplib.SMTPAuthenticationError):
                    ewrite('SMTP error: authentication failed.  Try again.\n')
                    tryagain = True
                    smtppasswd = None
                    retry += 1
                    if retry <= 2:
                        continue
                    else:
                        tryagain = False

                # In case of failure, ask to retry or to save & exit
                if ui.yes_no('SMTP send failure: %s. Do you want to retry (or else save the report and exit)?' % x, 'Yes, please retry.',
                         'No, save and exit.'):
                    tryagain = True
                    continue
                else:
                    failed = True

                    fh, msgname = TempFile(prefix=tfprefix, dir=draftpath)
                    fh.write(message)
                    fh.close()

                    ewrite('Wrote bug report to %s\n', msgname)
        # Handle when some recipients are refused.
        if refused:
            for (addr, err) in refused.iteritems():
                ewrite('Unable to send report to %s: %d %s\n', addr, err[0],
                       err[1])
            fh, msgname = TempFile(prefix=tfprefix, dir=draftpath)
            fh.write(message)
            fh.close()

            ewrite('Wrote bug report to %s\n', msgname)
예제 #7
0
            fh.close()

            ewrite('Wrote bug report to %s\n', msgname)
    else:
        try:
            pipe.write(message)
            pipe.flush()
            if msgname:
                ewrite("Bug report written as %s\n", msgname)
        except IOError:
            failed = True
            pipe.close()

        if failed or (pipe.close() and using_sendmail):
            failed = True
            fh, msgname = TempFile(prefix=tfprefix, dir=draftpath)
            fh.write(message)
            fh.close()
            ewrite('Original write failed, wrote bug report to %s\n', msgname)

    if mua:
        ewrite("Spawning %s...\n", mua.name)
        returnvalue = 0
        succeeded = False
        while not succeeded:
            returnvalue = mua.send(filename)
            if returnvalue != 0:
                ewrite("Mutt users should be aware it is mandatory to edit the draft before sending.\n")
                mtitle = 'Report has not been sent yet; what do you want to do now?'
                mopts = 'Eq'
                moptsdesc = {'e' : 'Edit the message.',
예제 #8
0
def send_report(body,
                attachments,
                mua,
                fromaddr,
                sendto,
                ccaddr,
                bccaddr,
                headers,
                package='x',
                charset="us-ascii",
                mailing=True,
                sysinfo=None,
                rtype='debbugs',
                exinfo=None,
                replyto=None,
                printonly=False,
                template=False,
                outfile=None,
                mta='',
                kudos=False,
                smtptls=False,
                smtphost='localhost',
                smtpuser=None,
                smtppasswd=None,
                paranoid=False,
                draftpath=None,
                envelopefrom=None):
    '''Send a report.'''

    failed = using_sendmail = False
    msgname = ''
    # Disable smtphost if mua is set
    if mua and smtphost:
        smtphost = ''

    # No, I'm not going to do a full MX lookup on every address... get a
    # real MTA!
    if kudos and smtphost == 'reportbug.debian.org':
        smtphost = 'packages.debian.org'

    body_charset = charset
    if isinstance(body, unicode):
        # Since the body is Unicode, utf-8 seems like a sensible body encoding
        # to choose pretty much all the time.
        body = body.encode('utf-8', 'replace')
        body_charset = 'utf-8'

    tfprefix = tempfile_prefix(package)
    if attachments and not mua:
        (message, failed) = mime_attach(body, attachments, charset,
                                        body_charset)
        if failed:
            ewrite("Error: Message creation failed, not sending\n")
            mua = mta = smtphost = None
    else:
        message = BetterMIMEText(body, _charset=body_charset)

    # Standard headers
    message['From'] = rfc2047_encode_address(fromaddr, 'utf-8', mua)
    message['To'] = rfc2047_encode_address(sendto, charset, mua)

    for (header, value) in headers:
        if header in [
                'From', 'To', 'Cc', 'Bcc', 'X-Debbugs-CC', 'Reply-To',
                'Mail-Followup-To'
        ]:
            message[header] = rfc2047_encode_address(value, charset, mua)
        else:
            message[header] = rfc2047_encode_header(value, charset, mua)

    if ccaddr:
        message['Cc'] = rfc2047_encode_address(ccaddr, charset, mua)

    if bccaddr:
        message['Bcc'] = rfc2047_encode_address(bccaddr, charset, mua)

    replyto = os.environ.get("REPLYTO", replyto)
    if replyto:
        message['Reply-To'] = rfc2047_encode_address(replyto, charset, mua)

    if mailing:
        message['Message-ID'] = email.Utils.make_msgid('reportbug')
        message['X-Mailer'] = VERSION
        message['Date'] = email.Utils.formatdate(localtime=True)
    elif mua and not (printonly or template):
        message['X-Reportbug-Version'] = VERSION_NUMBER

    addrs = [
        str(x)
        for x in (message.get_all('To', []) + message.get_all('Cc', []) +
                  message.get_all('Bcc', []))
    ]
    alist = email.Utils.getaddresses(addrs)

    cclist = [str(x) for x in message.get_all('X-Debbugs-Cc', [])]
    debbugs_cc = email.Utils.getaddresses(cclist)
    if cclist:
        del message['X-Debbugs-Cc']
        addrlist = ', '.join(cclist)
        message['X-Debbugs-Cc'] = rfc2047_encode_address(
            addrlist, charset, mua)

    # Drop any Bcc headers from the message to be sent
    if not outfile and not mua:
        try:
            del message['Bcc']
        except:
            pass

    message = message.as_string()
    if paranoid and not (template or printonly):
        pager = os.environ.get('PAGER', 'sensible-pager')
        os.popen(pager, 'w').write(message)
        if not ui.yes_no('Does your report seem satisfactory', 'Yes, send it.',
                         'No, don\'t send it.'):
            smtphost = mta = None

    filename = None
    if template or printonly:
        pipe = sys.stdout
    elif mua:
        pipe, filename = TempFile(prefix=tfprefix, dir=draftpath)
    elif outfile or not ((mta and os.path.exists(mta)) or smtphost):
        msgname = outfile or ('/var/tmp/%s.bug' % package)
        if os.path.exists(msgname):
            try:
                os.rename(msgname, msgname + '~')
            except OSError:
                ewrite('Unable to rename existing %s as %s~\n', msgname,
                       msgname)
        try:
            pipe = open_write_safe(msgname, 'w')
        except OSError:
            # we can't write to the selected file, use a temp file instead
            fh, newmsgname = TempFile(prefix=tfprefix, dir=draftpath)
            ewrite('Writing to %s failed; '
                   'using instead %s\n', msgname, newmsgname)
            msgname = newmsgname
            # we just need a place where to write() and a file handler
            # is here just for that
            pipe = fh
    elif mta and not smtphost:
        try:
            x = os.getcwd()
        except OSError:
            os.chdir('/')

        malist = [commands.mkarg(a[1]) for a in alist]
        jalist = ' '.join(malist)

        faddr = rfc822.parseaddr(fromaddr)[1]
        if envelopefrom:
            envfrom = rfc822.parseaddr(envelopefrom)[1]
        else:
            envfrom = faddr
        ewrite("Sending message via %s...\n", mta)
        pipe = os.popen(
            '%s -f %s -oi -oem %s' % (mta, commands.mkarg(envfrom), jalist),
            'w')
        using_sendmail = True

    if smtphost:
        toaddrs = [x[1] for x in alist]
        smtp_message = re.sub(r'(?m)^[.]', '..', message)

        tryagain = True
        refused = None
        retry = 0
        while tryagain:
            tryagain = False
            ewrite("Connecting to %s via SMTP...\n", smtphost)
            try:
                conn = None
                # if we're using reportbug.debian.org, send mail to
                # submit
                if smtphost.lower() == 'reportbug.debian.org':
                    conn = smtplib.SMTP(smtphost, 587)
                else:
                    conn = smtplib.SMTP(smtphost)
                response = conn.ehlo()
                if not (200 <= response[0] <= 299):
                    conn.helo()
                if smtptls:
                    conn.starttls()
                    response = conn.ehlo()
                    if not (200 <= response[0] <= 299):
                        conn.helo()
                if smtpuser:
                    if not smtppasswd:
                        smtppasswd = ui.get_password(
                            'Enter SMTP password for %s@%s: ' %
                            (smtpuser, smtphost))
                    conn.login(smtpuser, smtppasswd)
                refused = conn.sendmail(fromaddr, toaddrs, smtp_message)
                conn.quit()
            except (socket.error, smtplib.SMTPException), x:
                # If wrong password, try again...
                if isinstance(x, smtplib.SMTPAuthenticationError):
                    ewrite('SMTP error: authentication failed.  Try again.\n')
                    tryagain = True
                    smtppasswd = None
                    retry += 1
                    if retry <= 2:
                        continue
                    else:
                        tryagain = False

                # In case of failure, ask to retry or to save & exit
                if ui.yes_no(
                        'SMTP send failure: %s. Do you want to retry (or else save the report and exit)?'
                        % x, 'Yes, please retry.', 'No, save and exit.'):
                    tryagain = True
                    continue
                else:
                    failed = True

                    fh, msgname = TempFile(prefix=tfprefix, dir=draftpath)
                    fh.write(message)
                    fh.close()

                    ewrite('Wrote bug report to %s\n', msgname)
        # Handle when some recipients are refused.
        if refused:
            for (addr, err) in refused.iteritems():
                ewrite('Unable to send report to %s: %d %s\n', addr, err[0],
                       err[1])
            fh, msgname = TempFile(prefix=tfprefix, dir=draftpath)
            fh.write(message)
            fh.close()

            ewrite('Wrote bug report to %s\n', msgname)
예제 #9
0
            fh.close()

            ewrite('Wrote bug report to %s\n', msgname)
    else:
        try:
            pipe.write(message)
            pipe.flush()
            if msgname:
                ewrite("Bug report written as %s\n", msgname)
        except IOError:
            failed = True
            pipe.close()

        if failed or (pipe.close() and using_sendmail):
            failed = True
            fh, msgname = TempFile(prefix=tfprefix, dir=draftpath)
            fh.write(message)
            fh.close()
            ui.long_message(
                'Error: send/write operation failed, bug report '
                'saved to %s\n', msgname)

    if mua:
        ewrite("Spawning %s...\n", mua.name)
        returnvalue = 0
        succeeded = False
        while not succeeded:
            returnvalue = mua.send(filename)
            if returnvalue != 0:
                ewrite(
                    "Mutt users should be aware it is mandatory to edit the draft before sending.\n"