def a_question_was_asked(self, user_email, mail, messageid): """" Process a question that was asked by a user. """ mail_subject = str(mail['subject']) logmsg = 'The user has a question, please take care of that!' c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") c.send_email(self.sender_queue, user_email, "", "Question", "", "", "") # was the question asked to a specific task_nr that is valid? search_obj = re.search('[0-9]+', mail_subject, ) if (search_obj != None) and int(search_obj.group()) <= c.get_num_tasks(self.coursedb, \ self.logger_queue, self.name): fwd_mails = self.get_taskoperator_emails(search_obj.group()) else: fwd_mails = self.get_admin_emails() for mail_address in fwd_mails: c.send_email(self.sender_queue, mail_address, "", "QFwd", "", mail, messageid) c.increment_db_statcounter(self.semesterdb, 'nr_questions_received', \ self.logger_queue, self.name)
def a_question_was_asked(self, user_id, user_email, mail, messageid): """ Process a question that was asked by a user. """ mail_subject = str(mail['subject']) logmsg = 'The user has a question, please take care of that!' c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") c.send_email(self.sender_queue, user_email, "", "Question", "", "", "") # was the question asked to a specific task_nr that is valid? search_obj = re.search( '[0-9]+', mail_subject, ) if (search_obj != None) and int(search_obj.group()) <= c.get_num_tasks(self.coursedb, \ self.logger_queue, self.name): tasknr = search_obj.group() fwd_mails = self.get_taskoperator_emails(tasknr) if fwd_mails == "": logmsg = ("Error getting the taskoperator email for task {0}. " "Question from user with email={1} " "dropped.").format(tasknr, user_email) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") return else: fwd_mails = self.get_admin_emails() if fwd_mails == "": logmsg = ("Error getting the admin email for task {0}. " "Question from user with email={1} " "dropped.").format(tasknr, user_email) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") return for mail_address in fwd_mails: c.send_email(self.sender_queue, mail_address, user_id, "QFwd", "", mail, messageid) c.increment_db_statcounter(self.semesterdb, 'nr_questions_received', \ self.logger_queue, self.name)
def check_and_set_last_done(self, userid): """ The LastDone field is used to mark users who have successfully solved all tasks. Returns: If the LastDone had to be set right now """ #has he already last done? --> nothing to do if self.has_last_done(userid): return False curs, cons = c.connect_to_db(self.dbs["semester"], self.queues["logger"], \ self.name) #get number of successful tasks data = {'user_id': userid} sql_cmd = ("SELECT COUNT(*) FROM SuccessfulTasks " "WHERE UserId = :user_id") curs.execute(sql_cmd, data) count_successful = curs.fetchone()[0] num_tasks = c.get_num_tasks(self.dbs["course"], self.queues["logger"], self.name) last_done_set = False #has he solved all tasks? --> set LastDone if count_successful == num_tasks: data = {'user_id': str(userid), 'now': str(int(time.time()))} sql_cmd = ("UPDATE Users SET LastDone = datetime(:now, " "'unixepoch', 'localtime') WHERE UserId == :user_id") curs.execute(sql_cmd, data) cons.commit() last_done_set = True cons.close() return last_done_set
def handle_next_mail(self): """ parse the subject/content of a mail and take appropriate action. """ #blocking wait on sender_queue next_send_msg = self.queues["sender"].get(True) task_nr = str(next_send_msg.get('task_nr')) message_id = str(next_send_msg.get('message_id')) user_id = str(next_send_msg.get('user_id')) recipient = str(next_send_msg.get('recipient')) message_type = str(next_send_msg.get('message_type')) curs, cons = c.connect_to_db(self.dbs["semester"], self.queues["logger"], \ self.name) curc, conc = c.connect_to_db(self.dbs["course"], self.queues["logger"], \ self.name) attachments = [] # prepare fields for the e-mail msg = MIMEMultipart() msg['From'] = self.smtp_info["mail"] msg['To'] = recipient logmsg = "RECIPIENT: " + recipient c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") msg['Date'] = formatdate(localtime=True) if message_type == "Task": ################# # TASK # ################# logmsg = "Task in send_queue: " + str(next_send_msg) c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") # 2 Cases: # allow_requests == "once" or "multiple" -> send Task anyway # allow_requests == "no" : check if he is at a higher task_nr, # if yes: do not send cur_task = c.user_get_current_task(self.dbs["semester"], user_id, \ self.queues["logger"], self.name) at_higher_task = (cur_task > int(task_nr)) should_not_send = (self.allow_requests == "no") and at_higher_task if should_not_send: logmsg = ("Task sending initiated, but user already reveived " "this task!!!") c.log_a_msg(self.queues["logger"], self.name, logmsg, "ERROR") return data = {'task_nr': str(task_nr)} sql_cmd = ("SELECT TaskName FROM TaskConfiguration " "WHERE TaskNr == :task_nr") curc.execute(sql_cmd, data) res = curc.fetchone() if not res: logmsg = ("Failed to fetch Configuration for TaskNr: " "{0} from the database! Table " "TaskConfiguration corrupted?").format(task_nr) c.log_a_msg(self.queues["logger"], self.name, logmsg, "ERROR") message_text = ("Sorry, but something went wrong... " "probably misconfiguration or missing" "configuration of Task {0}").format(task_nr) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), \ message_type) self.archive_message(message_id) return task_name = res[0] description_path = self.course_info['tasks_dir'] + \ '/' + task_name + '/description.txt' if not os.path.isfile(description_path): logmsg = "No description.txt found for Task {0}.".format( task_nr) c.log_a_msg(self.queues["logger"], self.name, \ logmsg, "ERROR") message_text = ("Sorry, but something went wrong... " "probably misconfiguration or missing" "configuration of Task {0}").format(task_nr) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) return msg['Subject'] = "Description Task" + str(task_nr) task_deadline = c.get_task_deadline(self.dbs["course"], task_nr, self.queues["logger"], self.name) dl_text = "\nDeadline for this Task: {0}\n".format(task_deadline) message_text = self.read_text_file(description_path) \ + dl_text data = {'task_nr': str(task_nr), 'user_id': user_id} sql_cmd = ("SELECT TaskAttachments FROM UserTasks " "WHERE TaskNr == :task_nr AND UserId == :user_id") curs.execute(sql_cmd, data) res = curs.fetchone() logmsg = "got the following attachments: " + str(res) c.log_a_msg(self.queues["logger"], self.name, logmsg, \ "DEBUG") if res: attachments = str(res[0]).split() else: attachments = "" msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) # Everything went okay -> adjust cur_task_nr c.user_set_current_task(self.dbs["semester"], task_nr, user_id, \ self.queues["logger"], self.name) elif message_type == "Failed": ################# # FAILED # ################# # did user already solve this task? data = {"user_id": user_id, "task_nr": task_nr} sql_cmd = ("SELECT UserId FROM UserTasks WHERE UserId = :user_id " "AND TaskNr = :task_nr AND FirstSuccessful IS NOT NULL") curs.execute(sql_cmd, data) res = curs.fetchone() task_already_solved = (res != None) #only update stat if user did not solve this task if not task_already_solved: self.increment_db_taskcounter('NrSubmissions', task_nr) path_to_msg = "users/{0}/Task{1}".format(user_id, task_nr) error_msg = self.read_text_file( "{0}/error_msg".format(path_to_msg)) msg['Subject'] = "Failure Task" + task_nr message_text = "Error report:\n\n" "" + error_msg reply_attachments = [] try: logmsg = "searching attachments in: {0}/error_attachments".format( path_to_msg) c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") ats = os.listdir("{0}/error_attachments".format(path_to_msg)) logmsg = "got the following attachments: {0}".format(ats) c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") for next_attachment in ats: reply_attachments.append( "{0}/error_attachments/{1}".format( path_to_msg, next_attachment)) except: logmsg = "no attachments for failed task." c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") msg = self.assemble_email(msg, message_text, reply_attachments) self.send_out_email(recipient, msg.as_string(), message_type) # archive and notify that worker finished self.archive_message(message_id, is_finished_job=True) elif message_type == "Success": ################# # SUCCESS # ################# msg['Subject'] = "Success Task " + task_nr message_text = "You solved the task successfully. Congratulations!" msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) #set first done if not set yet self.check_and_set_first_successful(user_id, task_nr) # last done had to be set now? --> Send Congrats if self.check_and_set_last_done(user_id): #new message, prepare it msg = MIMEMultipart() msg['From'] = self.smtp_info["mail"] msg['To'] = recipient logmsg = "RECIPIENT: " + recipient c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") msg['Date'] = formatdate(localtime=True) message_text = self.read_specialmessage('CONGRATS') msg['Subject'] = "Congratulations on solving all Tasks!" msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), "LastSolved") # archive and notify that worker finished self.archive_message(message_id, is_finished_job=True) elif message_type == "SecAlert": ################# # SEC ALERT # ################# admin_mails = self.get_admin_emails() for admin_mail in admin_mails: msg['To'] = admin_mail path_to_msg = "users/" + user_id + "/Task" + task_nr + "/error_msg" error_msg = self.read_text_file(path_to_msg) msg['Subject'] = "Security Alert User:"******"Error report:\n\n" "" + error_msg msg = self.assemble_email(msg, message_text, '') self.send_out_email(admin_mail, msg.as_string(), message_type) elif message_type == "TaskAlert": ################# # TASK ALERT # ################# admin_mails = self.get_admin_emails() for admin_mail in admin_mails: msg['To'] = admin_mail msg['Subject'] = "Task Error Alert Task{0} User{1}".format( \ str(task_nr), str(user_id)) message_text = ("There was an error with the Task {0} " \ "and User {1}. Check the logfiles(tasks.stderr, tasks.stdout, " "autosub.log) to find what caused it.").format(task_nr, user_id) msg = self.assemble_email(msg, message_text, '') self.send_out_email(admin_mail, msg.as_string(), message_type) elif message_type == "TaskErrorNotice": #################### # TASKERROR NOTICE # #################### admins = ",".join(self.get_admin_emails()) msg['Subject'] = "Error processing your last message" message_text = ( "There was an error processing your last message, please write an " "email to the administrators {0} and tell them about the time and what you did last. " "They will work on resolving the issue as soon as possible." ).format(admins) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) # archive, is_finished_job=True for tester errors, so the job can be # deleted from the active jobs # in the case this error is from a generator, the is_finished will be # ignored as the message_id will not be in the active jobs (see # fetcher.py) self.archive_message(message_id, is_finished_job=True) elif message_type == "Status": ################# # STATUS # ################# msg['Subject'] = "Your current status" message_text = self.generate_status_update(user_id, recipient, \ task_nr) numtasks = c.get_num_tasks(self.dbs["course"], self.queues["logger"], \ self.name) if int(numtasks) >= int(task_nr): #also attach current task data = {'task_nr': str(task_nr), 'user_id': user_id} sql_cmd = ("SELECT TaskAttachments FROM UserTasks " "WHERE TaskNr == :task_nr AND UserId == :user_id") curs.execute(sql_cmd, data) res = curs.fetchone() logmsg = "got the following attachments: " + str(res) c.log_a_msg(self.queues["logger"], self.name, logmsg, "DEBUG") if res: attachments = str(res[0]).split() msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) else: msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "TasksList": ################# # TASKSLIST # ################# msg['Subject'] = "List of tasks" message_text = self.generate_tasks_list() msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "InvalidTask": ################# # INVALID TASK # ################# msg['Subject'] = "Invalid Task Number" message_text = self.read_specialmessage('INVALID') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "TaskNotSubmittable": ######################### # TASK NOT SUBMITTABLE # ######################### msg['Subject'] = "Submission for Task{0} not possible".format( str(task_nr)) message_text = self.read_specialmessage('TASKNOTSUBMITTABLE') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "TaskNotActive": ######################### # TASK NOT ACTIVE # ######################### msg['Subject'] = "Task{0} not active yet".format(str(task_nr)) message_text = self.read_specialmessage('TASKNOTACTIVE') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "NoMultipleRequest": ######################### # NO MULTIPLE REQUEST # ######################### msg['Subject'] = "Already received Task{0}".format(str(task_nr)) message_text = self.read_specialmessage('NOMULTIPLEREQUEST') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "CurLast": ################# # CUR LAST # ################# # we still need to increment the users task counter! c.user_set_current_task(self.dbs["semester"], task_nr, user_id, \ self.queues["logger"], self.name) msg['Subject'] = "Task{0} is not available yet".format( str(task_nr)) message_text = self.read_specialmessage('CURLAST') message_text = "{0}\n\nThe Task is currently scheduled for: {1}".format(message_text, \ c.get_task_starttime(self.dbs["course"], str(task_nr), \ self.queues["logger"], self.name)) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "DeadTask": ################# # DEAD TASK # ################# msg['Subject'] = "Deadline for Task{0} has passed.".format( str(task_nr)) message_text = self.read_specialmessage('DEADTASK') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "Usage": ################# # USAGE # ################# msg['Subject'] = "Usage" message_text = self.read_specialmessage('USAGE') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "Question": ################# # QUESTION # ################# msg['Subject'] = "Question received" message_text = self.read_specialmessage('QUESTION') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "QFwd": ################# # QFWD # ################# orig_mail = next_send_msg.get('body') orig_from = orig_mail['from'] orig_mail.replace_header("From", self.smtp_info["mail"]) orig_mail.replace_header("To", recipient) if task_nr: orig_mail.replace_header( "Subject", "Question Task" + task_nr + " from " + orig_from) else: orig_mail.replace_header("Subject", "Question from " + orig_from) self.send_out_email(recipient, orig_mail.as_string(), message_type) self.archive_message(message_id) elif message_type == "Welcome": ################# # WELCOME # ################# msg['Subject'] = "Welcome!" message_text = self.read_specialmessage('WELCOME') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "RegOver": ################# # REGOVER # ################# msg['Subject'] = "Registration Deadline has passed" message_text = self.read_specialmessage('REGOVER') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "NotAllowed": ################# # NOT ALLOWED # ################# msg['Subject'] = "Registration not successful." message_text = self.read_specialmessage('NOTALLOWED') message_text = message_text.replace("[[recipient]]", recipient) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) elif message_type == "DeletedFromWhitelist": ############################ # DELETED FROM WHITELIST # ############################ msg['Subject'] = "Not whitelisted anymore" message_text = self.read_specialmessage('DeletedFromWhitelist') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) else: ################# # UNKNOWN # ################# c.log_a_msg(self.queues["logger"], self.name, \ "Unkown Message Type in the sender_queue!", "ERROR") msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.archive_message(message_id) cons.close() conc.close()
def handle_next_mail(self): """ parse the subject/content of a mail and take appropriate action. """ #blocking wait on sender_queue next_send_msg = self.sender_queue.get(True) task_nr = str(next_send_msg.get('Task')) messageid = str(next_send_msg.get('MessageId')) user_id = str(next_send_msg.get('UserId')) recipient = str(next_send_msg.get('recipient')) message_type = str(next_send_msg.get('message_type')) curs, cons = c.connect_to_db(self.semesterdb, self.logger_queue, \ self.name) curc, conc = c.connect_to_db(self.coursedb, self.logger_queue, \ self.name) attachments = [] # prepare fields for the e-mail msg = MIMEMultipart() msg['From'] = self.smtp_mail msg['To'] = recipient logmsg = "RECIPIENT: " + recipient c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") msg['Date'] = formatdate(localtime=True) if message_type == "Task": ################# # TASK # ################# logmsg = "Task in send_queue: " + str(next_send_msg) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") numtasks = c.get_num_tasks(self.coursedb, \ self.logger_queue, self.name) cur_task_nr = c.user_get_current_task(self.semesterdb, user_id, \ self.logger_queue, self.name) ########################### NEEDED? ######################### # did user solve this task already? data = {"user_id": user_id, "task_nr": task_nr} sql_cmd = ("SELECT UserId FROM UserTasks WHERE UserId = :user_id " "AND TaskNr = :task_nr AND FirstSuccessful IS NOT NULL") curs.execute(sql_cmd, data) res = curs.fetchone() task_already_solved = (res != None) #did the user solve the previous task? data = {"user_id": user_id, "task_nr": int(task_nr) - 1} sql_cmd = ("SELECT UserId FROM UserTasks WHERE UserId = :user_id " "AND TaskNr = :task_nr AND FirstSuccessful IS NOT NULL") curs.execute(sql_cmd, data) res = curs.fetchone() prev_task_already_solved = (res != None) ############################################################# # user did not solve the task with highest TaskNr if numtasks + 1 != int(task_nr): # only send the task description, when the user just now got # to this task or it is the first task if int(task_nr) - 1 <= int(cur_task_nr) or int( cur_task_nr) == 1: msg['Subject'] = "Description Task" + str(task_nr) dl_text = "\nDeadline for this Task: {0}\n".format( c.get_task_deadline(self.coursedb, task_nr, self.logger_queue, self.name)) data = {'task_nr': str(task_nr)} sql_cmd = "SELECT PathToTask FROM TaskConfiguration WHERE TaskNr == :task_nr;" curc.execute(sql_cmd, data) paths = curc.fetchone() if not paths: logmsg = "It seems, the Path to Task {0} is not configured.".format( task_nr) c.log_a_msg(self.logger_queue, self.name, \ logmsg, "WARNING") message_text = "Sorry, but something went wrong... probably misconfiguration or missing configuration of Task {0}".format( task_nr) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), \ message_type) self.backup_message(messageid) else: path_to_task = str(paths[0]) path_to_msg = path_to_task + "/description.txt" message_text = self.read_text_file(path_to_msg) \ + dl_text data = {'task_nr': str(task_nr), 'user_id': user_id} sql_cmd = "SELECT TaskAttachments FROM UserTasks WHERE TaskNr == :task_nr AND UserId == :user_id;" curs.execute(sql_cmd, data) res = curs.fetchone() logmsg = "got the following attachments: " + str(res) c.log_a_msg(self.logger_queue, self.name, logmsg, \ "DEBUG") if res: attachments = str(res[0]).split() msg = self.assemble_email(msg, message_text, \ attachments) self.send_out_email(recipient, msg.as_string(), \ message_type) self.backup_message(messageid) #advance user's current TaskNr to the Task task_nr if he is not # at a higher task yet if int(cur_task_nr) < int(task_nr): c.user_set_current_task(self.semesterdb, task_nr, user_id, \ self.logger_queue, self.name) elif message_type == "Failed": ################# # FAILED # ################# # did user already solve this task? data = {"user_id": user_id, "task_nr": task_nr} sql_cmd = ("SELECT UserId FROM UserTasks WHERE UserId = :user_id " "AND TaskNr = :task_nr AND FirstSuccessful IS NOT NULL") curs.execute(sql_cmd, data) res = curs.fetchone() task_already_solved = (res != None) #only update stat if user did not solve this task if not task_already_solved: self.increment_db_taskcounter('NrSubmissions', task_nr) path_to_msg = "users/{0}/Task{1}".format(user_id, task_nr) error_msg = self.read_text_file( "{0}/error_msg".format(path_to_msg)) msg['Subject'] = "Task" + task_nr + ": submission rejected" message_text = "Error report:\n\n" "" + error_msg reply_attachments = [] try: logmsg = "searching attachments in: {0}/error_attachments".format( path_to_msg) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") ats = os.listdir("{0}/error_attachments".format(path_to_msg)) logmsg = "got the following attachments: {0}".format(ats) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") for next_attachment in ats: reply_attachments.append( "{0}/error_attachments/{1}".format( path_to_msg, next_attachment)) except: logmsg = "no attachments for failed task." c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") msg = self.assemble_email(msg, message_text, reply_attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "SecAlert": ################# # SEC ALERT # ################# admin_mails = self.get_admin_emails() for admin_mail in admin_mails: msg['To'] = admin_mail path_to_msg = "users/" + user_id + "/Task" + task_nr + "/error_msg" error_msg = self.read_text_file(path_to_msg) msg['Subject'] = "Security Alert User:"******"Error report:\n\n" "" + error_msg msg = self.assemble_email(msg, message_text, '') self.send_out_email(admin_mail, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "TaskAlert": ################# # TASK ALERT # ################# admin_mails = self.get_admin_emails() for admin_mail in admin_mails: msg['To'] = admin_mail msg['Subject'] = "Task Error Alert Task " \ + task_nr + " User " + user_id message_text = "Something went wrong with task/testbench analyzation for Task " + task_nr + " and User " + user_id + " . Either the entity or testbench analyzation threw an error." msg = self.assemble_email(msg, message_text, '') self.send_out_email(admin_mail, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "Success": ################# # SUCCESS # ################# msg['Subject'] = "Task " + task_nr + " submitted successfully" message_text = "Congratulations!" msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) #set first done if not set yet self.check_and_set_first_successful(user_id, task_nr) # last done had to be set now? --> Send Congrats if self.check_and_set_last_done(user_id): #new message, prepare it msg = MIMEMultipart() msg['From'] = self.smtp_mail msg['To'] = recipient logmsg = "RECIPIENT: " + recipient c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") msg['Date'] = formatdate(localtime=True) message_text = self.read_specialmessage('CONGRATS') msg['Subject'] = "Congratulations on solving all Tasks!" msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), "LastSolved") self.backup_message(messageid) elif message_type == "Status": ################# # STATUS # ################# msg['Subject'] = "Your Current Status" message_text = self.generate_status_update(user_id, recipient, \ task_nr) numtasks = c.get_num_tasks(self.coursedb, self.logger_queue, \ self.name) if int(numtasks) >= int(task_nr): #also attach current task data = {'task_nr': str(task_nr), 'user_id': user_id} sql_cmd = "SELECT TaskAttachments FROM UserTasks WHERE TaskNr == :task_nr AND UserId == :user_id;" curs.execute(sql_cmd, data) res = curs.fetchone() logmsg = "got the following attachments: " + str(res) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") if res: attachments = str(res[0]).split() msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) else: msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "InvalidTask": ################# # INVALID TASK # ################# msg['Subject'] = "Invalid Task Number" message_text = self.read_specialmessage('INVALID') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "SkipNotPossible": ###################### # SKIP NOT POSSIBLE # ###################### msg['Subject'] = "Requested Skip not possible" message_text = self.read_specialmessage('SKIPNOTPOSSIBLE') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "TaskNotSubmittable": ######################### # TASK NOT SUBMITTABLE # ######################### msg['Subject'] = "Submission for this task not possible" message_text = self.read_specialmessage('TASKNOTSUBMITTABLE') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "CurLast": ################# # CUR LAST # ################# # we still need to increment the users task counter! c.user_set_current_task(self.semesterdb, task_nr, user_id, \ self.logger_queue, self.name) msg['Subject'] = "Task{0} is not available yet".format( str(task_nr)) message_text = self.read_specialmessage('CURLAST') message_text = "{0}\n\nThe Task is currently scheduled for: {1}".format(message_text, \ c.get_task_starttime(self.coursedb, str(task_nr), \ self.logger_queue, self.name)) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "DeadTask": ################# # DEAD TASK # ################# msg['Subject'] = "Deadline for Task{0} has passed.".format( str(task_nr)) message_text = self.read_specialmessage('DEADTASK') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "Usage": ################# # USAGE # ################# msg['Subject'] = "Usage" message_text = self.read_specialmessage('USAGE') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "Question": ################# # QUESTION # ################# msg['Subject'] = "Question received" message_text = self.read_specialmessage('QUESTION') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "QFwd": ################# # QFWD # ################# orig_mail = next_send_msg.get('Body') msg['Subject'] = "Question from " + orig_mail['from'] if orig_mail.get_content_maintype() == 'multipart': part = orig_mail.get_payload(0) mbody = part.get_payload() message_text = "Original subject: " + orig_mail[ 'subject'] + "\n\nNote: This e-mail contained attachments which have been removed!\n" message_text = "{0}\n\nOriginal body:\n{1}".format( message_text, mbody) else: mbody = orig_mail.get_payload() message_text = "Original subject: " + orig_mail['subject'] + \ "\n\nOriginal body:\n" + str(mbody) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "Welcome": ################# # WELCOME # ################# msg['Subject'] = "Welcome!" message_text = self.read_specialmessage('WELCOME') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "RegOver": ################# # REGOVER # ################# msg['Subject'] = "Registration Deadline has passed" message_text = self.read_specialmessage('REGOVER') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "NotAllowed": ################# # NOT ALLOWED # ################# msg['Subject'] = "Registration Not Successful." message_text = self.read_specialmessage('NOTALLOWED') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) else: ################# # UNKNOWN # ################# c.log_a_msg(self.logger_queue, self.name, \ "Unkown Message Type in the sender_queue!", "ERROR") msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) cons.close() conc.close()
def handle_next_mail(self): """ parse the subject/content of a mail and take appropriate action. """ #blocking wait on sender_queue next_send_msg = self.sender_queue.get(True) tasknr = str(next_send_msg.get('Task')) messageid = str(next_send_msg.get('MessageId')) uid = str(next_send_msg.get('UserId')) recipient = str(next_send_msg.get('recipient')) message_type = str(next_send_msg.get('message_type')) curs, cons = c.connect_to_db(self.semesterdb, self.logger_queue, \ self.name) curc, conc = c.connect_to_db(self.coursedb, self.logger_queue, \ self.name) attachments = [] # prepare fields for the e-mail msg = MIMEMultipart() msg['From'] = self.mail_user msg['To'] = recipient logmsg = "RECIPIENT: " + recipient c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") msg['Date'] = formatdate(localtime=True) if message_type == "Task": logmsg = "Task in send_queue: " + str(next_send_msg) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") numtasks = c.get_num_tasks(self.coursedb, \ self.logger_queue, self.name) ctasknr = c.user_get_current_task(self.semesterdb, uid, \ self.logger_queue, self.name) if numtasks+1 == int(tasknr): # last task solved! msg['Subject'] = "Congratulations!" message_text = self.read_specialmessage('CONGRATS') if int(tasknr)-1 == int(ctasknr): # statistics shall only be udated on the first # successful submission c.user_set_current_task(self.semesterdb, tasknr, uid, \ self.logger_queue, self.name) self.increment_db_taskcounter(curs, cons, 'NrSuccessful', \ str(int(tasknr)-1)) self.increment_db_taskcounter(curs, cons, 'NrSubmissions', \ str(int(tasknr)-1)) self.check_and_set_last_done(curs, cons, uid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) else: # at least one more task to do: send out the description # only send the task description, after the first # successful submission if int(tasknr)-1 <= int(ctasknr) or int(ctasknr) == 1: msg['Subject'] = "Description Task" + str(tasknr) dl_text = "\nDeadline for this Task: {0}\n".format(c.get_task_deadline(self.coursedb, tasknr, self.logger_queue, self.name)) data = {'tasknr': str(tasknr)} sql_cmd = "SELECT PathToTask FROM TaskConfiguration WHERE TaskNr == :tasknr;" curc.execute(sql_cmd, data) paths = curc.fetchone() if not paths: logmsg = "It seems, the Path to Task {0} is not configured.".format(tasknr) c.log_a_msg(self.logger_queue, self.name, \ logmsg, "WARNING") message_text = "Sorry, but something went wrong... probably misconfiguration or missing configuration of Task {0}".format(tasknr) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), \ message_type) else: path_to_task = str(paths[0]) path_to_msg = path_to_task + "/description.txt" message_text = self.read_text_file(path_to_msg) \ + dl_text data = {'tasknr': str(tasknr), 'uid': uid} sql_cmd = "SELECT TaskAttachments FROM UserTasks WHERE TaskNr == :tasknr AND UserId == :uid;" curs.execute(sql_cmd, data) res = curs.fetchone() logmsg = "got the following attachments: " + str(res) c.log_a_msg(self.logger_queue, self.name, logmsg, \ "DEBUG") if res: attachments = str(res[0]).split() # statistics shall only be udated on the first # succesful submission c.user_set_current_task(self.semesterdb, tasknr, uid, \ self.logger_queue, self.name) self.increment_db_taskcounter(curs, cons, \ 'NrSuccessful', \ str(int(tasknr)-1)) self.increment_db_taskcounter(curs, cons, \ 'NrSubmissions', \ str(int(tasknr)-1)) msg = self.assemble_email(msg, message_text, \ attachments) self.send_out_email(recipient, msg.as_string(), \ message_type) self.backup_message(messageid) elif message_type == "Failed": self.increment_db_taskcounter(curs, cons, 'NrSubmissions', tasknr) path_to_msg = "users/{0}/Task{1}".format(uid, tasknr) error_msg = self.read_text_file("{0}/error_msg".format(path_to_msg)) msg['Subject'] = "Task" + tasknr + ": submission rejected" message_text = "Error report:\n\n""" + error_msg reply_attachments = [] try: logmsg = "searching attachments in: {0}/error_attachments".format(path_to_msg) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") ats = os.listdir("{0}/error_attachments".format(path_to_msg)) logmsg = "got the following attachments: {0}".format(ats) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") for next_attachment in ats: reply_attachments.append("{0}/error_attachments/{1}".format(path_to_msg, next_attachment)) except: logmsg = "no attachments for failed task." c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") msg = self.assemble_email(msg, message_text, reply_attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "SecAlert": admin_mails = self.get_admin_emails() for admin_mail in admin_mails: msg['To'] = admin_mail path_to_msg = "users/"+ uid + "/Task" + tasknr + "/error_msg" error_msg = self.read_text_file(path_to_msg) msg['Subject'] = "Autosub Security Alert User:"******"Error report:\n\n""" + error_msg msg = self.assemble_email(msg, message_text, '') self.send_out_email(admin_mail, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "TaskAlert": admin_mails = self.get_admin_emails() for admin_mail in admin_mails: msg['To'] = admin_mail msg['Subject'] = "Autosub Task Error Alert Task " \ + tasknr + " User " + uid message_text = "Something went wrong with task/testbench analyzation for Task " + tasknr +" and User " + uid + " . Either the entity or testbench analyzation threw an error." msg = self.assemble_email(msg, message_text, '') self.send_out_email(admin_mail, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "Success": msg['Subject'] = "Task " + tasknr + " submitted successfully" message_text = "Congratulations!" msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) #set first done if not set yet self.check_and_set_first_successful(curs, cons, uid, tasknr) # no backup of message -- this is done after the new task # description was sent to the user! elif message_type == "Status": msg['Subject'] = "Your Current Status" message_text = self.generate_status_update(curs, recipient) numtasks = c.get_num_tasks(self.coursedb, self.logger_queue, \ self.name) if int(numtasks) >= int(tasknr): #also attach current task data = {'tasknr': str(tasknr), 'uid': uid} sql_cmd = "SELECT TaskAttachments FROM UserTasks WHERE TaskNr == :tasknr AND UserId == :uid;" curs.execute(sql_cmd, data) res = curs.fetchone() logmsg = "got the following attachments: " + str(res) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") if res: attachments = str(res[0]).split() msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) else: msg = self.assemble_email(msg, message_text, attachments) self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) elif message_type == "InvalidTask": msg['Subject'] = "Invalid Task Number" message_text = self.read_specialmessage('INVALID') self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "CurLast": # we still need to increment the users task counter! c.user_set_current_task(self.semesterdb, tasknr, uid, \ self.logger_queue, self.name) msg['Subject'] = "Task{0} is not available yet".format(str(tasknr)) message_text = self.read_specialmessage('CURLAST') message_text = "{0}\n\nThe Task is currently scheduled for: {1}".format(message_text, \ c.get_task_starttime(self.coursedb, str(tasknr), \ self.logger_queue, self.name)) self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "DeadTask": msg['Subject'] = "Deadline for Task{0} has passed.".format(str(tasknr)) message_text = self.read_specialmessage('DEADTASK') self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "Usage": msg['Subject'] = "Autosub Usage" message_text = self.read_specialmessage('USAGE') self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "Question": msg['Subject'] = "Question received" message_text = self.read_specialmessage('QUESTION') self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "QFwd": orig_mail = next_send_msg.get('Body') msg['Subject'] = "Question from " + orig_mail['from'] if orig_mail.get_content_maintype() == 'multipart': part = orig_mail.get_payload(0) mbody = part.get_payload() message_text = "Original subject: " + orig_mail['subject'] + "\n\nNote: This e-mail contained attachments which have been removed!\n" message_text = "{0}\n\nOriginal body:\n{1}".format(message_text, mbody) else: mbody = orig_mail.get_payload() message_text = "Original subject: " + orig_mail['subject'] + \ "\n\nOriginal body:\n" + str(mbody) self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "Welcome": msg['Subject'] = "Welcome!" message_text = self.read_specialmessage('WELCOME') self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "RegOver": msg['Subject'] = "Registration Deadline has passed" message_text = self.read_specialmessage('REGOVER') self.backup_message(messageid) msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) elif message_type == "NotAllowed": msg['Subject'] = "Registration Not Successful." message_text = self.read_specialmessage('NOTALLOWED') msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) else: c.log_a_msg(self.logger_queue, self.name, \ "Unkown Message Type in the sender_queue!", "ERROR") msg = self.assemble_email(msg, message_text, '') self.send_out_email(recipient, msg.as_string(), message_type) self.backup_message(messageid) cons.close() conc.close()
def loop_code(self): """ The code run in the while True loop of the mail fetcher thread. """ m = self.connect_to_imapserver() if m != 0: curs, cons = c.connect_to_db(self.semesterdb, self.logger_queue, self.name) items = self.fetch_new_emails(m) # iterate over all new e-mails and take action according to the structure # of the subject line for emailid in items: c.increment_db_statcounter(self.semesterdb, 'nr_mails_fetched', \ self.logger_queue, self.name) # fetching the mail, "`(RFC822)`" means "get the whole stuff", but you # can ask for headers only, etc resp, data = m.fetch(emailid, "(RFC822)") # parsing the mail content to get a mail object mail = email.message_from_bytes(data[0][1]) mail_subject = str(mail['subject']) from_header = str(mail['From']) split_header = str(from_header).split("<") user_name = split_header[0] try: user_email = str(split_header[1].split(">")[0]) except: user_email = str(mail['From']) messageid = mail.get('Message-ID') whitelisted = self.check_if_whitelisted(user_email) if whitelisted: data = {'Email': user_email} sql_cmd = "SELECT UserId FROM Users WHERE Email = :Email" curs.execute(sql_cmd, data) res = curs.fetchall() if res: logmsg = "Got mail from an already known user!" c.log_a_msg(self.logger_queue, self.name, logmsg, "INFO") #TODO: Does sending a mail "Result bla" without number crash this? if re.search('[Rr][Ee][Ss][Uu][Ll][Tt]', mail_subject): searchObj = re.search('[0-9]+', mail_subject, ) if int(searchObj.group()) <= c.get_num_tasks(self.coursedb, \ self.logger_queue, self.name): logmsg = "Processing a Result, UserId:{0} TaskNr:{1}"\ .format(user_email, searchObj.group()) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") self.take_new_results(user_email, searchObj.group(), \ mail, messageid) else: logmsg = ("Given Task number is higher than actual Number" "of Tasks!") c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") c.send_email(self.sender_queue, user_email, "", \ "InvalidTask", "", "", messageid) elif re.search('[Qq][Uu][Ee][Ss][Tt][Ii][Oo][Nn]', mail_subject): self.a_question_was_asked(user_email, mail, messageid) elif re.search('[Ss][Tt][Aa][Tt][Uu][Ss]', mail_subject): self.a_status_is_requested(user_email, messageid) else: logmsg = ("Got a kind of message I do not understand. " "Sending a usage mail...") c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") c.send_email(self.sender_queue, user_email, "", "Usage", "", \ "", messageid) else: reg_deadline = self.get_registration_deadline() if reg_deadline > datetime.datetime.now(): self.add_new_user(user_name, user_email) c.send_email(self.sender_queue, user_email, "", "Welcome", \ "", "", messageid) else: c.send_email(self.sender_queue, user_email, "", "RegOver", \ "", "", messageid) else: c.send_email(self.sender_queue, user_email, "", "NotAllowed", \ "", "", messageid) try: m.close() except imaplib.IMAP4.abort: logmsg = ("Closing connection to server was aborted " "(probably a server-side problem). Trying to connect again ...") c.log_a_msg(self.logger_queue, self.name, logmsg, "ERROR") #m.close() except imaplib.IMAP4.error: logmsg = ("Got an error when trying to connect to the imap server." "Trying to connect again ...") c.log_a_msg(self.logger_queue, self.name, logmsg, "ERROR") except: logmsg = ("Got an unknown exception when trying to connect to the " "imap server. Trying to connect again ...") c.log_a_msg(self.logger_queue, self.name, logmsg, "ERROR") finally: logmsg = "closed connection to imapserver" c.log_a_msg(self.logger_queue, self.name, logmsg, "INFO") # check if messages have been handled and need to be archived now try: next_send_msg = self.arch_queue.get(False) except: next_send_msg = 'NONE' if next_send_msg != 'NONE': c.log_a_msg(self.logger_queue, self.name, "moving a message!!!!!!!", \ "INFO") m = self.connect_to_imapserver() for next_msg in next_send_msg: email_ids = self.fetch_all_emails(m) for emailid in email_ids: typ, msg_data = m.fetch(str(int(emailid)), "(BODY[HEADER])") mail = email.message_from_bytes(msg_data[0][1]) if mail['Message-ID'] == next_send_msg.get('mid'): logmsg = "Moving Message with ID: {0}"\ .format(mail['Message-ID']) c.log_a_msg(self.logger_queue, self.name, logmsg, "DEBUG") resp, data = m.fetch(emailid, "(UID)") pattern_uid = re.compile('\d+ \(UID (?P<uid>\d+)\)') match = pattern_uid.match(str(data[0]).split("'")[1]) msg_uid = match.group('uid') result = m.uid('COPY', msg_uid, 'archive_vels') if result[0] == 'OK': mov, data = m.uid('STORE', msg_uid, '+FLAGS', \ '(\Deleted)') m.expunge() break # m==0 is only possible in test-code (e.g. load_test.py) if m != 0: m.logout() cons.close() time.sleep(self.poll_period)