Repository: zulip/zulip

Issue:
stream settings: Use the .show-sender version of email address.
In stream settings, we should 
* show `announce.b64ccc11942283fe612c93a0c57af830.show-sender@zulipdev.com` instead of `announce.b64ccc11942283fe612c93a0c57af830@zulipdev.com`
* The (?) should just be a `target=_blank` link to /help/message-a-stream-by-email. You can copy how we do this in other places, e.g. to the right of Organization profile at http://localhost:9991/#organization/organization-profile).

Here's what it looks like now:

![image](https://user-images.githubusercontent.com/890911/64287477-aec5b980-cf14-11e9-9975-959f29ade08c.png)




Discussion:
Hello @zulip/server-streams members, this issue was labeled with the "area: stream settings" label, so you may want to check it out!

<!-- areaLabelAddition -->
@zulipbot claim

Resolving patch:
diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py
--- a/zerver/lib/actions.py
+++ b/zerver/lib/actions.py
@@ -2696,7 +2696,7 @@ def notify_subscriptions_added(user_profile: UserProfile,
                     is_web_public=stream.is_web_public,
                     is_announcement_only=stream.is_announcement_only,
                     color=subscription.color,
-                    email_address=encode_email_address(stream),
+                    email_address=encode_email_address(stream, show_sender=True),
                     desktop_notifications=subscription.desktop_notifications,
                     audible_notifications=subscription.audible_notifications,
                     push_notifications=subscription.push_notifications,
@@ -3557,7 +3557,7 @@ def do_rename_stream(stream: Stream,
     # date field in all cases.
     cache_delete_many(
         to_dict_cache_key_id(message.id) for message in messages)
-    new_email = encode_email_address(stream)
+    new_email = encode_email_address(stream, show_sender=True)
 
     # We will tell our users to essentially
     # update stream.name = new_name where name = old_name
@@ -4679,6 +4679,8 @@ def gather_subscriptions_helper(user_profile: UserProfile,
         if not sub["active"] and user_profile.is_guest:
             subscribers = None
 
+        email_address = encode_email_address_helper(stream["name"], stream["email_token"],
+                                                    show_sender=True)
         stream_dict = {'name': stream["name"],
                        'in_home_view': not sub["is_muted"],
                        'is_muted': sub["is_muted"],
@@ -4699,7 +4701,7 @@ def gather_subscriptions_helper(user_profile: UserProfile,
                        'stream_weekly_traffic': get_average_weekly_stream_traffic(stream["id"],
                                                                                   stream["date_created"],
                                                                                   recent_traffic),
-                       'email_address': encode_email_address_helper(stream["name"], stream["email_token"]),
+                       'email_address': email_address,
                        'history_public_to_subscribers': stream['history_public_to_subscribers']}
 
         if subscribers is not None:
diff --git a/zerver/lib/email_mirror_helpers.py b/zerver/lib/email_mirror_helpers.py
--- a/zerver/lib/email_mirror_helpers.py
+++ b/zerver/lib/email_mirror_helpers.py
@@ -26,10 +26,10 @@ def get_email_gateway_message_string_from_address(address: str) -> str:
 
     return msg_string
 
-def encode_email_address(stream: Stream) -> str:
-    return encode_email_address_helper(stream.name, stream.email_token)
+def encode_email_address(stream: Stream, show_sender: bool=False) -> str:
+    return encode_email_address_helper(stream.name, stream.email_token, show_sender)
 
-def encode_email_address_helper(name: str, email_token: str) -> str:
+def encode_email_address_helper(name: str, email_token: str, show_sender: bool=False) -> str:
     # Some deployments may not use the email gateway
     if settings.EMAIL_GATEWAY_PATTERN == '':
         return ''
@@ -52,6 +52,9 @@ def encode_email_address_helper(name: str, email_token: str) -> str:
     else:
         encoded_token = email_token
 
+    if show_sender:
+        encoded_token += ".show-sender"
+
     return settings.EMAIL_GATEWAY_PATTERN % (encoded_token,)
 
 def decode_email_address(email: str) -> Tuple[str, Dict[str, bool]]:


Test patch:
diff --git a/frontend_tests/node_tests/templates.js b/frontend_tests/node_tests/templates.js
--- a/frontend_tests/node_tests/templates.js
+++ b/frontend_tests/node_tests/templates.js
@@ -641,13 +641,6 @@ run_test('draft_table_body', () => {
     assert.equal(row_2.find(".message_content").text().trim(), "Private draft");
 });
 
-
-run_test('email_address_hint', () => {
-    var html = render('email_address_hint');
-    var li = $(html).find("li").first();
-    assert.equal(li.text(), 'translated: The email will be forwarded to this stream');
-});
-
 run_test('emoji_popover', () => {
     var args = {
         class: "emoji-info-popover",
diff --git a/zerver/tests/test_email_mirror.py b/zerver/tests/test_email_mirror.py
--- a/zerver/tests/test_email_mirror.py
+++ b/zerver/tests/test_email_mirror.py
@@ -69,16 +69,30 @@ def test_encode_decode(self) -> None:
         stream_name = 'dev. help'
         stream = ensure_stream(realm, stream_name)
         email_address = encode_email_address(stream)
-        self.assertTrue(email_address.startswith('dev-help'))
-        self.assertTrue(email_address.endswith('@testserver'))
+        self.assertEqual(email_address, "dev-help.{}@testserver".format(stream.email_token))
+
+        # The default form of the email address (with an option - "include-footer"):
+        token, options = decode_email_address(
+            "dev-help.{}.include-footer@testserver".format(stream.email_token)
+        )
+        self._assert_options(options, include_footer=True)
+        self.assertEqual(token, stream.email_token)
+
+        # Using + instead of . as the separator is also supported for backwards compatibility,
+        # since that was the original form of addresses that we used:
+        token, options = decode_email_address(
+            "dev-help+{}+include-footer@testserver".format(stream.email_token)
+        )
+        self._assert_options(options, include_footer=True)
+        self.assertEqual(token, stream.email_token)
+
         token, options = decode_email_address(email_address)
         self._assert_options(options)
         self.assertEqual(token, stream.email_token)
 
-        parts = email_address.split('@')
-        # Use a mix of + and . as separators, to test that it works:
-        parts[0] += "+include-footer.show-sender+include-quotes"
-        email_address_all_options = '@'.join(parts)
+        # We also handle mixing + and . but it shouldn't be recommended to users.
+        email_address_all_options = "dev-help.{}+include-footer.show-sender+include-quotes@testserver"
+        email_address_all_options = email_address_all_options.format(stream.email_token)
         token, options = decode_email_address(email_address_all_options)
         self._assert_options(options, show_sender=True, include_footer=True, include_quotes=True)
         self.assertEqual(token, stream.email_token)
@@ -136,6 +150,14 @@ def test_decode_ignores_stream_name(self) -> None:
         token = decode_email_address(stream_to_address)[0]
         self.assertEqual(token, stream.email_token)
 
+    def test_encode_with_show_sender(self) -> None:
+        stream = get_stream("Denmark", get_realm("zulip"))
+        stream_to_address = encode_email_address(stream, show_sender=True)
+
+        token, options = decode_email_address(stream_to_address)
+        self._assert_options(options, show_sender=True)
+        self.assertEqual(token, stream.email_token)
+
 class TestGetMissedMessageToken(ZulipTestCase):
     def test_get_missed_message_token(self) -> None:
         with self.settings(EMAIL_GATEWAY_PATTERN="%s@example.com"):