def assert_get_sailthru_client_raises(self, exc_class, config): """ Asserts an error is raised by a call to get_sailthru_client. """ overrides = { self.SITE_CODE: { 'SAILTHRU': config } } with mock.patch.dict(self.SITE_OVERRIDES_MODULE, overrides): with self.assertRaises(exc_class): get_sailthru_client(self.SITE_CODE)
def _get_client(self): """ Return the sailthru client or None if exception raised. """ sailthru_client = None try: sailthru_client = get_sailthru_client(self.site_code) except SailthruError: log.exception( '[{logger_prefix}] A client error occurred while attempting to send a notification.' ' Message: {message}'.format( logger_prefix=self.logger_prefix, message=self.email_vars.get('email_body') ) ) return sailthru_client
def test_get_sailthru_client(self): """ Verify the method returns an authenticated SailthruClient. """ key = 'key' secret = 'secret' overrides = { self.SITE_CODE: { 'SAILTHRU': { 'SAILTHRU_ENABLE': True, 'SAILTHRU_KEY': key, 'SAILTHRU_SECRET': secret } } } with mock.patch.dict(self.SITE_OVERRIDES_MODULE, overrides): client = get_sailthru_client(self.SITE_CODE) self.assertEqual(client.api_key, key) self.assertEqual(client.secret, secret)
def _send_offer_assignment_notification_email(config, user_email, subject, email_body, site_code, task): """Handles sending offer assignment notification emails and retrying failed emails when appropriate.""" try: sailthru_client = get_sailthru_client(site_code) except SailthruError: logger.exception( '[Offer Assignment] A client error occurred while attempting to send a offer assignment notification.' ' Message: {message}'.format(message=email_body)) return None email_vars = { 'subject': subject, 'email_body': email_body, } try: response = sailthru_client.send( template=config['templates']['assignment_email'], email=user_email, _vars=email_vars) except SailthruClientError: logger.exception( '[Offer Assignment] A client error occurred while attempting to send a offer assignment notification.' ' Message: {message}'.format(message=email_body)) return None if not response.is_ok(): error = response.get_error() logger.error( '[Offer Assignment] A {token_error_code} - {token_error_message} error occurred' ' while attempting to send a offer assignment notification.' ' Message: {message}'.format( message=email_body, token_error_code=error.get_error_code(), token_error_message=error.get_message())) if can_retry_sailthru_request(error): logger.info( '[Offer Assignment] An attempt will be made to resend the offer assignment notification.' ' Message: {message}'.format(message=email_body)) schedule_retry(task, config) else: logger.warning( '[Offer Assignment] No further attempts will be made to send the offer assignment notification.' ' Failed Message: {message}'.format(message=email_body)) return response
def send_course_refund_email(self, email, refund_id, amount, course_name, order_number, order_url, site_code=None): """ Sends the course refund email. Args: self: Ignore. email (str): Recipient's email address. refund_id (int): ID of the refund that initiated this task. amount (str): Formatted amount of the refund. course_name (str): Name of the course for which payment was refunded. order_number (str): Order number of the order that was refunded. order_url (str): Receipt URL of the refunded order. site_code (str): Identifier of the site sending the email. """ config = get_sailthru_configuration(site_code) try: sailthru_client = get_sailthru_client(site_code) except SailthruError: # NOTE: We rely on the function to log the error for us return email_vars = { 'amount': amount, 'course_name': course_name, 'order_number': order_number, 'order_url': order_url, } try: response = sailthru_client.send( template=config['templates']['course_refund'], email=email, _vars=email_vars) except SailthruClientError: logger.exception( 'A client error occurred while attempting to send a course refund notification for refund [%d].', refund_id) return if response.is_ok(): logger.info('Course refund notification sent for refund %d.', refund_id) else: error = response.get_error() logger.error( 'An error occurred while attempting to send a course refund notification for refund [%d]: %d - %s', refund_id, error.get_error_code(), error.get_message()) if can_retry_sailthru_request(error): logger.info( 'An attempt will be made again to send a course refund notification for refund [%d].', refund_id) schedule_retry(self, config) else: logger.warning( 'No further attempts will be made to send a course refund notification for refund [%d].', refund_id)
def update_course_enrollment(self, email, course_url, purchase_incomplete, mode, unit_cost=None, course_id=None, currency=None, message_id=None, site_code=None, sku=None): """Adds/updates Sailthru when a user adds to cart/purchases/upgrades a course Args: email(str): The user's email address course_url(str): Course home page url purchase_incomplete(boolean): True if adding to cart mode(string): enroll mode (audit, verification, ...) unit_cost(decimal): cost if purchase event course_id(CourseKey): course id currency(str): currency if purchase event - currently ignored since Sailthru only supports USD message_id(str): value from Sailthru marketing campaign cookie site_code(str): site code Returns: None """ # Get configuration config = get_sailthru_configuration(site_code) try: sailthru_client = get_sailthru_client(site_code) except SailthruError: # NOTE: We rely on the function to log the error for us return # Use event type to figure out processing required new_enroll = False send_template = None if not purchase_incomplete: if mode == 'verified': # upgrade complete send_template = config.get('SAILTHRU_UPGRADE_TEMPLATE') elif mode == 'audit' or mode == 'honor': # free enroll new_enroll = True send_template = config.get('SAILTHRU_ENROLL_TEMPLATE') else: # paid course purchase complete new_enroll = True send_template = config.get('SAILTHRU_PURCHASE_TEMPLATE') # calc price in pennies for Sailthru # https://getstarted.sailthru.com/new-for-developers-overview/advanced-features/purchase/ cost_in_cents = int(unit_cost * 100) # update the "unenrolled" course array in the user record on Sailthru if new enroll or unenroll if new_enroll: if not _update_unenrolled_list(sailthru_client, email, course_url, False): schedule_retry(self, config) # Get course data from Sailthru content library or cache course_data = _get_course_content(course_id, course_url, sailthru_client, site_code, config) # build item description item = _build_purchase_item(course_id, course_url, cost_in_cents, mode, course_data, sku) # build purchase api options list options = {} if purchase_incomplete and config.get('SAILTHRU_ABANDONED_CART_TEMPLATE'): options['reminder_template'] = config.get( 'SAILTHRU_ABANDONED_CART_TEMPLATE') # Sailthru reminder time format is '+n time unit' options['reminder_time'] = "+{} minutes".format( config.get('SAILTHRU_ABANDONED_CART_DELAY')) # add appropriate send template if send_template: options['send_template'] = send_template if not _record_purchase(sailthru_client, email, item, purchase_incomplete, message_id, options): schedule_retry(self, config)