email forwarder: encode stream names so they are safe in email addresses.

(imported from commit 6699d656e3cae58fad062a1403fb9923429fde89)
This commit is contained in:
Jessica McKellar
2013-08-12 16:12:43 -04:00
parent c4a0797413
commit 15afdf65eb
2 changed files with 20 additions and 1 deletions

View File

@@ -1042,6 +1042,24 @@ def do_update_message(user_profile, message_id, subject, content):
notice = dict(event=event, users=recipients)
tornado_callbacks.send_notification(notice)
def encode_email_address(stream):
# Given the fact that we have almost no restrictions on stream names and
# that what characters are allowed in e-mail addresses is complicated and
# dependent on context in the address, we opt for a very simple scheme:
#
# Only encode the stream name (leave the + and token alone). Encode
# everything that isn't alphanumeric plus _ as the percent-prefixed integer
# ordinal of that character, padded with zeroes to the maximum number of
# bytes of a UTF-8 encoded Unicode character.
encoded_name = re.sub("\W", lambda x: "%" + str(ord(x.group(0))).zfill(4),
stream.name)
return "%s+%s@streams.zulip.com" % (encoded_name, stream.email_token)
def decode_email_address(email):
# Perform the reverse of encode_email_address. Only the stream name will be
# transformed.
return re.sub("%\d{4}", lambda x: unichr(int(x.group(0)[1:])), email)
def gather_subscriptions(user_profile):
# For now, don't display subscriptions for private messages.
subs = Subscription.objects.select_related().filter(

View File

@@ -24,6 +24,7 @@ import sys
from django.conf import settings
from django.core.management.base import BaseCommand
from zerver.lib.actions import decode_email_address
from zerver.models import Stream, get_user_profile_by_email
from twisted.internet import protocol, reactor, ssl
@@ -104,7 +105,7 @@ def extract_and_validate(email):
# Recipient is of the form
# <stream name>+<regenerable stream token>@streams.zulip.com
try:
stream_name_and_token = email.rsplit("@", 1)[0]
stream_name_and_token = decode_email_address(email).rsplit("@", 1)[0]
stream_name, token = stream_name_and_token.rsplit("+", 1)
except ValueError:
log_and_raise("Malformed email recipient " + email)