def VALIDATE_EMAIL(parts=None, reply_address_object=None, from_address=None, **kwargs): """process the validation email and save the email signature todo: go a step further and """ reply_code = reply_address_object.address try: content, stored_files, signature = mail.process_parts( parts, reply_code) user = reply_address_object.user if signature and signature != user.email_signature: user.email_signature = signature user.email_isvalid = True user.save() data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': askbot_settings.APP_URL, 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail(subject_line=_('Re: Welcome to %(site_name)s') % data, body_text=template.render(Context(data)), recipient_list=[ from_address, ]) except ValueError: raise ValueError( _('Please reply to the welcome email ' 'without editing it'))
def VALIDATE_EMAIL(parts=None, reply_address_object=None, from_address=None, **kwargs): """process the validation email and save the email signature todo: go a step further and """ reply_code = reply_address_object.address try: content, stored_files, signature = mail.process_parts(parts, reply_code) user = reply_address_object.user if signature and signature != user.email_signature: user.email_signature = signature user.email_isvalid = True user.save() data = { "site_name": askbot_settings.APP_SHORT_NAME, "site_url": askbot_settings.APP_URL, "ask_address": "ask@" + askbot_settings.REPLY_BY_EMAIL_HOSTNAME, } template = get_template("email/re_welcome_lamson_on.html") mail.send_mail( subject_line=_("Re: Welcome to %(site_name)s") % data, body_text=template.render(Context(data)), recipient_list=[from_address], ) except ValueError: raise ValueError(_("Please reply to the welcome email " "without editing it"))
def send_instant_notifications_about_activity_in_post(update_activity=None, post=None, recipients=None): # reload object from the database post = Post.objects.get(id=post.id) if post.is_approved() is False: return if recipients is None: return acceptable_types = const.RESPONSE_ACTIVITY_TYPES_FOR_INSTANT_NOTIFICATIONS if update_activity.activity_type not in acceptable_types: return # calculate some variables used in the loop below update_type_map = const.RESPONSE_ACTIVITY_TYPE_MAP_FOR_TEMPLATES update_type = update_type_map[update_activity.activity_type] origin_post = post.get_origin_post() headers = mail.thread_headers(post, origin_post, update_activity.activity_type) logger = logging.getLogger() if logger.getEffectiveLevel() <= logging.DEBUG: log_id = uuid.uuid1() message = "email-alert %s, logId=%s" % (post.get_absolute_url(), log_id) logger.debug(message) else: log_id = None for user in recipients: if user.is_blocked(): continue reply_address, alt_reply_address = get_reply_to_addresses(user, post) subject_line, body_text = format_instant_notification_email( to_user=user, from_user=update_activity.user, post=post, reply_address=reply_address, alt_reply_address=alt_reply_address, update_type=update_type, template=get_template("email/instant_notification.html"), ) headers["Reply-To"] = reply_address try: mail.send_mail( subject_line=subject_line, body_text=body_text, recipient_list=[user.email], related_object=origin_post, activity_type=const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT, headers=headers, raise_on_failure=True, ) except askbot_exceptions.EmailNotSent, error: logger.debug("%s, error=%s, logId=%s" % (user.email, error, log_id)) else: logger.debug("success %s, logId=%s" % (user.email, log_id))
def process_reply(func): @functools.wraps(func) def wrapped(message, host = None, address = None): """processes forwarding rules, and run the handler in the case of error, send a bounce email """ try: for rule in django_settings.LAMSON_FORWARD: if re.match(rule['pattern'], message.base['to']): relay = Relay(host=rule['host'], port=rule['port'], debug=1) relay.deliver(message) return except AttributeError: pass error = None try: reply_address = ReplyAddress.objects.get( address = address, allowed_from_email = message.From ) #here is the business part of this function parts = get_parts(message) for part_type, content in parts: if part_type == 'body': print '===============================' print 'message :', content break else: continue func( from_address = message.From, subject_line = message['Subject'], parts = parts, reply_address_object = reply_address ) except ReplyAddress.DoesNotExist: error = _("You were replying to an email address\ unknown to the system or you were replying from a different address from the one where you\ received the notification.") except Exception, e: import sys sys.stderr.write(str(e)) import traceback sys.stderr.write(traceback.format_exc()) if error is not None: template = get_template('email/reply_by_email_error.html') body_text = template.render(Context({'error':error})) mail.send_mail( subject_line = "Error posting your reply", body_text = body_text, recipient_list = [message.From], )
def notify_moderator(user): template = get_template('email/notify_moderator.html') subject_line = _('%s moderation alert') % askbot_settings.APP_SHORT_NAME, mail.send_mail( subject_line=subject_line, body_text=template.render({'user': user}), recipient_list=[user,] )
def notify_moderator(user): template = get_template('email/notify_moderator.html') subject_line = _('%s moderation alert') % askbot_settings.APP_SHORT_NAME, mail.send_mail(subject_line=subject_line, body_text=template.render({'user': user}), recipient_list=[ user, ])
def PROCESS(parts=None, reply_address_object=None, subject_line=None, from_address=None, **kwargs): """handler to process the emailed message and make a post to askbot based on the contents of the email, including the text body and the file attachments""" #1) get actual email content # todo: factor this out into the process_reply decorator reply_code = reply_address_object.address body_text, stored_files, signature = mail.process_parts(parts, reply_code) #2) process body text and email signature user = reply_address_object.user if signature is not None: #if there, then it was stripped if signature != user.email_signature: user.email_signature = signature else: #try to strip signature stripped_body_text = user.strip_email_signature(body_text) #todo: add test cases for emails without the signature if stripped_body_text == body_text and user.email_signature: #todo: send an email asking to update the signature raise ValueError('email signature changed or unknown') body_text = stripped_body_text #3) validate email address and save user user.email_isvalid = True user.save() #todo: actually, saving is not necessary, if nothing changed #4) actually make an edit in the forum robj = reply_address_object add_post_actions = ('post_comment', 'post_answer', 'auto_answer_or_comment') if robj.reply_action == 'replace_content': robj.edit_post(body_text, title=subject_line) elif robj.reply_action == 'append_content': robj.edit_post(body_text) #in this case we don't touch the title elif robj.reply_action in add_post_actions: if robj.was_used: robj.edit_post(body_text, edit_response=True) else: robj.create_reply(body_text) elif robj.reply_action == 'validate_email': #todo: this is copy-paste - factor it out to askbot.mail.messages data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': askbot_settings.APP_URL, 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail( subject_line=_('Re: %s') % subject_line, body_text=template.render(Context(data)), #todo: set lang recipient_list=[ from_address, ])
def PROCESS( parts = None, reply_address_object = None, subject_line = None, from_address = None, **kwargs ): """handler to process the emailed message and make a post to askbot based on the contents of the email, including the text body and the file attachments""" #1) get actual email content # todo: factor this out into the process_reply decorator reply_code = reply_address_object.address body_text, stored_files, signature = mail.process_parts(parts, reply_code) #2) process body text and email signature user = reply_address_object.user if signature:#if there, then it was stripped if signature != user.email_signature: user.email_signature = signature else:#try to strip signature stripped_body_text = user.strip_email_signature(body_text) #todo: add test cases for emails without the signature if stripped_body_text == body_text and user.email_signature: #todo: send an email asking to update the signature raise ValueError('email signature changed or unknown') body_text = stripped_body_text #3) validate email address and save user user.email_isvalid = True user.save()#todo: actually, saving is not necessary, if nothing changed #4) actually make an edit in the forum robj = reply_address_object add_post_actions = ('post_comment', 'post_answer', 'auto_answer_or_comment') if robj.reply_action == 'replace_content': robj.edit_post(body_text, title = subject_line) elif robj.reply_action == 'append_content': robj.edit_post(body_text)#in this case we don't touch the title elif robj.reply_action in add_post_actions: if robj.was_used: robj.edit_post(body_text, edit_response = True) else: robj.create_reply(body_text) elif robj.reply_action == 'validate_email': #todo: this is copy-paste - factor it out to askbot.mail.messages data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': askbot_settings.APP_URL, 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail( subject_line = _('Re: %s') % subject_line, body_text = template.render(Context(data)), recipient_list = [from_address,] )
def PROCESS(parts=None, reply_address_object=None, subject_line=None, from_address=None, **kwargs): """handler to process the emailed message and make a post to askbot based on the contents of the email, including the text body and the file attachments""" #1) get actual email content # todo: factor this out into the process_reply decorator reply_code = reply_address_object.address body_text, stored_files, signature = mail.process_parts( parts, reply_code, from_address) #2) process body text and email signature user = reply_address_object.user if signature != user.email_signature: user.email_signature = signature #3) validate email address and save user along with maybe new signature user.email_isvalid = True user.save() #todo: actually, saving is not necessary, if nothing changed #here we might be in danger of chomping off some of the #message is body text ends with a legitimate text coinciding with #the user's email signature body_text = user.strip_email_signature(body_text) #4) actually make an edit in the forum robj = reply_address_object add_post_actions = ('post_comment', 'post_answer', 'auto_answer_or_comment') if robj.reply_action == 'replace_content': robj.edit_post(body_text, title=subject_line) elif robj.reply_action == 'append_content': robj.edit_post(body_text) #in this case we don't touch the title elif robj.reply_action in add_post_actions: if robj.was_used: robj.edit_post(body_text, edit_response=True) else: robj.create_reply(body_text) elif robj.reply_action == 'validate_email': #todo: this is copy-paste - factor it out to askbot.mail.messages data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': site_url(reverse('questions')), 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail( subject_line=_('Re: %s') % subject_line, body_text=template.render(Context(data)), #todo: set lang recipient_list=[ from_address, ])
def notify_author_of_published_revision_celery_task(revision): #todo: move this to ``askbot.mail`` module #for answerable email only for now, because #we don't yet have the template for the read-only notification data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'post': revision.post } headers = None if askbot_settings.REPLY_BY_EMAIL: #generate two reply codes (one for edit and one for addition) #to format an answerable email or not answerable email reply_options = { 'user': revision.author, 'post': revision.post, 'reply_action': 'append_content' } append_content_address = ReplyAddress.objects.create_new( **reply_options ).as_email_address() reply_options['reply_action'] = 'replace_content' replace_content_address = ReplyAddress.objects.create_new( **reply_options ).as_email_address() #populate template context variables reply_code = append_content_address + ',' + replace_content_address if revision.post.post_type == 'question': mailto_link_subject = revision.post.thread.title else: mailto_link_subject = _('make an edit by email') #todo: possibly add more mailto thread headers to organize messages prompt = _('To add to your post EDIT ABOVE THIS LINE') reply_separator_line = const.SIMPLE_REPLY_SEPARATOR_TEMPLATE % prompt data['reply_code'] = reply_code data['author_email_signature'] = revision.author.email_signature data['replace_content_address'] = replace_content_address data['reply_separator_line'] = reply_separator_line data['mailto_link_subject'] = mailto_link_subject headers = {'Reply-To': append_content_address} #load the template activate_language(revision.post.language_code) template = get_template('email/notify_author_about_approved_post.html') #todo: possibly add headers to organize messages in threads #send the message mail.send_mail( subject_line = _('Your post at %(site_name)s is now published') % data, body_text = template.render(Context(data)), recipient_list = [revision.author.email,], related_object = revision, activity_type = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT, headers = headers )
def process_reply(func): @functools.wraps(func) def wrapped(message, host=None, address=None): """processes forwarding rules, and run the handler in the case of error, send a bounce email """ try: for rule in django_settings.LAMSON_FORWARD: if re.match(rule['pattern'], message.base['to']): relay = Relay(host=rule['host'], port=rule['port'], debug=1) relay.deliver(message) return except AttributeError: pass error = None try: reply_address = ReplyAddress.objects.get( address=address, allowed_from_email=message.From) #here is the business part of this function parts = get_parts(message) for part_type, content in parts: if part_type == 'body': print '===============================' print 'message :', content break else: continue func(from_address=message.From, subject_line=message['Subject'], parts=parts, reply_address_object=reply_address) except ReplyAddress.DoesNotExist: error = _("You were replying to an email address\ unknown to the system or you were replying from a different address from the one where you\ received the notification.") except Exception, e: import sys sys.stderr.write(str(e)) import traceback sys.stderr.write(traceback.format_exc()) if error is not None: template = get_template('email/reply_by_email_error.html') body_text = template.render(Context({'error': error})) mail.send_mail( subject_line="Error posting your reply", body_text=body_text, recipient_list=[message.From], )
def PROCESS( parts = None, reply_address_object = None, subject_line = None, from_address = None, **kwargs ): """handler to process the emailed message and make a post to askbot based on the contents of the email, including the text body and the file attachments""" #1) get actual email content # todo: factor this out into the process_reply decorator reply_code = reply_address_object.address body_text, stored_files, signature = mail.process_parts(parts, reply_code) #2) process body text and email signature user = reply_address_object.user if signature != user.email_signature: user.email_signature = signature #3) validate email address and save user along with maybe new signature user.email_isvalid = True user.save()#todo: actually, saving is not necessary, if nothing changed #here we might be in danger of chomping off some of the #message is body text ends with a legitimate text coinciding with #the user's email signature body_text = user.strip_email_signature(body_text) #4) actually make an edit in the forum robj = reply_address_object add_post_actions = ('post_comment', 'post_answer', 'auto_answer_or_comment') if robj.reply_action == 'replace_content': robj.edit_post(body_text, title = subject_line) elif robj.reply_action == 'append_content': robj.edit_post(body_text)#in this case we don't touch the title elif robj.reply_action in add_post_actions: if robj.was_used: robj.edit_post(body_text, edit_response = True) else: robj.create_reply(body_text) elif robj.reply_action == 'validate_email': #todo: this is copy-paste - factor it out to askbot.mail.messages data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': site_url(reverse('questions')), 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail( subject_line = _('Re: %s') % subject_line, body_text = template.render(Context(data)),#todo: set lang recipient_list = [from_address,] )
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_ACCEPT_ANSWER_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_ANSWER_REMINDER, askbot_settings.ACCEPT_ANSWER_REMINDER_FREQUENCY, askbot_settings.MAX_ACCEPT_ANSWER_REMINDERS) questions = models.Post.objects.get_questions().exclude( deleted=True).added_between( start=schedule.start_cutoff_date, end=schedule.end_cutoff_date ).filter(thread__answer_count__gt=0).filter( thread__accepted_answer__isnull=True #answer_accepted = False ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status='b'): user_questions = questions.filter(author=user) final_question_list = user_questions.get_questions_needing_reminder( activity_type=const.TYPE_ACTIVITY_ACCEPT_ANSWER_REMINDER_SENT, user=user, recurrence_delay=schedule.recurrence_delay) #todo: rewrite using query set filter #may be a lot more efficient question_count = len(final_question_list) if question_count == 0: continue reminder_phrase = _('Please select the best responses to:') data = { 'site_url': site_url(''), #here we need only the domain name 'questions': final_question_list, 'reminder_phrase': reminder_phrase, 'recipient_user': user } template = get_template('email/accept_answer_reminder.html') body_text = template.render(Context(data)) #todo: set lang subject_line = askbot_settings.WORDS_ACCEPT_BEST_ANSWERS_FOR_YOUR_QUESTIONS if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail(subject_line=subject_line, body_text=body_text, recipient_list=(user.email, ))
def feedback(request): data = {'page_class': 'meta'} form = None if askbot_settings.ALLOW_ANONYMOUS_FEEDBACK is False: if request.user.is_anonymous(): message = _('Please sign in or register to send your feedback') request.user.message_set.create(message=message) redirect_url = get_login_url() + '?next=' + request.path return HttpResponseRedirect(redirect_url) if request.method == "POST": form = FeedbackForm( is_auth=request.user.is_authenticated(), data=request.POST ) if form.is_valid(): if not request.user.is_authenticated(): data['email'] = form.cleaned_data.get('email', None) else: data['email'] = request.user.email data['message'] = form.cleaned_data['message'] data['name'] = form.cleaned_data.get('name', None) template = get_template('email/feedback_email.txt') message = template.render(RequestContext(request, data)) headers = {} if data['email']: headers = {'Reply-To': data['email']} subject = _('Q&A forum feedback') if askbot_settings.FEEDBACK_EMAILS: recipients = re.split('\s*,\s*', askbot_settings.FEEDBACK_EMAILS) send_mail( subject_line=subject, body_text=message, headers=headers, recipient_list=recipients, ) else: mail_moderators( subject_line=subject, body_text=message, headers=headers ) msg = _('Thanks for the feedback!') request.user.message_set.create(message=msg) return HttpResponseRedirect(get_next_url(request)) else: form = FeedbackForm(is_auth = request.user.is_authenticated(), initial={'next':get_next_url(request)}) data['form'] = form return render(request, 'feedback.html', data)
def notify_author_of_published_revision_celery_task(revision): #todo: move this to ``askbot.mail`` module #for answerable email only for now, because #we don't yet have the template for the read-only notification if askbot_settings.REPLY_BY_EMAIL: #generate two reply codes (one for edit and one for addition) #to format an answerable email or not answerable email reply_options = { 'user': revision.author, 'post': revision.post, 'reply_action': 'append_content' } append_content_address = ReplyAddress.objects.create_new( **reply_options).as_email_address() reply_options['reply_action'] = 'replace_content' replace_content_address = ReplyAddress.objects.create_new( **reply_options).as_email_address() #populate template context variables reply_code = append_content_address + ',' + replace_content_address if revision.post.post_type == 'question': mailto_link_subject = revision.post.thread.title else: mailto_link_subject = _('make an edit by email') #todo: possibly add more mailto thread headers to organize messages prompt = _('To add to your post EDIT ABOVE THIS LINE') reply_separator_line = const.SIMPLE_REPLY_SEPARATOR_TEMPLATE % prompt data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'post': revision.post, 'author_email_signature': revision.author.email_signature, 'replace_content_address': replace_content_address, 'reply_separator_line': reply_separator_line, 'mailto_link_subject': mailto_link_subject, 'reply_code': reply_code } #load the template activate_language(revision.post.language_code) template = get_template('email/notify_author_about_approved_post.html') #todo: possibly add headers to organize messages in threads headers = {'Reply-To': append_content_address} #send the message mail.send_mail( subject_line=_('Your post at %(site_name)s is now published') % data, body_text=template.render(Context(data)), recipient_list=[ revision.author.email, ], related_object=revision, activity_type=const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT, headers=headers)
def __notify_if_duplicate_subject(subject, user, link): presentations = models.Presentation.objects.filter(subject=subject, deleted=False) if presentations.count() > 1: from askbot import mail, const mail.send_mail( subject_line = "Duplicate presentation subject", body_text = "You may need to change the subject of <a href='http://askbot%s'>this post</a>. <br/> <br/>\ This mail is sent automatically, please do not reply." % link, recipient_list = [user.email], activity_type = const.TYPE_ACTIVITY_VALIDATION_EMAIL_SENT, headers = {'Reply-To': "*****@*****.**"} )
def feedback(request): data = {'page_class': 'meta'} form = None if askbot_settings.ALLOW_ANONYMOUS_FEEDBACK is False: if request.user.is_anonymous(): message = _('Please sign in or register to send your feedback') request.user.message_set.create(message=message) redirect_url = get_login_url() + '?next=' + request.path return HttpResponseRedirect(redirect_url) if request.method == "POST": form = FeedbackForm(is_auth=request.user.is_authenticated(), data=request.POST) if form.is_valid(): if not request.user.is_authenticated(): data['email'] = form.cleaned_data.get('email', None) else: data['email'] = request.user.email data['message'] = form.cleaned_data['message'] data['name'] = form.cleaned_data.get('name', None) template = get_template('email/feedback_email.txt') message = template.render(RequestContext(request, data)) headers = {} if data['email']: headers = {'Reply-To': data['email']} subject = _('Q&A forum feedback') if askbot_settings.FEEDBACK_EMAILS: recipients = re.split('\s*,\s*', askbot_settings.FEEDBACK_EMAILS) send_mail( subject_line=subject, body_text=message, headers=headers, recipient_list=recipients, ) else: mail_moderators(subject_line=subject, body_text=message, headers=headers) msg = _('Thanks for the feedback!') request.user.message_set.create(message=msg) return HttpResponseRedirect(get_next_url(request)) else: form = FeedbackForm(is_auth=request.user.is_authenticated(), initial={'next': get_next_url(request)}) data['form'] = form return render(request, 'feedback.html', data)
def send_email_key(email, key, handler_url_name="user_account_recover"): """private function. sends email containing validation key to user's email address """ subject = _("Recover your %(site)s account") % {"site": askbot_settings.APP_SHORT_NAME} data = { "site_name": askbot_settings.APP_SHORT_NAME, "validation_link": site_url(reverse(handler_url_name)) + "?validation_code=" + key, } template = get_template("authopenid/email_validation.html") message = template.render(data) # todo: inject language preference send_mail(subject, message, django_settings.DEFAULT_FROM_EMAIL, [email])
def report_exception(self, user): """reports exception that happened during sending email alert to user""" message = self.format_debug_msg(user, traceback.format_exc()) print(message) admin_email = askbot_settings.ADMIN_EMAIL try: subject = "Error processing daily/weekly notification for User '%s' for Site '%s'" % (user.username, SITE_ID) send_mail(subject_line=subject, body_text=message, recipient_list=[admin_email]) except: message = "ERROR: was unable to report this exception to %s: %s" % (admin_email, traceback.format_exc()) print(self.format_debug_msg(user, message)) else: message = "Sent email reporting this exception to %s" % admin_email print(self.format_debug_msg(user, message))
def send(self, recipient_list, raise_on_failure=False, headers=None, attachments=None): if self.is_enabled(): from askbot.mail import send_mail send_mail( subject_line=self.render_subject(), body_text=self.render_body(), from_email=None, recipient_list=recipient_list, headers=headers or self.get_headers(), raise_on_failure=raise_on_failure, attachments=attachments or self.get_attachments() ) else: LOG.warning('Attempting to send disabled email "%s"' % force_text(self.title))
def send(self, recipient_list, raise_on_failure=False, headers=None, attachments=None): if self.is_enabled(): from askbot.mail import send_mail send_mail( subject_line=self.render_subject(), body_text=self.render_body(), from_email=None, recipient_list=recipient_list, headers=headers or self.get_headers(), raise_on_failure=raise_on_failure, attachments=attachments or self.get_attachments() ) else: LOG.warning('Attempting to send disabled email "%s"' % self.title)
def handle(self, *args, **options): if len(args) != 1: raise CommandError('Recipients email address required') try: validate_email(args[0]) except ValidationError: raise CommandError('%s is not a valid email address' % (args[0])) send_mail( subject_line='Askbot Mail Test', body_text='Askbot Mail Test', recipient_list=[args[0]], )
def handle(self, *args, **options): if len(args) != 1: raise CommandError('Recipients email address required') try: validate_email(args[0]) except ValidationError: raise CommandError('%s is not a valid email address' % (args[0])) send_mail( subject_line = 'Askbot Mail Test', body_text = 'Askbot Mail Test', recipient_list = [args[0]], )
def VALIDATE_EMAIL( parts = None, reply_address_object = None, from_address = None, **kwargs ): """process the validation email and save the email signature todo: go a step further and """ reply_code = reply_address_object.address if DEBUG_EMAIL: msg = u'Received email validation from %s\n' % from_address sys.stderr.write(msg.encode('utf-8')) try: content, stored_files, signature = mail.process_parts(parts, reply_code) user = reply_address_object.user if signature != user.email_signature: user.email_signature = signature user.email_isvalid = True user.save() data = { 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME, 'can_post_by_email': user.can_post_by_email(), 'recipient_user': user, 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': site_url(reverse('questions')), } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail( subject_line = _('Re: Welcome to %(site_name)s') % data, body_text = template.render(Context(data)),#todo: set lang recipient_list = [from_address,] ) except ValueError: raise ValueError( _( 'Please reply to the welcome email ' 'without editing it' ) )
def send_email_key(email, key, handler_url_name='user_account_recover'): """private function. sends email containing validation key to user's email address """ subject = _("Recover your %(site)s account") % \ {'site': askbot_settings.APP_SHORT_NAME} url = urlparse(askbot_settings.APP_URL) data = { 'validation_link': url.scheme + '://' + url.netloc + \ reverse(handler_url_name) +\ '?validation_code=' + key } template = get_template('authopenid/email_validation.html') message = template.render(data) send_mail(subject, message, django_settings.DEFAULT_FROM_EMAIL, [email])
def VALIDATE_EMAIL( parts = None, reply_address_object = None, from_address = None, **kwargs ): """process the validation email and save the email signature todo: go a step further and """ reply_code = reply_address_object.address if DEBUG_EMAIL: msg = u'Received email validation from %s\n' % from_address sys.stderr.write(msg.encode('utf-8')) try: content, stored_files, signature = mail.process_parts(parts, reply_code) user = reply_address_object.user if signature != user.email_signature: user.email_signature = signature user.email_isvalid = True user.save() data = { 'site_name': askbot_settings.APP_SHORT_NAME, 'site_url': site_url(reverse('questions')), 'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME, 'can_post_by_email': user.can_post_by_email() } template = get_template('email/re_welcome_lamson_on.html') mail.send_mail( subject_line = _('Re: Welcome to %(site_name)s') % data, body_text = template.render(Context(data)),#todo: set lang recipient_list = [from_address,] ) except ValueError: raise ValueError( _( 'Please reply to the welcome email ' 'without editing it' ) )
def notify_author_of_published_revision_celery_task(revision): # todo: move this to ``askbot.mail`` module # for answerable email only for now, because # we don't yet have the template for the read-only notification if askbot_settings.REPLY_BY_EMAIL: # generate two reply codes (one for edit and one for addition) # to format an answerable email or not answerable email reply_options = {"user": revision.author, "post": revision.post, "reply_action": "append_content"} append_content_address = ReplyAddress.objects.create_new(**reply_options).as_email_address() reply_options["reply_action"] = "replace_content" replace_content_address = ReplyAddress.objects.create_new(**reply_options).as_email_address() # populate template context variables reply_code = append_content_address + "," + replace_content_address if revision.post.post_type == "question": mailto_link_subject = revision.post.thread.title else: mailto_link_subject = _("An edit for my answer") # todo: possibly add more mailto thread headers to organize messages prompt = _("To add to your post EDIT ABOVE THIS LINE") reply_separator_line = const.SIMPLE_REPLY_SEPARATOR_TEMPLATE % prompt data = { "site_name": askbot_settings.APP_SHORT_NAME, "post": revision.post, "author_email_signature": revision.author.email_signature, "replace_content_address": replace_content_address, "reply_separator_line": reply_separator_line, "mailto_link_subject": mailto_link_subject, "reply_code": reply_code, } # load the template template = get_template("email/notify_author_about_approved_post.html") # todo: possibly add headers to organize messages in threads headers = {"Reply-To": append_content_address} # send the message mail.send_mail( subject_line=_("Your post at %(site_name)s is now published") % data, body_text=template.render(Context(data)), recipient_list=[revision.author.email], related_object=revision, activity_type=const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT, headers=headers, )
def report_exception(self, user): """reports exception that happened during sending email alert to user""" message = self.format_debug_msg(user, traceback.format_exc()) print(message) admin_email = askbot_settings.ADMIN_EMAIL try: subject = "Error processing daily/weekly notification for User '%s' for Site '%s'" % ( user.username, SITE_ID) send_mail(subject_line=subject, body_text=message, recipient_list=[admin_email]) except: message = "ERROR: was unable to report this exception to %s: %s" % ( admin_email, traceback.format_exc()) print(self.format_debug_msg(user, message)) else: message = "Sent email reporting this exception to %s" % admin_email print(self.format_debug_msg(user, message))
def send_email_alert(self): """signal handler for the message post-save""" root_message = self.get_root_message() data = { 'messages': self.get_timeline(), 'message': self, } for user in self.get_recipients_users(): # todo change url scheme so that all users have the same # urls within their personal areas of the user profile # so that we don't need to have loops like this one thread_url = root_message.get_absolute_url(user) thread_url = thread_url.replace('&', '&') # in the template we have a placeholder to be replaced like this: data['recipient_user'] = user email = GroupMessagingEmailAlert(data) body_text = email.render_body() body_text = body_text.replace('THREAD_URL_HOLE', thread_url) send_mail(email.render_subject(), body_text, django_settings.DEFAULT_FROM_EMAIL, [user.email])
def send_email_alert(self): """signal handler for the message post-save""" root_message = self.get_root_message() data = {'messages': self.get_timeline()} template = get_template('group_messaging/email_alert.html') body_text = template.render(data) subject = self.get_email_subject_line() for user in self.get_recipients_users(): #todo change url scheme so that all users have the same #urls within their personal areas of the user profile #so that we don't need to have loops like this one thread_url = root_message.get_absolute_url(user) thread_url = thread_url.replace('&', '&') #in the template we have a placeholder to be replaced like this: body_text = body_text.replace('THREAD_URL_HOLE', thread_url) send_mail( subject, body_text, django_settings.DEFAULT_FROM_EMAIL, [user.email,], )
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_ACCEPT_ANSWER_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_ANSWER_REMINDER, askbot_settings.ACCEPT_ANSWER_REMINDER_FREQUENCY, askbot_settings.MAX_ACCEPT_ANSWER_REMINDERS ) questions = models.Post.objects.get_questions().exclude( deleted = True ).added_between( start = schedule.start_cutoff_date, end = schedule.end_cutoff_date ).filter( thread__answer_count__gt = 0 ).filter( thread__accepted_answer__isnull=True #answer_accepted = False ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status = 'b'): user_questions = questions.filter(author = user) final_question_list = user_questions.get_questions_needing_reminder( activity_type = const.TYPE_ACTIVITY_ACCEPT_ANSWER_REMINDER_SENT, user = user, recurrence_delay = schedule.recurrence_delay ) #todo: rewrite using query set filter #may be a lot more efficient question_count = len(final_question_list) if question_count == 0: continue subject_line = _( 'Accept the best answer for %(question_count)d of your questions' ) % {'question_count': question_count} #todo - make a template for these if question_count == 1: reminder_phrase = _('Please accept the best answer for this question:') else: reminder_phrase = _('Please accept the best answer for these questions:') body_text = '<p>' + reminder_phrase + '</p>' body_text += '<ul>' for question in final_question_list: body_text += '<li><a href="%s%s?sort=latest">%s</a></li>' \ % ( askbot_settings.APP_URL, question.get_absolute_url(), question.thread.title ) body_text += '</ul>' if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail( subject_line = subject_line, body_text = body_text, recipient_list = (user.email,) )
def send_email_alerts(self): #does not change the database, only sends the email #todo: move this to template activate_language(django_settings.LANGUAGE_CODE) template = get_template('email/delayed_email_alert.html') for user in User.objects.all(): user.add_missing_askbot_subscriptions() #todo: q_list is a dictionary, not a list q_list = self.get_updated_questions_for_user(user) if len(q_list.keys()) == 0: continue num_q = 0 for question, meta_data in q_list.items(): if meta_data['skip']: del q_list[question] else: num_q += 1 if num_q > 0: threads = Thread.objects.filter( id__in=[qq.thread_id for qq in q_list.keys()]) tag_summary = Thread.objects.get_tag_summary_from_threads( threads) question_count = len(q_list.keys()) if tag_summary: subject_line = ungettext( '%(question_count)d update about %(topics)s', '%(question_count)d updates about %(topics)s', question_count) % { 'question_count': question_count, 'topics': tag_summary } else: subject_line = ungettext( '%(question_count)d update', '%(question_count)d updates', question_count) % { 'question_count': question_count, } items_added = 0 items_unreported = 0 questions_data = list() for q, meta_data in q_list.items(): act_list = [] if meta_data['skip']: continue if items_added >= askbot_settings.MAX_ALERTS_PER_EMAIL: items_unreported = num_q - items_added #may be inaccurate actually, but it's ok break else: items_added += 1 if meta_data['new_q']: act_list.append(_('new question')) format_action_count('%(num)d rev', meta_data['q_rev'], act_list) format_action_count('%(num)d ans', meta_data['new_ans'], act_list) format_action_count('%(num)d ans rev', meta_data['ans_rev'], act_list) questions_data.append({ 'url': site_url(q.get_absolute_url()), 'info': ', '.join(act_list), 'title': q.thread.title }) activate_language(user.get_primary_language()) text = template.render({ 'recipient_user': user, 'questions': questions_data, 'name': user.username, 'admin_email': askbot_settings.ADMIN_EMAIL, 'site_name': askbot_settings.APP_SHORT_NAME, 'is_multilingual': getattr(django_settings, 'ASKBOT_MULTILINGUAL', False) }) if DEBUG_THIS_COMMAND == True: recipient_email = askbot_settings.ADMIN_EMAIL else: recipient_email = user.email mail.send_mail(subject_line=subject_line, body_text=text, recipient_list=[recipient_email])
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER, askbot_settings.UNANSWERED_REMINDER_FREQUENCY, max_reminders = askbot_settings.MAX_UNANSWERED_REMINDERS ) questions = models.Post.objects.get_questions().exclude( thread__closed = True ).exclude( deleted = True ).added_between( start = schedule.start_cutoff_date, end = schedule.end_cutoff_date ).filter( thread__answer_count = 0 ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status = 'b'): user_questions = questions.exclude(author = user) user_questions = user.get_tag_filtered_questions(user_questions) if askbot_settings.GROUPS_ENABLED: user_groups = user.get_groups() user_questions = user_questions.filter(groups__in = user_groups) final_question_list = user_questions.get_questions_needing_reminder( user = user, activity_type = const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT, recurrence_delay = schedule.recurrence_delay ) question_count = len(final_question_list) if question_count == 0: continue threads = Thread.objects.filter(id__in=[qq.thread_id for qq in final_question_list]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) subject_line = ungettext( '%(question_count)d unanswered question about %(topics)s', '%(question_count)d unanswered questions about %(topics)s', question_count ) % { 'question_count': question_count, 'topics': tag_summary } data = { 'site_url': site_url(''), 'questions': final_question_list, 'subject_line': subject_line } template = get_template('email/unanswered_question_reminder.html') body_text = template.render(Context(data))#todo: set lang if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail( subject_line = subject_line, body_text = body_text, recipient_list = (user.email,) )
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER, askbot_settings.UNANSWERED_REMINDER_FREQUENCY, max_reminders = askbot_settings.MAX_UNANSWERED_REMINDERS ) questions = models.Post.objects.get_questions().exclude( thread__closed = True ).exclude( deleted = True ).added_between( start = schedule.start_cutoff_date, end = schedule.end_cutoff_date ).filter( thread__answer_count = 0 ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status = 'b'): user_questions = questions.exclude(author = user) user_questions = user.get_tag_filtered_questions(user_questions) final_question_list = user_questions.get_questions_needing_reminder( user = user, activity_type = const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT, recurrence_delay = schedule.recurrence_delay ) question_count = len(final_question_list) if question_count == 0: continue threads = Thread.objects.filter(id__in=[qq.thread_id for qq in final_question_list]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) subject_line = ungettext( '%(question_count)d unanswered question about %(topics)s', '%(question_count)d unanswered questions about %(topics)s', question_count ) % { 'question_count': question_count, 'topics': tag_summary } body_text = '<ul>' for question in final_question_list: body_text += '<li><a href="%s%s?sort=latest">%s</a></li>' \ % ( askbot_settings.APP_URL, question.get_absolute_url(), question.thread.title ) body_text += '</ul>' if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail( subject_line = subject_line, body_text = body_text, recipient_list = (user.email,) )
def send_email_alerts(self): #does not change the database, only sends the email #todo: move this to template for user in User.objects.all(): user.add_missing_askbot_subscriptions() #todo: q_list is a dictionary, not a list q_list = self.get_updated_questions_for_user(user) if len(q_list.keys()) == 0: continue num_q = 0 for question, meta_data in q_list.items(): if meta_data['skip']: del q_list[question] else: num_q += 1 if num_q > 0: threads = Thread.objects.filter(id__in=[qq.thread_id for qq in q_list.keys()]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) question_count = len(q_list.keys()) subject_line = ungettext( '%(question_count)d updated question about %(topics)s', '%(question_count)d updated questions about %(topics)s', question_count ) % { 'question_count': question_count, 'topics': tag_summary } #todo: send this to special log #print 'have %d updated questions for %s' % (num_q, user.username) text = ungettext( '<p>Dear %(name)s,</p><p>The following question has been updated ' '%(sitename)s</p>', '<p>Dear %(name)s,</p><p>The following %(num)d questions have been ' 'updated on %(sitename)s:</p>', num_q ) % { 'num':num_q, 'name':user.username, 'sitename': askbot_settings.APP_SHORT_NAME } text += '<ul>' items_added = 0 items_unreported = 0 for q, meta_data in q_list.items(): act_list = [] if meta_data['skip']: continue if items_added >= askbot_settings.MAX_ALERTS_PER_EMAIL: items_unreported = num_q - items_added #may be inaccurate actually, but it's ok else: items_added += 1 if meta_data['new_q']: act_list.append(_('new question')) format_action_count('%(num)d rev', meta_data['q_rev'],act_list) format_action_count('%(num)d ans', meta_data['new_ans'],act_list) format_action_count('%(num)d ans rev',meta_data['ans_rev'],act_list) act_token = ', '.join(act_list) text += '<li><a href="%s?sort=latest">%s</a> <font color="#777777">(%s)</font></li>' \ % (site_url(q.get_absolute_url()), q.thread.title, act_token) text += '</ul>' text += '<p></p>' #if len(q_list.keys()) >= askbot_settings.MAX_ALERTS_PER_EMAIL: # text += _('There may be more questions updated since ' # 'you have logged in last time as this list is ' # 'abridged for your convinience. Please visit ' # 'the askbot and see what\'s new!<br>' # ) link = reverse( 'user_subscriptions', kwargs = { 'id': user.id, 'slug': slugify(user.username) } ) text += _( '<p>Please remember that you can always <a ' 'href="%(email_settings_link)s">adjust</a> frequency of the email updates or ' 'turn them off entirely.<br/>If you believe that this message was sent in an ' 'error, please email about it the forum administrator at %(admin_email)s.</' 'p><p>Sincerely,</p><p>Your friendly %(sitename)s server.</p>' ) % { 'email_settings_link': site_url(link), 'admin_email': django_settings.ADMINS[0][1], 'sitename': askbot_settings.APP_SHORT_NAME } if DEBUG_THIS_COMMAND == True: recipient_email = django_settings.ADMINS[0][1] else: recipient_email = user.email mail.send_mail( subject_line = subject_line, body_text = text, recipient_list = [recipient_email] )
def moderate_post_edits(request): if request.user.is_anonymous(): raise exceptions.PermissionDenied() if not request.user.is_administrator_or_moderator(): raise exceptions.PermissionDenied() post_data = simplejson.loads(request.raw_post_data) #{'action': 'decline-with-reason', 'items': ['posts'], 'reason': 1, 'edit_ids': [827]} memo_set = models.ActivityAuditStatus.objects.filter( id__in=post_data['edit_ids']) result = {'message': '', 'memo_ids': set()} #if we are approving or declining users we need to expand the memo_set #to all of their edits of those users if post_data['action'] in ('block', 'approve') and 'users' in post_data['items']: editors = exclude_admins(get_editors(memo_set)) items = models.Activity.objects.filter( activity_type__in=const.MODERATED_EDIT_ACTIVITY_TYPES, user__in=editors) memo_filter = Q(user=request.user, activity__in=items) memo_set = models.ActivityAuditStatus.objects.filter(memo_filter) memo_set.select_related('activity') if post_data['action'] == 'approve': num_posts = 0 if 'posts' in post_data['items']: for memo in memo_set: if memo.activity.activity_type == const.TYPE_ACTIVITY_MARK_OFFENSIVE: #unflag the post content_object = memo.activity.content_object request.user.flag_post(content_object, cancel_all=True, force=True) num_posts += 1 else: revision = memo.activity.content_object if isinstance(revision, models.PostRevision): request.user.approve_post_revision(revision) num_posts += 1 if num_posts > 0: posts_message = ungettext('%d post approved', '%d posts approved', num_posts) % num_posts result['message'] = concat_messages(result['message'], posts_message) if 'users' in post_data['items']: editors = exclude_admins(get_editors(memo_set)) assert (request.user not in editors) for editor in editors: editor.set_status('a') num_users = len(editors) if num_users: users_message = ungettext('%d user approved', '%d users approved', num_users) % num_users result['message'] = concat_messages(result['message'], users_message) elif post_data['action'] == 'decline-with-reason': #todo: bunch notifications - one per recipient num_posts = 0 for memo in memo_set: post = get_object(memo) request.user.delete_post(post) reject_reason = models.PostFlagReason.objects.get( id=post_data['reason']) template = get_template('email/rejected_post.html') data = { 'post': post.html, 'reject_reason': reject_reason.details.html } body_text = template.render(RequestContext(request, data)) mail.send_mail(subject_line=_('your post was not accepted'), body_text=unicode(body_text), recipient_list=[ post.author.email, ]) num_posts += 1 #message to moderator if num_posts: posts_message = ungettext('%d post deleted', '%d posts deleted', num_posts) % num_posts result['message'] = concat_messages(result['message'], posts_message) elif post_data['action'] == 'block': num_users = 0 num_posts = 0 num_ips = 0 moderate_ips = getattr(django_settings, 'ASKBOT_IP_MODERATION_ENABLED', False) # If we block by IPs we always block users and posts # so we use a "spider" algorithm to find posts, users and IPs to block. # once we find users, posts and IPs, we block all of them summarily. if moderate_ips and 'ips' in post_data['items']: assert ('users' in post_data['items']) assert ('posts' in post_data['items']) assert (len(post_data['items']) == 3) revs = get_revision_set(memo_set) revs = expand_revision_set(revs) ips, users = get_revision_ips_and_authors(revs) memo_set = get_memos_by_revisions(revs, request.user) #to make sure to not block the admin and #in case REMOTE_ADDR is a proxy server - not #block access to the site my_ip = request.META.get('REMOTE_ADDR') if my_ip in ips: ips.remove(my_ip) #block IPs from stopforumspam.models import Cache already_blocked = Cache.objects.filter(ip__in=ips) already_blocked.update(permanent=True) already_blocked_ips = already_blocked.values_list('ip', flat=True) ips = ips - set(already_blocked_ips) for ip in ips: cache = Cache(ip=ip, permanent=True) cache.save() #block users and all their content users = exclude_admins(users) for user in users: user.set_status('b') #delete all content by the user num_posts += request.user.delete_all_content_authored_by_user( user) num_ips = len(ips) num_users = len(users) elif 'users' in post_data['items']: editors = exclude_admins(get_editors(memo_set)) assert (request.user not in editors) for editor in editors: #block user editor.set_status('b') #delete all content by the user num_posts += request.user.delete_all_content_authored_by_user( editor) num_users = len(editors) if num_ips: ips_message = ungettext('%d ip blocked', '%d ips blocked', num_ips) % num_ips result['message'] = concat_messages(result['message'], ips_message) if num_users: users_message = ungettext('%d user blocked', '%d users blocked', num_users) % num_users result['message'] = concat_messages(result['message'], users_message) if num_posts: posts_message = ungettext('%d post deleted', '%d posts deleted', num_posts) % num_posts result['message'] = concat_messages(result['message'], posts_message) result['memo_ids'] = [memo.id for memo in memo_set] #why values_list() fails here? result['message'] = force_text(result['message']) #delete items from the moderation queue act_ids = list(memo_set.values_list('activity_id', flat=True)) acts = models.Activity.objects.filter(id__in=act_ids) memos = models.ActivityAuditStatus.objects.filter(activity__id__in=act_ids) memos.delete() acts.delete() request.user.update_response_counts() result['memo_count'] = request.user.get_notifications( const.MODERATED_ACTIVITY_TYPES).count() return result
def user_moderate(request, subject, context): """user subview for moderation """ moderator = request.user if moderator.is_authenticated() and not moderator.can_moderate_user(subject): raise Http404 user_rep_changed = False user_status_changed = False message_sent = False email_error_message = None user_rep_form = forms.ChangeUserReputationForm() send_message_form = forms.SendMessageForm() if request.method == "POST": if "change_status" in request.POST: user_status_form = forms.ChangeUserStatusForm(request.POST, moderator=moderator, subject=subject) if user_status_form.is_valid(): subject.set_status(user_status_form.cleaned_data["user_status"]) user_status_changed = True elif "send_message" in request.POST: send_message_form = forms.SendMessageForm(request.POST) if send_message_form.is_valid(): subject_line = send_message_form.cleaned_data["subject_line"] body_text = send_message_form.cleaned_data["body_text"] try: send_mail( subject_line=subject_line, body_text=body_text, recipient_list=[subject.email], headers={"Reply-to": moderator.email}, raise_on_failure=True, ) message_sent = True except exceptions.EmailNotSent, e: email_error_message = unicode(e) send_message_form = forms.SendMessageForm() else: reputation_change_type = None if "subtract_reputation" in request.POST: rep_change_type = "subtract" elif "add_reputation" in request.POST: rep_change_type = "add" else: raise Http404 user_rep_form = forms.ChangeUserReputationForm(request.POST) if user_rep_form.is_valid(): rep_delta = user_rep_form.cleaned_data["user_reputation_delta"] comment = user_rep_form.cleaned_data["comment"] if rep_change_type == "subtract": rep_delta = -1 * rep_delta moderator.moderate_user_reputation( user=subject, reputation_change=rep_delta, comment=comment, timestamp=datetime.datetime.now() ) # reset form to preclude accidentally repeating submission user_rep_form = forms.ChangeUserReputationForm() user_rep_changed = True
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_ACCEPT_ANSWER_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_ANSWER_REMINDER, askbot_settings.ACCEPT_ANSWER_REMINDER_FREQUENCY, askbot_settings.MAX_ACCEPT_ANSWER_REMINDERS ) questions = models.Post.objects.get_questions().exclude( deleted = True ).added_between( start = schedule.start_cutoff_date, end = schedule.end_cutoff_date ).filter( thread__answer_count__gt = 0 ).filter( thread__accepted_answer__isnull=True #answer_accepted = False ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status = 'b'): user_questions = questions.filter(author = user) final_question_list = user_questions.get_questions_needing_reminder( activity_type = const.TYPE_ACTIVITY_ACCEPT_ANSWER_REMINDER_SENT, user = user, recurrence_delay = schedule.recurrence_delay ) #todo: rewrite using query set filter #may be a lot more efficient question_count = len(final_question_list) if question_count == 0: continue reminder_phrase = _('Please select the best responses to:') data = { 'site_url': site_url(''),#here we need only the domain name 'questions': final_question_list, 'reminder_phrase': reminder_phrase } template = get_template('email/accept_answer_reminder.html') body_text = template.render(Context(data))#todo: set lang subject_line = askbot_settings.WORDS_ACCEPT_BEST_ANSWERS_FOR_YOUR_QUESTIONS if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail( subject_line = subject_line, body_text = body_text, recipient_list = (user.email,) )
def send_email_alerts(self, user, template): #does not change the database, only sends the email #todo: move this to template user.add_missing_askbot_subscriptions() #todo: q_list is a dictionary, not a list q_list = self.get_updated_questions_for_user(user) if len(q_list.keys()) == 0: return num_q = 0 for question, meta_data in q_list.items(): if meta_data['skip']: del q_list[question] else: num_q += 1 if num_q > 0: threads = Thread.objects.filter(id__in=[qq.thread_id for qq in q_list.keys()]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) question_count = len(q_list.keys()) if tag_summary: subject_line = ungettext( '%(question_count)d update about %(topics)s', '%(question_count)d updates about %(topics)s', question_count ) % { 'question_count': question_count, 'topics': tag_summary } else: subject_line = ungettext( '%(question_count)d update', '%(question_count)d updates', question_count ) % { 'question_count': question_count, } items_added = 0 items_unreported = 0 questions_data = list() for q, meta_data in q_list.items(): act_list = [] if meta_data['skip']: continue if items_added >= askbot_settings.MAX_ALERTS_PER_EMAIL: items_unreported = num_q - items_added #may be inaccurate actually, but it's ok break else: items_added += 1 if meta_data['new_q']: act_list.append(_('new question')) format_action_count('%(num)d rev', meta_data['q_rev'], act_list) format_action_count('%(num)d ans', meta_data['new_ans'], act_list) format_action_count('%(num)d ans rev', meta_data['ans_rev'], act_list) questions_data.append({ 'url': site_url(q.get_absolute_url()), 'info': ', '.join(act_list), 'title': q.thread.title }) activate_language(user.get_primary_language()) text = template.render({ 'recipient_user': user, 'questions': questions_data, 'name': user.username, 'admin_email': askbot_settings.ADMIN_EMAIL, 'site_name': askbot_settings.APP_SHORT_NAME, 'is_multilingual': getattr(django_settings, 'ASKBOT_MULTILINGUAL', False) }) if DEBUG_THIS_COMMAND == True: recipient_email = askbot_settings.ADMIN_EMAIL else: recipient_email = user.email mail.send_mail( subject_line = subject_line, body_text = text, recipient_list = [recipient_email] )
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_ACCEPT_PROBLEM_REMINDERS == False: return #get exercises without problems, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_PROBLEM_REMINDER, askbot_settings.ACCEPT_PROBLEM_REMINDER_FREQUENCY, askbot_settings.MAX_ACCEPT_PROBLEM_REMINDERS ) exercises = models.Post.objects.get_exercises().exclude( deleted = True ).added_between( start = schedule.start_cutoff_date, end = schedule.end_cutoff_date ).filter( thread__problem_count__gt = 0 ).filter( thread__accepted_problem__isnull=True #problem_accepted = False ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status = 'b'): user_exercises = exercises.filter(author = user) final_exercise_list = user_exercises.get_exercises_needing_reminder( activity_type = const.TYPE_ACTIVITY_ACCEPT_PROBLEM_REMINDER_SENT, user = user, recurrence_delay = schedule.recurrence_delay ) #todo: rewrite using query set filter #may be a lot more efficient exercise_count = len(final_exercise_list) if exercise_count == 0: continue subject_line = _( 'Accept the best problem for %(exercise_count)d of your exercises' ) % {'exercise_count': exercise_count} #todo - make a template for these if exercise_count == 1: reminder_phrase = _('Please accept the best problem for this exercise:') else: reminder_phrase = _('Please accept the best problem for these exercises:') data = { 'site_url': askbot_settings.APP_URL, 'exercises': final_exercise_list, 'reminder_phrase': reminder_phrase } template = get_template('email/accept_problem_reminder.html') body_text = template.render(Context(data)) if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail( subject_line = subject_line, body_text = body_text, recipient_list = (user.email,) )
def moderate_post_edits(request): if request.user.is_anonymous(): raise exceptions.PermissionDenied() if not request.user.is_administrator_or_moderator(): raise exceptions.PermissionDenied() post_data = simplejson.loads(request.raw_post_data) #{'action': 'decline-with-reason', 'items': ['posts'], 'reason': 1, 'edit_ids': [827]} memo_set = models.ActivityAuditStatus.objects.filter(id__in=post_data['edit_ids']) result = { 'message': '', 'memo_ids': set() } #if we are approving or declining users we need to expand the memo_set #to all of their edits of those users if post_data['action'] in ('block', 'approve') and 'users' in post_data['items']: editors = filter_admins(get_editors(memo_set)) items = models.Activity.objects.filter( activity_type__in=const.MODERATED_EDIT_ACTIVITY_TYPES, user__in=editors ) memo_filter = Q(id__in=post_data['edit_ids']) | Q(user=request.user, activity__in=items) memo_set = models.ActivityAuditStatus.objects.filter(memo_filter) memo_set.select_related('activity') if post_data['action'] == 'decline-with-reason': #todo: bunch notifications - one per recipient num_posts = 0 for memo in memo_set: post = get_object(memo) request.user.delete_post(post) reject_reason = models.PostFlagReason.objects.get(id=post_data['reason']) template = get_template('email/rejected_post.html') data = { 'post': post.html, 'reject_reason': reject_reason.details.html } body_text = template.render(RequestContext(request, data)) mail.send_mail( subject_line = _('your post was not accepted'), body_text = unicode(body_text), recipient_list = [post.author.email,] ) num_posts += 1 #message to moderator if num_posts: posts_message = ungettext('%d post deleted', '%d posts deleted', num_posts) % num_posts result['message'] = concat_messages(result['message'], posts_message) elif post_data['action'] == 'approve': num_posts = 0 if 'posts' in post_data['items']: for memo in memo_set: if memo.activity.activity_type == const.TYPE_ACTIVITY_MARK_OFFENSIVE: #unflag the post content_object = memo.activity.content_object request.user.flag_post(content_object, cancel_all=True, force=True) num_posts += 1 else: revision = memo.activity.content_object if isinstance(revision, models.PostRevision): request.user.approve_post_revision(revision) num_posts += 1 if num_posts > 0: posts_message = ungettext('%d post approved', '%d posts approved', num_posts) % num_posts result['message'] = concat_messages(result['message'], posts_message) if 'users' in post_data['items']: editors = filter_admins(get_editors(memo_set)) assert(request.user not in editors) for editor in editors: editor.set_status('a') num_editors = len(editors) if num_editors: users_message = ungettext('%d user approved', '%d users approved', num_editors) % num_editors result['message'] = concat_messages(result['message'], users_message) elif post_data['action'] == 'block': if 'users' in post_data['items']: editors = filter_admins(get_editors(memo_set)) assert(request.user not in editors) num_posts = 0 for editor in editors: #block user editor.set_status('b') #delete all content by the user num_posts += request.user.delete_all_content_authored_by_user(editor) if num_posts: posts_message = ungettext('%d post deleted', '%d posts deleted', num_posts) % num_posts result['message'] = concat_messages(result['message'], posts_message) num_editors = len(editors) if num_editors: users_message = ungettext('%d user blocked', '%d users blocked', num_editors) % num_editors result['message'] = concat_messages(result['message'], users_message) moderate_ips = getattr(django_settings, 'ASKBOT_IP_MODERATION_ENABLED', False) if moderate_ips and 'ips' in post_data['items']: ips = set() for memo in memo_set: obj = memo.activity.content_object if isinstance(obj, models.PostRevision): ips.add(obj.ip_addr) #to make sure to not block the admin and #in case REMOTE_ADDR is a proxy server - not #block access to the site my_ip = request.META.get('REMOTE_ADDR') if my_ip in ips: ips.remove(my_ip) from stopforumspam.models import Cache already_blocked = Cache.objects.filter(ip__in=ips) already_blocked.update(permanent=True) already_blocked_ips = already_blocked.values_list('ip', flat=True) ips = ips - set(already_blocked_ips) for ip in ips: cache = Cache(ip=ip, permanent=True) cache.save() num_ips = len(ips) if num_ips: ips_message = ungettext('%d ip blocked', '%d ips blocked', num_ips) % num_ips result['message'] = concat_messages(result['message'], ips_message) result['memo_ids'] = [memo.id for memo in memo_set]#why values_list() fails here? result['message'] = force_text(result['message']) #delete items from the moderation queue act_ids = list(memo_set.values_list('activity_id', flat=True)) acts = models.Activity.objects.filter(id__in=act_ids) memos = models.ActivityAuditStatus.objects.filter(activity__id__in=act_ids) memos.delete() acts.delete() request.user.update_response_counts() result['memo_count'] = request.user.get_notifications(const.MODERATED_ACTIVITY_TYPES).count() return result
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER, askbot_settings.UNANSWERED_REMINDER_FREQUENCY, max_reminders=askbot_settings.MAX_UNANSWERED_REMINDERS) questions = models.Post.objects.get_questions() #we don't report closed, deleted or moderation queue questions exclude_filter = Q(thread__closed=True) | Q(deleted=True) if askbot_settings.CONTENT_MODERATION_MODE == 'premoderation': exclude_filter |= Q(approved=False) questions = questions.exclude(exclude_filter) #select questions within the range of the reminder schedule questions = questions.added_between(start=schedule.start_cutoff_date, end=schedule.end_cutoff_date) #take only questions with zero answers questions = questions.filter(thread__answer_count=0) if questions.count() == 0: #nothing to do return questions = questions.order_by('-added_at') if askbot_settings.UNANSWERED_REMINDER_RECIPIENTS == 'admins': recipient_statuses = ('d', 'm') else: recipient_statuses = ('a', 'w', 'd', 'm') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.filter(status__in=recipient_statuses): user_questions = questions.exclude(author=user) user_questions = user.get_tag_filtered_questions(user_questions) if askbot_settings.GROUPS_ENABLED: user_groups = user.get_groups() user_questions = user_questions.filter(groups__in=user_groups) final_question_list = user_questions.get_questions_needing_reminder( user=user, activity_type=const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT, recurrence_delay=schedule.recurrence_delay) question_count = len(final_question_list) if question_count == 0: continue threads = Thread.objects.filter( id__in=[qq.thread_id for qq in final_question_list]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) if question_count == 1: unanswered_questions_phrase = askbot_settings.WORDS_UNANSWERED_QUESTION_SINGULAR else: unanswered_questions_phrase = askbot_settings.WORDS_UNANSWERED_QUESTION_PLURAL subject_line = ungettext( '%(question_count)d %(unanswered_questions)s about %(topics)s', '%(question_count)d %(unanswered_questions)s about %(topics)s', question_count) % { 'question_count': question_count, 'unanswered_questions': unanswered_questions_phrase, 'topics': tag_summary } data = { 'site_url': site_url(''), 'questions': final_question_list, 'subject_line': subject_line } template = get_template('email/unanswered_question_reminder.html') body_text = template.render(Context(data)) #todo: set lang if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail(subject_line=subject_line, body_text=body_text, recipient_list=(user.email, ))
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER, askbot_settings.UNANSWERED_REMINDER_FREQUENCY, max_reminders=askbot_settings.MAX_UNANSWERED_REMINDERS) questions = models.Post.objects.get_questions().exclude( thread__closed=True).exclude(deleted=True).added_between( start=schedule.start_cutoff_date, end=schedule.end_cutoff_date).filter( thread__answer_count=0).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status='b'): user_questions = questions.exclude(author=user) user_questions = user.get_tag_filtered_questions(user_questions) if askbot_settings.GROUPS_ENABLED: user_groups = user.get_groups() user_questions = user_questions.filter(groups__in=user_groups) final_question_list = user_questions.get_questions_needing_reminder( user=user, activity_type=const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT, recurrence_delay=schedule.recurrence_delay) question_count = len(final_question_list) if question_count == 0: continue threads = Thread.objects.filter( id__in=[qq.thread_id for qq in final_question_list]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) subject_line = ungettext( '%(question_count)d unanswered question about %(topics)s', '%(question_count)d unanswered questions about %(topics)s', question_count) % { 'question_count': question_count, 'topics': tag_summary } data = { 'site_url': site_url(''), 'questions': final_question_list, 'subject_line': subject_line } template = get_template('email/unanswered_question_reminder.html') body_text = template.render(Context(data)) #todo: set lang if TRACK_USER_EMAIL: print "%s:%s" % (user.email, subject_line) if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail(subject_line=subject_line, body_text=body_text, recipient_list=(user.email, ))
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_ACCEPT_PROBLEM_REMINDERS == False: return #get exercises without problems, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_PROBLEM_REMINDER, askbot_settings.ACCEPT_PROBLEM_REMINDER_FREQUENCY, askbot_settings.MAX_ACCEPT_PROBLEM_REMINDERS) exercises = models.Post.objects.get_exercises( ).exclude(deleted=True).added_between( start=schedule.start_cutoff_date, end=schedule.end_cutoff_date ).filter(thread__problem_count__gt=0).filter( thread__accepted_problem__isnull=True #problem_accepted = False ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status='b'): user_exercises = exercises.filter(author=user) final_exercise_list = user_exercises.get_exercises_needing_reminder( activity_type=const.TYPE_ACTIVITY_ACCEPT_PROBLEM_REMINDER_SENT, user=user, recurrence_delay=schedule.recurrence_delay) #todo: rewrite using query set filter #may be a lot more efficient exercise_count = len(final_exercise_list) if exercise_count == 0: continue subject_line = _( 'Accept the best problem for %(exercise_count)d of your exercises' ) % { 'exercise_count': exercise_count } #todo - make a template for these if exercise_count == 1: reminder_phrase = _( 'Please accept the best problem for this exercise:') else: reminder_phrase = _( 'Please accept the best problem for these exercises:') data = { 'site_url': askbot_settings.APP_URL, 'exercises': final_exercise_list, 'reminder_phrase': reminder_phrase } template = get_template('email/accept_problem_reminder.html') body_text = template.render(Context(data)) if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail(subject_line=subject_line, body_text=body_text, recipient_list=(user.email, ))
def user_moderate(request, subject, context): """user subview for moderation """ moderator = request.user if moderator.is_authenticated( ) and not moderator.can_moderate_user(subject): raise Http404 user_rep_changed = False user_status_changed = False user_status_changed_message = _('User status changed') message_sent = False email_error_message = None user_rep_form = forms.ChangeUserReputationForm() send_message_form = forms.SendMessageForm() if request.method == 'POST': if 'change_status' in request.POST or 'hard_block' in request.POST: user_status_form = forms.ChangeUserStatusForm(request.POST, moderator=moderator, subject=subject) if user_status_form.is_valid(): subject.set_status( user_status_form.cleaned_data['user_status']) if user_status_form.cleaned_data['delete_content'] is True: num_deleted = request.user.delete_all_content_authored_by_user( subject) if num_deleted: num_deleted_message = ungettext( '%d post deleted', '%d posts deleted', num_deleted) % num_deleted user_status_changed_message = string_concat( user_status_changed_message, ', ', num_deleted_message) user_status_changed = True elif 'send_message' in request.POST: send_message_form = forms.SendMessageForm(request.POST) if send_message_form.is_valid(): subject_line = send_message_form.cleaned_data['subject_line'] body_text = send_message_form.cleaned_data['body_text'] try: send_mail(subject_line=subject_line, body_text=body_text, recipient_list=[subject.email], headers={'Reply-to': moderator.email}, raise_on_failure=True) message_sent = True except exceptions.EmailNotSent as e: email_error_message = force_text(e) send_message_form = forms.SendMessageForm() else: reputation_change_type = None if 'subtract_reputation' in request.POST: rep_change_type = 'subtract' elif 'add_reputation' in request.POST: rep_change_type = 'add' else: raise Http404 user_rep_form = forms.ChangeUserReputationForm(request.POST) if user_rep_form.is_valid(): rep_delta = user_rep_form.cleaned_data['user_reputation_delta'] comment = user_rep_form.cleaned_data['comment'] if rep_change_type == 'subtract': rep_delta = -1 * rep_delta moderator.moderate_user_reputation(user=subject, reputation_change=rep_delta, comment=comment, timestamp=timezone.now()) # reset form to preclude accidentally repeating submission user_rep_form = forms.ChangeUserReputationForm() user_rep_changed = True # need to re-initialize the form even if it was posted, because # initial values will most likely be different from the previous user_status_form = forms.ChangeUserStatusForm(moderator=moderator, subject=subject) context.update({ 'active_tab': 'users', 'page_class': 'user-profile-page', 'tab_name': 'moderation', 'page_title': _('moderate user'), 'change_user_status_form': user_status_form, 'change_user_reputation_form': user_rep_form, 'send_message_form': send_message_form, 'message_sent': message_sent, 'email_error_message': email_error_message, 'user_rep_changed': user_rep_changed, 'user_status_changed': user_status_changed, 'user_status_changed_message': user_status_changed_message }) return render(request, 'user_profile/user_moderate.jinja', context)
def send_email_alerts(self): #does not change the database, only sends the email #todo: move this to template activate_language(django_settings.LANGUAGE_CODE) template = get_template('email/delayed_email_alert.html') for user in User.objects.all(): user.add_missing_askbot_subscriptions() #todo: q_list is a dictionary, not a list q_list = self.get_updated_questions_for_user(user) if len(q_list.keys()) == 0: continue num_q = 0 for question, meta_data in q_list.items(): if meta_data['skip']: del q_list[question] else: num_q += 1 if num_q > 0: threads = Thread.objects.filter(id__in=[qq.thread_id for qq in q_list.keys()]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) question_count = len(q_list.keys()) subject_line = ungettext( '%(question_count)d updated question about %(topics)s', '%(question_count)d updated questions about %(topics)s', question_count ) % { 'question_count': question_count, 'topics': tag_summary } #todo: send this to special log print 'have %d updated questions for %s' % (num_q, user.username) if DEBUG_THIS_COMMAND == True: continue text = ungettext( '<p>Dear %(name)s,</p><p>The following question has been updated ' '%(sitename)s</p>', '<p>Dear %(name)s,</p><p>The following %(num)d questions have been ' 'updated on %(sitename)s:</p>', num_q ) % { 'num':num_q, 'name':user.username, 'sitename': askbot_settings.APP_SHORT_NAME } text += '<ul>' items_added = 0 items_unreported = 0 questions_data = list() for q, meta_data in q_list.items(): act_list = [] if meta_data['skip']: continue if items_added >= askbot_settings.MAX_ALERTS_PER_EMAIL: items_unreported = num_q - items_added #may be inaccurate actually, but it's ok break else: items_added += 1 if meta_data['new_q']: act_list.append(_('new question')) format_action_count('%(num)d rev', meta_data['q_rev'], act_list) format_action_count('%(num)d ans', meta_data['new_ans'], act_list) format_action_count('%(num)d ans rev', meta_data['ans_rev'], act_list) questions_data.append({ 'url': site_url(q.get_absolute_url()), 'info': ', '.join(act_list), 'title': q.thread.title }) activate_language(user.get_primary_language()) text = template.render({ 'recipient_user': user, 'questions': questions_data, 'name': user.username, 'admin_email': askbot_settings.ADMIN_EMAIL, 'site_name': askbot_settings.APP_SHORT_NAME, 'is_multilingual': django_settings.ASKBOT_MULTILINGUAL }) if DEBUG_THIS_COMMAND == True: recipient_email = askbot_settings.ADMIN_EMAIL else: recipient_email = user.email mail.send_mail( subject_line = subject_line, body_text = text, recipient_list = [recipient_email] )
def send_instant_notifications_about_activity_in_post( activity_id=None, post_id=None, recipients=None, ): if recipients is None: return acceptable_types = const.RESPONSE_ACTIVITY_TYPES_FOR_INSTANT_NOTIFICATIONS try: update_activity = Activity.objects.filter( activity_type__in=acceptable_types).get(id=activity_id) except Activity.DoesNotExist: logger.error("Unable to fetch activity with id %s" % post_id) return try: post = Post.objects.get(id=post_id) except Post.DoesNotExist: logger.error("Unable to fetch post with id %s" % post_id) return if post.is_approved() is False: return #calculate some variables used in the loop below update_type_map = const.RESPONSE_ACTIVITY_TYPE_MAP_FOR_TEMPLATES update_type = update_type_map[update_activity.activity_type] origin_post = post.get_origin_post() headers = mail.thread_headers(post, origin_post, update_activity.activity_type) if logger.getEffectiveLevel() <= logging.DEBUG: log_id = uuid.uuid1() message = 'email-alert %s, logId=%s' % (post.get_absolute_url(), log_id) logger.debug(message) else: log_id = None for user in recipients: if user.is_blocked(): continue reply_address, alt_reply_address = get_reply_to_addresses(user, post) activate_language(post.language_code) subject_line, body_text = format_instant_notification_email( to_user=user, from_user=update_activity.user, post=post, reply_address=reply_address, alt_reply_address=alt_reply_address, update_type=update_type, template=get_template('email/instant_notification.html')) headers['Reply-To'] = reply_address try: mail.send_mail(subject_line=subject_line, body_text=body_text, recipient_list=[user.email], related_object=origin_post, activity_type=const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT, headers=headers, raise_on_failure=True) except askbot_exceptions.EmailNotSent, error: logger.debug('%s, error=%s, logId=%s' % (user.email, error, log_id)) else: logger.debug('success %s, logId=%s' % (user.email, log_id))
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER, askbot_settings.UNANSWERED_REMINDER_FREQUENCY, max_reminders = askbot_settings.MAX_UNANSWERED_REMINDERS ) questions = models.Post.objects.get_questions() #we don't report closed, deleted or moderation queue questions exclude_filter = Q(thread__closed=True) | Q(deleted=True) if askbot_settings.CONTENT_MODERATION_MODE == 'premoderation': exclude_filter |= Q(approved=False) questions = questions.exclude(exclude_filter) #select questions within the range of the reminder schedule questions = questions.added_between( start=schedule.start_cutoff_date, end=schedule.end_cutoff_date ) #take only questions with zero answers questions = questions.filter(thread__answer_count=0) if questions.count() == 0: #nothing to do return questions = questions.order_by('-added_at') if askbot_settings.UNANSWERED_REMINDER_RECIPIENTS == 'admins': recipient_statuses = ('d', 'm') else: recipient_statuses = ('a', 'w', 'd', 'm') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.filter(status__in=recipient_statuses): user_questions = questions.exclude(author=user) user_questions = user.get_tag_filtered_questions(user_questions) if askbot_settings.GROUPS_ENABLED: user_groups = user.get_groups() user_questions = user_questions.filter(groups__in = user_groups) final_question_list = user_questions.get_questions_needing_reminder( user = user, activity_type = const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT, recurrence_delay = schedule.recurrence_delay ) question_count = len(final_question_list) if question_count == 0: continue threads = Thread.objects.filter(id__in=[qq.thread_id for qq in final_question_list]) tag_summary = Thread.objects.get_tag_summary_from_threads(threads) if question_count == 1: unanswered_questions_phrase = askbot_settings.WORDS_UNANSWERED_QUESTION_SINGULAR else: unanswered_questions_phrase = askbot_settings.WORDS_UNANSWERED_QUESTION_PLURAL subject_line = ungettext( '%(question_count)d %(unanswered_questions)s about %(topics)s', '%(question_count)d %(unanswered_questions)s about %(topics)s', question_count ) % { 'question_count': question_count, 'unanswered_questions': unanswered_questions_phrase, 'topics': tag_summary } data = { 'recipient_user': user, 'site_url': site_url(''), 'subject_line': subject_line, 'questions': final_question_list, } template = get_template('email/unanswered_question_reminder.html') body_text = template.render(Context(data))#todo: set lang if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail( subject_line = subject_line, body_text = body_text, recipient_list = (user.email,) )
def manage_inbox(request): """delete, mark as new or seen user's response memo objects, excluding flags request data is memo_list - list of integer id's of the ActivityAuditStatus items and action_type - string - one of delete|mark_new|mark_seen """ response_data = dict() try: if request.is_ajax(): if request.method == 'POST': post_data = simplejson.loads(request.raw_post_data) if request.user.is_authenticated(): activity_types = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY activity_types += ( const.TYPE_ACTIVITY_MENTION, const.TYPE_ACTIVITY_MARK_OFFENSIVE, const.TYPE_ACTIVITY_MODERATED_NEW_POST, const.TYPE_ACTIVITY_MODERATED_POST_EDIT ) user = request.user memo_set = models.ActivityAuditStatus.objects.filter( id__in = post_data['memo_list'], activity__activity_type__in = activity_types, user = user ) action_type = post_data['action_type'] if action_type == 'delete': memo_set.delete() elif action_type == 'mark_new': memo_set.update(status = models.ActivityAuditStatus.STATUS_NEW) elif action_type == 'mark_seen': memo_set.update(status = models.ActivityAuditStatus.STATUS_SEEN) elif action_type == 'remove_flag': for memo in memo_set: activity_type = memo.activity.activity_type if activity_type == const.TYPE_ACTIVITY_MARK_OFFENSIVE: request.user.flag_post( post = memo.activity.content_object, cancel_all = True ) elif activity_type in \ ( const.TYPE_ACTIVITY_MODERATED_NEW_POST, const.TYPE_ACTIVITY_MODERATED_POST_EDIT ): post_revision = memo.activity.content_object request.user.approve_post_revision(post_revision) memo.delete() #elif action_type == 'close': # for memo in memo_set: # if memo.activity.content_object.post_type == "question": # request.user.close_question(question = memo.activity.content_object, reason = 7) # memo.delete() elif action_type == 'delete_post': for memo in memo_set: content_object = memo.activity.content_object if isinstance(content_object, models.PostRevision): post = content_object.post else: post = content_object request.user.delete_post(post) reject_reason = models.PostFlagReason.objects.get( id = post_data['reject_reason_id'] ) body_text = string_concat( _('Your post (copied in the end),'), '<br/>', _('was rejected for the following reason:'), '<br/><br/>', reject_reason.details.html, '<br/><br/>', _('Here is your original post'), '<br/><br/>', post.text ) mail.send_mail( subject_line = _('your post was not accepted'), body_text = unicode(body_text), recipient_list = [post.author.email,] ) memo.delete() user.update_response_counts() response_data['success'] = True data = simplejson.dumps(response_data) return HttpResponse(data, mimetype="application/json") else: raise exceptions.PermissionDenied( _('Sorry, but anonymous users cannot access the inbox') ) else: raise exceptions.PermissionDenied('must use POST request') else: #todo: show error page but no-one is likely to get here return HttpResponseRedirect(reverse('index')) except Exception, e: message = unicode(e) if message == '': message = _('Oops, apologies - there was some error') response_data['message'] = message response_data['success'] = False data = simplejson.dumps(response_data) return HttpResponse(data, mimetype="application/json")
def user_moderate(request, subject, context): """user subview for moderation """ moderator = request.user if moderator.is_authenticated() and not moderator.can_moderate_user(subject): raise Http404 user_rep_changed = False user_status_changed = False user_status_changed_message = _('User status changed') message_sent = False email_error_message = None user_rep_form = forms.ChangeUserReputationForm() send_message_form = forms.SendMessageForm() if request.method == 'POST': if 'change_status' in request.POST or 'hard_block' in request.POST: user_status_form = forms.ChangeUserStatusForm( request.POST, moderator = moderator, subject = subject ) if user_status_form.is_valid(): subject.set_status( user_status_form.cleaned_data['user_status'] ) if user_status_form.cleaned_data['delete_content'] == True: num_deleted = request.user.delete_all_content_authored_by_user(subject) if num_deleted: num_deleted_message = ungettext('%d post deleted', '%d posts deleted', num_deleted) % num_deleted user_status_changed_message = string_concat(user_status_changed_message, ', ', num_deleted_message) user_status_changed = True elif 'send_message' in request.POST: send_message_form = forms.SendMessageForm(request.POST) if send_message_form.is_valid(): subject_line = send_message_form.cleaned_data['subject_line'] body_text = send_message_form.cleaned_data['body_text'] try: send_mail( subject_line = subject_line, body_text = body_text, recipient_list = [subject.email], headers={'Reply-to':moderator.email}, raise_on_failure = True ) message_sent = True except exceptions.EmailNotSent, e: email_error_message = unicode(e) send_message_form = forms.SendMessageForm() else: reputation_change_type = None if 'subtract_reputation' in request.POST: rep_change_type = 'subtract' elif 'add_reputation' in request.POST: rep_change_type = 'add' else: raise Http404 user_rep_form = forms.ChangeUserReputationForm(request.POST) if user_rep_form.is_valid(): rep_delta = user_rep_form.cleaned_data['user_reputation_delta'] comment = user_rep_form.cleaned_data['comment'] if rep_change_type == 'subtract': rep_delta = -1 * rep_delta moderator.moderate_user_reputation( user = subject, reputation_change = rep_delta, comment = comment, timestamp = datetime.datetime.now(), ) #reset form to preclude accidentally repeating submission user_rep_form = forms.ChangeUserReputationForm() user_rep_changed = True
def user_moderate(request, subject, context): """user subview for moderation """ moderator = request.user if moderator.is_authenticated( ) and not moderator.can_moderate_user(subject): raise Http404 user_rep_changed = False user_status_changed = False message_sent = False email_error_message = None user_rep_form = forms.ChangeUserReputationForm() send_message_form = forms.SendMessageForm() if request.method == 'POST': if 'change_status' in request.POST: user_status_form = forms.ChangeUserStatusForm(request.POST, moderator=moderator, subject=subject) if user_status_form.is_valid(): subject.set_status( user_status_form.cleaned_data['user_status']) user_status_changed = True elif 'send_message' in request.POST: send_message_form = forms.SendMessageForm(request.POST) if send_message_form.is_valid(): subject_line = send_message_form.cleaned_data['subject_line'] body_text = send_message_form.cleaned_data['body_text'] try: send_mail(subject_line=subject_line, body_text=body_text, recipient_list=[subject.email], headers={'Reply-to': moderator.email}, raise_on_failure=True) message_sent = True except exceptions.EmailNotSent, e: email_error_message = unicode(e) send_message_form = forms.SendMessageForm() else: reputation_change_type = None if 'subtract_reputation' in request.POST: rep_change_type = 'subtract' elif 'add_reputation' in request.POST: rep_change_type = 'add' else: raise Http404 user_rep_form = forms.ChangeUserReputationForm(request.POST) if user_rep_form.is_valid(): rep_delta = user_rep_form.cleaned_data['user_reputation_delta'] comment = user_rep_form.cleaned_data['comment'] if rep_change_type == 'subtract': rep_delta = -1 * rep_delta moderator.moderate_user_reputation( user=subject, reputation_change=rep_delta, comment=comment, timestamp=datetime.datetime.now(), ) #reset form to preclude accidentally repeating submission user_rep_form = forms.ChangeUserReputationForm() user_rep_changed = True
def handle_noargs(self, **options): if askbot_settings.ENABLE_EMAIL_ALERTS == False: return if askbot_settings.ENABLE_ACCEPT_ANSWER_REMINDERS == False: return #get questions without answers, excluding closed and deleted #order it by descending added_at date schedule = ReminderSchedule( askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_ANSWER_REMINDER, askbot_settings.ACCEPT_ANSWER_REMINDER_FREQUENCY, askbot_settings.MAX_ACCEPT_ANSWER_REMINDERS) questions = models.Post.objects.get_questions().exclude( deleted=True).added_between( start=schedule.start_cutoff_date, end=schedule.end_cutoff_date ).filter(thread__answer_count__gt=0).filter( thread__accepted_answer__isnull=True #answer_accepted = False ).order_by('-added_at') #for all users, excluding blocked #for each user, select a tag filtered subset #format the email reminder and send it for user in models.User.objects.exclude(status='b'): user_questions = questions.filter(author=user) final_question_list = user_questions.get_questions_needing_reminder( activity_type=const.TYPE_ACTIVITY_ACCEPT_ANSWER_REMINDER_SENT, user=user, recurrence_delay=schedule.recurrence_delay) #todo: rewrite using query set filter #may be a lot more efficient question_count = len(final_question_list) if question_count == 0: continue subject_line = _( 'Accept the best answer for %(question_count)d of your questions' ) % { 'question_count': question_count } #todo - make a template for these if question_count == 1: reminder_phrase = _( 'Please accept the best answer for this question:') else: reminder_phrase = _( 'Please accept the best answer for these questions:') body_text = '<p>' + reminder_phrase + '</p>' body_text += '<ul>' for question in final_question_list: body_text += '<li><a href="%s%s?sort=latest">%s</a></li>' \ % ( askbot_settings.APP_URL, question.get_absolute_url(), question.thread.title ) body_text += '</ul>' if DEBUG_THIS_COMMAND: print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \ (user.email, subject_line, body_text) else: mail.send_mail(subject_line=subject_line, body_text=body_text, recipient_list=(user.email, ))