From 224ffbe65c6f929b106275471a5d8a1657a06ffb Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Wed, 21 Aug 2019 14:25:20 +0200 Subject: [PATCH] working parsing of message, finding conflicts --- email_client.py | 138 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 33 deletions(-) diff --git a/email_client.py b/email_client.py index 18795f1..819df39 100644 --- a/email_client.py +++ b/email_client.py @@ -13,22 +13,28 @@ import imaplib import getpass import email import email.header -import datetime from IPython import embed import re +import datetime as dt EMAIL_ACCOUNT = "bzigr02" EMAIL_FOLDER = "INBOX" -fields = ["Fist name", "Last name", "e-Mail", "Institution", "Phone", "Country", "City", "ZIP code", "Street", - "Fees", "Farewell event (Thu 20 Feb)", "Gwinner Award", - "Food preferences", "LabTour (Fri 21 Feb)", "Messages"] - reg_fees = {'early': {"proMember": 95, "proNonMember":115, "studentMember": 55, "studentNonMember": 65}, 'late': {"proMember": 115, "proNonMember":135, "studentMember": 65, "studentNonMember": 75}} +farewell_fee = {"senior": 45, "student": 25} +early_bird = dt.datetime.fromisoformat('2020-01-16T00:00:00') class Participation(object): + field_mapping = [("First name", "_first_name"), ("Last name", "_last_name"), + ("Institution", "_institution", True), ("Street", "_address_street"), + ("City", "_address_city"), ("ZIP code", "_address_zip"), + ("Phone", "_phone"), ("e-Mail", "_email"), + ("Country", "_address_country"), ("Fee", "_role"), + ("Messages", "_message"), ("Food preferences", "_food_preference"), + ("Farewell event", "_farewell"), ("Gwinner", "_gwinner"), + ("Lab Tour (Fri 21 Feb)", "_lab_tour", True)] def __init__(self, email_message): self._registration_date = "" @@ -36,9 +42,10 @@ class Participation(object): self._last_name = "" self._phone = "" self._email = "" - self._student = False - self._member = False - self._farewell = False + self._farewell = "" + self._gwinner = "" + self._lab_tour = "" + self._food_preference = "" self._food_vegi = False self._food_vegan = False self._food_gluten = False @@ -46,41 +53,62 @@ class Participation(object): self._address_street = "" self._address_city = "" self._address_zip = "" - self._country = "" + self._address_country = "" self._institution = "" + self._role = "" + self._message = "" self._fee = 0.0 - + self._conflicts = [] self.__parse_message(email_message) def __parse_message(self, message): - self._registration_date = message["Date"] + date_tuple = email.utils.parsedate_tz(message['Date']) + if date_tuple: + local_date = dt.datetime.fromtimestamp( + email.utils.mktime_tz(date_tuple)) + self._registration_date = local_date msg_body = message.get_payload()[0].as_string() msg_body = re.sub(r'=20', ' ', msg_body) msg_body = re.sub(r'=\n', '', msg_body) msg_body = re.sub(r'=E2=82=AC', 'EUR', msg_body) msg_body = re.sub(r'&', 'and', msg_body) - lines = msg_body.split('\n') - self.__parse_food(lines) - self.__parse_address(lines) - embed() - pass - - def __parse_address(self, lines): - street = [s for s in lines if s.lower().startswith("street")] - self._address_street = street[0] - city = [s for s in lines if s.lower().startswith("city")] - self._address_city = city[0] - plz = [s for s in lines if s.lower().startswith("zip")] - self._address_zip = plz[0] - inst = [s for s in lines if s.lower().startswith("institution")] - self._institution = ', '.join(inst) - - def __parse_food(self, lines): - food = [l for l in lines if "Food preference" in l] - if len(food) > 0: - prefs = food[0].lower() + + for fm in Participation.field_mapping: + self.__parse_lines(lines, fm) + self.__process_food(lines) + self.__check() + + def __check(self): + if "student" not in self._role and self.gwinner_award: + self._conflicts.append("Gwinner award selected but not student!") + if (self._food_vegan or self._food_gluten or self.vegetarian) and self._food_normal: + self._conflicts.append("Conflict in food preferences!") + + def __calc_fee(self): + fee = .0 + early_or_late = "early" if self.registration_date < early_bird else "late" + pro_or_stud = "senior" if "pro" in self._role else "student" + fee += reg_fees[early_or_late][self._role] + fee += farewell_fee[pro_or_stud] if self.farewell_event else 0.0 + return fee + + def __parse_lines(self, lines, field_map): + assert(len(field_map) >= 2) + + ls = [l for l in lines if l.lower().startswith(field_map[0].lower())] + if len(ls) < 1: + print("%s not found: " % field_map[0]) + return + if len(field_map) == 2: + setattr(self, field_map[1], ls[0].split(field_map[0])[-1].strip()) + else: + setattr(self, field_map[1], ', '.join(map(lambda x:x.split(field_map[0])[-1].strip(), ls))) + + def __process_food(self, lines): + if len(self._food_preference) > 0: + prefs = self._food_preference.lower() self._food_normal = "no special" in prefs self._food_vegan = "vegan" in prefs self._food_vegi = "vegetarian" in prefs @@ -90,6 +118,48 @@ class Participation(object): def registration_date(self): return self._registration_date + @property + def fee(self): + return self.__calc_fee() + + @property + def farewell_event(self): + return len(self._farewell) > 0 + + @property + def gwinner_award(self): + return len(self._gwinner) > 0 + + @property + def labtour(self): + return self._lab_tour.split(",") + + @property + def valid(self): + return len(self._conflicts) == 0 + + def __str__(self): + str = "" + str += "Name: %s %s\n" % (self._first_name, self._last_name) + str += "Institution: %s\n" % self._institution + str += "Phone: %s\n" % self._phone + str += "e-Mail: %s\n" % self._email + str += "%s %s\n" % ("senior" if "pro" in self._role else "student", + "non-member" if "NonMember" in self._role else "member") + str += "Farewell event: %s\n" % "Yes" if self.farewell_event else "No" + str += "Fee: %f Eur\n" % self.fee + str += "Lab tour: %s\n" % ( "No" if len(self.labtour) == 0 else "Yes, " + ", ".join(self.labtour)) + str += "Gwinner award: %s\n" % "Yes" if self.gwinner_award else "No" + str += "Food preferences: %s, %s, %s, %s\n" % ("no prefs" if self._food_normal else "", + "vegetarian" if self._food_vegi else "", + "vegan" if self._food_vegan else "", + "gluten free" if self._food_gluten else "") + str += "Registration date: %s\n" % self.registration_date.isoformat() + str += "Message:%s\n" % self._message + if not self.valid: + str += "Inconsistencies: %s\n" % ", ".join(self._conflicts) + return str + def process_mailbox(M): """ @@ -116,7 +186,7 @@ def process_mailbox(M): # Now convert to local date-time date_tuple = email.utils.parsedate_tz(msg['Date']) if date_tuple: - local_date = datetime.datetime.fromtimestamp( + local_date = dt.datetime.fromtimestamp( email.utils.mktime_tz(date_tuple)) print ("Local Date:", \ local_date.strftime("%a, %d %b %Y %H:%M:%S")) @@ -168,6 +238,8 @@ if __name__ == "__main__": print("ERROR: Unable to open mailbox folder ", rv) new_participations = process_registrations(M) - embed() + for p in new_participations: + print(p) + M.close() M.logout()