コード例 #1
0
def process(message, sent_to_address=None):
    """
    Handles the dispatching of received messages.

    :param message: The received message
    :type message: ``bytes``

    :param sent_to_address: The address to which the message was sent.
        Necessary in order to determine which package it was sent to.
    """
    assert isinstance(message, six.binary_type), 'Message must be given as bytes'
    msg = message_from_bytes(message)

    logdata = {
        'from': extract_email_address_from_header(msg.get('From', '')),
        'msgid': msg.get('Message-ID', 'no-msgid-present@localhost'),
        'to': sent_to_address or '',
    }
    logger.info("dispatch <= %(from)s for %(to)s %(msgid)s", logdata)
    if sent_to_address is None:
        # No MTA was recognized, the last resort is to try and use the message
        # To header.
        sent_to_address = extract_email_address_from_header(msg['To'])

    if sent_to_address.startswith('bounces+'):
        return handle_bounces(sent_to_address)

    local_part = sent_to_address.split('@')[0]

    # Extract package name
    package_name = get_package_name(local_part)
    # Check loop
    package_email = '{package}@{distro_tracker_fqdn}'.format(
        package=package_name, distro_tracker_fqdn=DISTRO_TRACKER_FQDN)
    if package_email in msg.get_all('X-Loop', ()):
        # Bad X-Loop, discard the message
        logger.info('dispatch :: discarded %(msgid)s due to X-Loop', logdata)
        return

    # Extract keyword
    keyword = get_keyword(local_part, msg)
    logger.info('dispatch :: %s %s', package_name, keyword)
    # Default keywords require special approvement
    if keyword == 'default' and not approved_default(msg):
        logger.info('dispatch :: discarded non-approved message %(msgid)s',
                    logdata)
        return

    # Now send the message to subscribers
    add_new_headers(msg, package_name, keyword)
    send_to_subscribers(msg, package_name, keyword)
    send_to_teams(msg, package_name, keyword)
コード例 #2
0
def _get_logdata(msg, package, keyword):
    return {
        'from': extract_email_address_from_header(msg.get('From', '')),
        'msgid': msg.get('Message-ID', 'no-msgid-present@localhost'),
        'package': package or '<unknown>',
        'keyword': keyword or '<unknown>',
    }
コード例 #3
0
def process(message):
    """
    The function which actually processes a received command email message.

    :param message: The received command email message.
    :type message: ``bytes``
    """
    assert isinstance(message, six.binary_type), 'Message must be given as bytes'
    msg = message_from_bytes(message)
    email = extract_email_address_from_header(msg.get('From', ''))
    logdata = {
        'from': email,
        'msgid': msg.get('Message-ID', 'no-msgid-present@localhost'),
    }
    logger.info("control <= %(from)s %(msgid)s", logdata)
    if 'X-Loop' in msg and DISTRO_TRACKER_CONTROL_EMAIL in msg.get_all('X-Loop'):
        logger.info("control :: discarded %(msgid)s due to X-Loop", logdata)
        return
    # Get the first plain-text part of the message
    plain_text_part = next(typed_subpart_iterator(msg, 'text', 'plain'), None)
    if not plain_text_part:
        # There is no plain text in the email
        send_plain_text_warning(msg, logdata)
        return

    # Decode the plain text into a unicode string
    try:
        text = get_decoded_message_payload(plain_text_part)
    except UnicodeDecodeError:
        send_plain_text_warning(msg, logdata)
        return

    lines = extract_command_from_subject(msg) + text.splitlines()
    # Process the commands
    factory = CommandFactory({'email': email})
    confirmation_set = ConfirmationSet()
    processor = CommandProcessor(factory)
    processor.confirmation_set = confirmation_set
    processor.process(lines)

    confirmation_set.ask_confirmation_all()
    # Send a response only if there were some commands processed
    if processor.is_success():
        send_response(msg, processor.get_output(), recipient_email=email,
                      cc=set(confirmation_set.get_emails()))
    else:
        logger.info("control :: no command processed in %(msgid)s", logdata)