From: W. Trevor King Date: Tue, 24 Apr 2012 21:45:10 +0000 (-0400) Subject: Finish mailpipe respond() doctests. X-Git-Tag: v0.2~3 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=522783a9af5ade8cd7c0a6ce4435abe589eb5440;p=pygrader.git Finish mailpipe respond() doctests. Also: * Add course.name configuration to README example. * Standardize course.name examples on the more formal `Physics 101`. * Standardize robot nickname examples on `phys-101 robot`. --- diff --git a/README b/README index f3858f3..dba015f 100644 --- a/README +++ b/README @@ -79,10 +79,11 @@ the course directory:: $ cat test/course.conf [course] - robot: Robot101 + name: Physics 101 assignments: Attendance 1, Attendance 2, Attendance 3, Attendance 4, Attendance 5, Attendance 6, Attendance 7, Attendance 8, Attendance 9, Assignment 1, Assignment 2, Exam 1, Exam 2 + robot: Robot101 professors: Gandalf assistants: Sauron students: Bilbo Baggins, Frodo Baggins, Aragorn @@ -113,7 +114,7 @@ the course directory:: due: 2011-10-17 [Robot101] - nickname: phys101 robot + nickname: phys-101 robot emails: phys101@tower.edu pgp-key: 4332B6E3 diff --git a/pygrader/mailpipe.py b/pygrader/mailpipe.py index 10f4846..8d556fb 100644 --- a/pygrader/mailpipe.py +++ b/pygrader/mailpipe.py @@ -336,7 +336,7 @@ def mailpipe(basedir, course, stream=None, mailbox=None, input_=None, We got an email from you with the following subject: 'need help for the first homework' which does not match any submittable assignment name for - phys101. + Physics 101. Remember to use the full name for the assignment in the subject. For example: Assignment 1 submission @@ -375,8 +375,179 @@ def mailpipe(basedir, course, stream=None, mailbox=None, input_=None, --===============...==-- + Response to a missing subject: + + >>> server = SMTPServer( + ... ('localhost', 1025), None, process=process, count=1) + >>> del message['Subject'] + >>> messages = [message] + >>> ms = MessageSender(address=('localhost', 1025), messages=messages) + >>> loop() # doctest: +REPORT_UDIFF, +ELLIPSIS + respond with: + Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha1"; boundary="===============...==" + MIME-Version: 1.0 + Content-Disposition: inline + Date: ... + From: Robot101 + Reply-to: Robot101 + To: Bilbo Baggins + Subject: no subject in + + --===============...== + Content-Type: multipart/mixed; boundary="===============...==" + MIME-Version: 1.0 + + --===============...== + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Disposition: inline + + Billy, + + We received an email message from you without a subject. + + Yours, + phys-101 robot + --===============...== + Content-Type: message/rfc822 + MIME-Version: 1.0 + + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Disposition: inline + From: Billy B + To: phys101 + Return-Path: + Received: from smtp.mail.uu.edu (localhost.localdomain [127.0.0.1]) by smtp.mail.uu.edu (Postfix) with SMTP id 68CB45C8453 for ; Mon, 10 Oct 2011 12:50:46 -0400 (EDT) + Received: from smtp.home.net (smtp.home.net [123.456.123.456]) by smtp.mail.uu.edu (Postfix) with ESMTP id 5BA225C83EF for ; Mon, 09 Oct 2011 11:50:46 -0400 (EDT) + Message-ID: + + The answer is 42. + --===============...==-- + --===============...== + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Description: OpenPGP digital signature + Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" + + -----BEGIN PGP SIGNATURE----- + Version: GnuPG v2.0.17 (GNU/Linux) + + ... + -----END PGP SIGNATURE----- + + --===============...==-- + + Response to an insecure message from a person with a PGP key: + + >>> student = course.course.person(email='bb@greyhavens.net') + >>> student.pgp_key = '4332B6E3' + >>> server = SMTPServer( + ... ('localhost', 1025), None, process=process, count=1) + >>> del message['Subject'] + >>> messages = [message] + >>> ms = MessageSender(address=('localhost', 1025), messages=messages) + >>> loop() # doctest: +REPORT_UDIFF, +ELLIPSIS + respond with: + Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; micalg="pgp-sha1"; boundary="===============...==" + MIME-Version: 1.0 + Content-Disposition: inline + Date: ... + From: Robot101 + Reply-to: Robot101 + To: Bilbo Baggins + Subject: unsigned message + + --===============...== + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Type: application/pgp-encrypted; charset="us-ascii" + + Version: 1 + + --===============...== + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Description: OpenPGP encrypted message + Content-Type: application/octet-stream; name="encrypted.asc"; charset="us-ascii" + + -----BEGIN PGP MESSAGE----- + Version: GnuPG v2.0.17 (GNU/Linux) + + ... + -----END PGP MESSAGE----- + + --===============...==-- + + Response to a message from an unregistered person: + + >>> server = SMTPServer( + ... ('localhost', 1025), None, process=process, count=1) >>> del message['Return-Path'] - >>> message['Return-Path'] = '' + >>> message['Return-Path'] = '' + >>> messages = [message] + >>> ms = MessageSender(address=('localhost', 1025), messages=messages) + >>> loop() # doctest: +REPORT_UDIFF, +ELLIPSIS + respond with: + Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg="pgp-sha1"; boundary="===============...==" + MIME-Version: 1.0 + Content-Disposition: inline + Date: ... + From: Robot101 + Reply-to: Robot101 + To: "invalid.return.path@home.net" + Subject: unregistered address invalid.return.path@home.net + + --===============...== + Content-Type: multipart/mixed; boundary="===============...==" + MIME-Version: 1.0 + + --===============...== + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Disposition: inline + + invalid.return.path@home.net, + + Your email address is not registered with pygrader for + Physics 101. If you feel it should be, contact your professor + or TA. + + Yours, + phys-101 robot + --===============...== + Content-Type: message/rfc822 + MIME-Version: 1.0 + + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Disposition: inline + From: Billy B + To: phys101 + Received: from smtp.mail.uu.edu (localhost.localdomain [127.0.0.1]) by smtp.mail.uu.edu (Postfix) with SMTP id 68CB45C8453 for ; Mon, 10 Oct 2011 12:50:46 -0400 (EDT) + Received: from smtp.home.net (smtp.home.net [123.456.123.456]) by smtp.mail.uu.edu (Postfix) with ESMTP id 5BA225C83EF for ; Mon, 09 Oct 2011 11:50:46 -0400 (EDT) + Message-ID: + Return-Path: + + The answer is 42. + --===============...==-- + --===============...== + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Description: OpenPGP digital signature + Content-Type: application/pgp-signature; name="signature.asc"; charset="us-ascii" + + -----BEGIN PGP SIGNATURE----- + Version: GnuPG v2.0.17 (GNU/Linux) + + ... + -----END PGP SIGNATURE----- + + --===============...==-- >>> course.cleanup() """ @@ -433,14 +604,6 @@ def _parse_message(course, msg, respond=None, use_color=None): string='no Return-Path in {}'.format(mid), color=lowlight)) return None sender = sender[1:-1] # strip wrapping '<' and '>' - time = _message_time(message=msg, use_color=use_color) - - if respond: - if time: - time_str = _formatdate(time) - else: - time_str = 'unknown time' - response_subject = 'received {} at {}'.format(mid, time_str) people = list(course.find_people(email=sender)) if len(people) == 0: @@ -448,16 +611,15 @@ def _parse_message(course, msg, respond=None, use_color=None): string='no person found to match {}'.format(sender), color=bad)) if respond: - person = _Person(name=None, emails=[sender]) + person = _Person(name=sender, emails=[sender]) + response_subject = 'unregistered address {}'.format(sender) response_text = ( '{},\n\n' 'Your email address is not registered with pygrader for\n' '{}. If you feel it should be, contact your professor\n' 'or TA.\n\n' 'Yours,\n{}').format( - sender, course.robot.alias()) - response_text = 'Address {} is not registered for {}.'.format( - sender, course.name) + sender, course.name, course.robot.alias()) response = _construct_response( author=course.robot, targets=[person], subject=response_subject, text=response_text, original=msg) @@ -472,20 +634,21 @@ def _parse_message(course, msg, respond=None, use_color=None): person = people[0] if person.pgp_key: + original = msg msg = _get_verified_message(msg, person.pgp_key, use_color=use_color) if msg is None: if respond: + response_subject = 'unsigned message {}'.format(mid) response_text = ( '{},\n\n' 'We received an email message from you without a valid\n' 'PGP signature.\n\n' 'Yours,\n{}').format( person.alias(), course.robot.alias()) - response_text = 'Message not signed by {}.'.format( - person.pgp_key) response = _construct_response( author=course.robot, targets=[person], - subject=response_subject, text=response_text, original=msg) + subject=response_subject, text=response_text, + original=original) respond(response) return None @@ -493,6 +656,7 @@ def _parse_message(course, msg, respond=None, use_color=None): _LOG.warn(_color_string( string='no subject in {}'.format(mid), color=bad)) if respond: + response_subject = 'no subject in {}'.format(mid) response_text = ( '{},\n\n' 'We received an email message from you without a subject.\n\n' @@ -565,11 +729,17 @@ def _parse_message(course, msg, respond=None, use_color=None): subject=response_subject, text=response_text, original=msg) respond(response) + time = _message_time(message=msg, use_color=use_color) + if respond: response_subject = 'received {} submission'.format(assignment.name) + if time: + time_str = 'on {}'.format(_formatdate(time)) + else: + time_str = 'at an unknown time' response_text = ( '{},\n\n' - 'We received your submission for {} on {}.\n\n' + 'We received your submission for {} {}.\n\n' 'Yours,\n{}').format( person.alias(), assignment.name, time_str, course.robot.alias()) response = _construct_response( diff --git a/pygrader/storage.py b/pygrader/storage.py index 28ffd9c..8b0c8b8 100644 --- a/pygrader/storage.py +++ b/pygrader/storage.py @@ -45,7 +45,7 @@ def load_course(basedir): >>> stub_course = StubCourse(load=False) >>> course = load_course(basedir=stub_course.basedir) >>> course.name - 'phys101' + 'Physics 101' >>> course.assignments # doctest: +ELLIPSIS [, ...] >>> course.people # doctest: +ELLIPSIS diff --git a/pygrader/test/course.py b/pygrader/test/course.py index 1d8e3a9..62d3572 100644 --- a/pygrader/test/course.py +++ b/pygrader/test/course.py @@ -10,7 +10,7 @@ from pygrader.storage import load_course as _load_course COURSE_CONF = """ [course] -name: phys101 +name: Physics 101 assignments: Attendance 1, Attendance 2, Attendance 3, Attendance 4, Attendance 5, Attendance 6, Attendance 7, Attendance 8, Attendance 9, Assignment 1, Assignment 2, Exam 1, Exam 2 diff --git a/test/course.conf b/test/course.conf index 7fd41e3..b263a14 100644 --- a/test/course.conf +++ b/test/course.conf @@ -1,5 +1,5 @@ [course] -name: phys101 +name: Physics 101 assignments: Attendance 1, Attendance 2, Attendance 3, Attendance 4, Attendance 5, Attendance 6, Attendance 7, Attendance 8, Attendance 9, Assignment 1, Assignment 2, Exam 1, Exam 2 @@ -76,7 +76,7 @@ weight: 0.4/2 due: 2011-10-17 [Robot101] -nickname: phys101 robot +nickname: phys-101 robot emails: phys101@tower.edu pgp-key: 4332B6E3