def createResponseBody(lines, context, client, lang='en'):
    """Parse the **lines** from an incoming email request and determine how to
    respond.

    :param list lines: The list of lines from the original request sent by the
        client.
    :type context: :class:`bridgedb.distributors.email.server.MailServerContext`
    :param context: The context which contains settings for the email server.
    :type client: :api:`twisted.mail.smtp.Address`
    :param client: The client's email address which should be in the
        ``'To:'`` header of the response email.
    :param str lang: The 2-5 character locale code to use for translating the
        email. This is obtained from a client sending a email to a valid plus
        address which includes the translation desired, i.e. by sending an
        email to `[email protected]
        <mailto:[email protected]>`__, the client should receive a
        response in Farsi.
    :rtype: str
    :returns: ``None`` if we shouldn't respond to the client (i.e., if they
        have already received a rate-limiting warning email). Otherwise,
        returns a string containing the (optionally translated) body for the
        email response which we should send out.
    """
    translator = translations.installTranslations(lang)
    bridges = None
    try:
        bridgeRequest = request.determineBridgeRequestOptions(lines)
        bridgeRequest.client = str(client)

        # The request was invalid, respond with a help email which explains
        # valid email commands:
        if not bridgeRequest.isValid():
            raise EmailRequestedHelp("Email request from '%s' was invalid."
                                     % str(client))

        # Otherwise they must have requested bridges:
        interval = context.schedule.intervalStart(time.time())
        bridges = context.distributor.getBridges(bridgeRequest, interval)
    except EmailRequestedHelp as error:
        logging.info(error)
        return templates.buildWelcomeText(translator, client)
    except EmailRequestedKey as error:
        logging.info(error)
        return templates.buildKeyMessage(translator, client)
    except TooSoonEmail as error:
        logging.info("Got a mail too frequently: %s." % error)
        return templates.buildSpamWarning(translator, client)
    except (IgnoreEmail, addr.BadEmail) as error:
        logging.info(error)
        # Don't generate a response if their email address is unparsable or
        # invalid, or if we've already warned them about rate-limiting:
        return None
    else:
        answer = "(no bridges currently available)\r\n"
        if bridges:
            transport = bridgeRequest.justOnePTType()
            answer = "".join("  %s\r\n" % b.getBridgeLine(
                bridgeRequest, context.includeFingerprints) for b in bridges)
        return templates.buildAnswerMessage(translator, client, answer)
Exemple #2
0
def createResponseBody(lines, context, client, lang='en'):
    """Parse the **lines** from an incoming email request and determine how to
    respond.

    :param list lines: The list of lines from the original request sent by the
        client.
    :type context: :class:`bridgedb.email.server.MailServerContext`
    :param context: The context which contains settings for the email server.
    :type client: :api:`twisted.mail.smtp.Address`
    :param client: The client's email address which should be in the
        ``'To:'`` header of the response email.
    :param str lang: The 2-5 character locale code to use for translating the
        email. This is obtained from a client sending a email to a valid plus
        address which includes the translation desired, i.e. by sending an
        email to `[email protected]
        <mailto:[email protected]>`__, the client should receive a
        response in Farsi.
    :rtype: str
    :returns: ``None`` if we shouldn't respond to the client (i.e., if they
        have already received a rate-limiting warning email). Otherwise,
        returns a string containing the (optionally translated) body for the
        email response which we should send out.
    """
    translator = translations.installTranslations(lang)
    bridges = None
    try:
        bridgeRequest = request.determineBridgeRequestOptions(lines)
        bridgeRequest.client = str(client)

        # The request was invalid, respond with a help email which explains
        # valid email commands:
        if not bridgeRequest.isValid():
            raise EmailRequestedHelp("Email request from '%s' was invalid."
                                     % str(client))

        # Otherwise they must have requested bridges:
        interval = context.schedule.intervalStart(time.time())
        bridges = context.distributor.getBridges(bridgeRequest, interval)
    except EmailRequestedHelp as error:
        logging.info(error)
        return templates.buildWelcomeText(translator, client)
    except EmailRequestedKey as error:
        logging.info(error)
        return templates.buildKeyMessage(translator, client)
    except TooSoonEmail as error:
        logging.info("Got a mail too frequently: %s." % error)
        return templates.buildSpamWarning(translator, client)
    except (IgnoreEmail, addr.BadEmail) as error:
        logging.info(error)
        # Don't generate a response if their email address is unparsable or
        # invalid, or if we've already warned them about rate-limiting:
        return None
    else:
        answer = "(no bridges currently available)\r\n"
        if bridges:
            transport = bridgeRequest.justOnePTType()
            answer = "".join("  %s\r\n" % b.getBridgeLine(
                bridgeRequest, context.includeFingerprints) for b in bridges)
        return templates.buildAnswerMessage(translator, client, answer)
Exemple #3
0
    def getMailData(self):
        """Gather all the data for building the response to the client.

        This method must return a file-like object containing the data of the
        message to be sent. Lines in the file should be delimited by ``\\n``.

        :rtype: ``None`` or :class:`EmailResponse`
        :returns: An ``EmailResponse``, if we have a response to send in reply
            to the incoming email, otherwise, returns ``None``.
        """
        clients = self.getMailTo()
        if not clients: return
        client = clients[0]  # There should have been only one anyway

        # Log the email address that this message came from if SAFELOGGING is
        # not enabled:
        if not safelog.safe_logging:
            logging.debug("Incoming email was from %s ..." % client)

        if not self.runChecks(client): return

        recipient = self.getMailFrom()
        # Look up the locale part in the 'To:' address, if there is one, and
        # get the appropriate Translation object:
        lang = translations.getLocaleFromPlusAddr(recipient)
        logging.info("Client requested email translation: %s" % lang)

        body = createResponseBody(self.incoming.lines, self.incoming.context,
                                  client, lang)

        # The string EMAIL_MISC_TEXT[1] shows up in an email if BridgeDB
        # responds with bridges.  Everything else we count as an invalid
        # request.
        translator = translations.installTranslations(lang)
        if body is not None and translator.gettext(
                strings.EMAIL_MISC_TEXT[1]) in body:
            metrix.recordValidEmailRequest(self)
        else:
            metrix.recordInvalidEmailRequest(self)

        if not body: return  # The client was already warned.

        messageID = self.incoming.message.get("Message-ID", None)
        subject = self.incoming.message.get("Subject", None)
        response = generateResponse(recipient, client, body, subject,
                                    messageID,
                                    self.incoming.context.gpgSignFunc)
        return response