Exemplo n.º 1
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
        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)
        if not body: return  # The client was already warned.

        messageID = self.incoming.message.getheader("Message-ID", None)
        subject = self.incoming.message.getheader("Subject", None)
        response = generateResponse(recipient, client,
                                    body, subject, messageID,
                                    self.incoming.context.gpgContext)
        return response
Exemplo n.º 2
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
Exemplo n.º 3
0
 def test_getLocaleFromPlusAddr_ar(self):
     emailAddr = '*****@*****.**'
     replyLocale = translations.getLocaleFromPlusAddr(emailAddr)
     self.assertEqual('ar', replyLocale)
Exemplo n.º 4
0
    def reply(self):
        """Reply to an incoming email. Maybe.

        If no `response` is returned from :func:`createMailResponse`, then the
        incoming email will not be responded to at all. This can happen for
        several reasons, for example: if the DKIM signature was invalid or
        missing, or if the incoming email came from an unacceptable domain, or
        if there have been too many emails from this client in the allotted
        time period.

        :rtype: :api:`twisted.internet.defer.Deferred`
        :returns: A ``Deferred`` which will callback when the response has
            been successfully sent, or errback if an error occurred while
            sending the email.
        """
        logging.info("Got an email; deciding whether to reply.")

        def _replyEB(fail):
            """Errback for a :api:`twisted.mail.smtp.SMTPSenderFactory`.

            :param fail: A :api:`twisted.python.failure.Failure` which occurred during
            the transaction.
            """
            logging.debug("_replyToMailEB() called with %r" % fail)
            error = fail.getTraceback() or "Unknown"
            logging.error(error)

        d = defer.Deferred()
        d.addErrback(_replyEB)

        incoming = self.getIncomingMessage()
        recipient = self.getRecipient(incoming)
        client = self.getClientAddress(incoming)

        if not client:
            return d

        if not self.fromCanonical:
            self.fromCanonical = self.getCanonicalDomain(client.domain)
        rules = self.context.domainRules.get(self.fromCanonical, [])
        if not checkDKIM(incoming, rules):
            return d

        clientAddr = '@'.join([client.local, client.domain])
        messageID = incoming.getheader("Message-ID", None)
        subject = incoming.getheader("Subject", None)

        # 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.lines, self.context, client, lang)
        if not body: return d  # The client was already warned.

        response = generateResponse(self.context.fromAddr, clientAddr, body,
                                    subject, messageID, self.context.gpgContext)
        if not response: return d

        logging.info("Sending reply to %s" % client)
        factory = smtp.SMTPSenderFactory(self.context.smtpFromAddr, clientAddr,
                                         response, d, retries=0, timeout=30)
        reactor.connectTCP(self.context.smtpServerIP,
                           self.context.smtpServerPort,
                           factory)
        return d
Exemplo n.º 5
0
 def test_getLocaleFromPlusAddr_ar(self):
     emailAddr = '*****@*****.**'
     replyLocale = translations.getLocaleFromPlusAddr(emailAddr)
     self.assertEqual('ar', replyLocale)