commit 44992aaa7b78cfaf563892971ac4133bf37ca59a Author: meskio meskio@torproject.org Date: Tue Nov 16 18:35:26 2021 +0100
Improve the email text for small screens
Split bridges so they are easier to distinguis and add instructions for Tails.
Colses: #40028 --- bridgedb/distributors/email/autoresponder.py | 5 ++--- bridgedb/distributors/email/templates.py | 29 ++++++++++++++++++---------- bridgedb/strings.py | 18 +++++++++++++---- bridgedb/test/test_email_autoresponder.py | 16 +++++++-------- bridgedb/test/test_email_templates.py | 13 +++++++------ bridgedb/test/test_smtp.py | 6 +++--- scripts/nagios-email-check | 2 +- 7 files changed, 54 insertions(+), 35 deletions(-)
diff --git a/bridgedb/distributors/email/autoresponder.py b/bridgedb/distributors/email/autoresponder.py index 12f0ae1..6e901d7 100644 --- a/bridgedb/distributors/email/autoresponder.py +++ b/bridgedb/distributors/email/autoresponder.py @@ -111,17 +111,16 @@ def createResponseBody(lines, context, client, lang='en'): # invalid, or if we've already warned them about rate-limiting: return None, None else: - answer = "(no bridges currently available)\r\n" + bridgeLines = [] qrcode = None if bridges: transport = bridgeRequest.justOnePTType() bridgeLines = [b.getBridgeLine(bridgeRequest, context.includeFingerprints) for b in bridges] - answer = "".join(" %s\r\n" % line for line in bridgeLines) qrcode = generateQR(bridgeLines) internalMetrix.recordHandoutsPerBridge(bridgeRequest, bridges) else: internalMetrix.recordEmptyEmailResponse() - return templates.buildAnswerMessage(translator, client, answer), qrcode + return templates.buildAnswerMessage(translator, client, bridgeLines), qrcode
def generateResponse(fromAddress, client, body, subject=None, messageID=None, qrcode=None): diff --git a/bridgedb/distributors/email/templates.py b/bridgedb/distributors/email/templates.py index 44450ea..e058cac 100644 --- a/bridgedb/distributors/email/templates.py +++ b/bridgedb/distributors/email/templates.py @@ -67,14 +67,20 @@ def addGreeting(template):
return greeting
-def addBridgeAnswer(template, answer): +def addBridgeAnswer(template, bridgeLines): # Give the user their bridges, i.e. the `answer`: - bridgeLines = u"" - bridgeLines += template.gettext(strings.EMAIL_MISC_TEXT[1]) - bridgeLines += u"\n\n" - bridgeLines += u"%s\n" % answer - - return bridgeLines + bridgeText = u"" + bridgeText += template.gettext(strings.EMAIL_MISC_TEXT[1]) + bridgeText += u"\n\n" + bridgeText += "%s\r\n" % bridgeLines[0] + bridgeText += u"\n" + for line in bridgeLines[1:]: + bridgeText += template.gettext(strings.EMAIL_MISC_TEXT[4]) + bridgeText += u"\n\n" + bridgeText += "%s\r\n" % line + bridgeText += u"\n" + + return bridgeText
def addHowto(template): """Add help text on how to add bridges to Tor Browser. @@ -85,11 +91,14 @@ def addHowto(template): """ return template.gettext(strings.HOWTO_TBB[2])
-def buildAnswerMessage(template, clientAddress=None, answer=None): +def buildAnswerMessage(template, clientAddress=None, bridgeLines=None): try: message = addGreeting(template) - message += addBridgeAnswer(template, answer) - message += addHowto(template) + if bridgeLines: + message += addBridgeAnswer(template, bridgeLines) + message += addHowto(template) + else: + message += template.gettext(strings.EMAIL_MISC_TEXT[5]) message += u'\n\n' message += addCommands(template) except Exception as error: # pragma: no cover diff --git a/bridgedb/strings.py b/bridgedb/strings.py index 09eb91b..8310be6 100644 --- a/bridgedb/strings.py +++ b/bridgedb/strings.py @@ -33,13 +33,18 @@ EMAIL_MISC_TEXT = { 0: _("""\ [This is an automated email.]"""), 1: _("""\ -Here are your bridges:"""), +Here is your bridge:"""), 2: _("""\ You have exceeded the rate limit. Please slow down! The minimum time between emails is %s hours. All further emails during this time period will be ignored."""), 3: _("""\ If these bridges are not what you need, reply to this email with one of the following commands in the message body:"""), + # TRANSLATORS: "it" here is a bridge, this sentence comes after giving a first bridge to provide a second one + 4: _("""\ +If it doesn't work, you can try this other bridge:"""), + 5: _("""\ +There are no bridges currently available, sorry."""), }
WELCOME = { @@ -163,10 +168,15 @@ HOWTO_TBB = { Manual explains how you can add your bridges to Tor Browser. If you are using Windows, Linux, or OS X, %sclick here%s to learn more. If you are using Android, %sclick here%s."""), + # TRANSLATORS: Please DO NOT translate "Tor Browser" neither "Tails". 2: _("""\ -Add these bridges to your Tor Browser by opening your browser -preferences, clicking on "Tor", and then adding them to the "Provide a -bridge" field."""), +If you are using Tor Browser: + +1. Choose "☰ ▸ Settings ▸ Tor" to open your Tor settings. + +2. In the "Bridges" section, enter your bridge in the "Provide a bridge" field. + +If you are using Tails, enter your bridge in the Tor Connection assistant."""), }
EMAIL_COMMANDS = { diff --git a/bridgedb/test/test_email_autoresponder.py b/bridgedb/test/test_email_autoresponder.py index 566d837..7be492b 100644 --- a/bridgedb/test/test_email_autoresponder.py +++ b/bridgedb/test/test_email_autoresponder.py @@ -60,7 +60,7 @@ class CreateResponseBodyTests(unittest.TestCase): lines = self._getIncomingLines("testing@localhost") lines[4] = "transport obfs3" ret, qrcode = autoresponder.createResponseBody(lines, self.ctx, self.toAddress) - self.assertSubstring("Here are your bridges:", ret) + self.assertSubstring("Here is your bridge:", ret) self.assertIsNotNone(qrcode)
def test_createResponseBody_bridges_obfs3(self): @@ -68,7 +68,7 @@ class CreateResponseBodyTests(unittest.TestCase): lines = self._getIncomingLines("testing@localhost") lines[4] = "get transport obfs3" ret, qrcode = autoresponder.createResponseBody(lines, self.ctx, self.toAddress) - self.assertSubstring("Here are your bridges", ret) + self.assertSubstring("Here is your bridge", ret) self.assertSubstring("obfs3", ret) self.assertIsInstance(qrcode, bytes)
@@ -79,7 +79,7 @@ class CreateResponseBodyTests(unittest.TestCase): lines.append("get transport obfs2") lines.append("get transport obfs3") ret, qrcode = autoresponder.createResponseBody(lines, self.ctx, self.toAddress) - self.assertSubstring("Here are your bridges", ret) + self.assertSubstring("Here is your bridge", ret) self.assertSubstring("obfs3", ret) self.assertIsInstance(qrcode, bytes)
@@ -91,7 +91,7 @@ class CreateResponseBodyTests(unittest.TestCase): lines.append("get ipv6") lines.append("get transport obfs2") ret, qrcode = autoresponder.createResponseBody(lines, self.ctx, self.toAddress) - self.assertSubstring("Here are your bridges", ret) + self.assertSubstring("Here is your bridge", ret) self.assertSubstring("obfs2", ret) self.assertIsInstance(qrcode, bytes)
@@ -105,7 +105,7 @@ class CreateResponseBodyTests(unittest.TestCase):
lines = self._getIncomingLines("testing@localhost") first, qrcode = autoresponder.createResponseBody(lines, ctx, self.toAddress) - self.assertSubstring("Here are your bridges", first) + self.assertSubstring("Here is your bridge", first) self.assertIsInstance(qrcode, bytes) second, qrcode = autoresponder.createResponseBody(lines, ctx, self.toAddress) self.assertSubstring("Please slow down", second) @@ -123,13 +123,13 @@ class CreateResponseBodyTests(unittest.TestCase): aliceLines = self._getIncomingLines("alice@localhost") aliceFirst, qrcode = autoresponder.createResponseBody(aliceLines, ctx, self.toAddress) - self.assertSubstring("Here are your bridges", aliceFirst) + self.assertSubstring("Here is your bridge", aliceFirst) self.assertIsInstance(qrcode, bytes)
bobLines = self._getIncomingLines("bob@localhost") bobFirst, qrcode = autoresponder.createResponseBody(bobLines, ctx, self.toAddress) - self.assertSubstring("Here are your bridges", bobFirst) + self.assertSubstring("Here is your bridge", bobFirst) self.assertIsInstance(qrcode, bytes)
aliceSecond, qrcode = autoresponder.createResponseBody(aliceLines, ctx, @@ -148,7 +148,7 @@ class CreateResponseBodyTests(unittest.TestCase):
lines = self._getIncomingLines("testing@localhost") first, qrcode = autoresponder.createResponseBody(lines, ctx, self.toAddress) - self.assertSubstring("Here are your bridges", first) + self.assertSubstring("Here is your bridge", first) self.assertIsInstance(qrcode, bytes) second, qrcode = autoresponder.createResponseBody(lines, ctx, self.toAddress) self.assertSubstring("Please slow down", second) diff --git a/bridgedb/test/test_email_templates.py b/bridgedb/test/test_email_templates.py index a948c91..3be3e03 100644 --- a/bridgedb/test/test_email_templates.py +++ b/bridgedb/test/test_email_templates.py @@ -29,7 +29,7 @@ class EmailTemplatesTests(unittest.TestCase): def setUp(self): self.t = NullTranslations(StringIO('test')) self.client = Address('blackhole@torproject.org') - self.answer = 'obfs3 1.1.1.1:1111\nobfs3 2.2.2.2:2222' + self.bridgeLines = ['obfs3 1.1.1.1:1111', 'obfs3 2.2.2.2:2222']
def shouldIncludeCommands(self, text): self.assertSubstring('commands', text) @@ -38,8 +38,9 @@ class EmailTemplatesTests(unittest.TestCase): self.assertSubstring('Tor Browser', text)
def shouldIncludeBridges(self, text): - self.assertSubstring(self.answer, text) - self.assertSubstring('Here are your bridges:', text) + for line in self.bridgeLines: + self.assertSubstring(line, text) + self.assertSubstring('Here is your bridge:', text)
def shouldIncludeGreeting(self, text): self.assertSubstring('This is an automated email', text) @@ -60,12 +61,12 @@ class EmailTemplatesTests(unittest.TestCase): self.shouldIncludeInstructions(text)
def test_templates_addBridgeAnswer(self): - text = templates.addBridgeAnswer(self.t, self.answer) + text = templates.addBridgeAnswer(self.t, self.bridgeLines) self.shouldIncludeBridges(text)
def test_templates_buildAnswerMessage(self): - text = templates.buildAnswerMessage(self.t, self.client, self.answer) - self.assertSubstring(self.answer, text) + text = templates.buildAnswerMessage(self.t, self.client, self.bridgeLines) + self.shouldIncludeBridges(text) self.shouldIncludeAutomationNotice(text) self.shouldIncludeCommands(text)
diff --git a/bridgedb/test/test_smtp.py b/bridgedb/test/test_smtp.py index f7261da..ab70e9b 100644 --- a/bridgedb/test/test_smtp.py +++ b/bridgedb/test/test_smtp.py @@ -152,7 +152,7 @@ class SMTPTests(unittest.TestCase):
# then check that our local SMTP server received a response # and that response contained some bridges - self.server.getAndCheckMessageContains(b"Here are your bridges") + self.server.getAndCheckMessageContains(b"Here is your bridge")
def test_getBridges_rateLimitExceeded(self): if os.environ.get("CI"): @@ -168,7 +168,7 @@ class SMTPTests(unittest.TestCase):
# then check that our local SMTP server received a response # and that response contained some bridges - self.server.getAndCheckMessageContains(b"Here are your bridges") + self.server.getAndCheckMessageContains(b"Here is your bridge")
# send another request from the same email address sendMail(FROM_ADDRESS) @@ -203,4 +203,4 @@ class SMTPTests(unittest.TestCase): % random.randint(MIN_FROM_ADDRESS, MAX_FROM_ADDRESS))
for i in range(NUM_MAILS): - self.server.getAndCheckMessageContains(b"Here are your bridges") + self.server.getAndCheckMessageContains(b"Here is your bridge") diff --git a/scripts/nagios-email-check b/scripts/nagios-email-check index 51c63a1..983943e 100755 --- a/scripts/nagios-email-check +++ b/scripts/nagios-email-check @@ -32,7 +32,7 @@ SMTP_SERVER = "imap.gmail.com" SMTP_PORT = 993
MESSAGE_FROM = TO_EMAIL -MESSAGE_BODY = "Here are your bridges:" +MESSAGE_BODY = "Here is your bridge:"
STATUS_FILE = "/srv/bridges.torproject.org/check/status"
tor-commits@lists.torproject.org