Downloads message headers from the MS Live POP3 mailbox into a local gdata store (~/.outlook_headers.gdbm), then analyses them. Only new messages (UIDLs not already in the store) are fetched on each run.
import sys, os, importlib
sys.path.insert(0, os.path.expanduser('~/py/popit3'))
import outlook_to_analysis as ota
importlib.reload(ota)
answer = input('Clear the header store? (yes/no): ').strip().lower()
mode = 'n' if answer == 'yes' else 'c'
with ota.open_store(mode=mode) as store:
count = len(list(store.keys()))
if mode == 'n':
print('Store cleared.')
else:
print(f'Store has {count:,} messages.')
user, client_id, refresh_token = ota.load_credentials()
print(f'User: {user}')
print(f'Store: {ota.HEADER_STORE}')
with ota.open_store() as store:
count = len(list(store.keys()))
print(f'Stored: {count:,} messages')
access_token, expires_in = ota.get_access_token(client_id, refresh_token)
print(f'Token obtained (expires in {expires_in}s)')
pop = ota.connect_pop3(user, access_token)
total, total_size = pop.stat()
print(f'POP3: {total:,} messages {total_size/1_000_000:.1f} MB')
with ota.open_store() as store:
last = None
for fetched, skipped, grand_total in ota.fetch_new_headers(pop, store, progress_every=100):
new_total = grand_total - skipped
pct = 100 * fetched // max(new_total, 1)
print(f' {fetched:,}/{new_total:,} new fetched ({skipped:,} already known) {pct}%', end='\r')
last = (fetched, skipped, grand_total)
print()
count = len(list(store.keys()))
if last:
print(f'Fetched {last[0]:,} new messages. Store now has {count:,} total.')
else:
print(f'Nothing new. Store has {count:,} messages.')
pop.quit()
with ota.open_store() as store:
stats = ota.analyze_store(store)
total = stats['total']
lo, hi = stats['date_range']
print(f'Total messages: {total:,}')
print(f'Date range: {lo[:16]} to {hi[:16]}')
col = 52
print(f'\n--- To: address ({len(stats["to_counts"])} unique) ---')
print(f'{"Address":<{col}} {"Count":>6} {" %":>5}')
print('-' * (col + 16))
for addr, cnt in stats['to_counts'][:50]:
print(f'{addr:<{col}} {cnt:>6,} {100*cnt/total:>5.1f}%')
if len(stats['to_counts']) > 50:
print(f' ... and {len(stats["to_counts"]) - 50} more')
print(f'\n--- Sender domain (top 20) ---')
print(f'{"Domain":<{col}} {"Count":>6}')
print('-' * (col + 10))
for domain, cnt in stats['domain_counts'][:20]:
print(f'{domain:<{col}} {cnt:>6,}')
if stats['list_id_counts']:
print(f'\n--- Mailing lists (List-Id, top 20) ---')
print(f'{"List-Id":<{col}} {"Count":>6}')
print('-' * (col + 10))
for lid, cnt in stats['list_id_counts'][:20]:
print(f'{lid:<{col}} {cnt:>6,}')