working parsing of message, finding conflicts

This commit is contained in:
Jan Grewe 2019-08-21 14:25:20 +02:00
parent 34be02ccc7
commit 224ffbe65c

View File

@ -13,22 +13,28 @@ import imaplib
import getpass import getpass
import email import email
import email.header import email.header
import datetime
from IPython import embed from IPython import embed
import re import re
import datetime as dt
EMAIL_ACCOUNT = "bzigr02" EMAIL_ACCOUNT = "bzigr02"
EMAIL_FOLDER = "INBOX" 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}, reg_fees = {'early': {"proMember": 95, "proNonMember":115, "studentMember": 55, "studentNonMember": 65},
'late': {"proMember": 115, "proNonMember":135, "studentMember": 65, "studentNonMember": 75}} '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): 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): def __init__(self, email_message):
self._registration_date = "" self._registration_date = ""
@ -36,9 +42,10 @@ class Participation(object):
self._last_name = "" self._last_name = ""
self._phone = "" self._phone = ""
self._email = "" self._email = ""
self._student = False self._farewell = ""
self._member = False self._gwinner = ""
self._farewell = False self._lab_tour = ""
self._food_preference = ""
self._food_vegi = False self._food_vegi = False
self._food_vegan = False self._food_vegan = False
self._food_gluten = False self._food_gluten = False
@ -46,41 +53,62 @@ class Participation(object):
self._address_street = "" self._address_street = ""
self._address_city = "" self._address_city = ""
self._address_zip = "" self._address_zip = ""
self._country = "" self._address_country = ""
self._institution = "" self._institution = ""
self._role = ""
self._message = ""
self._fee = 0.0 self._fee = 0.0
self._conflicts = []
self.__parse_message(email_message) self.__parse_message(email_message)
def __parse_message(self, 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 = message.get_payload()[0].as_string()
msg_body = re.sub(r'=20', ' ', msg_body) msg_body = re.sub(r'=20', ' ', msg_body)
msg_body = re.sub(r'=\n', '', 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'=E2=82=AC', 'EUR', msg_body)
msg_body = re.sub(r'&', 'and', msg_body) msg_body = re.sub(r'&', 'and', msg_body)
lines = msg_body.split('\n') lines = msg_body.split('\n')
self.__parse_food(lines)
self.__parse_address(lines) for fm in Participation.field_mapping:
embed() self.__parse_lines(lines, fm)
pass self.__process_food(lines)
self.__check()
def __parse_address(self, lines):
street = [s for s in lines if s.lower().startswith("street")] def __check(self):
self._address_street = street[0] if "student" not in self._role and self.gwinner_award:
city = [s for s in lines if s.lower().startswith("city")] self._conflicts.append("Gwinner award selected but not student!")
self._address_city = city[0] if (self._food_vegan or self._food_gluten or self.vegetarian) and self._food_normal:
plz = [s for s in lines if s.lower().startswith("zip")] self._conflicts.append("Conflict in food preferences!")
self._address_zip = plz[0]
inst = [s for s in lines if s.lower().startswith("institution")] def __calc_fee(self):
self._institution = ', '.join(inst) fee = .0
early_or_late = "early" if self.registration_date < early_bird else "late"
def __parse_food(self, lines): pro_or_stud = "senior" if "pro" in self._role else "student"
food = [l for l in lines if "Food preference" in l] fee += reg_fees[early_or_late][self._role]
if len(food) > 0: fee += farewell_fee[pro_or_stud] if self.farewell_event else 0.0
prefs = food[0].lower() 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_normal = "no special" in prefs
self._food_vegan = "vegan" in prefs self._food_vegan = "vegan" in prefs
self._food_vegi = "vegetarian" in prefs self._food_vegi = "vegetarian" in prefs
@ -90,6 +118,48 @@ class Participation(object):
def registration_date(self): def registration_date(self):
return self._registration_date 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): def process_mailbox(M):
""" """
@ -116,7 +186,7 @@ def process_mailbox(M):
# Now convert to local date-time # Now convert to local date-time
date_tuple = email.utils.parsedate_tz(msg['Date']) date_tuple = email.utils.parsedate_tz(msg['Date'])
if date_tuple: if date_tuple:
local_date = datetime.datetime.fromtimestamp( local_date = dt.datetime.fromtimestamp(
email.utils.mktime_tz(date_tuple)) email.utils.mktime_tz(date_tuple))
print ("Local Date:", \ print ("Local Date:", \
local_date.strftime("%a, %d %b %Y %H:%M:%S")) 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) print("ERROR: Unable to open mailbox folder ", rv)
new_participations = process_registrations(M) new_participations = process_registrations(M)
embed() for p in new_participations:
print(p)
M.close() M.close()
M.logout() M.logout()