diff --git a/common/djangoapps/util/cache.py b/common/djangoapps/util/cache.py
index 7262fabd0991b612361eda29a955a4cde4dce646..cede8acb7159d32d0c9e0210f8bab49f5582df1a 100644
--- a/common/djangoapps/util/cache.py
+++ b/common/djangoapps/util/cache.py
@@ -20,8 +20,9 @@ except Exception:
     cache = cache.cache
 
 
-def cache_if_anonymous(view_func):
-    """
+def cache_if_anonymous(*get_parameters):
+    """Cache a page for anonymous users.
+
     Many of the pages in edX are identical when the user is not logged
     in, but should not be cached when the user is logged in (because
     of the navigation bar at the top with the username).
@@ -31,32 +32,46 @@ def cache_if_anonymous(view_func):
     the cookie to the vary header, and so every page is cached seperately
     for each user (because each user has a different csrf token).
 
+    Optionally, provide a series of GET parameters as arguments to cache
+    pages with these GET parameters separately.
+
     Note that this decorator should only be used on views that do not
     contain the csrftoken within the html. The csrf token can be included
     in the header by ordering the decorators as such:
 
     @ensure_csrftoken
-    @cache_if_anonymous
+    @cache_if_anonymous()
     def myView(request):
     """
 
-    @wraps(view_func)
-    def _decorated(request, *args, **kwargs):
-        if not request.user.is_authenticated():
-            #Use the cache
-            # same view accessed through different domain names may
-            # return different things, so include the domain name in the key.
-            domain = str(request.META.get('HTTP_HOST')) + '.'
-            cache_key = domain + "cache_if_anonymous." + get_language() + '.' + request.path
-            response = cache.get(cache_key)
-            if not response:
-                response = view_func(request, *args, **kwargs)
-                cache.set(cache_key, response, 60 * 3)
-
-            return response
-
-        else:
-            #Don't use the cache
-            return view_func(request, *args, **kwargs)
-
-    return _decorated
+    def decorator(view_func):
+        """The outer wrapper, used to allow the decorator to take optional
+        arguments.
+        """
+        @wraps(view_func)
+        def wrapper(request, *args, **kwargs):
+            """The inner wrapper, which wraps the view function."""
+            if not request.user.is_authenticated():
+                #Use the cache
+                # same view accessed through different domain names may
+                # return different things, so include the domain name in the key.
+                domain = str(request.META.get('HTTP_HOST')) + '.'
+                cache_key = domain + "cache_if_anonymous." + get_language() + '.' + request.path
+
+                # Include the values of GET parameters in the cache key.
+                for get_parameter in get_parameters:
+                    cache_key = cache_key + '.' + unicode(request.GET.get(get_parameter))
+
+                response = cache.get(cache_key)  # pylint: disable=maybe-no-member
+                if not response:
+                    response = view_func(request, *args, **kwargs)
+                    cache.set(cache_key, response, 60 * 3)  # pylint: disable=maybe-no-member
+
+                return response
+
+            else:
+                #Don't use the cache
+                return view_func(request, *args, **kwargs)
+
+        return wrapper
+    return decorator
diff --git a/lms/djangoapps/branding/views.py b/lms/djangoapps/branding/views.py
index 667ab7a9e01f34728bfdbba382edc4f1bf704841..b79df70f557f2f02117eb9f122e2419b07aa08dd 100644
--- a/lms/djangoapps/branding/views.py
+++ b/lms/djangoapps/branding/views.py
@@ -33,7 +33,7 @@ def get_course_enrollments(user):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous()
 def index(request):
     '''
     Redirects to main page -- info page if user authenticated, or marketing if not
@@ -81,7 +81,7 @@ def index(request):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous()
 def courses(request):
     """
     Render the "find courses" page. If the marketing site is enabled, redirect
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index b13c77165a22b4b817f28d1ec6d81a46657a9533..7556530daaac5e4a376cf6f9d661defe6a5a8139 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -3,6 +3,7 @@
 Tests courseware views.py
 """
 import unittest
+import cgi
 from datetime import datetime
 
 from mock import MagicMock, patch, create_autospec
@@ -99,6 +100,10 @@ class ViewsTestCase(TestCase):
         chapter = 'Overview'
         self.chapter_url = '%s/%s/%s' % ('/courses', self.course_key, chapter)
 
+        # For marketing email opt-in
+        self.organization_full_name = u"𝖀𝖒𝖇𝖗𝖊𝖑𝖑𝖆 𝕮𝖔𝖗𝖕𝖔𝖗𝖆𝖙𝖎𝖔𝖓"
+        self.organization_html = "<p>'+Umbrella/Corporation+'</p>"
+
     @unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), "Shopping Cart not enabled in settings")
     @patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True})
     def test_course_about_in_cart(self):
@@ -256,17 +261,26 @@ class ViewsTestCase(TestCase):
         #       generate/store a real password.
         self.assertEqual(chat_settings['password'], "johndoe@%s" % domain)
 
+    @patch.dict(settings.FEATURES, {'ENABLE_MKTG_EMAIL_OPT_IN': True})
     def test_course_mktg_about_coming_soon(self):
-        # we should not be able to find this course
+        # We should not be able to find this course
         url = reverse('mktg_about_course', kwargs={'course_id': 'no/course/here'})
-        response = self.client.get(url)
+        response = self.client.get(url, {'organization_full_name': self.organization_full_name})
         self.assertIn('Coming Soon', response.content)
 
+        # Verify that the checkbox is not displayed
+        self._email_opt_in_checkbox(response)
+
+    @patch.dict(settings.FEATURES, {'ENABLE_MKTG_EMAIL_OPT_IN': True})
     def test_course_mktg_register(self):
-        response = self._load_mktg_about()
+        response = self._load_mktg_about(organization_full_name=self.organization_full_name)
         self.assertIn('Enroll in', response.content)
         self.assertNotIn('and choose your student track', response.content)
 
+        # Verify that the checkbox is displayed
+        self._email_opt_in_checkbox(response, self.organization_full_name)
+
+    @patch.dict(settings.FEATURES, {'ENABLE_MKTG_EMAIL_OPT_IN': True})
     def test_course_mktg_register_multiple_modes(self):
         CourseMode.objects.get_or_create(
             mode_slug='honor',
@@ -279,12 +293,42 @@ class ViewsTestCase(TestCase):
             course_id=self.course_key
         )
 
-        response = self._load_mktg_about()
+        response = self._load_mktg_about(organization_full_name=self.organization_full_name)
         self.assertIn('Enroll in', response.content)
         self.assertIn('and choose your student track', response.content)
+
+        # Verify that the checkbox is displayed
+        self._email_opt_in_checkbox(response, self.organization_full_name)
+
         # clean up course modes
         CourseMode.objects.all().delete()
 
+    @patch.dict(settings.FEATURES, {'ENABLE_MKTG_EMAIL_OPT_IN': True})
+    def test_course_mktg_no_organization_name(self):
+        # Don't pass an organization name as a GET parameter, even though the email
+        # opt-in feature is enabled.
+        response = response = self._load_mktg_about()
+
+        # Verify that the checkbox is not displayed
+        self._email_opt_in_checkbox(response)
+
+    @patch.dict(settings.FEATURES, {'ENABLE_MKTG_EMAIL_OPT_IN': False})
+    def test_course_mktg_opt_in_disabled(self):
+        # Pass an organization name as a GET parameter, even though the email
+        # opt-in feature is disabled.
+        response = self._load_mktg_about(organization_full_name=self.organization_full_name)
+
+        # Verify that the checkbox is not displayed
+        self._email_opt_in_checkbox(response)
+
+    @patch.dict(settings.FEATURES, {'ENABLE_MKTG_EMAIL_OPT_IN': True})
+    def test_course_mktg_organization_html(self):
+        response = self._load_mktg_about(organization_full_name=self.organization_html)
+
+        # Verify that the checkbox is displayed with the organization name
+        # in the label escaped as expected.
+        self._email_opt_in_checkbox(response, cgi.escape(self.organization_html))
+
     @patch.dict(settings.FEATURES, {'IS_EDX_DOMAIN': True})
     def test_mktg_about_language_edx_domain(self):
         # Since we're in an edx-controlled domain, and our marketing site
@@ -340,9 +384,8 @@ class ViewsTestCase(TestCase):
         response = self.client.get(url)
         self.assertFalse('<script>' in response.content)
 
-    def _load_mktg_about(self, language=None):
-        """
-        Retrieve the marketing about button (iframed into the marketing site)
+    def _load_mktg_about(self, language=None, organization_full_name=None):
+        """Retrieve the marketing about button (iframed into the marketing site)
         and return the HTTP response.
 
         Keyword Args:
@@ -362,7 +405,22 @@ class ViewsTestCase(TestCase):
             headers['HTTP_ACCEPT_LANGUAGE'] = language
 
         url = reverse('mktg_about_course', kwargs={'course_id': unicode(self.course_key)})
-        return self.client.get(url, **headers)
+        if organization_full_name:
+            return self.client.get(url, {'organization_full_name': organization_full_name}, **headers)
+        else:
+            return self.client.get(url, **headers)
+
+    def _email_opt_in_checkbox(self, response, organization_full_name=None):
+        """Check if the email opt-in checkbox appears in the response content."""
+        checkbox_html = '<input id="email-opt-in" type="checkbox" name="opt-in" class="email-opt-in" value="true" checked>'
+        if organization_full_name:
+            # Verify that the email opt-in checkbox appears, and that the expected
+            # organization name is displayed.
+            self.assertContains(response, checkbox_html, html=True)
+            self.assertContains(response, organization_full_name)
+        else:
+            # Verify that the email opt-in checkbox does not appear
+            self.assertNotContains(response, checkbox_html, html=True)
 
 
 # setting TIME_ZONE_DISPLAYED_FOR_DEADLINES explicitly
diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py
index 5b0835d5bcf24a5b3d83e404664314cd2cc9c943..c1ec2e3d3812a58da4d82132d37479347b278307 100644
--- a/lms/djangoapps/courseware/views.py
+++ b/lms/djangoapps/courseware/views.py
@@ -5,6 +5,7 @@ Courseware views functions
 import logging
 import urllib
 import json
+import cgi
 
 from datetime import datetime
 from collections import defaultdict
@@ -93,7 +94,7 @@ def user_groups(user):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous()
 def courses(request):
     """
     Render "find courses" page.  The course selection work is done in courseware.courses.
@@ -713,7 +714,7 @@ def registered_for_course(course, user):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous()
 def course_about(request, course_id):
     """
     Display the course's about page.
@@ -802,13 +803,10 @@ def course_about(request, course_id):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous('organization_full_name')
 @ensure_valid_course_key
 def mktg_course_about(request, course_id):
-    """
-    This is the button that gets put into an iframe on the Drupal site
-    """
-
+    """This is the button that gets put into an iframe on the Drupal site."""
     course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
 
     try:
@@ -818,8 +816,7 @@ def mktg_course_about(request, course_id):
         )
         course = get_course_with_access(request.user, permission_name, course_key)
     except (ValueError, Http404):
-        # if a course does not exist yet, display a coming
-        # soon button
+        # If a course does not exist yet, display a "Coming Soon" button
         return render_to_response(
             'courseware/mktg_coming_soon.html', {'course_id': course_key.to_deprecated_string()}
         )
@@ -846,6 +843,12 @@ def mktg_course_about(request, course_id):
         'course_modes': course_modes,
     }
 
+    if settings.FEATURES.get('ENABLE_MKTG_EMAIL_OPT_IN'):
+        # Drupal will pass the organization's full name as a GET parameter. If no full name
+        # is provided, the marketing iframe won't show the email opt-in checkbox.
+        organization_full_name = request.GET.get('organization_full_name')
+        context['organization_full_name'] = cgi.escape(organization_full_name) if organization_full_name else organization_full_name
+
     # The edx.org marketing site currently displays only in English.
     # To avoid displaying a different language in the register / access button,
     # we force the language to English.
diff --git a/lms/djangoapps/static_template_view/views.py b/lms/djangoapps/static_template_view/views.py
index 4cff3c77ac71fba59562eb8bbc24e4ce664b1f2d..ea2639795ba008b42fbc511292bace0e99500d56 100644
--- a/lms/djangoapps/static_template_view/views.py
+++ b/lms/djangoapps/static_template_view/views.py
@@ -30,7 +30,7 @@ def index(request, template):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous()
 def render(request, template):
     """
     This view function renders the template sent without checking that it
@@ -43,7 +43,7 @@ def render(request, template):
 
 
 @ensure_csrf_cookie
-@cache_if_anonymous
+@cache_if_anonymous()
 def render_press_release(request, slug):
     """
     Render a press release given a slug.  Similar to the "render" function above,
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 8e167c00741f257c4c25ee770ee26facf0a6a826..7cd38d9d28ac9abd602683b443dd9d7b94a45ca4 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -283,6 +283,9 @@ FEATURES = {
     # Enable the combined login/registration form
     'ENABLE_COMBINED_LOGIN_REGISTRATION': False,
 
+    # Enable organizational email opt-in
+    'ENABLE_MKTG_EMAIL_OPT_IN': False,
+
     # Show a section in the membership tab of the instructor dashboard
     # to allow an upload of a CSV file that contains a list of new accounts to create
     # and register for course.
diff --git a/lms/templates/courseware/mktg_course_about.html b/lms/templates/courseware/mktg_course_about.html
index 3b63e61ebd451c1e27b73e394099b86c483a8992..be0be4e26131eba354e72482c70ef31166d574df 100644
--- a/lms/templates/courseware/mktg_course_about.html
+++ b/lms/templates/courseware/mktg_course_about.html
@@ -16,6 +16,14 @@
   <script type="text/javascript">
   (function() {
     $(".register").click(function(event) {
+      if ( !$("#email-opt-in").prop("checked") ) {
+        $("input[name='email_opt_in']").val("false");
+      }
+
+      var email_opt_in = $("input[name='email_opt_in']").val(),
+        current_href = $("a.register").attr("href");
+      $("a.register").attr("href", current_href + "&email_opt_in=" + email_opt_in)
+
       $("#class_enroll_form").submit();
       event.preventDefault();
     });
@@ -29,7 +37,9 @@
           window.top.location.href = "${reverse('dashboard')}";
         }
       } else if (xhr.status == 403) {
-        window.top.location.href = $("a.register").attr("href") || "${reverse('register_user')}?course_id=${course.id | u}&enrollment_action=enroll";
+        var email_opt_in = $("input[name='email_opt_in']").val();
+        ## Ugh.
+        window.top.location.href = $("a.register").attr("href") || "${reverse('register_user')}?course_id=${course.id | u}&enrollment_action=enroll&email_opt_in=" + email_opt_in;
       } else {
         $('#register_error').html(
             (xhr.responseText ? xhr.responseText : "${_("An error occurred. Please try again later.")}")
@@ -71,6 +81,23 @@
             </span>
             %endif
         </a>
+
+        % if settings.FEATURES.get('ENABLE_MKTG_EMAIL_OPT_IN'):
+          ## We only display the email opt-in checkbox if we've been given a valid full name (i.e., not None)
+          % if organization_full_name:
+            <p class="form-field">
+              <input id="email-opt-in" type="checkbox" name="opt-in" class="email-opt-in" value="true" checked>
+              <label for="email-opt-in">
+                ## Translators: This line appears next a checkbox which users can leave checked or uncheck in order
+                ## to indicate whether they want to receive emails from the organization offering the course.
+                ${_("I would like to receive email about other {organization_full_name} programs and offers.").format(
+                  organization_full_name=organization_full_name
+                )}
+              </label>
+            </p>
+          % endif
+        % endif
+
         %else:
           <div class="action registration-closed is-disabled">${_("Enrollment Is Closed")}</div>
         %endif
@@ -83,6 +110,7 @@
       <fieldset class="enroll_fieldset">
         <input name="course_id" type="hidden" value="${course.id | h}">
         <input name="enrollment_action" type="hidden" value="enroll">
+        <input name="email_opt_in" type="hidden" value="true">
         <input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
       </fieldset>
       <div class="submit">