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)
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)
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