From db8aa57e9a3caf9b2ed080b440703d634abd14a1 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 15 May 2017 15:00:48 +0530 Subject: Add send_bulk_mail function to send mails to students enrolled in a course --- yaksh/send_emails.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/yaksh/send_emails.py b/yaksh/send_emails.py index 37736d5..bcf633f 100644 --- a/yaksh/send_emails.py +++ b/yaksh/send_emails.py @@ -8,11 +8,14 @@ import hashlib from random import randint from textwrap import dedent import smtplib +import os # Django imports from django.utils.crypto import get_random_string from django.conf import settings -from django.core.mail import send_mass_mail, send_mail +from django.core.mail import EmailMultiAlternatives, send_mail +from django.core.files.storage import default_storage +from django.core.files.base import ContentFile def generate_activation_key(username): @@ -56,3 +59,30 @@ def send_user_mail(user_mail, key): success = False return success, msg + +def send_bulk_mail(subject, email_body, recipients, attachments): + try: + text_msg = "Yaksh" + msg = EmailMultiAlternatives(subject, text_msg, settings.SENDER_EMAIL, + recipients + ) + msg.attach_alternative(email_body, "text/html") + if attachments: + for file in attachments: + path = default_storage.save('attachments/'+file.name, + ContentFile(file.read()) + ) + msg.attach_file(os.sep.join((settings.MEDIA_ROOT, path)), + mimetype="text/html" + ) + default_storage.delete(path) + msg.send() + + message = "Email Sent Successfully" + + except Exception as exc_msg: + message = """Error: {0}. Please check email address.\ + If email address is correct then + Please contact {1}.""".format(exc_msg, settings.REPLY_EMAIL) + + return message -- cgit From bd255f751dbff97d92e9c34652af37c67b62b2ff Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 15 May 2017 15:01:10 +0530 Subject: Change urls.py and views.py - Change views to send mails to students enrolled in a course - Add reverse resolution in urls.py --- yaksh/urls.py | 2 +- yaksh/views.py | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/yaksh/urls.py b/yaksh/urls.py index e4676d3..825e5f5 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -79,7 +79,7 @@ urlpatterns = [ url(r'manage/enroll/rejected/(?P\d+)/$', views.enroll, {'was_rejected': True}), url(r'manage/enrolled/reject/(?P\d+)/$', - views.reject, {'was_enrolled': True}), + views.reject, {'was_enrolled': True}, name="reject_users"), url(r'^manage/searchteacher/(?P\d+)/$', views.search_teacher), url(r'^manage/addteacher/(?P\d+)/$', views.add_teacher, name='add_teacher'), url(r'^manage/remove_teachers/(?P\d+)/$', views.remove_teachers, name='remove_teacher'), diff --git a/yaksh/views.py b/yaksh/views.py index c7af5cc..41db80e 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -42,7 +42,7 @@ from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ from .settings import URL_ROOT from yaksh.models import AssignmentUpload from .file_utils import extract_files -from .send_emails import send_user_mail, generate_activation_key +from .send_emails import send_user_mail, generate_activation_key, send_bulk_mail from .decorators import email_verified @@ -771,12 +771,35 @@ def reject(request, course_id, user_id=None, was_enrolled=False): raise Http404('This course does not belong to you') if request.method == 'POST': - reject_ids = request.POST.getlist('check') + user_ids = request.POST.getlist('check') + if not user_ids: + message = "Please select atleast one User" + return my_render_to_response('yaksh/course_detail.html', + {'course': course, "message": message}, + context_instance=ci) + + if request.POST.get('send_mail') == 'send_mail': + users = User.objects.filter(id__in=user_ids) + recipients = [user.email for user in users] + email_body = request.POST.get('body') + subject = request.POST.get('subject') + attachments = request.FILES.getlist('email_attach') + message = send_bulk_mail(subject, email_body, recipients, + attachments) + + return my_render_to_response('yaksh/course_detail.html', + {'course': course, "message": message}, + context_instance=ci) + + if request.POST.get('reject') == 'reject': + reject_ids = user_ids else: reject_ids = [user_id] if not reject_ids: - return my_render_to_response('yaksh/course_detail.html', {'course': course}, - context_instance=ci) + message = "Please select atleast one User" + return my_render_to_response('yaksh/course_detail.html', + {'course': course, "message": message}, + context_instance=ci) users = User.objects.filter(id__in=reject_ids) course.reject(was_enrolled, *users) return course_detail(request, course_id) -- cgit From 2d62359adf671d5a75201a2314825039adc7291a Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 15 May 2017 15:03:21 +0530 Subject: Change course.js and course_detail.html - Allow moderator to send emails to students enrollded in a course - Add validations to check email data in course.js --- yaksh/static/yaksh/js/course.js | 45 ++++++++++++++++++++++++ yaksh/templates/yaksh/course_detail.html | 59 +++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 12 deletions(-) diff --git a/yaksh/static/yaksh/js/course.js b/yaksh/static/yaksh/js/course.js index 5b79e68..3e214be 100644 --- a/yaksh/static/yaksh/js/course.js +++ b/yaksh/static/yaksh/js/course.js @@ -35,4 +35,49 @@ $(".reject").change( function(){ }); } }); + +$(function() { + $('textarea#email_body').froalaEditor({ + heightMin: 100, + heightMax: 200 + }) + }); + +var status; +var btn_name; + +$("#send_mail").click(function(){ + btn_name = "send_mail"; + var subject = $("#subject").val(); + var body = $('#email_body').val(); + if (subject == '' || body == ''){ + status = false; + $("#error_msg").html("Please enter email details"); + $("#dialog").dialog(); + } + else{ + status = true; + } +}); + +$('#reject-form').submit(function(eventObj) { + if (btn_name == 'send_mail'){ + if(status == false){ + return false; + } + } + var selected = []; + $('#reject input:checked').each(function() { + selected.push($(this).attr('value')); + }); + if(selected.length > 0){ + return true; + } + else{ + $("#error_msg").html("Please select atleast one user"); + $( "#dialog" ).dialog(); + return false; + } +}); + }); diff --git a/yaksh/templates/yaksh/course_detail.html b/yaksh/templates/yaksh/course_detail.html index cd4144f..2cbdf8b 100644 --- a/yaksh/templates/yaksh/course_detail.html +++ b/yaksh/templates/yaksh/course_detail.html @@ -6,6 +6,14 @@ {% block script %} + + +{% endblock %} +{% block css %} + + + + {% endblock %} {% block content %}
@@ -29,11 +37,20 @@
+ {% if message %} + + {% endif %}
Requests

{% if course.get_requests %}  Select all
+
+ {% csrf_token %} @@ -43,9 +60,7 @@ - - {% csrf_token %} - {% for request in course.get_requests %} + {% for request in course.get_requests %} @@ -76,6 +91,8 @@ {% if course.get_enrolled %}  Select all
+ + {% csrf_token %}
Institute Department Enroll/Reject
{{ forloop.counter }}.
@@ -86,9 +103,7 @@ {% for enrolled in course.get_enrolled %} - - {% csrf_token %} - + @@ -99,11 +114,27 @@ - + + {% endfor %}
Department Reject
{{ forloop.counter }}. {{ enrolled.get_full_name|title }} Reject -
- + + + Click Here to send email to students + +
+
+ +

+
+ Attachments: +
+ +
+

+
{% endif %} @@ -114,6 +145,8 @@ {% if course.get_rejected %}  Select all
+
+ {% csrf_token %} @@ -123,9 +156,7 @@ - {% for rejected in course.get_rejected %} - - {% csrf_token %} + {% for rejected in course.get_rejected %} @@ -151,4 +182,8 @@ + +
+

+
{% endblock %} -- cgit From eff546b51b7b0d025b48472b4238325f406f06db Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 15 May 2017 15:06:11 +0530 Subject: Add tests to check bulk email sending --- yaksh/test_views.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 37e5ce4..7018bd2 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -8,6 +8,7 @@ from django.test import TestCase from django.test import Client from django.utils import timezone from django.core import mail +from django.core.files.uploadedfile import SimpleUploadedFile from yaksh.models import User, Profile, Question, Quiz, QuestionPaper,\ QuestionSet, AnswerPaper, Answer, Course, StandardTestCase,\ @@ -1072,6 +1073,57 @@ class TestCourseDetail(TestCase): self.assertTemplateUsed(response, 'yaksh/course_detail.html') + def test_send_mail_to_course_students(self): + """ Check if bulk mail is sent to multiple students enrolled in a course + """ + self.client.login( + username=self.user1.username, + password=self.user1_plaintext_pass + ) + self.student2 = User.objects.create_user( + username='demo_student2', + password=self.student_plaintext_pass, + first_name='student_first_name', + last_name='student_last_name', + email='demo_student2@test.com' + ) + self.student3 = User.objects.create_user( + username='demo_student3', + password=self.student_plaintext_pass, + first_name='student_first_name', + last_name='student_last_name', + email='demo_student3@test.com' + ) + self.student4 = User.objects.create_user( + username='demo_student4', + password=self.student_plaintext_pass, + first_name='student_first_name', + last_name='student_last_name', + email='demo_student4@test.com' + ) + user_ids = [self.student.id, self.student2.id, self.student3.id, + self.student4.id] + user_emails = [self.student.email, self.student2.email, + self.student3.email, self.student4.email] + + self.user1_course.students.add(*user_ids) + attachment = SimpleUploadedFile("file.txt", b"Test") + response = self.client.post(reverse('yaksh:reject_users', + kwargs={'course_id': self.user1_course.id}), + data={'send_mail': 'send_mail', 'email_attach': [attachment], + 'subject': 'test_bulk_mail', 'body': 'Test_Mail', + 'check': user_ids} + ) + attachment_file = mail.outbox[0].attachments[0][0] + subject = mail.outbox[0].subject + body = mail.outbox[0].alternatives[0][0] + recipients = mail.outbox[0].recipients() + self.assertEqual(attachment_file, "file.txt") + self.assertEqual(subject, "test_bulk_mail") + self.assertEqual(body, "Test_Mail") + self.assertSequenceEqual(recipients, user_emails) + + class TestEnrollRequest(TestCase): def setUp(self): self.client = Client() -- cgit From 928ebb23f8b2926240fc220791655614cc4192d2 Mon Sep 17 00:00:00 2001 From: Date: Mon, 12 Jun 2017 18:19:21 +0530 Subject: Change views.py and urls.py - Add new url for sending email - Add new view function to send email to students --- yaksh/urls.py | 1 + yaksh/views.py | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/yaksh/urls.py b/yaksh/urls.py index 825e5f5..068df7a 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -69,6 +69,7 @@ urlpatterns = [ url(r'manage/enroll/rejected/(?P\d+)/(?P\d+)/$', views.enroll, {'was_rejected': True}), url(r'manage/reject/(?P\d+)/(?P\d+)/$', views.reject), + url(r'manage/send_mail/(?P\d+)/$', views.send_mail, name="send_mail"), url(r'manage/enrolled/reject/(?P\d+)/(?P\d+)/$', views.reject, {'was_enrolled': True}), url(r'manage/toggle_status/(?P\d+)/$', views.toggle_course_status), diff --git a/yaksh/views.py b/yaksh/views.py index 41db80e..3319773 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -757,10 +757,9 @@ def enroll(request, course_id, user_id=None, was_rejected=False): course.enroll(was_rejected, *users) return course_detail(request, course_id) - @login_required @email_verified -def reject(request, course_id, user_id=None, was_enrolled=False): +def send_mail(request, course_id, user_id=None): user = request.user ci = RequestContext(request) if not is_moderator(user): @@ -770,6 +769,7 @@ def reject(request, course_id, user_id=None, was_enrolled=False): if not course.is_creator(user) and not course.is_teacher(user): raise Http404('This course does not belong to you') + message = None if request.method == 'POST': user_ids = request.POST.getlist('check') if not user_ids: @@ -787,12 +787,25 @@ def reject(request, course_id, user_id=None, was_enrolled=False): message = send_bulk_mail(subject, email_body, recipients, attachments) - return my_render_to_response('yaksh/course_detail.html', - {'course': course, "message": message}, - context_instance=ci) + return my_render_to_response('yaksh/course_detail.html', + {'course': course, "message": message, + 'msg': 'mail'}, + context_instance=ci) - if request.POST.get('reject') == 'reject': - reject_ids = user_ids +@login_required +@email_verified +def reject(request, course_id, user_id=None, was_enrolled=False): + user = request.user + ci = RequestContext(request) + if not is_moderator(user): + raise Http404('You are not allowed to view this page') + + course = get_object_or_404(Course, pk=course_id) + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') + + if request.method == 'POST': + reject_ids = request.POST.getlist('check') else: reject_ids = [user_id] if not reject_ids: -- cgit From a7c9591eac66eb2751a2706b5686a997d7c236dd Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 12 Jun 2017 18:22:21 +0530 Subject: Add separate form to send emails --- yaksh/static/yaksh/js/course.js | 2 +- yaksh/templates/yaksh/course_detail.html | 67 ++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/yaksh/static/yaksh/js/course.js b/yaksh/static/yaksh/js/course.js index 3e214be..74ad37c 100644 --- a/yaksh/static/yaksh/js/course.js +++ b/yaksh/static/yaksh/js/course.js @@ -60,7 +60,7 @@ $("#send_mail").click(function(){ } }); -$('#reject-form').submit(function(eventObj) { +$('#send_mail_form').submit(function(eventObj) { if (btn_name == 'send_mail'){ if(status == false){ return false; diff --git a/yaksh/templates/yaksh/course_detail.html b/yaksh/templates/yaksh/course_detail.html index 2cbdf8b..676d7f3 100644 --- a/yaksh/templates/yaksh/course_detail.html +++ b/yaksh/templates/yaksh/course_detail.html @@ -21,9 +21,13 @@ @@ -44,6 +52,47 @@ {% endif %} + {% if msg == 'mail' %} +
+
Send Mails to Students

+ {% if course.get_enrolled %} +  Select all +
+ + {% csrf_token %} +
Institute Department Enroll
{{ forloop.counter }}.
+ + + + + + + + {% for enrolled in course.get_enrolled %} + + + + + + + + + + {% endfor %} +
Full NameEmailRoll NumberInstituteDepartment
{{ forloop.counter }}. {{ enrolled.get_full_name|title }} {{enrolled.email}} {{enrolled.profile.roll_number}} {{enrolled.profile.institute}} {{enrolled.profile.department}}
+
+ +

+
+ Attachments: +
+ +
+ {% endif %} + +
+ {% else %}
Requests

{% if course.get_requests %} @@ -91,7 +140,7 @@ {% if course.get_enrolled %}  Select all
-
+ {% csrf_token %} @@ -118,21 +167,6 @@ {% endfor %}
- - - Click Here to send email to students - -
-
- -

-
- Attachments: -
- -
-

@@ -180,6 +214,7 @@ {% endif %}
+ {% endif %}
-- cgit From a002ab59dbff856ee3838078cbe4f8fa439fd894 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 12 Jun 2017 18:23:17 +0530 Subject: Change views tests to check send email --- yaksh/test_views.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 7018bd2..caec9d4 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -1108,7 +1108,7 @@ class TestCourseDetail(TestCase): self.user1_course.students.add(*user_ids) attachment = SimpleUploadedFile("file.txt", b"Test") - response = self.client.post(reverse('yaksh:reject_users', + response = self.client.post(reverse('yaksh:send_mail', kwargs={'course_id': self.user1_course.id}), data={'send_mail': 'send_mail', 'email_attach': [attachment], 'subject': 'test_bulk_mail', 'body': 'Test_Mail', @@ -1123,6 +1123,20 @@ class TestCourseDetail(TestCase): self.assertEqual(body, "Test_Mail") self.assertSequenceEqual(recipients, user_emails) + # Test for get request in send mail + get_response = self.client.get(reverse('yaksh:send_mail', + kwargs={'course_id': self.user1_course.id} + )) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['course'], self.user1_course) + + # Test if no users are selected + post_response = self.client.post(reverse('yaksh:send_mail', + kwargs={'course_id': self.user1_course.id}), + data={'check': []} + ) + self.assertIn('select', post_response.context['message']) + class TestEnrollRequest(TestCase): def setUp(self): -- cgit From 57eaf342d16f33b8ea67b89c78907d9c1f7b4632 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 14 Jun 2017 12:33:45 +0530 Subject: Change send_emails.py and course_detail.html - Change variable assignment in send_emails.py - Add proper indentation in course_detail.html --- yaksh/send_emails.py | 2 +- yaksh/templates/yaksh/course_detail.html | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/yaksh/send_emails.py b/yaksh/send_emails.py index 4465ce9..ae49f23 100644 --- a/yaksh/send_emails.py +++ b/yaksh/send_emails.py @@ -63,7 +63,7 @@ def send_user_mail(user_mail, key): def send_bulk_mail(subject, email_body, recipients, attachments): try: - text_msg = "Yaksh" + text_msg = "" msg = EmailMultiAlternatives(subject, text_msg, settings.SENDER_EMAIL, recipients ) diff --git a/yaksh/templates/yaksh/course_detail.html b/yaksh/templates/yaksh/course_detail.html index 676d7f3..4ff380e 100644 --- a/yaksh/templates/yaksh/course_detail.html +++ b/yaksh/templates/yaksh/course_detail.html @@ -22,11 +22,15 @@