def send_failed_notice(repo_id, transaction_id, timestamp, user_email): BLOXBERG_MSG = [] msg = _( 'The certification has failed, please try again in a few minutes. In case it keeps failing, please contact the Keeper Support.' ) BLOXBERG_MSG.append(msg) UserNotification.objects._add_user_notification( user_email, MSG_TYPE_KEEPER_BLOXBERG_MSG, json.dumps({ 'message': ('; '.join(BLOXBERG_MSG)), 'repo_id': repo_id, 'author_name': email2nickname(user_email), })) c1 = { 'to_user': user_email, 'notice_count': 1, 'message_type': 'certify_snapshot_failed_msg', #message_type for email 'message': ('; '.join(BLOXBERG_MSG)), 'repo_id': repo_id, 'author_name': email2nickname(user_email), 'timestamp': timestamp, } try: send_html_email( _('New notice on %s') % get_site_name(), 'notifications/keeper_email.html', c1, None, [user_email]) logger.info('Successfully sent email to %s' % user_email) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (user_email, e)) admin_email = '*****@*****.**' BLOXBERG_MSG.append(f'repo_id: {repo_id}') BLOXBERG_MSG.append(f'transaction_id: {transaction_id}') c2 = { 'to_user': admin_email, 'notice_count': 1, 'message_type': 'certify_snapshot_failed_msg', #message_type for email 'message': ('; '.join(BLOXBERG_MSG)), 'repo_id': repo_id, 'author_name': 'Keeper Admins', 'timestamp': timestamp, } try: send_html_email( _('New notice on %s') % get_site_name(), 'notifications/keeper_email.html', c2, None, [admin_email]) logger.info('Successfully sent email to %s' % admin_email) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (admin_email, e))
def send_to(self, email=None): """ Send an invitation email to ``email``. """ if not email: email = self.accepter context = self.to_dict() context['site_name'] = get_site_name() subject = _('You are invited to join %(site_name)s.') % {'site_name': get_site_name()} return send_html_email_with_dj_template(email, subject=subject, dj_template='invitations/invitation_email.html', context=context)
def send_email(self, email): # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(email) translation.activate(user_language) orgs = ccnet_api.get_orgs_by_user(email) if orgs: org_id = orgs[0].org_id quota_usage = seafile_api.get_org_user_quota_usage(org_id, email) quota_total = seafile_api.get_org_user_quota(org_id, email) else: quota_usage = seafile_api.get_user_self_usage(email) quota_total = seafile_api.get_user_quota(email) if IS_EMAIL_CONFIGURED and quota_total > 0 and quota_usage/quota_total > 0.9: data = {'email': email, 'quota_total': quota_total, 'quota_usage': quota_usage} contact_email = Profile.objects.get_contact_email_by_user(email) print('Send email to %s(%s)' % (contact_email, email)) send_html_email(_(u'Your quota is almost full on %s') % get_site_name(), 'user_quota_full.html', data, None, [contact_email]) # restore current language translation.activate(cur_language)
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}, sender=None, template=None, message='', headers=None, priority=None, backend=''): """ Arguments: - `recipients`: - `subject`: - `sender`: - `template`: - `context`: """ # get logo path logo_path = LOGO_PATH custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': get_site_name(), 'media_url': MEDIA_URL, 'logo_path': logo_path, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(context) return mail.send(recipients, sender=sender, template=template, context=context, subject=subject, message=message, html_message=html_message, headers=headers, priority=priority, backend=backend)
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html', use_https=False, token_generator=default_token_generator): """ Generates a one-use only link for resetting password and sends to the user """ user = self.users_cache if not domain_override: site_name = get_site_name() else: site_name = domain_override c = { 'email': user.username, 'uid': int_to_base36(user.id), 'user': user, 'token': token_generator.make_token(user), } send_html_email( _("Reset Password on %s") % site_name, email_template_name, c, None, [user.username])
def email_admins(self): db_users = seaserv.get_emailusers('DB', -1, -1) ldpa_imported_users = seaserv.get_emailusers('LDAPImport', -1, -1) admins = [] for user in db_users + ldpa_imported_users: if user.is_staff: admins.append(user) for u in admins: # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(u.email) translation.activate(user_language) send_html_email_with_dj_template( u.email, dj_template='notifications/notify_virus.html', subject=_('Virus detected on %s') % get_site_name(), priority=MAIL_PRIORITY.now ) # restore current language translation.activate(cur_language)
def freeze_user(self, notify_admins=False): self.is_active = False self.save() if notify_admins: admins = get_system_admins() for u in admins: # save current language cur_language = translation.get_language() # get and active user language user_language = Profile.objects.get_user_language(u.email) translation.activate(user_language) send_html_email_with_dj_template( u.email, dj_template='sysadmin/user_freeze_email.html', subject=_('Account %(account)s froze on %(site)s.') % { "account": self.email, "site": get_site_name(), }, context={'user': self.email}, priority=MAIL_PRIORITY.now) # restore current language translation.activate(cur_language)
def email_repo_owner(self, repo_file): repo_id, file_path = repo_file.split(':', 1) owner = seafile_api.get_repo_owner(repo_id) if not owner: return # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(owner) translation.activate(user_language) contact_email = Profile.objects.get_contact_email_by_user(owner) send_html_email_with_dj_template( contact_email, subject=_('Virus detected on %s') % get_site_name(), dj_template='notifications/notify_virus.html', context={ 'owner': owner, 'file_url': reverse('view_lib_file', args=[repo_id, file_path]), 'file_name': os.path.basename(file_path) }) # restore current language translation.activate(cur_language)
def email_repo_owner(self, repo_file): repo_id, file_path = repo_file.split(':', 1) owner = seafile_api.get_repo_owner(repo_id) if not owner: return # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(owner) translation.activate(user_language) contact_email = Profile.objects.get_contact_email_by_user(owner) send_html_email_with_dj_template( contact_email, dj_template='notifications/notify_virus.html', context={'owner': owner, 'file_url': reverse('view_lib_file', args=[repo_id, file_path]), 'file_name': os.path.basename(file_path), }, subject=_('Virus detected on %s') % get_site_name(), priority=MAIL_PRIORITY.now ) # restore current language translation.activate(cur_language)
def email_user_on_activation(user): """Send an email to user when admin activate his/her account. """ c = { 'username': user.email, } send_html_email(_('Your account on %s is activated') % get_site_name(), 'sysadmin/user_activation_email.html', c, None, [user.email])
def send_group_member_add_mail(request, group, from_user, to_user): c = { 'email': from_user, 'to_email': to_user, 'group': group, } subject = _(u'You are invited to join a group on %s') % get_site_name() send_html_email(subject, 'group/add_member_email.html', c, None, [to_user])
def send_user_add_mail(request, email, password): """Send email when add new user.""" c = { 'user': request.user.username, 'org': request.user.org, 'email': email, 'password': password, } send_html_email(_('You are invited to join %s') % get_site_name(), 'sysadmin/user_add_email.html', c, None, [email])
def post(self, request, token, format=None): """Revoke invitation when the accepter successfully creates an account. And set the account to inactive. """ # recourse check invitation = Invitation.objects.get_by_token(token) if not invitation: error_msg = "Invitation not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if request.user.username != invitation.inviter: error_msg = "Permission denied." return api_error(status.HTTP_403_FORBIDDEN, error_msg) if invitation.accept_time is None: error_msg = "The email address didn't accept the invitation." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) email = invitation.accepter inviter = invitation.inviter try: user = User.objects.get(email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) # set the account to inactive. user.freeze_user() # delete the invitation. invitation.delete() # send email site_name = get_site_name() subject = _('%(user)s revoked your access to %(site_name)s.') % { 'user': email2nickname(inviter), 'site_name': site_name } context = { 'inviter': email2nickname(inviter), 'site_name': site_name, } send_success = send_html_email_with_dj_template( email, subject=subject, dj_template='invitations/invitation_revoke_email.html', context=context) if not send_success: logger.warning('send revoke access email to %s failed') return Response({'success': True})
def put(self, request, email): """Reset password for user Permission checking: 1. only admin can perform this action. """ if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') if not is_valid_username2(email): error_msg = 'email invalid' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: user = User.objects.get(email=email) except User.DoesNotExist as e: logger.error(e) error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if isinstance(INIT_PASSWD, FunctionType): new_password = INIT_PASSWD() else: new_password = INIT_PASSWD user.set_password(new_password) user.save() if config.FORCE_PASSWORD_CHANGE: UserOptions.objects.set_force_passwd_change(user.username) if IS_EMAIL_CONFIGURED: if SEND_EMAIL_ON_RESETTING_USER_PASSWD: c = {'email': email, 'password': new_password} contact_email = Profile.objects.get_contact_email_by_user( email) try: send_html_email( _(u'Password has been reset on %s') % get_site_name(), 'sysadmin/user_reset_email.html', c, None, [contact_email]) reset_tip = _('Successfully reset password to %(passwd)s, an email has been sent to %(user)s.') % \ {'passwd': new_password, 'user': contact_email} except Exception as e: logger.warning(e) reset_tip = _('Successfully reset password to %(passwd)s, but failed to send email to %(user)s, please check your email configuration.') % \ {'passwd': new_password, 'user': email} else: reset_tip = _('Successfully reset password to %(passwd)s for user %(user)s.') % \ {'passwd': new_password, 'user': email} else: reset_tip = _('Successfully reset password to %(passwd)s for user %(user)s. But email notification can not be sent, because Email service is not properly configured.') % \ {'passwd': new_password, 'user': email} return Response({'new_password': new_password, 'reset_tip': reset_tip})
def send_user_reset_email(request, email, password): """ Send email when reset user password. """ c = { 'email': email, 'password': password, } send_html_email(_('Password has been reset on %s') % get_site_name(), 'sysadmin/user_reset_email.html', c, None, [email])
def send_to(self, email=None): """ Send an invitation email to ``email``. """ if not email: email = self.accepter context = self.to_dict() context['site_name'] = get_site_name() # subject = render_to_string('invitations/invitation_email_subject.txt', # context).rstrip() subject = _('%(user)s invited you to join %(site_name)s.') % { 'user': self.inviter, 'site_name': get_site_name()} return send_html_email_with_dj_template( email, dj_template='invitations/invitation_email.html', context=context, subject=subject, priority=MAIL_PRIORITY.now )
def email_mail_list(self): try: notify_list = dj_settings.VIRUS_SCAN_NOTIFY_LIST except AttributeError: return for mail in notify_list: send_html_email_with_dj_template( mail, subject=_('Virus detected on %s') % get_site_name(), dj_template='notifications/notify_virus.html')
def email_mail_list(self): try: notify_list = dj_settings.VIRUS_SCAN_NOTIFY_LIST except AttributeError: return for mail in notify_list: send_html_email_with_dj_template( mail, dj_template='notifications/notify_virus.html', subject=_('Virus detected on %s') % get_site_name(), priority=MAIL_PRIORITY.now )
def email_user_on_activation(user): """Send an email to user when admin activate his/her account. """ send_to = user.username profile = Profile.objects.get_profile_by_user(user.username) if profile and profile.contact_email: send_to = profile.contact_email c = { 'username': send_to, } send_html_email(_('Your account on %s is activated') % get_site_name(), 'sysadmin/user_activation_email.html', c, None, [send_to])
def send_final_notification(repo_id, path, transaction_id, timestamp, user_email, content_type): BLOXBERG_MSG = [] msg = _('Your data was successfully certified!') msg_transaction = 'Transaction ID: ' + transaction_id file_name = path.rsplit('/', 1)[-1] repo_name = get_repo(repo_id).repo_name BLOXBERG_MSG.append(msg) BLOXBERG_MSG.append(msg_transaction) UserNotification.objects._add_user_notification( user_email, MSG_TYPE_KEEPER_BLOXBERG_MSG, json.dumps({ 'message': ('; '.join(BLOXBERG_MSG)), 'content_type': content_type, 'transaction_id': transaction_id, 'repo_id': repo_id, 'repo_name': repo_name, 'link_to_file': path, 'file_name': file_name, 'author_name': email2nickname(user_email), })) c = { 'to_user': user_email, 'notice_count': 1, 'message_type': 'bloxberg_msg', 'content_type': content_type, 'message': ('; '.join(BLOXBERG_MSG)), 'transaction_id': transaction_id, 'repo_id': repo_id, 'repo_name': repo_name, 'link_to_file': path, 'file_name': file_name, 'author_name': email2nickname(user_email), 'timestamp': timestamp, } try: send_html_email( _('New notice on %s') % get_site_name(), 'notifications/keeper_email.html', c, None, [user_email]) logger.info('Successfully sent email to %s' % user_email) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (user_email, e))
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}, sender=None, template=None, message='', headers=None, priority=None, backend=''): """ Arguments: - `recipients`: - `subject`: - `sender`: - `template`: - `context`: """ # get logo path logo_path = LOGO_PATH custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': get_site_name(), 'media_url': MEDIA_URL, 'logo_path': logo_path, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(context) mail.send(recipients, sender=sender, template=template, context=context, subject=subject, message=message, html_message=html_message, headers=headers, priority=priority, backend=backend)
def send_user_add_mail(request, email, password): """Send email when add new user.""" c = { 'user': request.user.username, 'org': request.user.org, 'email': email, 'password': password, } # KEEPER try: from keeper.utils import get_user_name c['user'] = get_user_name(c['user']) except Exception as e: logger.error(str(e)) send_html_email( _('You are invited to join %s') % get_site_name(), 'sysadmin/user_add_email.html', c, None, [email])
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html', use_https=False, token_generator=default_token_generator): """ Generates a one-use only link for resetting password and sends to the user """ user = self.users_cache if not domain_override: site_name = get_site_name() else: site_name = domain_override c = { 'email': user.username, 'uid': int_to_base36(user.id), 'user': user, 'token': token_generator.make_token(user), } send_html_email(_("Reset Password on %s") % site_name, email_template_name, c, None, [user.username])
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}): """ Arguments: - `recipients`: - `subject`: - `dj_template`: - `context`: """ # get logo path logo_path = LOGO_PATH custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': get_site_name(), 'media_url': MEDIA_URL, 'logo_path': logo_path, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(context) mail = EmailMessage(subject=subject, body=html_message, to=[recipients]) mail.content_subtype = "html" try: mail.send() return True except Exception as e: logger.error(e) return False
def put(self, request, email): """Reset password for user Permission checking: 1. only admin can perform this action. """ if not is_valid_username(email): error_msg = 'email invalid' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: user = User.objects.get(email=email) except User.DoesNotExist as e: logger.error(e) error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if isinstance(INIT_PASSWD, FunctionType): new_password = INIT_PASSWD() else: new_password = INIT_PASSWD user.set_password(new_password) user.save() if config.FORCE_PASSWORD_CHANGE: UserOptions.objects.set_force_passwd_change(user.username) if IS_EMAIL_CONFIGURED and SEND_EMAIL_ON_RESETTING_USER_PASSWD: c = {'email': email, 'password': new_password} try: send_html_email(_(u'Password has been reset on %s') % get_site_name(), 'sysadmin/user_reset_email.html', c, None, [email]) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'new_password': new_password})
def send_start_snapshot_notification(repo_id, timestamp, user_email): BLOXBERG_MSG = [] repo_name = get_repo(repo_id).repo_name msg = _( 'Your files with the library %(name)s are currently being certified. We will inform you once the task has successfully finished. This may take a while.' ) % { 'name': repo_name } BLOXBERG_MSG.append(msg) UserNotification.objects._add_user_notification( user_email, MSG_TYPE_KEEPER_BLOXBERG_MSG, json.dumps({ 'message': ('; '.join(BLOXBERG_MSG)), 'repo_id': repo_id, 'author_name': email2nickname(user_email), })) c = { 'to_user': user_email, 'notice_count': 1, 'message_type': 'start_snapshot_msg', #message_type for email 'message': ('; '.join(BLOXBERG_MSG)), 'repo_id': repo_id, 'author_name': email2nickname(user_email), 'timestamp': timestamp, } try: send_html_email( _('New notice on %s') % get_site_name(), 'notifications/keeper_email.html', c, None, [user_email]) logger.info('Successfully sent email to %s' % user_email) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (user_email, e))
def base(request): """ Add seahub base configure to the context. """ try: org = request.user.org except AttributeError: org = None # extra repo id from request path, use in search repo_id_patt = r".*/([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})/.*" m = re.match(repo_id_patt, request.get_full_path()) search_repo_id = m.group(1) if m is not None else None file_server_root = config.FILE_SERVER_ROOT if not file_server_root.endswith('/'): file_server_root += '/' logo_path = LOGO_PATH favicon_path = FAVICON_PATH # filter ajax/api request out if (not request.is_ajax()) and ("api2/" not in request.path) and \ ("api/v2.1/" not in request.path): # get logo path custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH # get favicon path custom_favicon_file = os.path.join(MEDIA_ROOT, CUSTOM_FAVICON_PATH) if os.path.exists(custom_favicon_file): favicon_path = CUSTOM_FAVICON_PATH result = { 'seafile_version': SEAFILE_VERSION, 'site_title': config.SITE_TITLE, 'enable_branding_css': config.ENABLE_BRANDING_CSS, 'favicon_path': favicon_path, 'logo_path': logo_path, 'logo_width': LOGO_WIDTH, 'logo_height': LOGO_HEIGHT, 'seacloud_mode': SEACLOUD_MODE, 'cloud_mode': request.cloud_mode, 'org': org, 'site_name': get_site_name(), 'enable_signup': config.ENABLE_SIGNUP, 'max_file_name': MAX_FILE_NAME, 'has_file_search': HAS_FILE_SEARCH, 'enable_pubfile': ENABLE_PUBFILE, 'show_repo_download_button': SHOW_REPO_DOWNLOAD_BUTTON, 'share_link_password_min_length': config.SHARE_LINK_PASSWORD_MIN_LENGTH, 'repo_password_min_length': config.REPO_PASSWORD_MIN_LENGTH, 'events_enabled': EVENTS_ENABLED, 'traffic_stats_enabled': TRAFFIC_STATS_ENABLED, 'sysadmin_extra_enabled': ENABLE_SYSADMIN_EXTRA, 'multi_tenancy': MULTI_TENANCY, 'multi_institution': getattr(dj_settings, 'MULTI_INSTITUTION', False), 'search_repo_id': search_repo_id, 'SITE_ROOT': SITE_ROOT, 'constance_enabled': dj_settings.CONSTANCE_ENABLED, 'FILE_SERVER_ROOT': file_server_root, 'enable_thumbnail': ENABLE_THUMBNAIL, 'thumbnail_size_for_original': THUMBNAIL_SIZE_FOR_ORIGINAL, 'enable_guest_invitation': ENABLE_GUEST_INVITATION, 'enable_terms_and_conditions': dj_settings.ENABLE_TERMS_AND_CONDITIONS, 'show_logout_icon': SHOW_LOGOUT_ICON, 'is_pro': True if is_pro_version() else False, } if request.user.is_staff: result['is_default_admin'] = request.user.admin_role == DEFAULT_ADMIN return result
def do_action(self): today = datetime.utcnow().replace(hour=0).replace(minute=0).replace( second=0).replace(microsecond=0) emails = [] user_file_updates_email_intervals = [] for ele in UserOptions.objects.filter( option_key=KEY_FILE_UPDATES_EMAIL_INTERVAL): try: user_file_updates_email_intervals.append( (ele.email, int(ele.option_val)) ) emails.append(ele.email) except Exception as e: logger.error(e) continue user_last_emailed_time_dict = {} for ele in UserOptions.objects.filter( option_key=KEY_FILE_UPDATES_LAST_EMAILED_TIME).filter( email__in=emails): try: user_last_emailed_time_dict[ele.email] = datetime.strptime( ele.option_val, "%Y-%m-%d %H:%M:%S") except Exception as e: logger.error(e) continue for (username, interval_val) in user_file_updates_email_intervals: # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(username) translation.activate(user_language) logger.debug('Set language code to %s for user: %s' % ( user_language, username)) self.stdout.write('[%s] Set language code to %s' % ( str(datetime.now()), user_language)) # get last_emailed_time if any, defaults to today last_emailed_time = user_last_emailed_time_dict.get(username, today) now = datetime.utcnow().replace(microsecond=0) if (now - last_emailed_time).seconds < interval_val: continue # get file updates(from: last_emailed_time, to: now) for repos # user can access res = seafevents_api.get_user_activities_by_timestamp( username, last_emailed_time, now) if not res: continue # remove my activities res = filter(lambda x: x.op_user != username, res) if not res: continue # format mail content & send file updates email to user try: for ele in res: ele.user_avatar = self.get_avatar_src(ele.op_user) ele.local_timestamp = utc_to_local(ele.timestamp) ele.op_user_link = a_tag(email2nickname(ele.op_user), user_info_url(ele.op_user)) ele.operation, ele.op_details = self.format_file_operation(ele) except Exception as e: logger.error('Failed to format mail content for user: %s' % username) logger.error(e, exc_info=True) continue nickname = email2nickname(username) contact_email = Profile.objects.get_contact_email_by_user(username) c = { 'name': nickname, 'updates_count': len(res), 'updates': res, } try: send_html_email(_('New file updates on %s') % get_site_name(), 'notifications/file_updates_email.html', c, None, [contact_email]) # set new last_emailed_time UserOptions.objects.set_file_updates_last_emailed_time( username, now) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (contact_email, e)) self.stderr.write('[%s] Failed to send email to %s, error ' 'detail: %s' % (str(now), contact_email, e)) finally: # reset lang translation.activate(cur_language)
def do_action(self): now = datetime.now() today = datetime.now().replace(hour=0).replace(minute=0).replace( second=0).replace(microsecond=0) # 1. get all users who are connected wechat work socials = UserSocialAuth.objects.filter(provider='weixin-work') users = [(x.username, x.uid) for x in socials] if not users: return user_uid_map = {} for username, uid in users: user_uid_map[username] = uid # 2. get previous time that command last runs try: cmd_last_check = CommandsLastCheck.objects.get(command_type=self.label) self.log_debug('Last check time is %s' % cmd_last_check.last_check) last_check_dt = cmd_last_check.last_check cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: last_check_dt = today self.log_debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() # 3. get all unseen notices for those users qs = UserNotification.objects.filter( timestamp__gt=last_check_dt ).filter(seen=False).filter( to_user__in=user_uid_map.keys() ) user_notices = {} for q in qs: if q.to_user not in user_notices: user_notices[q.to_user] = [q] else: user_notices[q.to_user].append(q) # 4. send msg to users url = get_site_scheme_and_netloc().rstrip('/') + reverse('user_notification_list') for username, uid in users: notices = user_notices.get(username, []) count = len(notices) if count == 0: continue # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(username) translation.activate(user_language) self.log_debug('Set language code to %s for user: %s' % ( user_language, username)) title = ungettext( "\n" "You've got 1 new notice on %(site_name)s:\n", "\n" "You've got %(num)s new notices on %(site_name)s:\n", count ) % { 'num': count, 'site_name': get_site_name(), } content = ''.join([wrap_div(x.format_msg()) for x in notices]) self.send_wx_msg(uid, title, content, url) translation.activate(cur_language)
def post(self, request): if not IS_EMAIL_CONFIGURED: error_msg = _('Sending shared link failed. Email service is not properly configured, please contact administrator.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check args email = request.POST.get('email', None) if not email: error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) token = request.POST.get('token', None) if not token: error_msg = 'token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) extra_msg = request.POST.get('extra_msg', '') # check if token exists try: link = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'token %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check if is share link owner username = request.user.username if not link.is_owner(username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) result = {} result['failed'] = [] result['success'] = [] to_email_list = string2list(email) # use contact_email, if present useremail = Profile.objects.get_contact_email_by_user(request.user.username) for to_email in to_email_list: failed_info = {} if not is_valid_email(to_email): failed_info['email'] = to_email failed_info['error_msg'] = 'email invalid.' result['failed'].append(failed_info) continue # prepare basic info c = { 'email': username, 'to_email': to_email, 'extra_msg': extra_msg, } if REPLACE_FROM_EMAIL: from_email = useremail else: from_email = None # use default from email if ADD_REPLY_TO_HEADER: reply_to = useremail else: reply_to = None c['file_shared_link'] = gen_shared_link(token, link.s_type) c['file_shared_name'] = os.path.basename(link.path.rstrip('/')) template = 'shared_link_email.html' if link.s_type == 'f': c['file_shared_type'] = _("file") title = _('A file is shared to you on %s') % get_site_name() else: c['file_shared_type'] = _("directory") title = _('A directory is shared to you on %s') % get_site_name() # send email try: send_html_email(title, template, c, from_email, [to_email], reply_to=reply_to) result['success'].append(to_email) except Exception as e: logger.error(e) failed_info['email'] = to_email failed_info['error_msg'] = 'Internal Server Error' result['failed'].append(failed_info) return Response(result)
def do_action(self): emails = [] user_file_updates_email_intervals = [] for ele in UserOptions.objects.filter( option_key=KEY_FILE_UPDATES_EMAIL_INTERVAL): try: user_file_updates_email_intervals.append( (ele.email, int(ele.option_val))) emails.append(ele.email) except Exception as e: logger.error(e) self.stderr.write('[%s]: %s' % (str(datetime.now()), e)) continue user_last_emailed_time_dict = {} for ele in UserOptions.objects.filter( option_key=KEY_FILE_UPDATES_LAST_EMAILED_TIME).filter( email__in=emails): try: user_last_emailed_time_dict[ele.email] = datetime.strptime( ele.option_val, "%Y-%m-%d %H:%M:%S") except Exception as e: logger.error(e) self.stderr.write('[%s]: %s' % (str(datetime.now()), e)) continue for (username, interval_val) in user_file_updates_email_intervals: # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(username) translation.activate(user_language) logger.debug('Set language code to %s for user: %s' % (user_language, username)) self.stdout.write('[%s] Set language code to %s for user: %s' % (str(datetime.now()), user_language, username)) # get last_emailed_time if any, defaults to today 00:00:00.0 last_emailed_time = user_last_emailed_time_dict.get(username, None) now = datetime.utcnow().replace(microsecond=0) if not last_emailed_time: last_emailed_time = datetime.utcnow().replace(hour=0).replace( minute=0).replace(second=0).replace(microsecond=0) else: if (now - last_emailed_time).total_seconds() < interval_val: continue # get file updates(from: last_emailed_time, to: now) for repos # user can access res = seafevents_api.get_user_activities_by_timestamp( username, last_emailed_time, now) if not res: continue # remove my activities res = [x for x in res if x.op_user != username] if not res: continue # format mail content & send file updates email to user try: for ele in res: ele.user_avatar = self.get_avatar_src(ele.op_user) ele.local_timestamp = utc_to_local(ele.timestamp) ele.op_user_link = a_tag(email2nickname(ele.op_user), user_info_url(ele.op_user)) ele.operation, ele.op_details = self.format_file_operation( ele) except Exception as e: logger.error('Failed to format mail content for user: %s' % username) logger.error(e, exc_info=True) self.stderr.write( '[%s] Failed to format mail content for user: %s' % (str(datetime.now()), username)) self.stderr.write('[%s]: %s' % (str(datetime.now()), e)) continue nickname = email2nickname(username) contact_email = Profile.objects.get_contact_email_by_user(username) c = { 'name': nickname, 'updates_count': len(res), 'updates': res, } try: send_html_email( _('New file updates on %s') % get_site_name(), 'notifications/file_updates_email.html', c, None, [contact_email]) # set new last_emailed_time UserOptions.objects.set_file_updates_last_emailed_time( username, now) self.stdout.write('[%s] Successful to send email to %s' % (str(datetime.now()), contact_email)) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (contact_email, e)) self.stderr.write('[%s] Failed to send email to %s, error ' 'detail: %s' % (str(datetime.now()), contact_email, e)) finally: # reset lang translation.activate(cur_language)
def post(self, request): if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') if user_number_over_limit(): error_msg = _("The number of users exceeds the limit.") return api_error(status.HTTP_400_BAD_REQUEST, error_msg) email = request.data.get('email', None) if not email or not is_valid_email(email): error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # basic user info check is_staff = request.data.get("is_staff", 'False') try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", 'True') try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = '' if is_pro_version(): role = request.data.get("role", None) if role: available_roles = get_available_roles() if role not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) contact_email = request.data.get('contact_email', None) if contact_email and not is_valid_email(contact_email): error_msg = 'contact_email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: User.objects.get(email=email) user_exist = True except User.DoesNotExist: user_exist = False if user_exist: error_msg = "User %s already exists." % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.data.get('password', None) if not password: error_msg = 'password required.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # create user try: user_obj = User.objects.create_user(email, password, is_staff, is_active) create_user_info(request, email=user_obj.username, role=role, nickname=name, contact_email=contact_email, quota_total_mb=quota_total_mb) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) add_user_tip = _('Successfully added user %(user)s.') % {'user': email} if IS_EMAIL_CONFIGURED and SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER: c = { 'user': request.user.username, 'email': email, 'password': password } try: send_html_email( _('You are invited to join %s') % get_site_name(), 'sysadmin/user_add_email.html', c, None, [email2contact_email(email)]) add_user_tip = _( 'Successfully added user %(user)s. An email notification has been sent.' ) % { 'user': email } except Exception as e: logger.error(str(e)) add_user_tip = _( 'Successfully added user %(user)s. But email notification can not be sent, because Email service is not properly configured.' ) % { 'user': email } user_info = get_user_info(email) user_info['add_user_tip'] = add_user_tip # send admin operation log signal admin_op_detail = { "email": email, } admin_operation.send(sender=None, admin_name=request.user.username, operation=USER_ADD, detail=admin_op_detail) return Response(user_info)
def send_shared_upload_link(request): """ Handle ajax post request to send shared upload link. """ if not request.method == 'POST': raise Http404 content_type = 'application/json; charset=utf-8' if not IS_EMAIL_CONFIGURED: data = json.dumps({'error':_(u'Sending shared upload link failed. Email service is not properly configured, please contact administrator.')}) return HttpResponse(data, status=500, content_type=content_type) form = UploadLinkShareForm(request.POST) if form.is_valid(): email = form.cleaned_data['email'] shared_upload_link = form.cleaned_data['shared_upload_link'] extra_msg = escape(form.cleaned_data['extra_msg']) to_email_list = string2list(email) send_success, send_failed = [], [] # use contact_email, if present username = Profile.objects.get_contact_email_by_user(request.user.username) for to_email in to_email_list: if not is_valid_email(to_email): send_failed.append(to_email) continue # Add email to contacts. mail_sended.send(sender=None, user=request.user.username, email=to_email) c = { 'email': request.user.username, 'to_email': to_email, 'shared_upload_link': shared_upload_link, } if extra_msg: c['extra_msg'] = extra_msg if REPLACE_FROM_EMAIL: from_email = username else: from_email = None # use default from email if ADD_REPLY_TO_HEADER: reply_to = username else: reply_to = None try: send_html_email(_(u'An upload link is shared to you on %s') % get_site_name(), 'shared_upload_link_email.html', c, from_email, [to_email], reply_to=reply_to) send_success.append(to_email) except Exception: send_failed.append(to_email) if len(send_success) > 0: data = json.dumps({"send_success": send_success, "send_failed": send_failed}) return HttpResponse(data, status=200, content_type=content_type) else: data = json.dumps({"error": _("Internal server error, or please check the email(s) you entered")}) return HttpResponse(data, status=400, content_type=content_type) else: return HttpResponseBadRequest(json.dumps(form.errors), content_type=content_type)
def send_shared_upload_link(request): """ Handle ajax post request to send shared upload link. """ if not request.method == 'POST': raise Http404 content_type = 'application/json; charset=utf-8' if not IS_EMAIL_CONFIGURED: data = json.dumps({ 'error': _('Failed to send email, email service is not properly configured, please contact administrator.' ) }) return HttpResponse(data, status=500, content_type=content_type) form = UploadLinkShareForm(request.POST) if form.is_valid(): email = form.cleaned_data['email'] shared_upload_link = form.cleaned_data['shared_upload_link'] extra_msg = escape(form.cleaned_data['extra_msg']) to_email_list = string2list(email) send_success, send_failed = [], [] # use contact_email, if present username = Profile.objects.get_contact_email_by_user( request.user.username) for to_email in to_email_list: if not is_valid_email(to_email): send_failed.append(to_email) continue # Add email to contacts. mail_sended.send(sender=None, user=request.user.username, email=to_email) c = { 'email': request.user.username, 'to_email': to_email, 'shared_upload_link': shared_upload_link, } if extra_msg: c['extra_msg'] = extra_msg if REPLACE_FROM_EMAIL: from_email = username else: from_email = None # use default from email if ADD_REPLY_TO_HEADER: reply_to = username else: reply_to = None try: send_html_email(_('An upload link is shared to you on %s') % get_site_name(), 'shared_upload_link_email.html', c, from_email, [to_email], reply_to=reply_to) send_success.append(to_email) except Exception: send_failed.append(to_email) if len(send_success) > 0: data = json.dumps({ "send_success": send_success, "send_failed": send_failed }) return HttpResponse(data, status=200, content_type=content_type) else: data = json.dumps({ "error": _("Internal server error, or please check the email(s) you entered" ) }) return HttpResponse(data, status=400, content_type=content_type) else: return HttpResponseBadRequest(json.dumps(form.errors), content_type=content_type)
def post(self, request): if not IS_EMAIL_CONFIGURED: error_msg = _(u'Sending shared link failed. Email service is not properly configured, please contact administrator.') return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check args email = request.POST.get('email', None) if not email: error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) token = request.POST.get('token', None) if not token: error_msg = 'token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) extra_msg = request.POST.get('extra_msg', '') # check if token exists try: link = UploadLinkShare.objects.get(token=token) except UploadLinkShare.DoesNotExist: error_msg = 'token %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check if is upload link owner username = request.user.username if not link.is_owner(username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) result = {} result['failed'] = [] result['success'] = [] to_email_list = string2list(email) # use contact_email, if present useremail = Profile.objects.get_contact_email_by_user(request.user.username) for to_email in to_email_list: failed_info = {} if not is_valid_email(to_email): failed_info['email'] = to_email failed_info['error_msg'] = 'email invalid.' result['failed'].append(failed_info) continue # prepare basic info c = { 'email': username, 'to_email': to_email, 'extra_msg': extra_msg, } if REPLACE_FROM_EMAIL: from_email = useremail else: from_email = None # use default from email if ADD_REPLY_TO_HEADER: reply_to = useremail else: reply_to = None c['shared_upload_link'] = gen_shared_upload_link(token) title = _(u'An upload link is shared to you on %s') % get_site_name() template = 'shared_upload_link_email.html' # send email try: send_html_email(title, template, c, from_email, [to_email], reply_to=reply_to) result['success'].append(to_email) except Exception as e: logger.error(e) failed_info['email'] = to_email failed_info['error_msg'] = 'Internal Server Error' result['failed'].append(failed_info) return Response(result)
def put(self, request, email): if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') # basic user info check is_staff = request.data.get("is_staff", None) if is_staff: try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", None) if is_active: try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = request.data.get("role", None) if role: available_roles = get_available_roles() if role not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # argument check for login_id login_id = request.data.get("login_id", None) if login_id is not None: login_id = login_id.strip() username_by_login_id = Profile.objects.get_username_by_login_id( login_id) if username_by_login_id is not None: return api_error(status.HTTP_400_BAD_REQUEST, _("Login id %s already exists." % login_id)) contact_email = request.data.get("contact_email", None) if contact_email is not None and contact_email.strip() != '': if not is_valid_email(contact_email): error_msg = 'Contact email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.data.get("password") reference_id = request.data.get("reference_id", None) if reference_id: if ' ' in reference_id: return api_error(status.HTTP_400_BAD_REQUEST, 'Reference ID can not contain spaces.') primary_id = ccnet_api.get_primary_id(reference_id) if primary_id: return api_error( status.HTTP_400_BAD_REQUEST, 'Reference ID %s already exists.' % reference_id) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) institution = request.data.get("institution", None) if institution: try: Institution.objects.get(name=institution) except Institution.DoesNotExist: error_msg = 'Institution %s does not exist' % institution return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # query user info try: user_obj = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: update_user_info(request, user=user_obj, password=password, is_active=is_active, is_staff=is_staff, role=role, nickname=name, login_id=login_id, contact_email=contact_email, reference_id=reference_id, quota_total_mb=quota_total_mb, institution_name=institution) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # update user try: user_obj.save() except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) update_status_tip = '' if is_active is not None: update_status_tip = _('Edit succeeded') if user_obj.is_active and IS_EMAIL_CONFIGURED: try: send_html_email( _(u'Your account on %s is activated') % get_site_name(), 'sysadmin/user_activation_email.html', {'username': user_obj.email}, None, [email2contact_email(user_obj.email)]) update_status_tip = _( 'Edit succeeded, an email has been sent.') except Exception as e: logger.error(e) update_status_tip = _( 'Edit succeeded, but failed to send email, please check your email configuration.' ) user_info = get_user_info(email) user_info['update_status_tip'] = update_status_tip return Response(user_info)
def post(self, request): """ Import users from xlsx file Permission checking: 1. admin user. """ xlsx_file = request.FILES.get('file', None) if not xlsx_file: error_msg = 'file can not be found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_type, ext = get_file_type_and_ext(xlsx_file.name) if ext != 'xlsx': error_msg = file_type_error_msg(ext, 'xlsx') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) content = xlsx_file.read() try: fs = BytesIO(content) wb = load_workbook(filename=fs, read_only=True) except Exception as e: logger.error(e) # example file is like: # Email Password Name(Optional) Role(Optional) Space Quota(MB, Optional) # [email protected] a a default 1024 # [email protected] b b default 2048 rows = wb.worksheets[0].rows records = [] # skip first row(head field). next(rows) for row in rows: records.append([col.value for col in row]) if user_number_over_limit(new_users=len(records)): error_msg = 'The number of users exceeds the limit.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] for record in records: if record[0]: email = record[0].strip() if not is_valid_username(email): result['failed'].append({ 'email': email, 'error_msg': 'email %s invalid.' % email }) continue else: result['failed'].append({ 'email': '', 'error_msg': 'email invalid.' }) continue if record[1]: password = str(record[1]).strip() if not password: result['failed'].append({ 'email': email, 'error_msg': 'password invalid.' }) continue else: result['failed'].append({ 'email': email, 'error_msg': 'password invalid.' }) continue vid = get_virtual_id_by_email(email) try: User.objects.get(email=vid) result['failed'].append({ 'email': email, 'error_msg': 'user %s exists.' % email }) continue except User.DoesNotExist: pass user = User.objects.create_user(email, password, is_staff=False, is_active=True) virtual_id = get_virtual_id_by_email(email) if config.FORCE_PASSWORD_CHANGE: UserOptions.objects.set_force_passwd_change(virtual_id) # update the user's optional info # update nikename nickname = email.split('@')[0] try: if record[2]: input_nickname = str(record[2]).strip() if len(input_nickname) <= 64 and '/' not in input_nickname: nickname = input_nickname Profile.objects.add_or_update(virtual_id, nickname, '') except Exception as e: logger.error(e) # update role if record[3]: try: role = record[3].strip() if is_pro_version() and role in get_available_roles(): User.objects.update_role(virtual_id, role) except Exception as e: logger.error(e) # update quota if record[4]: try: space_quota_mb = int(record[4]) if space_quota_mb >= 0: space_quota = int(space_quota_mb) * get_file_size_unit('MB') seafile_api.set_user_quota(virtual_id, space_quota) except Exception as e: logger.error(e) try: send_html_email_with_dj_template( email, dj_template='sysadmin/user_batch_add_email.html', subject=_('You are invited to join %s') % get_site_name(), context={ 'user': email2nickname(request.user.username), 'email': email, 'password': password, }) except Exception as e: logger.error(e) user_info = get_user_info(virtual_id) result['success'].append(user_info) # send admin operation log signal admin_op_detail = { "email": email, } admin_operation.send(sender=None, admin_name=request.user.username, operation=USER_ADD, detail=admin_op_detail) return Response(result)
def do_action(self): now = datetime.datetime.now() try: cmd_last_check = CommandsLastCheck.objects.get(command_type=self.label) logger.debug('Last check time is %s' % cmd_last_check.last_check) unseen_notices = UserNotification.objects.get_all_notifications( seen=False, time_since=cmd_last_check.last_check) logger.debug('Update last check time to %s' % now) cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: logger.debug('No last check time found, get all unread notices.') unseen_notices = UserNotification.objects.get_all_notifications( seen=False) logger.debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() email_ctx = {} for notice in unseen_notices: if notice.to_user in email_ctx: email_ctx[notice.to_user] += 1 else: email_ctx[notice.to_user] = 1 for to_user, count in email_ctx.items(): # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(to_user) translation.activate(user_language) logger.debug('Set language code to %s for user: %s' % (user_language, to_user)) self.stdout.write('[%s] Set language code to %s' % ( str(datetime.datetime.now()), user_language)) notices = [] for notice in unseen_notices: logger.info('Processing unseen notice: [%s]' % (notice)) d = json.loads(notice.detail) repo_id = d.get('repo_id', None) group_id = d.get('group_id', None) try: if repo_id and not seafile_api.get_repo(repo_id): notice.delete() continue if group_id and not ccnet_api.get_group(group_id): notice.delete() continue except Exception as e: logger.error(e) continue if notice.to_user != to_user: continue elif notice.is_group_msg(): notice = self.format_group_message(notice) elif notice.is_repo_share_msg(): notice = self.format_repo_share_msg(notice) elif notice.is_repo_share_to_group_msg(): notice = self.format_repo_share_to_group_msg(notice) elif notice.is_file_uploaded_msg(): notice = self.format_file_uploaded_msg(notice) elif notice.is_group_join_request(): notice = self.format_group_join_request(notice) elif notice.is_add_user_to_group(): notice = self.format_add_user_to_group(notice) elif notice.is_file_comment_msg(): notice = self.format_file_comment_msg(notice) elif notice.is_guest_invitation_accepted_msg(): notice = self.format_guest_invitation_accepted_msg(notice) if notice is None: continue notices.append(notice) if not notices: continue contact_email = Profile.objects.get_contact_email_by_user(to_user) to_user = contact_email # use contact email if any c = { 'to_user': to_user, 'notice_count': count, 'notices': notices, } try: send_html_email(_('New notice on %s') % get_site_name(), 'notifications/notice_email.html', c, None, [to_user]) logger.info('Successfully sent email to %s' % to_user) self.stdout.write('[%s] Successfully sent email to %s' % (str(datetime.datetime.now()), to_user)) except Exception as e: logger.error('Failed to send email to %s, error detail: %s' % (to_user, e)) self.stderr.write('[%s] Failed to send email to %s, error detail: %s' % (str(datetime.datetime.now()), to_user, e)) # restore current language translation.activate(cur_language)