コード例 #1
0
ファイル: utils.py プロジェクト: weicliu/edx-platform
def get_id_token(user):
    """
    Return a JWT for `user`, suitable for use with the course discovery service.

    Arguments:
        user (User): User for whom to generate the JWT.

    Returns:
        str: The JWT.
    """
    try:
        # Service users may not have user profiles.
        full_name = UserProfile.objects.get(user=user).name
    except UserProfile.DoesNotExist:
        full_name = None

    now = datetime.datetime.utcnow()
    expires_in = getattr(settings, 'OAUTH_ID_TOKEN_EXPIRATION', 30)

    payload = {
        'preferred_username': user.username,
        'name': full_name,
        'email': user.email,
        'administrator': user.is_staff,
        'iss': helpers.get_value('OAUTH_OIDC_ISSUER', settings.OAUTH_OIDC_ISSUER),
        'exp': now + datetime.timedelta(seconds=expires_in),
        'iat': now,
        'aud': helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_AUDIENCE'],
        'sub': anonymous_id_for_user(user, None),
    }
    secret_key = helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_SECRET_KEY']

    return jwt.encode(payload, secret_key)
コード例 #2
0
ファイル: utils.py プロジェクト: 48dB/edx-platform
def is_commerce_service_configured():
    """
    Return a Boolean indicating whether or not configuration is present to use
    the external commerce service.
    """
    ecommerce_api_url = helpers.get_value("ECOMMERCE_API_URL", settings.ECOMMERCE_API_URL)
    ecommerce_api_signing_key = helpers.get_value("ECOMMERCE_API_SIGNING_KEY", settings.ECOMMERCE_API_SIGNING_KEY)
    return bool(ecommerce_api_url and ecommerce_api_signing_key)
コード例 #3
0
def is_commerce_service_configured():
    """
    Return a Boolean indicating whether or not configuration is present to use
    the external commerce service.
    """
    ecommerce_api_url = helpers.get_value("ECOMMERCE_API_URL",
                                          settings.ECOMMERCE_API_URL)
    ecommerce_api_signing_key = helpers.get_value(
        "ECOMMERCE_API_SIGNING_KEY", settings.ECOMMERCE_API_SIGNING_KEY)
    return bool(ecommerce_api_url and ecommerce_api_signing_key)
コード例 #4
0
ファイル: utils.py プロジェクト: 48dB/edx-platform
def ecommerce_api_client(user):
    """ Returns an E-Commerce API client setup with authentication for the specified user. """
    return EdxRestApiClient(
        helpers.get_value("ECOMMERCE_API_URL", settings.ECOMMERCE_API_URL),
        helpers.get_value("ECOMMERCE_API_SIGNING_KEY", settings.ECOMMERCE_API_SIGNING_KEY),
        user.username,
        user.profile.name if hasattr(user, 'profile') else None,
        user.email,
        tracking_context=create_tracking_context(user),
        issuer=settings.JWT_ISSUER,
        expires_in=settings.JWT_EXPIRATION
    )
コード例 #5
0
def ecommerce_api_client(user):
    """ Returns an E-Commerce API client setup with authentication for the specified user. """
    jwt_auth = helpers.get_value("JWT_AUTH", settings.JWT_AUTH)
    return EdxRestApiClient(
        helpers.get_value("ECOMMERCE_API_URL", settings.ECOMMERCE_API_URL),
        helpers.get_value("ECOMMERCE_API_SIGNING_KEY",
                          settings.ECOMMERCE_API_SIGNING_KEY),
        user.username,
        user.profile.name if hasattr(user, 'profile') else None,
        user.email,
        tracking_context=create_tracking_context(user),
        issuer=jwt_auth['JWT_ISSUER'],
        expires_in=jwt_auth['JWT_EXPIRATION'])
コード例 #6
0
def request_password_change(email, orig_host, is_secure):
    """Email a single-use link for performing a password reset.

    Users must confirm the password change before we update their information.

    Args:
        email (str): An email address
        orig_host (str): An originating host, extracted from a request with get_host
        is_secure (bool): Whether the request was made with HTTPS

    Returns:
        None

    Raises:
        UserNotFound
        AccountRequestError
        UserAPIInternalError: the operation failed due to an unexpected error.
    """
    # Binding data to a form requires that the data be passed as a dictionary
    # to the Form class constructor.
    form = PasswordResetFormNoActive({'email': email})

    # Validate that a user exists with the given email address.
    if form.is_valid():
        # Generate a single-use link for performing a password reset
        # and email it to the user.
        form.save(from_email=theming_helpers.get_value(
            'default_from_email', settings.DEFAULT_FROM_EMAIL),
                  domain_override=orig_host,
                  use_https=is_secure)
    else:
        # No user with the provided email address exists.
        raise UserNotFound
コード例 #7
0
    def test_reset_password_email(self, send_email):
        """Tests contents of reset password email, and that user is not active"""

        good_req = self.request_factory.post('/password_reset/', {'email': self.user.email})
        good_req.user = self.user
        good_resp = password_reset(good_req)
        self.assertEquals(good_resp.status_code, 200)
        obj = json.loads(good_resp.content)
        self.assertEquals(obj, {
            'success': True,
            'value': "('registration/password_reset_done.html', [])",
        })

        (subject, msg, from_addr, to_addrs) = send_email.call_args[0]
        self.assertIn("Password reset", subject)
        self.assertIn("You're receiving this e-mail because you requested a password reset", msg)
        self.assertEquals(from_addr, theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL))
        self.assertEquals(len(to_addrs), 1)
        self.assertIn(self.user.email, to_addrs)

        self.assert_event_emitted(
            SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'password', old=None, new=None,
        )

        #test that the user is not active
        self.user = User.objects.get(pk=self.user.pk)
        self.assertFalse(self.user.is_active)
        re.search(r'password_reset_confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/', msg).groupdict()
コード例 #8
0
    def test_reset_password_email(self, send_email):
        """Tests contents of reset password email, and that user is not active"""

        good_req = self.request_factory.post('/password_reset/', {'email': self.user.email})
        good_req.user = self.user
        good_resp = password_reset(good_req)
        self.assertEquals(good_resp.status_code, 200)
        obj = json.loads(good_resp.content)
        self.assertEquals(obj, {
            'success': True,
            'value': "('registration/password_reset_done.html', [])",
        })

        (subject, msg, from_addr, to_addrs) = send_email.call_args[0]
        self.assertIn("Password reset", subject)
        self.assertIn("You're receiving this e-mail because you requested a password reset", msg)
        self.assertEquals(from_addr, theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL))
        self.assertEquals(len(to_addrs), 1)
        self.assertIn(self.user.email, to_addrs)

        self.assert_event_emitted(
            SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'password', old=None, new=None,
        )

        #test that the user is not active
        self.user = User.objects.get(pk=self.user.pk)
        self.assertFalse(self.user.is_active)
        re.search(r'password_reset_confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/', msg).groupdict()
コード例 #9
0
    def _generate_jwt(self, user, scopes, expires_in):
        """ Returns a JWT access token. """
        now = int(time())
        jwt_auth = helpers.get_value("JWT_AUTH", settings.JWT_AUTH)
        payload = {
            'iss': jwt_auth['JWT_ISSUER'],
            'aud': jwt_auth['JWT_AUDIENCE'],
            'exp': now + expires_in,
            'iat': now,
            'preferred_username': user.username,
            'scopes': scopes,
        }

        for scope in scopes:
            handler = self.claim_handlers.get(scope)

            if handler:
                handler(payload, user)

        secret = jwt_auth['JWT_SECRET_KEY']
        token = jwt.encode(payload,
                           secret,
                           algorithm=jwt_auth['JWT_ALGORITHM'])

        return token
コード例 #10
0
ファイル: api.py プロジェクト: Rosivania/edx-platform
def request_password_change(email, orig_host, is_secure):
    """Email a single-use link for performing a password reset.

    Users must confirm the password change before we update their information.

    Args:
        email (str): An email address
        orig_host (str): An originating host, extracted from a request with get_host
        is_secure (bool): Whether the request was made with HTTPS

    Returns:
        None

    Raises:
        UserNotFound
        AccountRequestError
        UserAPIInternalError: the operation failed due to an unexpected error.
    """
    # Binding data to a form requires that the data be passed as a dictionary
    # to the Form class constructor.
    form = PasswordResetFormNoActive({'email': email})

    # Validate that a user exists with the given email address.
    if form.is_valid():
        # Generate a single-use link for performing a password reset
        # and email it to the user.
        form.save(
            from_email=theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL),
            domain_override=orig_host,
            use_https=is_secure
        )
    else:
        # No user with the provided email address exists.
        raise UserNotFound
コード例 #11
0
def _get_course_email_context(course):
    """
    Returns context arguments to apply to all emails, independent of recipient.
    """
    course_id = course.id.to_deprecated_string()
    course_title = course.display_name
    course_end_date = get_default_time_display(course.end)
    course_url = 'https://{}{}'.format(
        settings.SITE_NAME,
        reverse('course_root', kwargs={'course_id': course_id}))
    image_url = u'https://{}{}'.format(settings.SITE_NAME,
                                       course_image_url(course))
    email_context = {
        'course_title':
        course_title,
        'course_url':
        course_url,
        'course_image_url':
        image_url,
        'course_end_date':
        course_end_date,
        'account_settings_url':
        'https://{}{}'.format(settings.SITE_NAME, reverse('account_settings')),
        'email_settings_url':
        'https://{}{}'.format(settings.SITE_NAME, reverse('dashboard')),
        'platform_name':
        theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
    }
    return email_context
コード例 #12
0
ファイル: utils.py プロジェクト: dadasoz/edx-platform
def course_discovery_api_client(user):
    """ Returns a Course Discovery API client setup with authentication for the specified user. """
    course_discovery_client = Client.objects.get(name=CLIENT_NAME)
    secret_key = helpers.get_value('JWT_AUTH', settings.JWT_AUTH)['JWT_SECRET_KEY']
    return EdxRestApiClient(
        course_discovery_client.url,
        jwt=get_id_token(user, CLIENT_NAME, secret_key=secret_key)
    )
コード例 #13
0
ファイル: utils.py プロジェクト: zzy25/edx-platform
    def payment_page_url(self):
        """ Return the URL for the checkout page.

        Example:
            http://localhost:8002/basket/single_item/
        """
        ecommerce_url_root = helpers.get_value('ECOMMERCE_PUBLIC_URL_ROOT', settings.ECOMMERCE_PUBLIC_URL_ROOT)
        return urljoin(ecommerce_url_root, self.config.single_course_checkout_page)
コード例 #14
0
ファイル: utils.py プロジェクト: progh2/edx-platform
def course_discovery_api_client(user):
    """ Returns a Course Discovery API client setup with authentication for the specified user. """
    course_discovery_client = Client.objects.get(name=CLIENT_NAME)
    secret_key = helpers.get_value('JWT_AUTH',
                                   settings.JWT_AUTH)['JWT_SECRET_KEY']
    return EdxRestApiClient(course_discovery_client.url,
                            jwt=get_id_token(user,
                                             CLIENT_NAME,
                                             secret_key=secret_key))
コード例 #15
0
 def test_get_value_returns_override(self):
     """
     Tests to make sure the get_value() operation returns a combined dictionary consisting
     of the base container with overridden keys from the microsite configuration
     """
     with patch('microsite_configuration.microsite.get_value') as mock_get_value:
         override_key = 'JWT_ISSUER'
         override_value = 'testing'
         mock_get_value.return_value = {override_key: override_value}
         jwt_auth = helpers.get_value('JWT_AUTH')
         self.assertEqual(jwt_auth[override_key], override_value)
コード例 #16
0
ファイル: signals.py プロジェクト: 10clouds/edx-platform
def generate_refund_notification_body(student, refund_ids):  # pylint: disable=invalid-name
    """ Returns a refund notification message body. """
    msg = _(
        "A refund request has been initiated for {username} ({email}). "
        "To process this request, please visit the link(s) below."
    ).format(username=student.username, email=student.email)

    ecommerce_url_root = get_value('ECOMMERCE_PUBLIC_URL_ROOT', settings.ECOMMERCE_PUBLIC_URL_ROOT)
    refund_urls = [urljoin(ecommerce_url_root, '/dashboard/refunds/{}/'.format(refund_id))
                   for refund_id in refund_ids]

    return '{msg}\n\n{urls}'.format(msg=msg, urls='\n'.join(refund_urls))
コード例 #17
0
 def test_get_value_returns_override(self):
     """
     Tests to make sure the get_value() operation returns a combined dictionary consisting
     of the base container with overridden keys from the microsite configuration
     """
     with patch('microsite_configuration.microsite.get_value'
                ) as mock_get_value:
         override_key = 'JWT_ISSUER'
         override_value = 'testing'
         mock_get_value.return_value = {override_key: override_value}
         jwt_auth = helpers.get_value('JWT_AUTH')
         self.assertEqual(jwt_auth[override_key], override_value)
コード例 #18
0
ファイル: signals.py プロジェクト: devs1991/test_edx_docmode
def generate_refund_notification_body(student, refund_ids):  # pylint: disable=invalid-name
    """ Returns a refund notification message body. """
    msg = _("A refund request has been initiated for {username} ({email}). "
            "To process this request, please visit the link(s) below.").format(
                username=student.username, email=student.email)

    ecommerce_url_root = get_value('ECOMMERCE_PUBLIC_URL_ROOT',
                                   settings.ECOMMERCE_PUBLIC_URL_ROOT)
    refund_urls = [
        urljoin(ecommerce_url_root, '/dashboard/refunds/{}/'.format(refund_id))
        for refund_id in refund_ids
    ]

    return '{msg}\n\n{urls}'.format(msg=msg, urls='\n'.join(refund_urls))
コード例 #19
0
ファイル: tasks.py プロジェクト: zzy25/edx-platform
 def format_address(course_title_no_quotes):
     """
     Partial function for formatting the from_addr. Since
     `course_title_no_quotes` may be truncated to make sure the returned
     string has fewer than 320 characters, we define this function to make
     it easy to determine quickly what the max length is for
     `course_title_no_quotes`.
     """
     return from_addr_format.format(
         course_title=course_title_no_quotes,
         course_name=course_name,
         from_email=theming_helpers.get_value(
             'bulk_email_default_from_email',
             settings.BULK_EMAIL_DEFAULT_FROM_EMAIL))
コード例 #20
0
    def assertEmailUser(self, email_user, subject_template, subject_context, body_template, body_context):
        """Assert that `email_user` was used to send and email with the supplied subject and body

        `email_user`: The mock `django.contrib.auth.models.User.email_user` function
            to verify
        `subject_template`: The template to have been used for the subject
        `subject_context`: The context to have been used for the subject
        `body_template`: The template to have been used for the body
        `body_context`: The context to have been used for the body
        """
        email_user.assert_called_with(
            mock_render_to_string(subject_template, subject_context),
            mock_render_to_string(body_template, body_context),
            theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
        )
コード例 #21
0
    def assertEmailUser(self, email_user, subject_template, subject_context, body_template, body_context):
        """Assert that `email_user` was used to send and email with the supplied subject and body

        `email_user`: The mock `django.contrib.auth.models.User.email_user` function
            to verify
        `subject_template`: The template to have been used for the subject
        `subject_context`: The context to have been used for the subject
        `body_template`: The template to have been used for the body
        `body_context`: The context to have been used for the body
        """
        email_user.assert_called_with(
            mock_render_to_string(subject_template, subject_context),
            mock_render_to_string(body_template, body_context),
            theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL)
        )
コード例 #22
0
ファイル: tasks.py プロジェクト: AndreySonetico/edx-platform
 def format_address(course_title_no_quotes):
     """
     Partial function for formatting the from_addr. Since
     `course_title_no_quotes` may be truncated to make sure the returned
     string has fewer than 320 characters, we define this function to make
     it easy to determine quickly what the max length is for
     `course_title_no_quotes`.
     """
     return from_addr_format.format(
         course_title=course_title_no_quotes,
         course_name=course_name,
         from_email=theming_helpers.get_value(
             'bulk_email_default_from_email',
             settings.BULK_EMAIL_DEFAULT_FROM_EMAIL
         )
     )
コード例 #23
0
 def save(self,
          domain_override=None,
          subject_template_name='registration/password_reset_subject.txt',
          email_template_name='registration/password_reset_email.html',
          use_https=False,
          token_generator=default_token_generator,
          from_email=theming_helpers.get_value('default_from_email',
                                               settings.DEFAULT_FROM_EMAIL),
          request=None):
     """
     Generates a one-use only link for resetting password and sends to the
     user.
     """
     # This import is here because we are copying and modifying the .save from Django 1.4.5's
     # django.contrib.auth.forms.PasswordResetForm directly, which has this import in this place.
     from django.core.mail import send_mail
     for user in self.users_cache:
         if not domain_override:
             site_name = microsite.get_value('SITE_NAME',
                                             settings.SITE_NAME)
         else:
             site_name = domain_override
         context = {
             'email':
             user.email,
             'site_name':
             site_name,
             'uid':
             int_to_base36(user.id),
             'user':
             user,
             'token':
             token_generator.make_token(user),
             'protocol':
             'https' if use_https else 'http',
             'platform_name':
             microsite.get_value('platform_name', settings.PLATFORM_NAME)
         }
         subject = loader.render_to_string(subject_template_name, context)
         # Email subject *must not* contain newlines
         subject = subject.replace('\n', '')
         email = loader.render_to_string(email_template_name, context)
         send_mail(subject, email, from_email, [user.email])
コード例 #24
0
 def test_email_success(self, send_mail):
     """ Test email was sent if no errors encountered. """
     old_email = self.user.email
     new_email = "*****@*****.**"
     registration_key = "test registration key"
     self.assertIsNone(self.do_email_change(self.user, new_email, registration_key))
     context = {
         'key': registration_key,
         'old_email': old_email,
         'new_email': new_email
     }
     send_mail.assert_called_with(
         mock_render_to_string('emails/email_change_subject.txt', context),
         mock_render_to_string('emails/email_change.txt', context),
         theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
         [new_email]
     )
     self.assert_event_emitted(
         SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'email', old=old_email, new=new_email
     )
コード例 #25
0
 def test_email_success(self, send_mail):
     """ Test email was sent if no errors encountered. """
     old_email = self.user.email
     new_email = "*****@*****.**"
     registration_key = "test registration key"
     self.assertIsNone(self.do_email_change(self.user, new_email, registration_key))
     context = {
         'key': registration_key,
         'old_email': old_email,
         'new_email': new_email
     }
     send_mail.assert_called_with(
         mock_render_to_string('emails/email_change_subject.txt', context),
         mock_render_to_string('emails/email_change.txt', context),
         theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL),
         [new_email]
     )
     self.assert_event_emitted(
         SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'email', old=old_email, new=new_email
     )
コード例 #26
0
ファイル: views.py プロジェクト: zzy25/edx-platform
    def _generate_jwt(self, user, scopes, expires_in):
        """ Returns a JWT access token. """
        now = int(time())
        jwt_auth = helpers.get_value("JWT_AUTH", settings.JWT_AUTH)
        payload = {
            'iss': jwt_auth['JWT_ISSUER'],
            'aud': jwt_auth['JWT_AUDIENCE'],
            'exp': now + expires_in,
            'iat': now,
            'preferred_username': user.username,
        }

        for scope in scopes:
            handler = self.claim_handlers.get(scope)

            if handler:
                handler(payload, user)

        secret = jwt_auth['JWT_SECRET_KEY']
        token = jwt.encode(payload, secret, algorithm=jwt_auth['JWT_ALGORITHM'])

        return token
コード例 #27
0
ファイル: forms.py プロジェクト: AndreySonetico/edx-platform
 def save(
         self,
         domain_override=None,
         subject_template_name='registration/password_reset_subject.txt',
         email_template_name='registration/password_reset_email.html',
         use_https=False,
         token_generator=default_token_generator,
         from_email=theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL),
         request=None
 ):
     """
     Generates a one-use only link for resetting password and sends to the
     user.
     """
     # This import is here because we are copying and modifying the .save from Django 1.4.5's
     # django.contrib.auth.forms.PasswordResetForm directly, which has this import in this place.
     from django.core.mail import send_mail
     for user in self.users_cache:
         if not domain_override:
             site_name = microsite.get_value(
                 'SITE_NAME',
                 settings.SITE_NAME
             )
         else:
             site_name = domain_override
         context = {
             'email': user.email,
             'site_name': site_name,
             'uid': int_to_base36(user.id),
             'user': user,
             'token': token_generator.make_token(user),
             'protocol': 'https' if use_https else 'http',
             'platform_name': microsite.get_value('platform_name', settings.PLATFORM_NAME)
         }
         subject = loader.render_to_string(subject_template_name, context)
         # Email subject *must not* contain newlines
         subject = subject.replace('\n', '')
         email = loader.render_to_string(email_template_name, context)
         send_mail(subject, email, from_email, [user.email])
コード例 #28
0
ファイル: tasks.py プロジェクト: AndreySonetico/edx-platform
def _get_course_email_context(course):
    """
    Returns context arguments to apply to all emails, independent of recipient.
    """
    course_id = course.id.to_deprecated_string()
    course_title = course.display_name
    course_end_date = get_default_time_display(course.end)
    course_url = 'https://{}{}'.format(
        settings.SITE_NAME,
        reverse('course_root', kwargs={'course_id': course_id})
    )
    image_url = u'https://{}{}'.format(settings.SITE_NAME, course_image_url(course))
    email_context = {
        'course_title': course_title,
        'course_url': course_url,
        'course_image_url': image_url,
        'course_end_date': course_end_date,
        'account_settings_url': 'https://{}{}'.format(settings.SITE_NAME, reverse('account_settings')),
        'email_settings_url': 'https://{}{}'.format(settings.SITE_NAME, reverse('dashboard')),
        'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
    }
    return email_context
コード例 #29
0
ファイル: forms.py プロジェクト: zhenzhai/edx-platform
    def save(
        self,
        domain_override=None,
        subject_template_name="registration/password_reset_subject.txt",
        email_template_name="registration/password_reset_email.html",
        use_https=False,
        token_generator=default_token_generator,
        from_email=theming_helpers.get_value("email_from_address", settings.DEFAULT_FROM_EMAIL),
        request=None,
    ):
        """
        Generates a one-use only link for resetting password and sends to the
        user.
        """
        # This import is here because we are copying and modifying the .save from Django 1.4.5's
        # django.contrib.auth.forms.PasswordResetForm directly, which has this import in this place.
        from django.core.mail import send_mail

        for user in self.users_cache:
            if not domain_override:
                site_name = microsite.get_value("SITE_NAME", settings.SITE_NAME)
            else:
                site_name = domain_override
            context = {
                "email": user.email,
                "site_name": site_name,
                "uid": int_to_base36(user.id),
                "user": user,
                "token": token_generator.make_token(user),
                "protocol": "https" if use_https else "http",
                "platform_name": microsite.get_value("platform_name", settings.PLATFORM_NAME),
            }
            subject = loader.render_to_string(subject_template_name, context)
            # Email subject *must not* contain newlines
            subject = subject.replace("\n", "")
            email = loader.render_to_string(email_template_name, context)
            send_mail(subject, email, from_email, [user.email])
コード例 #30
0
ファイル: token_utils.py プロジェクト: LeslieZhu/edx-platform
 def __init__(self, user, asymmetric=False, secret=None):
     self.user = user
     self.asymmetric = asymmetric
     self.secret = secret
     self.jwt_auth = helpers.get_value('JWT_AUTH', settings.JWT_AUTH)
コード例 #31
0
ファイル: email_utils.py プロジェクト: zhenzhai/edx-platform
def send_credit_notifications(username, course_key):
    """Sends email notification to user on different phases during credit
    course e.g., credit eligibility, credit payment etc.
    """
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        log.error("No user with %s exist", username)
        return

    course = modulestore().get_course(course_key, depth=0)
    course_display_name = course.display_name
    tracking_context = tracker.get_tracker().resolve_context()
    tracking_id = str(tracking_context.get("user_id"))
    client_id = str(tracking_context.get("client_id"))
    events = "&t=event&ec=email&ea=open"
    tracking_pixel = "https://www.google-analytics.com/collect?v=1&tid" + tracking_id + "&cid" + client_id + events
    dashboard_link = _email_url_parser("dashboard")
    credit_course_link = _email_url_parser("courses", "?type=credit")

    # get attached branded logo
    logo_image = cache.get("credit.email.attached-logo")
    if logo_image is None:
        branded_logo = {"title": "Logo", "path": settings.NOTIFICATION_EMAIL_EDX_LOGO, "cid": str(uuid.uuid4())}
        logo_image_id = branded_logo["cid"]
        logo_image = attach_image(branded_logo, "Header Logo")
        if logo_image:
            cache.set("credit.email.attached-logo", logo_image, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT)
    else:
        # strip enclosing angle brackets from 'logo_image' cache 'Content-ID'
        logo_image_id = logo_image.get("Content-ID", "")[1:-1]

    providers_names = get_credit_provider_display_names(course_key)
    providers_string = make_providers_strings(providers_names)
    context = {
        "full_name": user.get_full_name(),
        "platform_name": theming_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
        "course_name": course_display_name,
        "branded_logo": logo_image_id,
        "dashboard_link": dashboard_link,
        "credit_course_link": credit_course_link,
        "tracking_pixel": tracking_pixel,
        "providers": providers_string,
    }

    # create the root email message
    notification_msg = MIMEMultipart("related")
    # add 'alternative' part to root email message to encapsulate the plain and
    # HTML versions, so message agents can decide which they want to display.
    msg_alternative = MIMEMultipart("alternative")
    notification_msg.attach(msg_alternative)
    # render the credit notification templates
    subject = _(u"Course Credit Eligibility")

    if providers_string:
        subject = _(u"You are eligible for credit from {providers_string}").format(providers_string=providers_string)

    # add alternative plain text message
    email_body_plain = render_to_string("credit_notifications/credit_eligibility_email.txt", context)
    msg_alternative.attach(SafeMIMEText(email_body_plain, _subtype="plain", _charset="utf-8"))

    # add alternative html message
    email_body_content = cache.get("credit.email.css-email-body")
    if email_body_content is None:
        html_file_path = file_path_finder("templates/credit_notifications/credit_eligibility_email.html")
        if html_file_path:
            with open(html_file_path, "r") as cur_file:
                cur_text = cur_file.read()
                # use html parser to unescape html characters which are changed
                # by the 'pynliner' while adding inline css to html content
                html_parser = HTMLParser.HTMLParser()
                email_body_content = html_parser.unescape(with_inline_css(cur_text))
                # cache the email body content before rendering it since the
                # email context will change for each user e.g., 'full_name'
                cache.set("credit.email.css-email-body", email_body_content, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT)
        else:
            email_body_content = ""

    email_body = Template(email_body_content).render([context])
    msg_alternative.attach(SafeMIMEText(email_body, _subtype="html", _charset="utf-8"))

    # attach logo image
    if logo_image:
        notification_msg.attach(logo_image)

    # add email addresses of sender and receiver
    from_address = theming_helpers.get_value("email_from_address", settings.DEFAULT_FROM_EMAIL)
    to_address = user.email

    # send the root email message
    msg = EmailMessage(subject, None, from_address, [to_address])
    msg.attach(notification_msg)
    msg.send()
コード例 #32
0
ファイル: email_utils.py プロジェクト: Rosivania/edx-platform
def send_credit_notifications(username, course_key):
    """Sends email notification to user on different phases during credit
    course e.g., credit eligibility, credit payment etc.
    """
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        log.error('No user with %s exist', username)
        return

    course = modulestore().get_course(course_key, depth=0)
    course_display_name = course.display_name
    tracking_context = tracker.get_tracker().resolve_context()
    tracking_id = str(tracking_context.get('user_id'))
    client_id = str(tracking_context.get('client_id'))
    events = '&t=event&ec=email&ea=open'
    tracking_pixel = 'https://www.google-analytics.com/collect?v=1&tid' + tracking_id + '&cid' + client_id + events
    dashboard_link = _email_url_parser('dashboard')
    credit_course_link = _email_url_parser('courses', '?type=credit')

    # get attached branded logo
    logo_image = cache.get('credit.email.attached-logo')
    if logo_image is None:
        branded_logo = {
            'title': 'Logo',
            'path': settings.NOTIFICATION_EMAIL_EDX_LOGO,
            'cid': str(uuid.uuid4())
        }
        logo_image_id = branded_logo['cid']
        logo_image = attach_image(branded_logo, 'Header Logo')
        if logo_image:
            cache.set('credit.email.attached-logo', logo_image, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT)
    else:
        # strip enclosing angle brackets from 'logo_image' cache 'Content-ID'
        logo_image_id = logo_image.get('Content-ID', '')[1:-1]

    providers_names = get_credit_provider_display_names(course_key)
    providers_string = make_providers_strings(providers_names)
    context = {
        'full_name': user.get_full_name(),
        'platform_name': settings.PLATFORM_NAME,
        'course_name': course_display_name,
        'branded_logo': logo_image_id,
        'dashboard_link': dashboard_link,
        'credit_course_link': credit_course_link,
        'tracking_pixel': tracking_pixel,
        'providers': providers_string,
    }

    # create the root email message
    notification_msg = MIMEMultipart('related')
    # add 'alternative' part to root email message to encapsulate the plain and
    # HTML versions, so message agents can decide which they want to display.
    msg_alternative = MIMEMultipart('alternative')
    notification_msg.attach(msg_alternative)
    # render the credit notification templates
    subject = _(u'Course Credit Eligibility')

    if providers_string:
        subject = _(u'You are eligible for credit from {providers_string}').format(
            providers_string=providers_string
        )

    # add alternative plain text message
    email_body_plain = render_to_string('credit_notifications/credit_eligibility_email.txt', context)
    msg_alternative.attach(SafeMIMEText(email_body_plain, _subtype='plain', _charset='utf-8'))

    # add alternative html message
    email_body_content = cache.get('credit.email.css-email-body')
    if email_body_content is None:
        html_file_path = file_path_finder('templates/credit_notifications/credit_eligibility_email.html')
        if html_file_path:
            with open(html_file_path, 'r') as cur_file:
                cur_text = cur_file.read()
                # use html parser to unescape html characters which are changed
                # by the 'pynliner' while adding inline css to html content
                html_parser = HTMLParser.HTMLParser()
                email_body_content = html_parser.unescape(with_inline_css(cur_text))
                # cache the email body content before rendering it since the
                # email context will change for each user e.g., 'full_name'
                cache.set('credit.email.css-email-body', email_body_content, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT)
        else:
            email_body_content = ''

    email_body = Template(email_body_content).render([context])
    msg_alternative.attach(SafeMIMEText(email_body, _subtype='html', _charset='utf-8'))

    # attach logo image
    if logo_image:
        notification_msg.attach(logo_image)

    # add email addresses of sender and receiver
    from_address = theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL)
    to_address = user.email

    # send the root email message
    msg = EmailMessage(subject, None, from_address, [to_address])
    msg.attach(notification_msg)
    msg.send()
コード例 #33
0
def send_credit_notifications(username, course_key):
    """Sends email notification to user on different phases during credit
    course e.g., credit eligibility, credit payment etc.
    """
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        log.error('No user with %s exist', username)
        return

    course = modulestore().get_course(course_key, depth=0)
    course_display_name = course.display_name
    tracking_context = tracker.get_tracker().resolve_context()
    tracking_id = str(tracking_context.get('user_id'))
    client_id = str(tracking_context.get('client_id'))
    events = '&t=event&ec=email&ea=open'
    tracking_pixel = 'https://www.google-analytics.com/collect?v=1&tid' + tracking_id + '&cid' + client_id + events
    dashboard_link = _email_url_parser('dashboard')
    credit_course_link = _email_url_parser('courses', '?type=credit')

    # get attached branded logo
    logo_image = cache.get('credit.email.attached-logo')
    if logo_image is None:
        branded_logo = {
            'title': 'Logo',
            'path': settings.NOTIFICATION_EMAIL_EDX_LOGO,
            'cid': str(uuid.uuid4())
        }
        logo_image_id = branded_logo['cid']
        logo_image = attach_image(branded_logo, 'Header Logo')
        if logo_image:
            cache.set('credit.email.attached-logo', logo_image,
                      settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT)
    else:
        # strip enclosing angle brackets from 'logo_image' cache 'Content-ID'
        logo_image_id = logo_image.get('Content-ID', '')[1:-1]

    providers_names = get_credit_provider_display_names(course_key)
    providers_string = make_providers_strings(providers_names)
    context = {
        'full_name': user.get_full_name(),
        'platform_name': settings.PLATFORM_NAME,
        'course_name': course_display_name,
        'branded_logo': logo_image_id,
        'dashboard_link': dashboard_link,
        'credit_course_link': credit_course_link,
        'tracking_pixel': tracking_pixel,
        'providers': providers_string,
    }

    # create the root email message
    notification_msg = MIMEMultipart('related')
    # add 'alternative' part to root email message to encapsulate the plain and
    # HTML versions, so message agents can decide which they want to display.
    msg_alternative = MIMEMultipart('alternative')
    notification_msg.attach(msg_alternative)
    # render the credit notification templates
    subject = _(u'Course Credit Eligibility')

    if providers_string:
        subject = _(u'You are eligible for credit from {providers_string}'
                    ).format(providers_string=providers_string)

    # add alternative plain text message
    email_body_plain = render_to_string(
        'credit_notifications/credit_eligibility_email.txt', context)
    msg_alternative.attach(
        SafeMIMEText(email_body_plain, _subtype='plain', _charset='utf-8'))

    # add alternative html message
    email_body_content = cache.get('credit.email.css-email-body')
    if email_body_content is None:
        html_file_path = file_path_finder(
            'templates/credit_notifications/credit_eligibility_email.html')
        if html_file_path:
            with open(html_file_path, 'r') as cur_file:
                cur_text = cur_file.read()
                # use html parser to unescape html characters which are changed
                # by the 'pynliner' while adding inline css to html content
                html_parser = HTMLParser.HTMLParser()
                email_body_content = html_parser.unescape(
                    with_inline_css(cur_text))
                # cache the email body content before rendering it since the
                # email context will change for each user e.g., 'full_name'
                cache.set('credit.email.css-email-body', email_body_content,
                          settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT)
        else:
            email_body_content = ''

    email_body = Template(email_body_content).render([context])
    msg_alternative.attach(
        SafeMIMEText(email_body, _subtype='html', _charset='utf-8'))

    # attach logo image
    if logo_image:
        notification_msg.attach(logo_image)

    # add email addresses of sender and receiver
    from_address = theming_helpers.get_value('default_from_email',
                                             settings.DEFAULT_FROM_EMAIL)
    to_address = user.email

    # send the root email message
    msg = EmailMessage(subject, None, from_address, [to_address])
    msg.attach(notification_msg)
    msg.send()
コード例 #34
0
def send_mail_to_student(student, param_dict, language=None):
    """
    Construct the email using templates and then send it.
    `student` is the student's email address (a `str`),

    `param_dict` is a `dict` with keys
    [
        `site_name`: name given to edX instance (a `str`)
        `registration_url`: url for registration (a `str`)
        `display_name` : display name of a course (a `str`)
        `course_id`: id of course (a `str`)
        `auto_enroll`: user input option (a `str`)
        `course_url`: url of course (a `str`)
        `email_address`: email of student (a `str`)
        `full_name`: student full name (a `str`)
        `message`: type of email to send and template to use (a `str`)
        `is_shib_course`: (a `boolean`)
    ]

    `language` is the language used to render the email. If None the language
    of the currently-logged in user (that is, the user sending the email) will
    be used.

    Returns a boolean indicating whether the email was sent successfully.
    """

    # add some helpers and microconfig subsitutions
    if 'display_name' in param_dict:
        param_dict['course_name'] = param_dict['display_name']

    param_dict['site_name'] = microsite.get_value(
        'SITE_NAME',
        param_dict['site_name']
    )

    subject = None
    message = None

    # see if we are running in a microsite and that there is an
    # activation email template definition available as configuration, if so, then render that
    message_type = param_dict['message']

    email_template_dict = {
        'allowed_enroll': (
            'emails/enroll_email_allowedsubject.txt',
            'emails/enroll_email_allowedmessage.txt'
        ),
        'enrolled_enroll': (
            'emails/enroll_email_enrolledsubject.txt',
            'emails/enroll_email_enrolledmessage.txt'
        ),
        'allowed_unenroll': (
            'emails/unenroll_email_subject.txt',
            'emails/unenroll_email_allowedmessage.txt'
        ),
        'enrolled_unenroll': (
            'emails/unenroll_email_subject.txt',
            'emails/unenroll_email_enrolledmessage.txt'
        ),
        'add_beta_tester': (
            'emails/add_beta_tester_email_subject.txt',
            'emails/add_beta_tester_email_message.txt'
        ),
        'remove_beta_tester': (
            'emails/remove_beta_tester_email_subject.txt',
            'emails/remove_beta_tester_email_message.txt'
        ),
        'account_creation_and_enrollment': (
            'emails/enroll_email_enrolledsubject.txt',
            'emails/account_creation_and_enroll_emailMessage.txt'
        ),
    }

    subject_template, message_template = email_template_dict.get(message_type, (None, None))
    if subject_template is not None and message_template is not None:
        subject, message = render_message_to_string(
            subject_template, message_template, param_dict, language=language
        )

    if subject and message:
        # Remove leading and trailing whitespace from body
        message = message.strip()

        # Email subject *must not* contain newlines
        subject = ''.join(subject.splitlines())
        from_address = theming_helpers.get_value(
            'email_from_address',
            settings.DEFAULT_FROM_EMAIL
        )

        send_mail(subject, message, from_address, [student], fail_silently=False)
コード例 #35
0
ファイル: enrollment.py プロジェクト: workrocks/edx-platform
def send_mail_to_student(student, param_dict, language=None):
    """
    Construct the email using templates and then send it.
    `student` is the student's email address (a `str`),

    `param_dict` is a `dict` with keys
    [
        `site_name`: name given to edX instance (a `str`)
        `registration_url`: url for registration (a `str`)
        `display_name` : display name of a course (a `str`)
        `course_id`: id of course (a `str`)
        `auto_enroll`: user input option (a `str`)
        `course_url`: url of course (a `str`)
        `email_address`: email of student (a `str`)
        `full_name`: student full name (a `str`)
        `message`: type of email to send and template to use (a `str`)
        `is_shib_course`: (a `boolean`)
    ]

    `language` is the language used to render the email. If None the language
    of the currently-logged in user (that is, the user sending the email) will
    be used.

    Returns a boolean indicating whether the email was sent successfully.
    """

    # add some helpers and microconfig subsitutions
    if 'display_name' in param_dict:
        param_dict['course_name'] = param_dict['display_name']

    param_dict['site_name'] = microsite.get_value('SITE_NAME',
                                                  param_dict['site_name'])

    subject = None
    message = None

    # see if we are running in a microsite and that there is an
    # activation email template definition available as configuration, if so, then render that
    message_type = param_dict['message']

    email_template_dict = {
        'allowed_enroll': ('emails/enroll_email_allowedsubject.txt',
                           'emails/enroll_email_allowedmessage.txt'),
        'enrolled_enroll': ('emails/enroll_email_enrolledsubject.txt',
                            'emails/enroll_email_enrolledmessage.txt'),
        'allowed_unenroll': ('emails/unenroll_email_subject.txt',
                             'emails/unenroll_email_allowedmessage.txt'),
        'enrolled_unenroll': ('emails/unenroll_email_subject.txt',
                              'emails/unenroll_email_enrolledmessage.txt'),
        'add_beta_tester': ('emails/add_beta_tester_email_subject.txt',
                            'emails/add_beta_tester_email_message.txt'),
        'remove_beta_tester': ('emails/remove_beta_tester_email_subject.txt',
                               'emails/remove_beta_tester_email_message.txt'),
        'account_creation_and_enrollment':
        ('emails/enroll_email_enrolledsubject.txt',
         'emails/account_creation_and_enroll_emailMessage.txt'),
    }

    subject_template, message_template = email_template_dict.get(
        message_type, (None, None))
    if subject_template is not None and message_template is not None:
        subject, message = render_message_to_string(subject_template,
                                                    message_template,
                                                    param_dict,
                                                    language=language)

    if subject and message:
        # Remove leading and trailing whitespace from body
        message = message.strip()

        # Email subject *must not* contain newlines
        subject = ''.join(subject.splitlines())
        from_address = theming_helpers.get_value('email_from_address',
                                                 settings.DEFAULT_FROM_EMAIL)

        send_mail(subject,
                  message,
                  from_address, [student],
                  fail_silently=False)