Esempio n. 1
0
def bounce_email(email, subject, reason=None, body_text=None):
    """sends a bounce email at address ``email``, with the subject
    line ``subject``, accepts several reasons for the bounce:

    * ``'problem_posting'``, ``unknown_user`` and ``permission_denied``
    * ``body_text`` in an optional parameter that allows to append
      extra text to the message
    """
    if reason == "problem_posting":
        error_message = _(
            "<p>Sorry, there was an error posting your question " "please contact the %(site)s administrator</p>"
        ) % {"site": askbot_settings.APP_SHORT_NAME}
        error_message = string_concat(error_message, USAGE)
    elif reason == "unknown_user":
        error_message = _(
            "<p>Sorry, in order to post questions on %(site)s "
            'by email, please <a href="%(url)s">register first</a></p>'
        ) % {"site": askbot_settings.APP_SHORT_NAME, "url": url_utils.get_login_url()}
    elif reason == "permission_denied":
        error_message = _(
            "<p>Sorry, your question could not be posted " "due to insufficient privileges of your user account</p>"
        )
    else:
        raise ValueError('unknown reason to bounce an email: "%s"' % reason)

    if body_text != None:
        error_message = string_concat(error_message, body_text)

    # print 'sending email'
    # print email
    # print subject
    # print error_message
    mail.send_mail(recipient_list=(email,), subject_line="Re: " + subject, body_text=error_message)
Esempio n. 2
0
def user_add_transaction(request, subject, context):
    """user subview for moderation
    """
    moderator = request.user

    if not moderator.can_moderate_user(subject):
        raise Http404

    user_transaction_added  = False
    message_sent = False
    email_error_message = None

    user_transaction_form = forms.AddUserTransactionForm()
    send_message_form = forms.SendMessageForm()
    if request.method == 'POST':
        if '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:
            transaction_change_type = None

            user_transaction_form = forms.AddUserTransactionForm(request.POST)
            if user_transaction_form.is_valid():
                user_income = user_transaction_form.cleaned_data['user_income']
                user_outcome = user_transaction_form.cleaned_data['user_outcome']
                transaction_type = user_transaction_form.cleaned_data['transaction_type'] 
                comment = user_transaction_form.cleaned_data['comment']

                moderator.add_user_transaction(
                                    user = subject,
                                    income =user_income,
                                    outcome =user_outcome,
                                    transaction_type=transaction_type,
                                    comment = comment,
                                    timestamp = datetime.datetime.now()
                                )
                #reset form to preclude accidentally repeating submission
                user_transaction_form = forms.AddUserTransactionForm()
                user_transaction_added = True
Esempio n. 3
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]],
        )
Esempio n. 4
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]],
        )
Esempio n. 5
0
    def handle(self, *args, **options):
        if len(args) != 1:
          print "Need a message file"
          return

        if not os.path.exists(args[0]):
           print "File '%s' does not exist" % args[0]
           return

        message=open(args[0], 'r').read()
        title = message.split('\n')[0]
        print "Title: ", title
        print "Message:\n", message

        users = models.User.objects.all().order_by('username')
        for user in users:
          if len(user.email) > 5:
              mail.send_mail(
                  subject_line = title,
                  body_text = message,
                  recipient_list = [user.email]
              ) 
Esempio n. 6
0
def PROCESS(message, address = None, host = None):
    try:
        for rule in 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_unused(address, message.From)
        separator = _("======= Reply above this line. ====-=-=")
        parts = message.body().split(separator)
        if len(parts) != 2 :
            error = _("Your message was malformed. Please make sure to qoute \
                the original notification you received at the end of your reply.")
        else:
            reply_part = parts[0]
            reply_part = '\n'.join(reply_part.splitlines(True)[:-3])
            reply_address.create_reply(reply_part.strip())
    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.")
    if error is not None:
        from askbot.utils import mail
        from django.template import Context
        from askbot.skins.loaders import get_template

        template = get_template('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],
        )        
Esempio n. 7
0
def bounce_email(email, subject, reason=None, body_text=None):
    """sends a bounce email at address ``email``, with the subject
    line ``subject``, accepts several reasons for the bounce:

    * ``'problem_posting'``, ``unknown_user`` and ``permission_denied``
    * ``body_text`` in an optional parameter that allows to append
      extra text to the message
    """
    if reason == 'problem_posting':
        error_message = _('<p>Sorry, there was an error posting your question '
                          'please contact the %(site)s administrator</p>') % {
                              'site': askbot_settings.APP_SHORT_NAME
                          }
        error_message = string_concat(error_message, USAGE)
    elif reason == 'unknown_user':
        error_message = _(
            '<p>Sorry, in order to post questions on %(site)s '
            'by email, please <a href="%(url)s">register first</a></p>') % {
                'site': askbot_settings.APP_SHORT_NAME,
                'url': askbot_settings.APP_URL + reverse('user_signin')
            }
    elif reason == 'permission_denied':
        error_message = _(
            '<p>Sorry, your question could not be posted '
            'due to insufficient privileges of your user account</p>')
    else:
        raise ValueError('unknown reason to bounce an email: "%s"' % reason)

    if body_text != None:
        error_message = string_concat(error_message, body_text)

    #print 'sending email'
    #print email
    #print subject
    #print error_message
    mail.send_mail(recipient_list=(email, ),
                   subject_line='Re: ' + subject,
                   body_text=error_message)
    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:
                url_prefix = askbot_settings.APP_URL

                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('%(name)s, this is an update message header for %(num)d question', 
                            '%(name)s, this is an update message header for %(num)d questions',num_q) \
                                % {'num':num_q, 'name':user.username}

                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>' \
                                    % (url_prefix + 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 = url_prefix + reverse(
                                        'user_subscriptions', 
                                        kwargs = {
                                            'id': user.id,
                                            'slug': slugify(user.username)
                                        }
                                    )

                text += _(
                    'go to %(email_settings_link)s to change '
                    'frequency of email updates or '
                    '%(admin_email)s administrator'
                ) % {
                    'email_settings_link': link,
                    'admin_email': django_settings.ADMINS[0][1]
                }
                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]
                )
Esempio n. 9
0
                                        address = address,
                                        allowed_from_email = message.From
                                    )
        parts = get_parts(message)
        if reply_address.was_used:
            reply_address.edit_post(parts)
        else:
            reply_address.create_reply(parts)
    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:
        from askbot.utils import mail
        from django.template import Context
        from askbot.skins.loaders import get_template

        template = get_template('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 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,)
                )
Esempio n. 11
0
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
Esempio n. 12
0
def user_moderate(request, subject, context):
    """user subview for moderation
    """
    moderator = request.user

    if 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(self, *args, **options):
        DEBUG_THIS_COMMAND = False
        FORCE_EMAIL = False
        IGNORE_DATES = False
        TEXT_FORMAT = False

        if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False:
            return

        if options['ignore_dates']:
           IGNORE_DATES = True
           FORCE_EMAIL = True
        if options['debug']:
           DEBUG_THIS_COMMAND = True
        if options['force_email']:
           FORCE_EMAIL = True
        if options['text']:
           TEXT_FORMAT = True

        #get questions without answers, excluding closed and deleted
        #order it by descending added_at date
        wait_period = datetime.timedelta(
            askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER
        )
        start_cutoff_date = datetime.datetime.now() - wait_period

        recurrence_delay = datetime.timedelta(
            askbot_settings.UNANSWERED_REMINDER_FREQUENCY
        )
        max_emails = askbot_settings.MAX_UNANSWERED_REMINDERS
        end_cutoff_date = start_cutoff_date - (max_emails - 1)*recurrence_delay

        if IGNORE_DATES:
            print "Email Reminders: Questions Asked BEFORE %s" % (start_cutoff_date)
            questions = models.Question.objects.exclude(
                                        closed = True
                                    ).exclude(
                                        deleted = True
                                    ).filter(
                                        added_at__lt = start_cutoff_date
                                    ).filter(
                                        answer_count = 0
                                    ).order_by('-added_at')
        else: 
            print "Email Reminders: Wait Period: %s - Email Every: %s - Max Emails: %d" % (
                      wait_period, recurrence_delay, max_emails)
            print "From %s to %s" % (end_cutoff_date, start_cutoff_date)
            questions = models.Question.objects.exclude(
                                        closed = True
                                    ).exclude(
                                        deleted = True
                                    ).filter(
                                        added_at__lt = start_cutoff_date
                                    ).exclude(
                                        added_at__lt = end_cutoff_date
                                    ).filter(
                                        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
        now = datetime.datetime.now()
        print "Unanswered Question Set:"
        print_question_list(questions)

        for user in models.User.objects.exclude(status = 'b'):
            # Sanity check to catch invalid email
            if len(user.email) < 5:
                continue

            #user_questions = questions.exclude(author = user)
            user_questions = user.get_tag_filtered_questions(
                                                questions = questions,
                                                context = 'email'
                                            )

            user_questions = list(user_questions)
            if user_questions:
                last = user_questions[-1]
                for i in range(len(user_questions)-2,-1,-1):
                    if last == user_questions[i]:
                       del user_questions[i]
                    else:
                       last=user_questions[i]

            final_question_list = list()
            #todo: rewrite using query set filter
            #may be a lot more efficient
            for question in user_questions:
                activity_type = const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT
                try:
                    activity = models.Activity.objects.get(
                        user = user,
                        question = question,
                        activity_type = activity_type
                    )
                    now = datetime.datetime.now()
                    if now < activity.active_at + recurrence_delay:
                        #print "Time Reject: %s < %s" % (now, activity.active_at + recurrence_delay)
                        # Only send email if minimum delay between emails has been met
                        if not DEBUG_THIS_COMMAND and not FORCE_EMAIL:
                            continue
                except models.Activity.DoesNotExist:
                    activity = models.Activity(
                        user = user,
                        question = question,
                        activity_type = activity_type,
                        content_object = question,
                    )
                if not DEBUG_THIS_COMMAND:
                    activity.active_at = datetime.datetime.now()
                    activity.save()
                final_question_list.append(question)

            question_count = len(final_question_list)
            if question_count == 0:
                    continue

            tag_summary = get_tag_summary_from_questions(final_question_list)

            body_text = '<p>This email is sent as a reminder that the following questions do not have ' \
                        'an answer. If you can provide an answer, please click on the link and share ' \
                        'your knowlege.</p><hr><p><b>Summary List</b></p>'

            if TEXT_FORMAT:
                body_text = 'This email is sent as a reminder that the following questions do not have\n' \
                        'an answer. If you can provide an answer, please share ' \
                        'your knowlege.\nSummary List\n'

            tag_list = {}
            # Build list of Tags
            for question in final_question_list:
               tag_names = question.get_tag_names()
               tag_string = ""
               days = now - question.added_at
               for tag in tag_names:
                 tag_string += tag + ", "
                 if tag in tag_list:
                    tag_list[tag].append((question, days))
                 else:
                    tag_list[tag] = [(question, now - question.added_at)]


               if TEXT_FORMAT:
                   body_text += '  - (%02d days old) %s [%s]\n' \
                      % (
                          days.days,
                          question.title,
                          tag_string[:-2]
                      )
               else:
                   body_text += '<li>(%02d days old) <a href="%s%s">%s</a> [%s]</li>' \
                      % (
                          days.days,
                          askbot_settings.APP_URL,
                          question.get_absolute_url(),
                          question.title,
                          tag_string[:-2]
                      )

            tag_keys = tag_list.keys()
            tag_keys.sort()
            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
            }

            if TEXT_FORMAT:
              body_text += "\nList ordered by Tags\n\n"
            else:
              body_text += "<hr><p><b>List ordered by Tags</b></p><br>"
            for tag in tag_keys:
                if TEXT_FORMAT:
                    body_text += tag + '\n'
                else:
                    body_text += '<p><b>' + tag + '</b></p><ul>'
                for question in tag_list[tag]:
                    if TEXT_FORMAT:
                        body_text += '  - (%02d days old) %s\n' \
                            % (
                                question[1].days,
                                question[0].title
                            )
                    else:
                        body_text += '<li>(%02d days old) <a href="%s%s">%s</a></li>' \
                            % (
                                question[1].days,
                                askbot_settings.APP_URL,
                                question[0].get_absolute_url(),
                                question[0].title
                            )
                if not TEXT_FORMAT:
                    body_text += '</ul>'
                body_text += '\n'

            if DEBUG_THIS_COMMAND:
                print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \
                    (user.email, subject_line, body_text)
            else:
                print "User: %s - %s" % (user.email, subject_line)
                mail.send_mail(
                    subject_line = subject_line,
                    body_text = body_text,
                    recipient_list = (user.email,)
                )
Esempio n. 14
0
    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():
            #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:
                url_prefix = askbot_settings.APP_URL

                tag_summary = get_tag_summary_from_questions(q_list.keys())
                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('%(name)s, this is an update message header for %(num)d question', 
                            '%(name)s, this is an update message header for %(num)d questions',num_q) \
                                % {'num':num_q, 'name':user.username}

                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>' \
                                    % (url_prefix + q.get_absolute_url(), q.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>'
                #              )

                text += _(
                            'Please visit the askbot and see what\'s new! '
                            'Could you spread the word about it - '
                            'can somebody you know help answering those questions or '
                            'benefit from posting one?'
                        )

                feeds = EmailFeedSetting.objects.filter(
                                                        subscriber=user,
                                                    )
                feed_freq = [feed.frequency for feed in feeds]
                text += '<p></p>'
                if 'd' in feed_freq:
                    text += _('Your most frequent subscription setting is \'daily\' '
                               'on selected questions. If you are receiving more than one '
                               'email per day'
                               'please tell about this issue to the askbot administrator.'
                               )
                elif 'w' in feed_freq:
                    text += _('Your most frequent subscription setting is \'weekly\' '
                               'if you are receiving this email more than once a week '
                               'please report this issue to the askbot administrator.'
                               )
                text += ' '
                text += _(
                            'There is a chance that you may be receiving links seen '
                            'before - due to a technicality that will eventually go away. '
                        )

                link = url_prefix + user.get_profile_url() + '?sort=email_subscriptions'
                text += _(
                    'go to %(email_settings_link)s to change '
                    'frequency of email updates or '
                    '%(admin_email)s administrator'
                ) % {
                    'email_settings_link': link,
                    'admin_email': django_settings.ADMINS[0][1]
                }
                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 handle_noargs(self, **options):
        if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False:
            return
        #get questions without answers, excluding closed and deleted
        #order it by descending added_at date
        wait_period = datetime.timedelta(
            askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER
        )
        cutoff_date = datetime.datetime.now() + wait_period

        questions = models.Question.objects.exclude(
                                        closed = True
                                    ).exclude(
                                        deleted = True
                                    ).filter(
                                        added_at__lt = cutoff_date
                                    ).filter(
                                        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 = list()
            #todo: rewrite using query set filter
            #may be a lot more efficient
            for question in user_questions:
                activity_type = const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT
                try:
                    activity = models.Activity.objects.get(
                        user = user,
                        question = question,
                        activity_type = activity_type
                    )
                    now = datetime.datetime.now()
                    recurrence_delay = datetime.timedelta(
                        askbot_settings.UNANSWERED_REMINDER_FREQUENCY
                    )
                    if now < activity.active_at + recurrence_delay:
                        continue
                except models.Activity.DoesNotExist:
                    activity = models.Activity(
                        user = user,
                        question = question,
                        activity_type = activity_type,
                        content_object = question,
                    )
                activity.active_at = datetime.datetime.now()
                activity.save()
                final_question_list.append(question)

            question_count = len(final_question_list)
            if question_count == 0:
                continue

            tag_summary = get_tag_summary_from_questions(user_questions)
            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.title
                            )
            body_text += '</ul>'

            mail.send_mail(
                subject_line = subject_line,
                body_text = body_text,
                recipient_list = (user.email,)
            )
Esempio n. 16
0
    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:
                url_prefix = askbot_settings.APP_URL

                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>' \
                                    % (url_prefix + 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 = url_prefix + 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': 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])
Esempio n. 17
0
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")
Esempio n. 18
0
    def handle_noargs(self, **options):
        if askbot_settings.ENABLE_UNANSWERED_REMINDERS == False:
            return
        #get questions without answers, excluding closed and deleted
        #order it by descending added_at date
        wait_period = datetime.timedelta(
            askbot_settings.DAYS_BEFORE_SENDING_UNANSWERED_REMINDER)
        cutoff_date = datetime.datetime.now() + wait_period

        questions = models.Question.objects.exclude(closed=True).exclude(
            deleted=True).filter(added_at__lt=cutoff_date).filter(
                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 = list()
            #todo: rewrite using query set filter
            #may be a lot more efficient
            for question in user_questions:
                activity_type = const.TYPE_ACTIVITY_UNANSWERED_REMINDER_SENT
                try:
                    activity = models.Activity.objects.get(
                        user=user,
                        question=question,
                        activity_type=activity_type)
                    now = datetime.datetime.now()
                    recurrence_delay = datetime.timedelta(
                        askbot_settings.UNANSWERED_REMINDER_FREQUENCY)
                    if now < activity.active_at + recurrence_delay:
                        continue
                except models.Activity.DoesNotExist:
                    activity = models.Activity(
                        user=user,
                        question=question,
                        activity_type=activity_type,
                        content_object=question,
                    )
                activity.active_at = datetime.datetime.now()
                activity.save()
                final_question_list.append(question)

            question_count = len(final_question_list)
            if question_count == 0:
                continue

            tag_summary = get_tag_summary_from_questions(user_questions)
            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.title
                            )
            body_text += '</ul>'

            mail.send_mail(subject_line=subject_line,
                           body_text=body_text,
                           recipient_list=(user.email, ))
Esempio n. 19
0
def user_moderate(request, subject):
    """user subview for moderation 
    """
    moderator = request.user

    if 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
Esempio n. 20
0
                    reply_part.strip(),
                    attachments = attachments
                )
            else:
                reply_address.create_reply(
                    reply_part.strip(),
                    attachments = attachments
                )
    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:
        from askbot.utils import mail
        from django.template import Context
        from askbot.skins.loaders import get_template

        template = get_template('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],
        )        
Esempio n. 21
0
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,]
                            )
                            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")
Esempio n. 22
0
    def handle_noargs(self, **options):
        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.Question.objects.exclude(
                                        deleted = True
                                    ).added_between(
                                        start = schedule.start_cutoff_date,
                                        end = schedule.end_cutoff_date
                                    ).filter(
                                        answer_count__gt = 0
                                    ).filter(
                                        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

            #tag_summary = get_tag_summary_from_questions(final_question_list)
            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.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,)
                )