#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Created on 07.03.2013
@author: andi
'''
import imaplib
import dateutil.parser
import datetime
from pytz import timezone
from email.parser import HeaderParser
import email.utils
import pickle
import os
wer = []
name = []
recvsubj = []
sentsubj = []
recv = []
sent = []
recvcnt = []
sentcnt = []
user="bla@bla.de" # anpassen
pwd="geheim" # anpassen
inbox="[Gmail]/Alle Nachrichten"
outbox="[Gmail]/Gesendet"
maxCheckDays=365 # so viele Tage maximal in die Vergangenheit schauen
minInteract = 2 # nur Mailverkehr zeigen, bei dem mindestens x mal Mails hin und her gingen
minWaitDays = 5 # erst nach x Tagen ohne Antwort / Aktivität erinnern
showOnlyOpenConversations = True # nur Konversationen zeigen, bei denen mehr Recv als Sent oder umgekehrt vorhanden sind
def readmails():
import time
# wir benutzen ein paar globale Variablen
# nicht unbedingt schön, aber einfach
global wer
global name
global recvsubj
global sentsubj
global recv
global sent
global recvcnt
global sentcnt
# Verbindung mit dem Mailkonto herstellen
conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.login(user,pwd)
# und die Eingangsmailbox auswählen - von hier wollen wir die Mails lesen
conn.select(inbox)
# Falls das Programm schon mal gelaufen ist, dann laden wir die bestehenden Daten
# damit wir nicht immer alle Mails von Anfang an bearbeiten müssen
if os.path.exists("./list_wer.p"):
wer=pickle.load(open("./list_wer.p", "rb" ))
name=pickle.load(open("./list_name.p", "rb" ))
recvsubj=pickle.load(open("./list_recvsubj.p", "rb" ))
sentsubj=pickle.load(open("./list_sentsubj.p", "rb" ))
recv=pickle.load(open("./list_recv.p", "rb" ))
sent=pickle.load(open("./list_sent.p", "rb" ))
recvcnt=pickle.load(open("./list_recvcnt.p", "rb" ))
sentcnt=pickle.load(open("./list_sentcnt.p", "rb" ))
mydate=pickle.load(open("./mydate.p", "rb" ))
# Vor wie vielen Tagen wurden das letzte mal Mails eingelesen?
# So viele Tage sollten wir jetzt aktuell einlesen
checkdays=(datetime.date.today()-mydate).days
# Falls heute schon einmal eingelesen wurde, nimm den kompletten Tag nochmal
# sicher ist sicher
if checkdays<1:
checkdays=1
else:
# Wenn noch keine Daten vorhanden sind, ließ von Anfang an ein -
# wobei Anfang die maximale Anzahl von Tagen bedeutet, die oben festgelegt wurde
checkdays=maxCheckDays
# Wir beginnen mit dem Einlesen
# Das Datum für unsere Suchabfrage in der Mailbox
date = (datetime.date.today() - datetime.timedelta(checkdays)).strftime("%d-%b-%Y")
# So viele Mails müssen wir jetzt bearbeiten
print "Anzahl Mails: "+str(len(conn.search(None, 'ALL','(SENTSINCE {date})'.format(date=date))[1][0].split()))
msg_cnt=0
# In der Schleife werden nach und nach die Mails eingelesen und bearbeitet
for msg_num in conn.search(None, 'ALL','(SENTSINCE {date})'.format(date=date))[1][0].split():
# wir zählen mal mit
msg_cnt=msg_cnt+1
print msg_cnt
# Hol Dir eine Mail
data = conn.fetch(str(msg_num), '(BODY[HEADER])')
# Hol Dir die richtigen Daten
header_data = data[1][0][1]
# und lade sie in msg
parser = HeaderParser()
msg = parser.parsestr(header_data)
# uns interessiert hier der Absender
# sein Name
myfrom=email.utils.parseaddr(msg['From'])[1].lower()
# seine Email-Adresse
myname=email.utils.parseaddr(msg['From'])[0]
# von wann stammt die Nachricht?
try:
c=datetime.datetime.now(timezone('UTC'))-dateutil.parser.parse(msg['Date'],fuzzy=True)
except:
c=datetime.datetime.now()-dateutil.parser.parse(msg['Date'],fuzzy=True)
# Wenn wir den Absender noch nicht in unserer Liste wer haben, füge ihn und die Daten hinzu
if not myfrom in wer:
# Email-Adresse
wer.append(myfrom)
# Name
name.append(myname)
# Betreffzeile der empfangenen Nachricht
recvsubj.append(msg['Subject'])
# Es gibt keine Betreffzeile für eine gesendete Nachricht
sentsubj.append(None)
# Datum des Empfang
recv.append(c)
# Es gibt kein Datum für Senden
sent.append(None)
# da wir ihn neu aufnehmen, ist es die erste empfangene Nachricht
recvcnt.append(1)
# Zähler für gesendete Nachrichten ist 0
sentcnt.append(0)
else:
# Der Absender ist also schon in unserer Liste
# wo genau?
i=wer.index(myfrom)
# wenn noch kein Empfangsdatum, dann setze es
if recv[i]==None:
recv[i]=c
recvsubj[i]=msg['Subject']
# Wenn diese Nachricht jünger ist, ändere das Empfangsdatum für den Absender
if recv[i]>c:
recv[i]=c
# und ändere die letzte empfangene Betreffzeile
recvsubj[i]=msg['Subject']
# Und erhöhe die Anzahl der Interaktionen mit empfangenen Mails um 1
recvcnt[i]=recvcnt[i]+1
# Jetzt wiederholen wir das alles für unsere gesendeten Nachrichten
# Wechsle in die Imap-Mailbox der gesendeten Nachrichten
conn.select(outbox)
# Das Datum für unsere Suchabfrage in der Mailbox
date = (datetime.date.today() - datetime.timedelta(checkdays)).strftime("%d-%b-%Y")
# So viele Mails müssen wir jetzt bearbeiten
print "Anzahl Mails: "+str(len(conn.search(None, 'ALL','(SENTSINCE {date})'.format(date=date))[1][0].split()))
msg_cnt=0
# In der Schleife werden nach und nach die Mails eingelesen und bearbeitet
# analog oben
for msg_num in conn.search(None, 'ALL','(SENTSINCE {date})'.format(date=date))[1][0].split(): # returns a nice list of messag let's say I pick #1 from this
# wir zählen mal mit
msg_cnt=msg_cnt+1
print msg_cnt
data = conn.fetch(str(msg_num), '(BODY[HEADER])')
header_data = data[1][0][1]
parser = HeaderParser()
msg = parser.parsestr(header_data)
# anders als bei den empfangenen Mails, die immer nur einen Absender haben
# können die gesendeten Mails an mehrere Leute gehen
# uns interessieren hier die Email-Felder
# an wen (to), Kopie an (cc) und Blindkopie an (bcc)
tos = msg.get_all('to', [])
ccs = msg.get_all('cc', [])
bccs = msg.get_all('bcc', [])
emails = email.utils.getaddresses(tos + ccs + bccs)
print emails
print len(emails)
# Wir haben eine Liste aller Empfänger der Mails, die wir jetzt bearbeiten
for b in range(0,len(emails)):
# seine Email-Adresse
myto=emails[b][1].lower()
# sein Name
myname=emails[b][0]
print myto
print msg['Date']
# von wann stammt die Nachricht?
try:
c=datetime.datetime.now(timezone('UTC'))-dateutil.parser.parse(msg['Date'],fuzzy=True)
except:
c=datetime.datetime.now()-dateutil.parser.parse(msg['Date'],fuzzy=True)
# wie oben
# ist die Email-Adresse noch nicht in unserer Liste, dann nehmen wir sie auf
if not myto in wer:
wer.append(myto)
name.append(myname)
sentsubj.append(msg['Subject'])
recvsubj.append(None)
sent.append(c)
recv.append(None)
recvcnt.append(0)
sentcnt.append(1)
else:
# andernfalls ändern wir ggf. letzten Betreff und letztes Datum
i=wer.index(myto)
if sent[i]==None:
sent[i]=c
sentsubj[i]=msg['Subject']
if sent[i]>c:
sent[i]=c
sentsubj[i]=msg['Subject']
# und erhöhen den Zähler für die Interaktionen
sentcnt[i]=sentcnt[i]+1
# Puh, und die ganze Arbeit machen wir uns nicht jedes mal neu
# deshalb speichern wir die so erzeugten Listen jetzt schnell mal ab
pickle.dump(wer,open("./list_wer.p", "wb" ))
pickle.dump(name,open("./list_name.p", "wb" ))
pickle.dump(recvsubj,open("./list_recvsubj.p", "wb" ))
pickle.dump(sentsubj,open("./list_sentsubj.p", "wb" ))
pickle.dump(recvcnt,open("./list_recvcnt.p", "wb" ))
pickle.dump(sentcnt,open("./list_sentcnt.p", "wb" ))
pickle.dump(recv,open("./list_recv.p", "wb" ))
pickle.dump(sent,open("./list_sent.p", "wb" ))
pickle.dump(datetime.date.today(),open("./mydate.p", "wb" ))
return
def missingconversation():
# wir wollen schauen, mit wem wir schon eine Weile nicht mehr gemailt haben
# Hier kommt das Ergebnis als lesbarer Text rein
report=""
# die Liste enthält die Leute, die auf eine Reaktion von uns warten (könnten)
recvlist = []
# die Liste enthält die Leute, die auf eine Mail von uns nicht mehr geantwortet haben
sentlist = []
# Gehen wir mal unsere gesamten eingelesen Mails durch
for a in range(0,len(wer)):
# Wir betrachten nur Mails, auf die zutrifft dass:
# wir mindestens minInteract Nachrichten bekommen und
# wir mindestens minInteract Nachrichten geschrieben haben
# Damit fallen z.B. Newsletter, auf die man nicht antwortet, raus
# Falls showOnlyOpenConversations gesetzt ist, werden zudem nur Mails betrachtet,
# bei denen Anzahl der gesendeten und empfangenen Mails ungleich ist, also noch eine Antwort aussteht
if (recvcnt[a]>=minInteract) and (sentcnt[a]>=minInteract) and ((sentcnt[a]!=recvcnt[a]) or not showOnlyOpenConversations):
# In die Listen sollen zudem nur Mailadressen, die länger als minWaitDays
# auf eine Interaktion warten
if (recv[a]<sent[a]) and (recv[a].days>=minWaitDays):
recvlist.append([name[a],wer[a],recv[a].days,recvsubj[a],recvcnt[a]])
if (sent[a]<recv[a]) and (sent[a].days>=minWaitDays):
sentlist.append([name[a],wer[a],sent[a].days,sentsubj[a],sentcnt[a]])
# wir sortieren die beiden neu generieten Listen nach der Anzahl der Tage,
# die Mails bereits offen sind
recvlist.sort(key=lambda xlist: xlist[2],reverse=True)
sentlist.sort(key=lambda xlist: xlist[2],reverse=True)
# Dann basteln wir unseren Report aus diesen sortierten Listen
for a in range(0,len(recvlist)):
report=report+"\r\n"+recvlist[a][0]+" <"+recvlist[a][1]+"> wartet seit "+str(recvlist[a][2])+" Tagen auf Antwort von Dir zum Thema "+recvlist[a][3]+". Insgesamt Kontakt: "+str(recvlist[a][4])+"."
report=report+"\r\n###\r\n"
# Und zwar für beide
for a in range(0,len(sentlist)):
report=report+"\r\n"+sentlist[a][0]+" <"+sentlist[a][1]+"> hat seit "+str(sentlist[a][2])+" Tagen nicht geantwortet zum Thema "+sentlist[a][3]+". Insgesamt Kontakt: "+str(sentlist[a][4])+"."
# und geben ihn zurück
return report
# MAIN #
readmails()
print missingconversation()