Implements keyword sub feature for bulk emails

This commit pulls in changes from #4487 that implement keyword
substitution for bulk emails. With these changes, an instructor can
include keywords in their bulk emails which will be automatically substituted
with the corresponding value for the recipient of the email. Keywords are
of the form %%keyword%%, and the keywords implemented in this commit include:

%%USER_ID%% => anonymous_user_id
%%USER_FULLNAME%% => user profile name
%%COURSE_DISPLAY_NAME%% => display name of the course
%%COURSE_END_DATE%% => end date of the course

Client-side validations have also been implemented to ensure that only emails
with well-formed keywords can be sent.
The architecture is designed such that adding in new keywords in the future
would be relatively straight-forward.
This is what I get for simply asking someone to look into ddt - I actually have never used this decorator. But... I LOVE IT! :heart: :heartbeat: :heart_eyes_cat: 

I've previously mostly used `ddt.data` with or without `ddt.unpack`: https://github.com/edx/edx-platform/blob/master/common/djangoapps/course_modes/tests/test_views.py#L88 and https://github.com/edx/edx-platform/blob/master/common/djangoapps/course_modes/tests/test_views.py#L34 

I think in future uses of `ddt` I might advocate you use `ddt.data`, especially when you're testing on just one variable (eg the first example). However the data you're using here is big and I like the use of json.