# Processes emails sent to workouts@rowsandall.com import time from django.conf import settings from rowers.tasks import handle_sendemail_unrecognized from django_mailbox.models import Mailbox,Message,MessageAttachment from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage,AdvancedWorkoutForm from django.core.files.base import ContentFile from django.core.mail import send_mail, BadHeaderError,EmailMessage from rowsandall_app.settings import BASE_DIR from rowingdata import rower as rrower from rowingdata import main as rmain from rowingdata import rowingdata as rrdata from rowingdata import TCXParser,RowProParser,ErgDataParser,TCXParserNoHR from rowingdata import MysteryParser,BoatCoachParser from rowingdata import painsledDesktopParser,speedcoachParser,ErgStickParser from rowingdata import SpeedCoach2Parser,FITParser,fitsummarydata from rowingdata import make_cumvalues from rowingdata import summarydata,get_file_type from scipy.signal import savgol_filter import zipfile import os import rowers.dataprep as dataprep # Sends a confirmation with a link to the workout def send_confirm(u,name,link): fullemail = u.email subject = 'Workout added: '+name message = 'Dear '+u.first_name+',\n\n' message += "Your workout has been added to Rowsandall.com.\n" message += "Link to workout: "+link+"\n\n" message += "Best Regards, the Rowsandall Team" email = EmailMessage(subject,message, 'Rowsandall ', [fullemail]) res = email.send() return 1 # Reads a "rowingdata" object, plus some error protections def rdata(file,rower=rrower()): try: res = rrdata(file,rower=rower) except IOError: try: res = rrdata(file+'.gz',rower=rower) except IOError: res = 0 return res # Some error protection around process attachments def safeprocessattachments(): try: return processattachments() except: return [0] # This is duplicated in management/commands/processemail # Need to double check the code there, update here, and only # use the code here. def processattachments(): # in res, we store the ids of the new workouts res = [] attachments = MessageAttachment.objects.all() for a in attachments: donotdelete = 0 m = Message.objects.get(id=a.message_id) from_address = m.from_address[0] name = m.subject # get a list of users theusers = User.objects.filter(email=from_address) for u in theusers: try: rr = Rower.objects.get(user=u.id) # move attachment and make workout try: wid = [make_new_workout_from_email(rr,a.document,name)] res += wid link = 'https://rowsandall.com/rowers/workout/'+str(wid[0])+'/edit' dd = send_confirm(u,name,link) except: # replace with code to process error res += ['fail: '+name] donotdelete = 1 except Rower.DoesNotExist: pass # remove attachment if donotdelete == 0: a.delete() if m.attachments.exists()==False: # no attachments, so can be deleted m.delete() # Delete remaining messages (which should not have attachments) mm = Message.objects.all() for m in mm: if m.attachments.exists()==False: m.delete() return res # As above, but with some print commands for debugging purposes def processattachments_debug(): res = [] attachments = MessageAttachment.objects.all() for a in attachments: donotdelete = 1 m = Message.objects.get(id=a.message_id) from_address = m.from_address[0] name = m.subject # get a list of users theusers = User.objects.filter(email=from_address) print theusers for u in theusers: try: rr = Rower.objects.get(user=u.id) doorgaan = 1 except: doorgaan = 0 if doorgaan: # move attachment and make workout print a.document print name wid = [make_new_workout_from_email(rr,a.document,name)] res += wid print wid link = 'https://rowsandall.com/rowers/workout/'+str(wid[0])+'/edit' dd = send_confirm(u,name,link) # remove attachment if donotdelete == 0: a.delete() if m.attachments.exists()==False: # no attachments, so can be deleted m.delete() mm = Message.objects.all() for m in mm: if m.attachments.exists()==False: m.delete() return res # Process the attachment file, create new workout # The code here is duplication of the code in views.py (workout_upload_view) # Need to move the code to a subroutine used both in views.py and here def make_new_workout_from_email(rr,f2,name,cntr=0): workouttype = 'rower' try: f2 = f2.name fileformat = get_file_type('media/'+f2) except IOError: f2 = f2.name+'.gz' fileformat = get_file_type('media/'+f2) except AttributeError: fileformat = get_file_type('media/'+f2) if len(fileformat)==3 and fileformat[0]=='zip': f_to_be_deleted = f2 with zipfile.ZipFile('media/'+f2) as z: f2 = z.extract(z.namelist()[0],path='media/')[6:] fileformat = fileformat[2] if fileformat == 'unknown': if settings.DEBUG: res = handle_sendemail_unrecognized.delay(f2, "roosendaalsander@gmail.com") else: res = queuehigh.enqueue(handle_sendemail_unrecognized, f2,"roosendaalsander@gmail.com") return 0 summary = '' # handle non-Painsled if fileformat != 'csv': f3,summary,oarlength,inboard = dataprep.handle_nonpainsled('media/'+f2,fileformat,summary) else: f3 = 'media/'+f2 # make workout and put in database #r = rrower(hrmax=rr.max,hrut2=rr.ut2, # hrut1=rr.ut1,hrat=rr.at, # hrtr=rr.tr,hran=rr.an,ftp=r.ftp) row = rdata(f3) #,rower=r) if row == 0: return 0 # change filename if f2[:5] != 'media': timestr = time.strftime("%Y%m%d-%H%M%S") f2 = 'media/'+timestr+str(cntr)+'o.csv' try: avglat = row.df[' latitude'].mean() avglon = row.df[' longitude'].mean() if avglat != 0 or avglon != 0: workouttype = 'water' except KeyError: pass row.write_csv(f2,gzip=True) dosummary = (fileformat != 'fit') if name == '': name = 'imported through email' id,message = dataprep.save_workout_database(f2,rr, workouttype=workouttype, dosummary=dosummary, inboard=inboard, oarlength=oarlength, title=name, notes='imported through email') return id