My favorites | Sign in
Project Home Downloads Wiki Source
Search
for
GettingStarted  
How to install and run mail-trends
Phase-Deploy, Featured
Updated Feb 4, 2010 by mihai.parparita

Requirements

  • A Gmail or Google Apps mail account
  • Python 2.5 or later

Installation

Download a stable snapshot of the code. Alternatively, if you'd like to get the latest code from Subversion, you can do this with:

svn checkout http://mail-trends.googlecode.com/svn/trunk/ mail-trends

You will also need Cheetah (a template system) installed. You can download it and then follow the installation instructions. If you are using an apt-based Linux distribution sudo apt-get install python-cheetah may be enough for you.

Running

Go into the mail-trends directory:

cd mail-trends

Run the program, replacing the username and passwords as appropriate (if you omit the password in the commandline you will be (securely) prompted for it):

python main.py \
  --server=imap.gmail.com \
  --use_ssl \
  --username=username@gmail.com \
  --me=username@gmail.com,username@somedomain.com \
  --skip_labels

You will be prompted for the password for your account (you can also use --password= to specify it as an argument. The --me argument lets you specify what emails should be considered as being sent to/from you.

The output is in HTML, placed in out/index.html. Open that in your favorite web browser.

Other options

--skip_labels does not categorize messages into labels (there are not stats that use them yet).

--filter_out=... can be used to ignore certain messages. You can use to:username@example.com, from:username@example.com or list:listid.example.com to filter out by recipient, sender or list (you can have multiple filter clauses by separating them with commas).

You can pass in --record and --replay as command line arguments to respectively capture and play black message fetches from the IMAP server. This is meant to aid in development by speeding up data fetches.

--max_messages=NNNN can be used to limit the number of messages that are fetched. Normally the most recent messages are selected, use --random_subset to specify that the messages be chosen over all the messages.

Comment by avif...@gmail.com, Mar 25, 2008

I'm encountering an issue: on Mac OS X 10.5.2, with a "stock" python as supplied/patched by Apple.

The error is "ImportError?: No module named util". The top line on the trace is main.py, line 274.

Please help!

BTW, suggest you set up a Google Group for this tool. Thanks!

Comment by jonathan...@gmail.com, Mar 25, 2008

I also saw the "import util" issue. You can hack around it by editing the files in mail-trends/templates/.tmpl to remove the dependency on util.

Comment by koali...@gmail.com, Mar 25, 2008

re: import util

I have python2.4 and 2.5 installed on the Debian box I tested this with; /usr/bin/python on my box points to 2.4. I changed main.py to use 2.5 and it worked fine.

Comment by codex...@gmail.com, Mar 25, 2008

i just ran 'sudo cp mail-trends/templates/util.py /usr/lib/python2.5/'

Comment by raybooys...@gmail.com, Mar 25, 2008

Any ideas on this one? Running Vista, latest python download

File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)
File "C:\Users\ray\Documents\mail-trends\jwzthreading.py", line 54, in len
count += len(c)

RuntimeError?: maximum recursion depth exceeded

Comment by fsilva...@gmail.com, Mar 25, 2008

Ubuntu 7.10 only with Python 2.5 has the same import problem. 'sudo cp mail-trends/templates/util.py /usr/lib/python2.5/' solves the problem.

Comment by AniMatri...@gmail.com, Mar 25, 2008

I got a problem, Python 2.5.2 on Windows XP Pro SP2 Updated.


Traceback (most recent call last):

File "C:\mail\main.py", line 7, in <module>
import messageinfo
File "C:\mail\messageinfo.py", line 16, in <module>
class MessageInfo?(object):
File "C:\mail\messageinfo.py", line 18, in MessageInfo?
newestMessageSec = time.mktime([1970, 1, 1, 0, 0, 0, 0, 0, 0])
OverflowError?: mktime argument out of range

I fixed it by changing the 1970 on line 18 in messageinfo.py to 1972 (1971 would work well too I think) :)

Comment by AniMatri...@gmail.com, Mar 25, 2008

But still stuck on the same problem the 'aviflax' has, and the suggestion 'jonathanbetz' says is one that I do not understand. Tried several things that could work. But they dont, so if anyone has a more precise description that would be great.

Comment by windypo...@gmail.com, Mar 25, 2008

I had the "import util" problem too, all I did was to copy util.py from /mail-trends/templates/ to /mail-trends/. Windows XP SP2, Python 2.5

Comment by david...@gmail.com, Mar 25, 2008

There is this messages came out after processing the 8000th email messages:

`Traceback (most recent call last):

File "./main.py", line 253, in <module>
message_infos = GetMessageInfos?(opts)
File "./main.py", line 58, in GetMessageInfos?
message_infos = m.GetMessageInfos?()
File "/home/david/mail-trends/mail.py", line 78, in GetMessageInfos?
self.max_messages)
File "/home/david/mail-trends/mail.py", line 135, in UidFetch?
fetch_parts)
File "/home/david/mail-trends/mail.py", line 156, in UidCommand?
r, data = self.mail.uid(command, args)
File "/usr/lib64/python2.5/imaplib.py", line 752, in uid
typ, dat = self.simple_command(name, command, args)
File "/usr/lib64/python2.5/imaplib.py", line 1055, in simple_command
return self.command_complete(name, self.command(name, args))
File "/usr/lib64/python2.5/imaplib.py", line 885, in command_complete
typ, data = self.get_tagged_response(tag)
File "/usr/lib64/python2.5/imaplib.py", line 986, in get_tagged_response
self.get_response()
File "/usr/lib64/python2.5/imaplib.py", line 903, in get_response
resp = self.get_line()
File "/usr/lib64/python2.5/imaplib.py", line 996, in get_line
line = self.readline()
File "/usr/lib64/python2.5/imaplib.py", line 1162, in readline
char = self.sslobj.read(1)
socket.sslerror: (8, 'EOF occurred in violation of protocol')`

Comment by edward.v...@gmail.com, Mar 25, 2008

Working now on Mac OS 10.4.11, using the MacPython? package after doing several of the tweaks above (esp moving the "util.py" file).

This error message appears, apparently harmless:

/Users/emv/src/mail-trends/mail-trends/Cheetah/NameMapper?.py:289: RuntimeWarning?: Python C API version mismatch for module namemapper: This Python has API version 1013, module namemapper has version 1012.

from namemapper import NotFound?, valueForKey, valueForName, \

Comment by amar.r...@gmail.com, Mar 26, 2008

I got this message before the program shut down. Where do I find the compiled C version of namemapper? You don't have the C version of NameMapper? installed! I'm disabling Cheetah's us eStackFrames option as it is painfully slow with the Python version of NameMappe? r. You should get a copy of Cheetah with the compiled C version of NameMapper?.

"\nYou don't have the C version of NameMapper? installed! "

Comment by amar.r...@gmail.com, Mar 26, 2008

I got the C-version of NameMapper? but the program is re-fetching all the email again. Is there a way to ask it to just generate the report?

Comment by just...@gmail.com, Mar 26, 2008

if you are using ubuntu just type sudo apt-get install python-cheetah

to install the cheetah templating library.

Comment by AniMatri...@gmail.com, Mar 26, 2008

amar.rama

Looks at the text above:


You can pass in --record and --replay as command line arguments to respectively capture and play black message fetches from the IMAP server. This is meant to aid in development by speeding up data fetches.

Comment by matt.be...@madhatted.com, Mar 26, 2008

Jeez, this is a mess under linux, there are some typos too. I've got this diff to fix non-ssl, fix library paths and untie the code from Gmail:

Index: messageinfo.py
===================================================================
--- messageinfo.py	(revision 125)
+++ messageinfo.py	(working copy)
@@ -1,6 +1,6 @@
 import email
-import email.utils
-import email.header
+import email.Utils
+import email.Header
 import imaplib
 import md5
 import time
@@ -77,7 +77,7 @@
     ccs = self.GetHeaderAll('cc')
     resent_tos = self.GetHeaderAll('resent-to')
     resent_ccs = self.GetHeaderAll('resent-cc')
-    all_recipients = email.utils.getaddresses(
+    all_recipients = email.Utils.getaddresses(
         tos + ccs + resent_tos + resent_ccs)
     
     # Cleaned up and uniquefied
@@ -98,7 +98,7 @@
       header_value = self.GetHeader(header)
       header_value = header_value.replace("\n", " ")
       header_value = header_value.replace("\r", " ")
-      name, address = email.utils.parseaddr(header_value)
+      name, address = email.Utils.parseaddr(header_value)
       
       if address:
         name, address = self._GetCleanedUpNameAddress(name, address)
@@ -118,7 +118,7 @@
 
   def _GetDecodedValue(self, value):
     try:
-      pieces = email.header.decode_header(value)
+      pieces = email.Header.decode_header(value)
       unicode_pieces = \
           [unicode(text, charset or "ascii") for text, charset in pieces]
       return u"".join(unicode_pieces)
@@ -165,4 +165,4 @@
   
   def __str__(self):
     return "%s (size: %d, date: %s)" % (
-        self.GetHeader("subject"), self.size, self.__date_string)
\ No newline at end of file
+        self.GetHeader("subject"), self.size, self.__date_string)
Index: mail.py
===================================================================
--- mail.py	(revision 125)
+++ mail.py	(working copy)
@@ -6,8 +6,8 @@
 import messageinfo
 import stringscanner
 
-MAILBOX_GMAIL_ALL_MAIL = "[Gmail]/All Mail"
-MAILBOX_GMAIL_PREFIX = "[Gmail]"
+MAILBOX_GMAIL_ALL_MAIL = "INBOX"
+MAILBOX_GMAIL_PREFIX = "INBOX"
 
 class Mail(object):
   def __init__(self, server, use_ssl, username, password, 
@@ -24,7 +24,7 @@
     if record or replay:
       self.__cache = cache.FileCache()
     
-    imap_constructor = use_ssl and imaplib.IMAP4_SSL or imablib.IMAP4
+    imap_constructor = use_ssl and imaplib.IMAP4_SSL or imaplib.IMAP4
     
     logging.info("Connecting")
     
@@ -190,4 +190,4 @@
     return message_infos
   
   def __AssertOk(self, response):
-    assert response == "OK"
\ No newline at end of file
+    assert response == "OK"

Most was about email.header and email.utils needing to be email.Header and email.Utils. Also a imablib typo.

Now I'm stuck on this:

[2008-03-26 11:48:33,422] Connecting
[2008-03-26 11:48:35,665] Logging in
[2008-03-26 11:48:36,912] Selecting mailbox 'INBOX'
[2008-03-26 11:48:38,319] Fetching message infos
[2008-03-26 11:48:38,319]   Fetching message list
[2008-03-26 11:48:39,878]   6869 messages were listed
[2008-03-26 11:48:39,878]   Fetching info for 100 messages (100/100)
[2008-03-26 11:48:42,297]   Parsing replies
[2008-03-26 11:48:42,472]   Got 100 message infos
[2008-03-26 11:48:42,472] Logging out
[2008-03-26 11:48:42,627] Identifying "me" messages
Traceback (most recent call last):
  File "main.py", line 251, in ?
    message_infos = GetMessageInfos(opts)
  File "main.py", line 102, in GetMessageInfos
    for name, address in message_info.GetRecipients():
  File "/home/mixonic/Projects/mail-trends/messageinfo.py", line 88, in GetRecipients
    name, address = self._GetCleanedUpNameAddress(name, address)
  File "/home/mixonic/Projects/mail-trends/messageinfo.py", line 147, in _GetCleanedUpNameAddress
    popular_name_pair = \
TypeError: max() takes no keyword arguments

I'm no python programmer, but I do see max() getting a key:

      popular_name_pair = \
          max(cache[address].items(), key=lambda pair: pair[1])

Though I'm not sure what's going on there, nor why such a major language feature would be different on my box than others. Oh wait, python 2.5.

Oh well. Maybe I can rewrite it in ruby :-).

Comment by AniMatri...@gmail.com, Mar 26, 2008

I tested it on another account, but it didnt work.

When I changed the language from English (UK) to English (US) it worked. Just to let you know.

Comment by rdeav...@gmail.com, Mar 26, 2008

Hi all, if you read about this software in MeioBit?, you need to change your language from brazilian portuguese to English (US) to make the software work.

Se você lei sobre este software no meiobit, você vai precisar alterar o idioma do seu gmail, de português do brasil (pt_BR) para Inglês (US). Senão, não funciona.

Comment by doarm...@gmail.com, Mar 26, 2008

Nice. Just worked for me with OS X 10.4 and Python 2.5

~Matt

Comment by bpgergo, Mar 26, 2008

Hi, just downloaded and played around with this on my Win XP, Python 2.5 system. I encountered into this error on the first run:

newestMessageSec = time.mktime([1970, 1, 1, 0, 0, 0, 0, 0, 0])
OverflowError?: mktime argument out of range

however, this modification eliminated the error and then the whole thing worked

newestMessageSec = time.mktime([1970, 1, 1, 1, 0, 0, 0, 0, 0])

According to my doc installed with Python 2.5, the 4th element in the tuple is hour and can have a value in the range 0-23, so it is strange: The time value as returned by gmtime(), localtime(), and strptime(), and accepted by asctime(), mktime() and strftime(), is a sequence of 9 integers. The return values of gmtime(), localtime(), and strptime() also offer attribute names for individual fields.

Index Attribute Values 0 tm_year (for example, 1993) 1 tm_mon range [1,12] 2 tm_mday range [1,31] 3 tm_hour range [0,23] 4 tm_min range [0,59] 5 tm_sec range [0,61]; see (1) in strftime() description 6 tm_wday range [0,6], Monday is 0 7 tm_yday range [1,366] 8 tm_isdst 0, 1 or -1; see below

Comment by bpgergo, Mar 26, 2008

I also encountered the following error when setting to --max-messages=10000 I guess it's google banning my IP. Is there a workaround for this?

[2008-03-26 21:00:22,608] Fetching info for 1000 messages (6000/7128) Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 56, in GetMessageInfos?
message_infos = m.GetMessageInfos?()
File "F:\workspaces\pydev\mail-trends\mail.py", line 78, in GetMessageInfos?
self.max_messages)
File "F:\workspaces\pydev\mail-trends\mail.py", line 135, in UidFetch?
fetch_parts)
File "F:\workspaces\pydev\mail-trends\mail.py", line 156, in UidCommand?
r, data = self.mail.uid(command, args)
File "E:\Python25\Lib\imaplib.py", line 752, in uid
typ, dat = self.simple_command(name, command, args)
File "E:\Python25\Lib\imaplib.py", line 1055, in simple_command
return self.command_complete(name, self.command(name, args))
File "E:\Python25\Lib\imaplib.py", line 885, in command_complete
typ, data = self.get_tagged_response(tag)
File "E:\Python25\Lib\imaplib.py", line 986, in get_tagged_response
self.get_response()
File "E:\Python25\Lib\imaplib.py", line 903, in get_response
resp = self.get_line()
File "E:\Python25\Lib\imaplib.py", line 996, in get_line
line = self.readline()
File "E:\Python25\Lib\imaplib.py", line 1162, in readline
char = self.sslobj.read(1)
socket.sslerror: (8, 'EOF occurred in violation of protocol')

Comment by guillaum...@gmail.com, Mar 27, 2008

Hello,

My problem is a time out problem, I tried manually like above [root@fennec mail-trends]# python Python 2.5.1 (r251:54863, Oct 30 2007, 13:54:11) 4.1.2 20070925 (Red Hat 4.1.2-33)? on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import imaplib >>> m=imaplib.IMAP4_SSL("imap.gmail.com")

And I never get connected ...

I tested gmail with the web interface (using firefox) and it works perfectly.

Does google blocks python access and if so how can I do a work-around ?

Comment by bpgergo, Mar 27, 2008

For windows users not having a compiled C version of namemapper: you'll find it here: http://cheetahtemplate.org/download.html

Comment by ihor.pol...@gmail.com, Mar 27, 2008

I have this mistake in result:

[2008-03-27 17:17:02,109] Connecting [2008-03-27 17:17:02,357] Logging in [2008-03-27 17:17:02,955] Selecting mailbox 'Gmail?/All Mail' Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 54, in GetMessageInfos?
m.SelectAllMail?()
File "/home/ihor/mail-trends/mail.py", line 60, in SelectAllMail?
self.SelectMailbox?(MAILBOX_GMAIL_ALL_MAIL)
File "/home/ihor/mail-trends/mail.py", line 65, in SelectMailbox?
self.AssertOk?(r)
File "/home/ihor/mail-trends/mail.py", line 193, in AssertOk?
assert response == "OK"
AssertionError?

please, mail me if u can: ihor.polyakov@ GOOGLE

Comment by a.kulikov, Mar 27, 2008

Hm... I get an error as well

[2008-03-27 16:08:39,411] Initializing Traceback (most recent call last):

File "main.py", line 249, in <module>
opts = GetOptsMap?()
File "main.py", line 35, in GetOptsMap?
assert "username" in opts_map
AssertionError?

Comment by drew.cou...@gmail.com, Mar 27, 2008

Very slick. Thank you for this useful application.

Comment by tma...@gmail.com, Mar 27, 2008

This is really cool... well done

Comment by r.flut...@gmail.com, Mar 27, 2008

Same error :

[2008-03-27 23:41:44,948] Connecting [2008-03-27 23:41:45,194] Logging in [2008-03-27 23:41:45,975] Selecting mailbox 'Gmail?/All Mail' Traceback (most recent call last):

    File "main.py", line 251, in <module>

        message_infos = GetMessageInfos?(opts) 

    File "main.py", line 54, in GetMessageInfos?

        m.SelectAllMail?() 

    File "/home/tyn0r/mail-trends/mail.py", line 60, in SelectAllMail?

        self.SelectMailbox?(MAILBOX_GMAIL_ALL_MAIL) 

    File "/home/tyn0r/mail-trends/mail.py", line 65, in SelectMailbox?

        self.AssertOk?(r) 

    File "/home/tyn0r/mail-trends/mail.py", line 193, in AssertOk?

        assert response == "OK" 

AssertionError?

I'm on Ubuntu Hardy with Cheetah install by sudo apt-get install python-cheetah ... Any ideas ? Thanks

Comment by hkust.is...@gmail.com, Mar 27, 2008

I've got Bus error ... What's that?

> python main.py --server=imap.gmail.com --use_ssl --username=abc@gmail.com
[2008-03-28 14:14:24,430] Initializing
Password for abc@gmail.com:
[2008-03-28 14:14:30,755] Connecting
Bus error (core dumped)

Any idea?

OS: FreeBSD 4.10-RELEASE Python version: 2.5 (port version) Cheetah version: 2.0.1 (port version)

Comment by andy.edmonds, Mar 28, 2008

@r.fluttaz - I'm getting the same problem too (Mac 10.5.2)

Comment by carlosj....@gmail.com, Mar 28, 2008

With python2.5 and Cheeter installed, I have applied the patch of mixo...@synitech.com and this is a good result:

charlie:/home/charlie/mail-trends# python2.5 main.py --server=imap.gmail.com --use_ssl --username=xzy@gmail.com --me=xzy@gmail.com --skip_labels
[2008-03-28 16:07:14,670] Initializing
Password for xzy@gmail.com:
[2008-03-28 16:07:16,092] Connecting
[2008-03-28 16:07:16,519] Logging in
[2008-03-28 16:07:17,370] Selecting mailbox 'INBOX'
[2008-03-28 16:07:17,633] Fetching message infos
[2008-03-28 16:07:17,633]   Fetching message list
[2008-03-28 16:07:17,890]   98 messages were listed
[2008-03-28 16:07:17,891]   Fetching info for 98 messages (98/98)
[2008-03-28 16:07:26,750]   Parsing replies
[2008-03-28 16:07:26,960]   Got 98 message infos
[2008-03-28 16:07:26,960] Logging out
[2008-03-28 16:07:27,506] Identifying "me" messages
[2008-03-28 16:07:27,588]   0 messages are from "me"
[2008-03-28 16:07:27,589]   61 messages are to "me"
[2008-03-28 16:07:27,589] Extracting threads
[2008-03-28 16:07:27,604] Generating stats
[2008-03-28 16:07:27,745] Outputting HTML
[2008-03-28 16:07:28,095] Done

Works with GMail and Google Apps.

My OS is Debian Etch.

Cheers, Carlos Hellín.

Comment by leejack, Mar 28, 2008

The "maximum recusion depth" error seems to be a function of the number of email messages. The only way I've worked around it is to use max_messages= and pick a number smaller than my total (~114K). I've seen this problem on both my Mac Pro (4GB RAM) and Ubuntu Linux (8GB RAM).

Comment by french...@gmail.com, Mar 31, 2008

this seems to work for no one but its author. That's too bad, it looks really cool. I get the same issue as most here, with Assertion Errors

Comment by yohan.em...@gmail.com, Mar 31, 2008

Traceback (most recent call last):

File "C:\mail-trends-20080326\mail-trends\main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "C:\mail-trends-20080326\mail-trends\main.py", line 51, in GetMessageInfo?
s
"random_subset" in opts)
File "C:\mail-trends-20080326\mail-trends\mail.py", line 35, in init
self.mail.login(username, password)
File "C:\Python25\lib\imaplib.py", line 501, in login
raise self.error(dat[-1])
imaplib.error: ALERT? Invalid credentials (Failure)

Please help me. Maybe Restart computer after installing Python ?? Thanks

Comment by liep...@gmail.com, Mar 31, 2008

Worked fine for me on an MBP running OSX 10.5.2. Looking forward to a future version that works with other IMAP setups, as I don't use gmail for my primary email. I'd chip in, but I've got no python experience yet. Keep up the good work!

Comment by ajh...@gmail.com, Mar 31, 2008

getting the message_infos error. Running 10.4, Fink installation, Py2.5 and just installed Cheetah...

Comment by ajh...@gmail.com, Mar 31, 2008

was worried about the json dependency to python-twitter, so I installed it. No change to the python errors

  File "main.py", line 251, in <module>
    message_infos = GetMessageInfos(opts)
  File "main.py", line 51, in GetMessageInfos
    "random_subset" in opts
...
Comment by danec...@gmail.com, Apr 1, 2008

I want to change the colors of the graphs. How can I do that. I don't like the yellow color.

Comment by joel.m.a...@gmail.com, Apr 2, 2008

Hey, thanks for writing this!

Comment by bdwe...@gmail.com, Apr 3, 2008

I get "RuntimeError?: maximum recursion depth exceeded" when I try to run with 20000+ messages. It runs OK with 10000. I have 45000+ total, so it would be nice to get this fixed... thx

Comment by rbpas...@gmail.com, Apr 3, 2008

worked fine for me on gmail, but not on another imap server

Comment by clint...@gmail.com, Apr 7, 2008

Has yet to work for me. Oh, it might download the first 50,000 messages, but it never, ever, ever finishes. Tried at least 4 times. Tried stopping all other connections. Simply does not work.

Comment by bosm...@gmail.com, Apr 12, 2008

Worked well for me.. thanks!

Comment by oscar...@gmail.com, Apr 13, 2008

It also worked for me!! Thank you! I had to adjust it with max_messages=8000 (i have more than 14000, and i got "Maximun recursion depth exceeded" at "Extracting threads" when i try with 9000 or more messages).

Anyway, it's very nice. It could be better for me if I can get some graphs with absolute numbers, not just relative graphs.

I will keep an eye how it evolves! Thanks again!

Comment by joshi.a, Apr 14, 2008

This looks like pure awesomeness!! Running it right now.

Comment by flatlin...@gmail.com, Apr 14, 2008

I got it to work, in Ubuntu 7.04 (the only LiveCD I had lying around), after enabling the Universe source in Synaptic and installing both python 2.5 and python-cheetah, I was able to run this with the following command: python2.5 main.py --server=imap.gmail.com --use_ssl --username=xzy@gmail.com --me=xzy@gmail.com --skip_labels

make sure you put your own address in there. you will get prompted for your password. It completed successfully for 9018 messages. This project still needs a lot of work. I'm having a hard time believing that this was not tested in Ubuntu 7.04.

Comment by jdvalent...@gmail.com, Apr 14, 2008

I get:

[2008-04-15 00:31:34,320] Connecting [2008-04-15 00:31:34,476] Logging in [2008-04-15 00:31:35,800] Selecting mailbox 'Gmail?/All Mail' Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 54, in GetMessageInfos?
m.SelectAllMail?()
File "/usr/src/mail-trends/mail.py", line 60, in SelectAllMail?
self.SelectMailbox?(MAILBOX_GMAIL_ALL_MAIL)
File "/usr/src/mail-trends/mail.py", line 65, in SelectMailbox?
self.AssertOk?(r)
File "/usr/src/mail-trends/mail.py", line 193, in AssertOk?
assert response == "OK"
AssertionError?

Comment by jdvalent...@gmail.com, Apr 14, 2008

That's on Ubuntu Gutsy, and occurred with both a fresh install of Cheetah and a reinstall with an apt repository.

Comment by alejandr...@gmail.com, Apr 14, 2008

To solve the problem: File "main.py", line 35, in GetOptsMap? assert "username" in opts_map AssertionError?

a solution is to hardcode the program parameteres. Open main.py and change lines 33 and 34: for name, value in opts:

opts_map[name[2:]] = value

with:

opts_map["server"] = "imap.gmail.com" opts_map["username"] = "example@gmail.com" opts_map["use_ssl"] = "" opts_map["me"] = "example@gmail.com opts_map["skip_labels"] = ""

After this you just call: python main.py from the command line and you are good to go.

Comment by romihard...@gmail.com, Apr 14, 2008

if you are using localized version of gmail, then you should change constant from: MAILBOX_GMAIL_ALL_MAIL = "Gmail?/All Mail" to match your localized gmail, in my case (Indonesian), it is: MAILBOX_GMAIL_ALL_MAIL = "Gmail?/Semua Email" it works for me

maybe there sould be automatic detection of localized version?

Comment by velth...@gmail.com, Apr 14, 2008

I can confirm that the localization solutions works. I couldn't get it to work for Dutch (Alle Berichten) but when I switched Gmail to English (US) before running the .py script it worked and all of my emails were processed. Anyone has a clue how to get the correct description for a certain language?

Comment by justinhomi@gmail.com, Apr 14, 2008

I tried to run it on 110,000 emails in my gmail account. It was using about 1GB of RAM (can something be done about this?).

After waiting for a good hour, I got the following error:

File "mail-trends\jwzthreading.py", line 54, in len

count += len(c)
RuntimeError?: maximum recursion depth exceeded

I'm using Windows XP. I tried on my linux box, but it only has 512MB RAM, and the script was taking forever to run with all the swapping going on.

Comment by artem.sk...@gmail.com, Apr 14, 2008

Did anyone find a fix for 'socket.sslerror: (8, 'EOF occurred in violation of protocol')'

error?

Thanks!

Comment by chasseur...@gmail.com, Apr 15, 2008

Personally, I'm running on a MBP with OS 10.5.2 and at the beginning I had some problems running the main.py. In fact I got the following error: [2008-04-15 12:05:36,281] Selecting mailbox 'Gmail?/All Mail' Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 54, in GetMessageInfos?
m.SelectAllMail?()
File "/Users/michelangelo/Downloads/mail-trends/mail.py", line 60, in SelectAllMail?
self.SelectMailbox?(MAILBOX_GMAIL_ALL_MAIL)
File "/Users/michelangelo/Downloads/mail-trends/mail.py", line 65, in SelectMailbox?
self.AssertOk?(r)
File "/Users/michelangelo/Downloads/mail-trends/mail.py", line 193, in AssertOk?
assert response == "OK"
AssertionError?

Then I tried to change the language of my mailbox from Italian to English (US) and I re-ran the script: everything is just fine now. So if you use a localized version of your Gmail, before running the script, just change your language from the prefs panel.

Comment by dro...@gmail.com, Apr 15, 2008

Artem:

I just ran into the 'socket.sslerror: (8, 'EOF occurred in violation of protocol')' when I was hacking the script to parse a local imap server.

The error is a result of a typo on line 27 of mail.py (imablib.IMAP4_SSL versus imaplib.IMAP4_SSL). Here's the diff.

27c27
<     imap_constructor = use_ssl and imablib.IMAP4_SSL or imaplib.IMAP4
---
>     imap_constructor = use_ssl and imaplib.IMAP4_SSL or imaplib.IMAP4
Comment by mgarri...@gmail.com, Apr 15, 2008

I have had the "assertion" error and I've tried changin Gmail from Spanish to English and it works. I want to apply the patch described by romihardiyanto but I don't know my localized version. I'm using Spanish but 'Gmail/Spanish Mail' don't work. Neither do 'Gmail/Español Mail' because 'ñ' gives an error.

Comment by freezing...@gmail.com, Apr 15, 2008

For those (jdvalentine, ihor.polyakov, r.fluttaz, chasseurmic, etc.) with the following error:


File "D:\Projects\personal\mail-trends\mail.py", line 197, in AssertOk?
assert response == "OK"
AssertionError?
I encountered the same. I discovered that the mailbox "Gmail?/All Mail" doesn't exist - turns out because I have a @googlemail.com account, rather than @gmail.com.

I simply edited lines 9 and 10 of mail.py :

MAILBOX_GMAIL_ALL_MAIL = "[Google Mail]/All Mail"

MAILBOX_GMAIL_PREFIX = "[Google Mail]"

And it worked a treat.

Comment by mgarri...@gmail.com, Apr 16, 2008

freezingkiwis, what is your Google Mail language?

Comment by purn...@gmail.com, Apr 16, 2008

See, Open source really works... So many people around have improved and fixed this up!

By the way, Word for me on Ubuntu In single "go" The commands to run, sudo easy_install-2.5 cheetah svn checkout http://mail-trends.googlecode.com/svn/trunk/ mail-trends And the python main.py...

Comment by bijay.ru...@gmail.com, Apr 18, 2008

I get the following error ` Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 56, in GetMessageInfos?
message_infos = m.GetMessageInfos?()
`
File "/home/bijay/lib/mail-trends/mail.py", line 78, in GetMessageInfos?
self.max_messages)
File "/home/bijay/lib/mail-trends/mail.py", line 135, in UidFetch?
fetch_parts)
File "/home/bijay/lib/mail-trends/mail.py", line 156, in UidCommand?
r, data = self.mail.uid(command, args)
File "/usr/lib/python2.5/imaplib.py", line 752, in uid
typ, dat = self.simple_command(name, command, args)
File "/usr/lib/python2.5/imaplib.py", line 1055, in simple_command
return self.command_complete(name, self.command(name, args))
File "/usr/lib/python2.5/imaplib.py", line 890, in command_complete
self.check_bye()
File "/usr/lib/python2.5/imaplib.py", line 807, in check_bye
raise self.abort(bye[-1])
imaplib.abort: System Error

Comment by randomfoo@gmail.com, Apr 20, 2008

In reference to some of the previous comments, I've gotten mail-trends working with Python 2.4 as there's actually only one 2.5 dependency, in messageinfo.py:148 there's a lambda:

      popular_name_pair = \
          max(cache[address].items(), key=lambda pair: pair[1])

A simple try/except fixes things:

      try:
        popular_name_pair = \
            max(cache[address].items(), key=lambda pair: pair[1])
      except TypeError:
        import operator
        popular_name_pair = \
            sorted(cache[address].items(), reverse=True, key=operator.itemgetter(1))[0]
Comment by synful.i...@gmail.com, May 9, 2008

ola! :D i got it working :)

/me makes a teaseface @windypower

Opensuse users can read a How-to here> http://sindhu.tumblr.com/post/34309550

thanks :)

Comment by mccormac...@gmail.com, May 30, 2008

Help! I have the Import Util problem too. I'm new to Python Mac os 10.4.11 I copied util.py whats the next step?

Comment by rynlds...@gmail.com, Jul 27, 2008

i would really like to use mail trends but i do not have any python or command prompt experience could someone put the instructions in easier to understand language

thank you

Comment by bdmo...@gmail.com, Aug 7, 2008

Thank you for creating this amazing software. It worked perfectly in my environment. Windows Vista, 32bit Cygwin Shell Python 2.5 (Cygwin) gcc version 3.4.4 (for Cheeta)

I had copied your command above, modified my addresses, and 2 minutes later it ran through all my emails and generated a great report.

Thank you so much for your work on this.

Comment by bwick.l...@gmail.com, Aug 12, 2008

Worked perfectly. Found it through lifehacker. My company uses gmail as our e-mail service and this helps us a lot.

I'm running vista.

Comment by unfnknbl...@gmail.com, Sep 21, 2008

I have the latest stable versions of Python and Cheetah installed on Vista (64bit), and no matter what I do, I just get the same error message:

Traceback (most recent call last):

File "main.py", line 5, in <module>
import messageinfo
File "Y:\Users\unfunk\Desktop\mail-trends\messageinfo.py", line 16, in <module>
class MessageInfo??(object):
File "Y:\Users\unfunk\Desktop\mail-trends\messageinfo.py", line 18, in Message
Info
newestMessageSec = time.mktime([1970, 1, 1, 0, 0, 0, 0, 0, 0])
OverflowError?: mktime argument out of range

I'm not a programmer by any stretch of the imagination, so I'd really appreciate it if somebody could help me out with this?

Thanks

(I'd also really like a "preview post" function here...)

Comment by peterfra...@gmail.com, Oct 15, 2008

I'm getting this error message... any ideas?

C:\Documents and Settings\Administrator\Desktop\mail-trends>python main.py --ser ver=ipam.gmail.com --use_ssl --contact@mail.dropio.com --me=contact@mail.dropio. com C:\Documents and Settings\Administrator\Desktop\mail-trends\messageinfo.py:5: De precationWarning: the md5 module is deprecated; use hashlib instead

import md5
[2008-10-15 17:01:32,812] Initializing Traceback (most recent call last):
File "main.py", line 249, in <module>
opts = GetOptsMap?()
File "main.py", line 29, in GetOptsMap?
"skip_labels"])
File "C:\Python26\lib\getopt.py", line 89, in getopt
opts, args = do_longs(opts, args0?[2:], longopts, args[1:])
File "C:\Python26\lib\getopt.py", line 153, in do_longs
has_arg, opt = long_has_args(opt, longopts)
File "C:\Python26\lib\getopt.py", line 170, in long_has_args
raise GetoptError?('option --%s not recognized' % opt, opt)
getopt.GetoptError?: option --contact@mail.dropio.com not recognized

Thanks in advance.

Comment by ddruckerccn, Oct 26, 2008

I really wish the max recursion problem could be fixed. I've tried increasing sys.setrecursion limit. I've tried using Stackless Python. I've tried changing my ulimit values. Nothing works.

Comment by david.ri...@gmail.com, Nov 8, 2008

Problem: Dreaded Assertion Error when trying to select 'Gmail?/All Mail'.

Solution: Switch to US language localization before running it. Disable Google Labs Advanced IMAP plugin.

I'd previously turned off the 'Gmail?/All Mail' folder using advanced IMAP, and thus it couldn't select it.

Error Message (to find on page): [2008-11-08 12:42:17,040] Selecting mailbox 'Gmail?/All Mail' Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 54, in GetMessageInfos?
m.SelectAllMail?()
File "/Users/driordan/Downloads/mail-trends/mail.py", line 60, in SelectAllMail?
self.SelectMailbox?(MAILBOX_GMAIL_ALL_MAIL)
File "/Users/driordan/Downloads/mail-trends/mail.py", line 65, in SelectMailbox?
self.AssertOk?(r)
File "/Users/driordan/Downloads/mail-trends/mail.py", line 193, in AssertOk?
assert response == "OK"
AssertionError?

Comment by peterfra...@gmail.com, Jan 6, 2009

Okay, so I was getting the same error that alejandro.echev on Apr 14, 2008 fix but I was then getting this:

PS C:\Users\peter\mail-trends> python main.py --server=imap.gmail.com --use_ssl --username=contact@XXXXXXXX.com --me=contact@XXXXXXXX.com -

File "main.py", line 33
opts_map["server"] = "imap.gmail.com" opts_map["username"] = "example@gmail.com" opts_map["use_ssl"] = "" opts_map["me"] = "example
labels"] = ""
^
SyntaxError?: invalid syntax

Thanks to my coworker Peeja I was able to fix this. Here is the fix:

http://pastie.org/353994

Good luck!

Peter F.

Comment by Tsvi...@gmail.com, Jan 14, 2009

i got the same "AssertionError?" on windows xp, AFTER fetching of the emails. turns out including "--skip_labels" fix that.

Comment by matt.ha...@gmail.com, Feb 9, 2009

Hmmmm, getting the following error:

Traceback (most recent call last):
  File "main.py", line 251, in <module>
    message_infos = GetMessageInfos(opts)
  File "main.py", line 56, in GetMessageInfos
    message_infos = m.GetMessageInfos()
  File "c:\Program Files\Cheetah\mail-trends\mail.py", line 78, in GetMessageInfos
    self.__max_messages)
  File "c:\Program Files\Cheetah\mail-trends\mail.py", line 135, in __UidFetch
    fetch_parts)
  File "c:\Program Files\Cheetah\mail-trends\mail.py", line 156, in __UidCommand
    r, data = self.__mail.uid(command, *args)
  File "c:\Program Files\Python26\lib\imaplib.py", line 754, in uid
    typ, dat = self._simple_command(name, command, *args)
  File "c:\Program Files\Python26\lib\imaplib.py", line 1059, in _simple_command
    return self._command_complete(name, self._command(name, *args))
  File "c:\Program Files\Python26\lib\imaplib.py", line 894, in _command_complete
    self._check_bye()
  File "c:\Program Files\Python26\lib\imaplib.py", line 809, in _check_bye
    raise self.abort(bye[-1])
imaplib.abort: System Error

Any ideas? I seemed to get a good chunk prior to going in there... but would like to get it all. If this is a means of an IP being banned or something, perhaps there could be a delay function available... might take longer, but i'd rather get the whole thing eventually than nothing at all.

Comment by matt.ha...@gmail.com, Feb 9, 2009

Odd... I changed the max to 50000 (which is how far it got in the above error) and this time I got the same error except after only 15000. I wonder what might be changing that would cause the difference? Line 78 of mail.py has to do with logout... feel free to email me with thoughts.

Comment by 94fordtr...@gmail.com, Mar 6, 2009

Anybody having timeout problems?

python main.py --server=imap.gmail.com:993 --use_ssl --username=tom@shing.com --me=tom@shing.com --skip_labels

[2009-03-06 16:04:15,570] Connecting
Traceback (most recent call last):
  File "main.py", line 251, in <module>
    message_infos = GetMessageInfos(opts)
  File "main.py", line 51, in GetMessageInfos
    "random_subset" in opts)
  File "/Users/projects/mail-trends/mail.py", line 31, in __init__
    self.__mail = imap_constructor(server)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/imaplib.py", line 1128, in __init__
    IMAP4.__init__(self, host, port)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/imaplib.py", line 163, in __init__
    self.open(host, port)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/imaplib.py", line 1140, in open
    self.sock.connect((host, port))
  File "<string>", line 1, in connect
socket.error: (60, 'Operation timed out')
Comment by Riel.Not...@gmail.com, Apr 24, 2009

Only working in US English as I found ...

Comment by darcy.quesnel, Apr 25, 2009

Worked well on my GMail account.

I've also got an archived directory of mbox mail from another (old) account. I don't see offhand how to point main.py to that directory instead of an IMAP server.

Any ideas?

Comment by seanhor...@gmail.com, Apr 26, 2009

Just worked out of the box for me with ubuntu 9.04. Scanned 11k messages back to 2004. Nice work.

Comment by dentonb...@gmail.com, Apr 28, 2009

I HIGHLY recommend that you follow the instruction list found on LifeHacker?. It saved me lots of time.

http://lifehacker.com/379328/analyze-your-email-usage-with-mail-trends

Comment by jonjan...@gmail.com, Apr 29, 2009

Wish it worked through a proxy.

Comment by trevy...@gmail.com, Jun 4, 2009
I am running Windows XP, SP3 on a powerful workstation. I have tried numerous times, for the last 4 hours, to install, configure and run Mail-Trends. I write now with a question.
I have finally gotten mail-trends to login, grab all of my messages (~11K); however, I then receive the error message about Cheetah, and NameMapper?:
"Where do I find the compiled C version of namemapper? You don't have the C version of NameMapper?? installed! I'm disabling Cheetah's us eStackFrames option as it is painfully slow with the Python version of NameMappe?? r. You should get a copy of Cheetah with the compiled C version of NameMapper??.

"\nYou don't have the C version of NameMapper?? installed! " "

I have tried Cheetah 2.0.1 and 2.2.1; I have tried both of those with Python 2.5, 2.6 and 3. I can't get Mail-trends to understand that I have the C-language NameMapper?.

Please advise! I truly appreciate all the work that already been done in support of this project and will gladly work with whomever would like to help me solve this problem!

Comment by stijn.he...@gmail.com, Jun 9, 2009

I have the same timeout problem as t...@soomopublishing.com :

[2009-06-09 10:38:56,427] Connecting
Traceback (most recent call last):
  File "main.py", line 253, in <module>
    message_infos = GetMessageInfos(opts)
  File "main.py", line 53, in GetMessageInfos
    "random_subset" in opts)
  File "/home/staff/heymans/src/mail-trends/mail.py", line 31, in __init__
    self.__mail = imap_constructor(server)
  File "/usr/lib64/python2.5/imaplib.py", line 1128, in __init__
    IMAP4.__init__(self, host, port)
  File "/usr/lib64/python2.5/imaplib.py", line 163, in __init__
    self.open(host, port)
  File "/usr/lib64/python2.5/imaplib.py", line 1140, in open
    self.sock.connect((host, port))
  File "<string>", line 1, in connect
socket.error: (110, 'Connection timed out')

Anyone knows how to solve this? Thanks!

Comment by stijn.he...@gmail.com, Jun 9, 2009

Solved the time out problem. It was a port problem: ask your administrator to open the 993 port on your machine for imap usage.

Comment by drewb...@gmail.com, Jul 18, 2009

If you are getting the 'maximum recursion depth exceeded' (in len(c)) error, you could try this patch, which is how I bypassed that error:

--- a/mail-trends/jwzthreading.py	2008-03-26 05:53:42.000000000 -0700
+++ b/mail-trends/jwzthreading.py	2009-07-17 21:19:47.000000000 -0700
@@ -48,11 +48,14 @@
                 return True
         return False
 
-    def __len__(self):
-      count = 1
-      for c in self.children:
-        count += len(c)
-      return count
+    def __len__(self, sum=1):
+        count = 1
+        if sum > 332:
+            print 'uh oh reached 332!'
+        else:
+            for c in self.children:
+                count += c.__len__(sum + 1)
+        return count
     
 def uniq(alist):
     set = {}

It's a workaround, not a real fix, and I think you will end up with some bad/missing/incomplete data, but you will at least end up with viewable results. I don't know exactly what that is counting, but I hit that limit 21 times in ~40k messages. You might need a different value than 332 (for reference, I am running Python 2.6.2 in Ubuntu 9.04 64-bit with 2GB of RAM); I picked that value by counting how many lines deep the stack trace was when I ran mail-trends without this patch.

Comment by BUGabu...@gmail.com, Jul 31, 2009

Hi. How can I just check email from a special label like Trash or Spam?

Comment by lpica...@gmail.com, Aug 18, 2009

Wish it worked through a proxy 2?

Comment by greg.mer...@gmail.com, Oct 10, 2009

Ubuntu 8 (2.6.27-7) stalls at 8000/14187 messages. Ran several times, each with same result. Last run, I let it sit for two hours in its own windows before breaking.

Comment by Amos.Bla...@gmail.com, Feb 9, 2010

Ubuntu 9.04 works great. :) One question - is it possible to use --filter_out= to exclude all but, say, two of the lists, so you could look at those list's trends over time? I tried --filter_out=!list:my.list.com No dice.

Comment by carsten....@gmail.com, Feb 17, 2010

I stumbled upon the language setup today too. I was set to "German" and wondered why the script doesn't run. But after reading the messages and the one line saying Selecting mailbox 'Gmail?/All Mail' it was quite obvious what to do. I hint on the getting started page would be nice though.

Comment by jake.van...@gmail.com, Apr 2, 2010

I get that this is kinda a programmers place to be but couldn't the instructions be a bit more step by step for newbies like me? For example, "Go into the mail-trends directory: cd mail-trends" isn't intuitive for folks like me. Anyway, I would love to try this out just don't have the expertise and or python knowledge.

Best,

Jake Van Epps Windows 7 64 bit

Comment by eduloy...@gmail.com, May 25, 2010

I get this error:

C:\Python26\mail-trends>c:\python26\python main.py --server=imap.gmail.com --use rname=eduloyola@gmail.com --me=eduloyola@gmail.com --skip_labels C:\Python26\mail-trends\messageinfo.py:5: DeprecationWarning?: the md5 module is deprecated; use hashlib instead

import md5
Traceback (most recent call last):
File "main.py", line 5, in <module>
import messageinfo
File "C:\Python26\mail-trends\messageinfo.py", line 16, in <module>
class MessageInfo?(object):
File "C:\Python26\mail-trends\messageinfo.py", line 18, in MessageInfo?
newestMessageSec = time.mktime([1970, 1, 1, 0, 0, 0, 0, 0, 0])
OverflowError?: mktime argument out of range

Any help, please?

I'm running Windows Vista and the latest versions of Python (26) and Cheetah.

Thanks in advance.

Comment by lela.pra...@gmail.com, Jun 2, 2010

I can get this to run on my Ubuntu machine for my regular Gmail account, and one of my Google Apps accounts. When I try to set this up for my username@asu.edu Gmail account I get this error:

2010-06-02 13:39:01,893] Connecting [2010-06-02 13:39:02,659] Logging in Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 51, in GetMessageInfos?
"random_subset" in opts)
File "/home/lela/Desktop/mail-trends/mail.py", line 35, in init
self.mail.login(username, password)
File "/usr/lib/python2.6/imaplib.py", line 500, in login
raise self.error(dat[-1])
imaplib.error: Invalid credentials 7if504901eyb.4

Any ideas?

Comment by ludovic....@gmail.com, Jun 20, 2010

About the non-US Gmail versions, you'll find the correct name of the label in "Parameters" then "Labels".

For example, for my french version the label is : MAILBOX_GMAIL_ALL_MAIL = "Gmail?/Tous les messages"

Comment by xlau...@gmail.com, Jul 9, 2010

Do you know if it's possible to have statistics of emails having a particular label? Is it possible to modify the source code?

Thanks!

Comment by david.gr...@gmail.com, Jul 14, 2010

Got it working following instructions here:

http://lifehacker.com/379328/analyze-your-email-usage-with-mail-trends

python main.py --server=imap.gmail.com --use_ssl --username=example@gmail.com --me=example@gmail.com --skip_labels

Comment by jedima...@gmail.com, Aug 3, 2010

Has there been any updates lately? I'd like to see a filter_only (to get individual sender, receiver or group recipient stats without getting everything else).

Comment by julien....@gmail.com, Aug 8, 2010

As I didn't get any response from Mihai, I post my patch here.

Here is the things that I add:

  • usage
  • short/long arguments
  • arg lang for different gmail 'All Messages'
  • arg prefix to use with common imap server
  • Sender/Recipients domains stats
  • X-Mailer stat
  • switch lib md5 (deprecated) to hashlib

code may not be good quality or optimal as I'm only a beginner in python but it works, at least in my case.

There is also some start code to handle generic imap server but I didn't manage to make it work (need to first retrieve all mailboxes name and after retrieve all messages). I will probably not have time to finish it.

diff -urN mail-trends.orig/cache.py mail-trends/cache.py
--- mail-trends.orig/cache.py	2008-03-26 13:53:42.000000000 +0100
+++ mail-trends/cache.py	2010-07-28 15:25:10.000000000 +0200
@@ -2,7 +2,7 @@
 # http://python-twitter.googlecode.com/svn/trunk/twitter.py
 # Modified to pickle/unpickle data
 
-import md5
+import hashlib
 import os
 import tempfile
 import cPickle
@@ -83,7 +83,7 @@
     self._root_directory = root_directory
 
   def _GetPath(self, key):
-    hashed_key = md5.new(key).hexdigest()
+    hashed_key = hashlib.new(key).hexdigest()
     return os.path.join(self._root_directory,
                         self._GetPrefix(hashed_key),
                         hashed_key)
Binary files mail-trends.orig/cache.pyc and mail-trends/cache.pyc differ
Binary files mail-trends.orig/jwzthreading.pyc and mail-trends/jwzthreading.pyc differ
diff -urN mail-trends.orig/mail.py mail-trends/mail.py
--- mail-trends.orig/mail.py	2008-03-26 13:53:42.000000000 +0100
+++ mail-trends/mail.py	2010-07-29 08:09:06.000000000 +0200
@@ -5,9 +5,8 @@
 import cache
 import messageinfo
 import stringscanner
-
-MAILBOX_GMAIL_ALL_MAIL = "[Gmail]/All Mail"
-MAILBOX_GMAIL_PREFIX = "[Gmail]"
+import re
+import pprint
 
 class Mail(object):
   def __init__(self, server, use_ssl, username, password, 
@@ -20,7 +19,7 @@
     self.__random_subset = random_subset
     
     self.__current_mailbox = None
-    
+
     if record or replay:
       self.__cache = cache.FileCache()
     
@@ -34,11 +33,13 @@
     
     self.__mail.login(username, password)
 
-  def GetMailboxes(self):
+  def GetMailboxes(self, prefix):
     logging.info("Getting mailboxes")
     
-    r, mailboxes_data = self.__mail.list()
+    r, mailboxes_data = self.__mail.list(prefix)
     self.__AssertOk(r)
+
+    pprint.pprint(mailboxes_data)
     
     mailboxes = []
     for mailbox_data in mailboxes_data:
@@ -49,15 +50,29 @@
       delimiter = s.ConsumeValue()
       s.ConsumeAll(" ")
       name = s.ConsumeValue()
-      
-      if not "\\Noselect" in attributes and \
-          name.find(MAILBOX_GMAIL_PREFIX) != 0:
+
+      print "1 mailbox_data = "
+      pprint.pprint(mailbox_data)
+      print "2 s = "
+      pprint.pprint(s)
+      print "3 name = "
+      pprint.pprint(name)
+      print "4 attributes = "
+      pprint.pprint(attributes)
+      
+      if not "\\Noselect" in attributes:
+#      if not "\\Noselect" in attributes and \
+#          name.find('"/" '+prefix+'/') != 0:
+#          re.match('"/" '+prefix+'/', name):
         mailboxes.append(name)
+        print "=> Adding mailbox"+name
     
+    pprint.pprint(mailboxes)
+
     return mailboxes
   
-  def SelectAllMail(self):
-    self.SelectMailbox(MAILBOX_GMAIL_ALL_MAIL)
+  def SelectAllMail(self, value):
+    self.SelectMailbox(value)
 
   def SelectMailbox(self, mailbox):
     logging.info("Selecting mailbox '%s'", mailbox)
@@ -190,4 +205,4 @@
     return message_infos
   
   def __AssertOk(self, response):
-    assert response == "OK"
\ No newline at end of file
+    assert response == "OK"
Binary files mail-trends.orig/mail.pyc and mail-trends/mail.pyc differ
diff -urN mail-trends.orig/main.py mail-trends/main.py
--- mail-trends.orig/main.py	2008-03-26 13:53:42.000000000 +0100
+++ mail-trends/main.py	2010-07-29 08:10:42.000000000 +0200
@@ -4,33 +4,94 @@
 import logging
 import messageinfo
 import re
+import os
 import sys
+sys.path.append('/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages')
+import pprint
 
 from Cheetah.Template import Template
 import jwzthreading
 
-import mail
 import stats.base
 import stats.bucket
 import stats.group
 import stats.table
 
+MAILBOX_GMAIL_PREFIX = "[Gmail]"
+
+def usage():
+  print "mailtrends python script"
+  print "Usage:"
+  print "    -s, --server=<imap.server>: Remote IMAP server (currently only Gmail supported)."
+  print "    -u, --username=<user>: Remote user."
+  print "    -p, --password=<pass>: Remote password (optional)."
+  print "    --use_ssl"
+  print "    -m, --me=<email1,email2>: list of email address corresponding to user (separated with comma)."
+  print "    --skip_labels (only for Gmail)"
+  print "    -f, --filter_out=<...>: ignore some messages"
+  print "    -x, --max_messages=<N>: limit number of messages."
+  print "    -l, --lang=<[EN|FR|ID]>: Gmail language box."
+  print "    -r, --prefix=<...>: IMAP Prefix (ex: '[Gmail]', 'Mail')."
+  print "    --random_subset"
+  print "    ..."
+  print ""
+  print "Examples:"
+  print "    mailtrends.py --server=imap.gmail.com \\"
+  print "    	  --use_ssl \\"
+  print "    	  --username=username@gmail.com \\"
+  print "    	  --me=username@gmail.com,username@somedomain.com \\"
+  print "    	  --skip_labels"
+
+
 def GetOptsMap():
-  opts, args = getopt.getopt(sys.argv[1:], "", [
+  try:
+    opts, args = getopt.getopt(sys.argv[1:],
+      "s:u:p:m:hf:x:l:r:", [
+
       # Standard options
       "username=", "password=", "use_ssl", "server=", 
 
       # Other params
-      "filter_out=", "me=",
+      "filter_out=", "me=", "lang=", "help", "prefix=",
       
       # Development options
       "record", "replay", 
       "max_messages=", "random_subset",
       "skip_labels"])
-  
+  except getopt.GetoptError, err:
+    print str(err)
+    usage()
+    sys.exit(2)
+
   opts_map = {}
-  for name, value in opts:
-    opts_map[name[2:]] = value
+  for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif o in ("-s", "--server"):
+            opts_map["server"] = a
+        elif o in ("-u", "--username"):
+            opts_map["username"] = a
+        elif o in ("-p", "--password"):
+            opts_map["password"] = a
+        elif o in ("-m", "--me"):
+            opts_map["me"] = a
+        elif o in ("-f", "--filter_out"):
+            opts_map["filter_out"] = a
+        elif o in ("-x", "--max_messages"):
+            opts_map["max_messages"] = a
+        elif o in ("-l", "--lang"):
+            opts_map["lang"] = a
+        elif o in ("-r", "--prefix"):
+            opts_map["prefix"] = a
+        elif o in ("--use_ssl", "--skip_labels", "--random_subset"):
+            opts_map[o[2:]] = a
+        else:
+            assert False, "unhandled option"
+  
+  if "help" in opts_map:
+    usage()
+    sys.exit(2)
 
   assert "username" in opts_map
   
@@ -40,6 +101,9 @@
   
   assert "password" in opts_map
   assert "server" in opts_map
+
+  if "lang" not in opts_map:
+    opts_map["lang"] = "EN"
   
   return opts_map
 
@@ -50,33 +114,54 @@
       "max_messages" in opts and int(opts["max_messages"]) or -1,
       "random_subset" in opts)
   
-  # First, get all message infos
-  m.SelectAllMail()
-  
-  message_infos = m.GetMessageInfos()
-  
-  # Then for each mailbox, see which messages are in it, and attach that to 
-  # the mail info
-  if "skip_labels" not in opts:
-    message_infos_by_id = \
-        dict([(mi.GetMessageId(), mi) for mi in message_infos])
+  pprint.pprint(m)
+
+  if opts["server"] == "imap.gmail.com":
+    ## begin gmail
+    # First, get all message infos
+    m.SelectAllMail(MAILBOX_GMAIL_ALL_MAIL)
+    
+    message_infos = m.GetMessageInfos()
     
-    # Don't want to parse all these dates, since we already have them from the
-    # message infos above.
-    messageinfo.MessageInfo.SetParseDate(False)
+    # Then for each mailbox, see which messages are in it, and attach that to 
+    # the mail info
+    if "skip_labels" not in opts:
+      message_infos_by_id = \
+          dict([(mi.GetMessageId(), mi) for mi in message_infos])
+      
+      # Don't want to parse all these dates, since we already have them from the
+      # message infos above.
+      messageinfo.MessageInfo.SetParseDate(False)
+      
+      for mailbox in m.GetMailboxes(MAILBOX_GMAIL_PREFIX):
+        m.SelectMailbox(mailbox)
+        message_ids = m.GetMessageIds()
+        for mid in message_ids:
+          if mid in message_infos_by_id:
+            message_info = message_infos_by_id[mid]
+            message_info.AddMailbox(mailbox)
     
-    for mailbox in m.GetMailboxes():
-      m.SelectMailbox(mailbox)
-      message_ids = m.GetMessageIds()
-      for mid in message_ids:
-        if mid in message_infos_by_id:
-          message_info = message_infos_by_id[mid]
-          message_info.AddMailbox(mailbox)
+      messageinfo.MessageInfo.SetParseDate(True)
   
-    messageinfo.MessageInfo.SetParseDate(True)
-
-  m.Logout()
+    ## end gmail
+  else: 
+    ## begin imap server (ignore skip_labels)
+    # First, get all folders
+    assert "prefix" in opts	# FIXME! what about empty prefix ???
+    for mailbox in m.GetMailboxes(opts["prefix"]):
+      if len(mailbox) != 0:
+        pprint.pprint(mailbox)
+        m.SelectMailbox(mailbox)
+        message_ids = m.GetMessageIds()
+        for mid in message_ids:
+          if mid in message_infos_by_id:
+            message_info = message_infos_by_id[mid]
+            message_info.AddMailbox(mailbox)
+    
+    ## end imap server
   
+  m.Logout()
+
   # Filter out those that we're not interested in
   if "filter_out" in opts:
     message_infos = FilterMessageInfos(message_infos, opts["filter_out"])
@@ -131,6 +216,8 @@
         pairs = [message_info.GetSender()]
       elif operator == "list":
         pairs = [message_info.GetListId()]
+      elif operator == "xmailer":
+        pairs = [message_info.GetXMailer()]
       else:
         raise AssertionError("unknown operator: %s" % operator)
 
@@ -235,19 +322,51 @@
           stats.table.ThreadStarterTableStat(),
           stats.table.ThreadListTableStat(),
         )
+      ),
+      (
+        "People domains",
+        stats.group.StatColumnGroup(
+          stats.table.SenderDomainTableStat(),
+          stats.group.SenderDomainDistributionStatCollection(date_range),
+        ),
+        stats.group.StatColumnGroup(
+          stats.table.RecipientDomainTableStat(),
+          stats.group.RecipientDomainDistributionStatCollection(date_range),
+        ),
+      ),
+      (
+        "X-Mailer",
+        stats.group.StatColumnGroup(
+          stats.table.XMailerTableStat(),
+          stats.group.XMailerDistributionStatCollection(date_range),
+        )
       )
     )
   ]
   
   return s
 
+## usage if no argument
+if (len(sys.argv) <= 1):
+    usage()
+    sys.exit(2)
+
+opts = GetOptsMap()
+
 logging.basicConfig(level=logging.DEBUG,
                     format="[%(asctime)s] %(message)s")
 
 logging.info("Initializing")
 
-opts = GetOptsMap()
-
+## FIXME! this part fail as variable does not seem global
+if opts["lang"] == "FR":
+  MAILBOX_GMAIL_ALL_MAIL = "[Gmail]/Tous les messages"
+elif opts["lang"] == "ID":
+  MAILBOX_GMAIL_ALL_MAIL = "[Gmail]/Semua Email"
+else:
+  MAILBOX_GMAIL_ALL_MAIL = "[Gmail]/All Mail"
+import mail
+ 
 message_infos = GetMessageInfos(opts)
 
 logging.info("Extracting threads")
@@ -268,8 +387,12 @@
       "host": re.sub("^.*@", "", opts["username"])
     }
 )
+
+if not os.path.isdir("out"):
+  os.mkdir("out")
+  logging.info("Warning! missing output directory ... recreating but don't forget to add *.js*.css files.")
 out = codecs.open("out/index.html", mode="w", encoding='utf-8')
 out.write(unicode(t))
 out.close()
 
-logging.info("Done")
\ No newline at end of file
+logging.info("Done")
diff -urN mail-trends.orig/messageinfo.py mail-trends/messageinfo.py
--- mail-trends.orig/messageinfo.py	2008-03-26 13:53:42.000000000 +0100
+++ mail-trends/messageinfo.py	2010-07-30 16:13:49.000000000 +0200
@@ -2,7 +2,7 @@
 import email.utils
 import email.header
 import imaplib
-import md5
+import hashlib
 import time
 
 import re
@@ -51,7 +51,7 @@
 
   def GetMessageId(self):
     if not self.__message_id:
-      d = md5.new()
+      d = hashlib.new()
       d.update(str(self.size))
       d.update(self.__date_string)
       self.__message_id = d.digest()
@@ -90,6 +90,49 @@
     
     return [(name, address) for address, name in recipients_map.items()]
 
+## FIXME! suboptimal way to get domain but working ...
+  def GetSenderDomain(self):
+    name, address= self._GetNameAddress("from")
+    p = re.compile( '.*@')
+    domain = p.sub( '', address)
+    return domain, domain
+
+  def GetRecipientsDomain(self):
+    tos = self.GetHeaderAll('to')
+    ccs = self.GetHeaderAll('cc')
+    resent_tos = self.GetHeaderAll('resent-to')
+    resent_ccs = self.GetHeaderAll('resent-cc')
+    all_recipients = email.utils.getaddresses(
+        tos + ccs + resent_tos + resent_ccs)
+    
+    # Cleaned up and uniquefied
+    recipientsdomain_map = {}
+    
+    for name, address in all_recipients:
+      if address:
+        name, address = self._GetCleanedUpNameAddress(name, address)
+        p = re.compile( '.*@')
+        address = p.sub( '', address)
+        recipientsdomain_map[address] = address
+    
+    return [(address, address) for address, name in recipientsdomain_map.items()]
+
+  def GetXMailer(self):
+    value = self.GetHeader("X-Mailer")
+    value = value.replace("\n", " ")
+    value = value.replace("\r", " ")
+    p = re.compile( '\(.*\)')
+    value = p.sub( '', value)
+    p = re.compile( '\[.*\]')
+    value = p.sub( '', value)
+    value.strip()
+    return value, value
+
+  def GetMailDomain(self):
+    p = re.compile( '.*@')
+    value = p.sub( '', self)
+    return value, value
+
   def _GetNameAddress(self, header):
     if not header in self.headers:
       return None, None
@@ -165,4 +208,5 @@
   
   def __str__(self):
     return "%s (size: %d, date: %s)" % (
-        self.GetHeader("subject"), self.size, self.__date_string)
\ No newline at end of file
+        self.GetHeader("subject"), self.size, self.__date_string)
+
Binary files mail-trends.orig/messageinfo.pyc and mail-trends/messageinfo.pyc differ
Binary files mail-trends.orig/pygooglechart.pyc and mail-trends/pygooglechart.pyc differ
Binary files mail-trends.orig/stats/__init__.pyc and mail-trends/stats/__init__.pyc differ
Binary files mail-trends.orig/stats/base.pyc and mail-trends/stats/base.pyc differ
Binary files mail-trends.orig/stats/bucket.pyc and mail-trends/stats/bucket.pyc differ
diff -urN mail-trends.orig/stats/distribution.py mail-trends/stats/distribution.py
--- mail-trends.orig/stats/distribution.py	2008-03-26 13:53:41.000000000 +0100
+++ mail-trends/stats/distribution.py	2010-07-30 15:20:51.000000000 +0200
@@ -202,4 +202,26 @@
     if message_info.is_to_me:
       return [message_info.GetSender()]    
     else:
-      return []
\ No newline at end of file
+      return []
+
+class SenderDomainDistribution(Distribution):
+  def __init__(self, year):
+    Distribution.__init__(self, year, "senderdomain")
+  
+  def _GetAddresses(self, message_info):
+    return [message_info.GetSenderDomain()]
+
+class RecipientDomainDistribution(Distribution):
+  def __init__(self, year):
+    Distribution.__init__(self, year, "recipientdomain")
+  
+  def _GetAddresses(self, message_info):
+    return message_info.GetRecipientsDomain()
+    
+class XMailerDistribution(Distribution):
+  def __init__(self, year):
+    Distribution.__init__(self, year, "xmailer")
+    
+  def _GetAddresses(self, message_info):
+    return [message_info.GetXMailer()]
+    
Binary files mail-trends.orig/stats/distribution.pyc and mail-trends/stats/distribution.pyc differ
diff -urN mail-trends.orig/stats/group.py mail-trends/stats/group.py
--- mail-trends.orig/stats/group.py	2008-03-26 13:53:41.000000000 +0100
+++ mail-trends/stats/group.py	2010-07-28 17:26:53.000000000 +0200
@@ -111,6 +111,27 @@
     for year in GetYearRange(date_range):
       self._AddStatRef(MeSenderDistribution(year), "%s" % year)
             
+class SenderDomainDistributionStatCollection(StatCollection):
+  def __init__(self, date_range):
+    StatCollection.__init__(self, "Sender domain distribution for ")
+
+    for year in GetYearRange(date_range):
+      self._AddStatRef(SenderDomainDistribution(year), "%s" % year)
+
+class RecipientDomainDistributionStatCollection(StatCollection):
+  def __init__(self, date_range):
+    StatCollection.__init__(self, "Recipient domain distribution for ")
+
+    for year in GetYearRange(date_range):
+      self._AddStatRef(RecipientDomainDistribution(year), "%s" % year)
+
+class XMailerDistributionStatCollection(StatCollection):
+  def __init__(self, date_range):
+    StatCollection.__init__(self, "X-Mailer distribution for ")
+
+    for year in GetYearRange(date_range):
+      self._AddStatRef(XMailerDistribution(year), "%s" % year)
+
 class StatColumnGroup(StatGroup):
   def __init__(self, *args):
     StatGroup.__init__(self)
@@ -154,4 +175,4 @@
     self.stats = stats
     
     self.id = "tab-%d" % StatTab._IdIndex
-    StatTab._IdIndex += 1
\ No newline at end of file
+    StatTab._IdIndex += 1
Binary files mail-trends.orig/stats/group.pyc and mail-trends/stats/group.pyc differ
diff -urN mail-trends.orig/stats/table.py mail-trends/stats/table.py
--- mail-trends.orig/stats/table.py	2008-03-26 13:53:41.000000000 +0100
+++ mail-trends/stats/table.py	2010-07-30 15:20:38.000000000 +0200
@@ -352,4 +352,41 @@
     if message_info.is_to_me:  
       return [message_info.GetSender()]
     else:
-      return []
\ No newline at end of file
+      return []
+
+class SenderDomainTableStat(UniqueAddressTableStat):
+  def __init__(self):
+    UniqueAddressTableStat.__init__(
+        self,
+        "Top sender domains",
+        "Sender domain",
+        "senderdomain")
+  
+  def _GetAddresses(self, message_info):
+    return [message_info.GetSenderDomain()]
+
+class RecipientDomainTableStat(UniqueAddressTableStat):
+  def __init__(self):
+    UniqueAddressTableStat.__init__(
+      self,
+      "Top recipient domain",
+      "Recipient domain",
+      "recipientdomain")
+  
+  def _GetAddresses(self, message_info):
+    return message_info.GetRecipientsDomain()
+    
+class XMailerTableStat(UniqueAddressTableStat):
+  def __init__(self):
+    UniqueAddressTableStat.__init__(
+        self,
+        "Top Mailer that send mail to me",
+        "X-Mailer",
+        "xmailer")
+  
+  def _GetAddresses(self, message_info):
+    if message_info.is_to_me:  
+      return [message_info.GetXMailer()]
+    else:
+      return []
+
Binary files mail-trends.orig/stats/table.pyc and mail-trends/stats/table.pyc differ
Binary files mail-trends.orig/stringscanner.pyc and mail-trends/stringscanner.pyc differ
Binary files mail-trends.orig/templates/__init__.pyc and mail-trends/templates/__init__.pyc differ
Binary files mail-trends.orig/templates/util.pyc and mail-trends/templates/util.pyc differ
Comment by pastr...@gmail.com, Oct 25, 2010

For newcomers like me: I was getting the same errors first reported in Comment by chasseurmic, Apr 15, 2008. Solved them just changing two GMail Settings: # in General > Language: English US # in Labs > Advanced IMAP Controls: Disable No need to edit main.py

Comment by chris.da...@gmail.com, Apr 2, 2011

i keep getting the same assertion error. I've hard coded. Imap is not in labs. English (US).

Any other suggestions?

Comment by toulorge...@gmail.com, Apr 25, 2011

hello,

I am not a python user even though I know it is time to make a html page directly used on chrome.

I'm an economist and I am ready to relationship management needs to deal with your mail tool that seems to be a very good response and strong future development.

well to you, contact me if you are interested to do this study together.

William T.

Comment by misha.de...@gmail.com, May 4, 2011

Fix the maximum recursion depth reached bug:

Add this line to the top of main.py after the imports

sys.setrecursionlimit(1000000)

Use some other horribly large number if 1000000 isn't big enough.

Comment by students...@gams.com, May 13, 2011

Hello,

It's a nice tool and I got it working on my system, but I would like to sort the mails by month and not by max messages. Additionally is it possible to save the output into different files when I want to run over different mail accounts without renaming index.html on my own or copy & paste to another folder?

Any ideas?

Comment by lindsey....@gmail.com, Jun 4, 2011

This is awesome, totally fits my needs. Thanks a lot.

Comment by chatain...@gmail.com, Jun 6, 2011

Hi,

Any update for the last change made by Google ? We can't disable advanced imap in labs since it's no more a lab feature.

Regards,

Nomis

Comment by chatain...@gmail.com, Jun 6, 2011

Hi again,

I got this error :

[2011-06-06 16:08:12,679] Logging out [2011-06-06 16:08:12,974] Identifying "me" messages Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 102, in GetMessageInfos?
for name, address in message_info.GetRecipients?():
File "/root/mail-trends-grillon/messageinfo.py", line 81, in GetRecipients?
tos + ccs + resent_tos + resent_ccs)
File "/usr/lib/python2.6/email/utils.py", line 105, in getaddresses
all = COMMASPACE.join(fieldvalues)
UnicodeDecodeError?: 'ascii' codec can't decode byte 0xef in position 129: ordinal not in range(128)

Any infos about this problem ?

Regards,

Nomis

Comment by jare...@gmail.com, Jun 17, 2011

Ran it and got the following. Any thoughts?

/home2/foo/downloads/mail-trends/stats/table.py:37: UnicodeWarning?: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal

heapq.heapify(data)
Traceback (most recent call last):
File "main.py", line 260, in <module>
stat.ProcessMessageInfos?(message_infos, threads)
File "/home2/foo/downloads/mail-trends/stats/group.py", line 16, in ProcessMessageInfos?
stat.ProcessMessageInfos?(message_infos, threads)
File "/home2/foo/downloads/mail-trends/stats/group.py", line 16, in ProcessMessageInfos?
stat.ProcessMessageInfos?(message_infos, threads)
File "/home2/foo/downloads/mail-trends/stats/table.py", line 37, in ProcessMessageInfos?
heapq.heapify(data)
UnicodeDecodeError?: 'ascii' codec can't decode byte 0xef in position 6: ordinal not in range(128)

Comment by massimo....@gmail.com, Jul 13, 2011

Same "UnicodeDecodeError?: 'ascii' codec etc." error as chatain and jare reported above..... any resolution/workaround?

Thanks, Massimo

Comment by android....@gmail.com, Jul 15, 2011

So I'm getting:

Traceback (most recent call last):
  File "main.py", line 251, in <module>
    message_infos = GetMessageInfos(opts)
  File "main.py", line 102, in GetMessageInfos
    for name, address in message_info.GetRecipients():
  File "D:\Downloads\mail-trends\messageinfo.py", line 76, in GetRecipients
    tos = self.GetHeaderAll('to')
  File "D:\Downloads\mail-trends\messageinfo.py", line 117, in GetHeaderAll
    return [self._GetDecodedValue(value) for value in values]
  File "D:\Downloads\mail-trends\messageinfo.py", line 121, in _GetDecodedValue
    pieces = email.header.decode_header(value)
  File "C:\python27\lib\email\header.py", line 108, in decode_header
    raise HeaderParseError
email.errors.HeaderParseError

On both my mac-air (running stock python and cheetah 2.4.4) and my windows 7 (python 2.7.2 and cheetah 2.0.1).

Even after googling it I have absolutely no idea how to fix this, does anyone have any ideas?

Also, if I change to an email address without a period in it, I get the ascii error reported by the last 3 people.

Comment by HerChloe...@gmail.com, Jul 19, 2011

I get this error:

UnicodeWarning?: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal

heapq.heapify(data)
Traceback (most recent call last):
File "main.py", line 260, in <module>
stat.ProcessMessageInfos?(message_infos, threads)
File "/Users/chloef/Documents/mail-trends/stats/group.py", line 16, in ProcessMessageInfos?
stat.ProcessMessageInfos?(message_infos, threads)
File "/Users/chloef/Documents/mail-trends/stats/group.py", line 16, in ProcessMessageInfos?
stat.ProcessMessageInfos?(message_infos, threads)
File "/Users/chloef/Documents/mail-trends/stats/table.py", line 37, in ProcessMessageInfos?
heapq.heapify(data)
UnicodeDecodeError?: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)

Comment by nikolami...@gmail.com, Sep 7, 2011

Hi there,

I installed mail trends, but when I run it, I get the following error:

C:\Program Files\mail-trends>main.py Traceback (most recent call last):

File "C:\Program Files\mail-trends\main.py", line 5, in <module>
import messageinfo
File "C:\Program Files\mail-trends\messageinfo.py", line 124
return u"".join(unicode_pieces)
^
SyntaxError?: invalid syntax

Does anybody know what could be the problem?

Sincerely, Nikola

Comment by leoned...@gmail.com, Oct 17, 2011

for the people with "codec can't decode" problem. Open messageinfo.py and look for

unicode(text, charset or "ascii")

change it to

unicode(text, charset or "UTF-8")

done

Comment by nicolas....@gmail.com, Oct 17, 2011

Thanks @leonedgar.

FYI, you can grab a github fork here: https://github.com/npinto/mail-trends -- BTW, any reason not to switch to github instead of google code ?

Comment by florian....@my-flow.com, Nov 1, 2011

The latest version at https://github.com/npinto/mail-trends solves the maximum recursion depth problem by using iteration instead of recursion.

Comment by chatain...@gmail.com, Nov 2, 2011

@flow : There is an error when using the github version :

[2011-11-02 20:56:19,494] Connecting [2011-11-02 20:56:19,815] Logging in [2011-11-02 20:56:20,319] Selecting mailbox 'Gmail?/All Mail' Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 54, in GetMessageInfos?
m.SelectAllMail?()
File "/home/simon/SRC/mail-trends/mail.py", line 60, in SelectAllMail?
self.SelectMailbox?(MAILBOX_GMAIL_ALL_MAIL)
File "/home/simon/SRC/mail-trends/mail.py", line 65, in SelectMailbox?
self.AssertOk?(r)
File "/home/simon/SRC/mail-trends/mail.py", line 193, in AssertOk?
assert response == "OK"
AssertionError?

Any info on how to solves this error ? Does it is about the recent gmail update ?

Comment by chatain...@gmail.com, Nov 3, 2011

It's all good ! Go give a try to the github fork ! https://github.com/npinto/mail-trends

Author of the fork is really good ! And reply quickly to the issue you could have !!!

Big thanks to him !

Comment by asadnaf...@gmail.com, Nov 20, 2011

I was able to run mail-trends for a Microsoft Exchange 2010 Mailbox successfully. All I had to do was make the following changes to mail.py:

Lines 9-10 (Change Folder Name): {{{MAILBOX_GMAIL_ALL_MAIL = "Inbox" MAILBOX_GMAIL_PREFIX = ""}}}

Line 157 (Comment Assertion): #self.__AssertOk(r)

Great tool - Thank you! -Asad

Comment by nadzo...@gmail.com, Apr 12, 2012

Mac OS 10.7.3 python -V Python 2.7.1

[2012-04-12 16:17:02,020] Initializing Password for vladimir.nadzorov@ottoruss.ru: Traceback (most recent call last):

File "main.py", line 251, in <module>
message_infos = GetMessageInfos?(opts)
File "main.py", line 51, in GetMessageInfos?
"random_subset" in opts)
File "/Users/vn/Downloads/mail-trends/mail.py", line 27, in init
imap_constructor = use_ssl and imaplib.IMAP4_SSL or imablib.IMAP4
NameError?: global name 'imablib' is not defined


Sign in to add a comment
Powered by Google Project Hosting