Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Mathematica has a function for sending mail (SendMail) and can import the MBOX format. But what I'd like to do is programmatically retrieve mail from a Gmail account, from within Mathematica on a Windows system. Is this possible?

Use case: I use MarineTraffic.com's e-mail notifications about ship arrivals to watch interesting ships as they pass by. I'd like to filter incoming messages from them and use data from previous notifications to filter 'seen' ships. I may want to do some automated lookup on ship names too to find those that are more likely to be interesting. A perfect task for Mathematica — if only I could periodically get the new mails and process them!

share|improve this question
    
What ship is that in the photo? –  acl Jun 26 '12 at 21:37
    
Do you mean a Vowelfail ship, for example? –  belisarius Jun 27 '12 at 0:01
    
@acl It's the MPI Discovery. It's built for installing offshore wind turbines. Some time ago I saw it sail into the harbour while taking a walk in Valletta, it was quite surprising (and this is what motivated me to try to find 'interesting' ships). –  Szabolcs Jun 27 '12 at 10:19

1 Answer 1

up vote 21 down vote accepted

I've implemented a java program using the JavaMail API to only fetch unread emails from a particular user (and mark it as read). This will allow you to periodically get emails from your ship traffic service. This is inspired by this blog post on Stephen Wolfram's email analytics.

1. Java code to fetch unread email from a sender

Below is the java code, which is saved in the file FetchMail.java.

import java.io.IOException                 ;
import java.util.Properties                ;
import javax.mail.*                        ;
import javax.mail.search.FlagTerm          ;
import javax.mail.internet.InternetAddress ;

public class FetchMail {
    public static String[] UnreadMail(
            String server   ,
            String folder   ,
            String from     ,
            String username ,
            String password
            ) {
        Properties props = System.getProperties()                                     ;
        props.setProperty("mail.store.protocol", "imaps")                             ;
        try {
            Session session  = Session.getDefaultInstance(props, null)                ;
            Store store      = session.getStore("imaps")                              ;
            store.connect(server, username, password)                                 ;
            Folder inbox     = store.getFolder(folder)                                ;
            inbox.open(Folder.READ_WRITE)                                             ;
            FlagTerm ft      = new FlagTerm(new Flags(Flags.Flag.SEEN), false)        ;
            Message msgs[]   = inbox.search(ft)                                       ;

            String[] emails  = new String[msgs.length]                                ;
            String[] content = new String[msgs.length]                                ;

            if (msgs.length > 0)
            {
                for (int i = 0; i < msgs.length ; i++)
                {
                    emails[i] = ((InternetAddress) msgs[i].getFrom()[0]).getAddress() ;
                    if (emails[i].equals(from))
                    {
                        content[i] = msgs[i].getContent().toString()                  ;
                    }
                }
            }
            store.close()                                                             ;
            return content                                                            ;
        }
        catch (NoSuchProviderException e) {
            return null                                                               ;
        }
        catch (MessagingException e) {
            return null                                                               ;
        }
        catch (IOException e) {
            return null                                                               ;
        }
    }
}

Next, compile the above file. You will need the mail.jar file from the above API download. Drop it in the same folder and execute

javac -classpath ./mail.jar FetchMail.java

2. Calling it from Mathematica

After compiling, include the FetchMail.class file in the same directory as your Mathematica notebook. Here's a convenient function that uses this class file to fetch unread mail from the Gmail server from a particular sender

Needs["JLink`"];
AddToClassPath[NotebookDirectory[]];
Clear[unreadMail]
unreadMail[server_String, email_String, pass_String, folder_String, from_String] :=         
    DynamicModule[{messages, monthname2num, datelists, parsedate},
        LoadJavaClass["FetchMail"];
        messages = FetchMail`UnreadMail[server, folder, from, email, pass];
        DeleteCases[messages, Null]
    ][[2]];

3. Usage and caveats

Usage is fairly straightforward from the arguments. As a sample demonstration, I just marked the last email from you as unread and ran this function and voila!

unreadMail["imap.gmail.com", "myEmail@gmail.com", "hunter2", "Inbox", "szabolcsEmail"]

enter image description here

However, do note that

  • If you're running this as a ScheduledTask, you will have to enter your password as a string argument. Not necessarily a wise idea to do with your primary email ID, but you could always create a throwaway for this specific purpose and use that instead.
  • Unread mail from this sender is automatically marked as read when you fetch it. This is necessary so that you don't keep retrieving the same mail again and again. However if you're automating it, be aware that there might be some emails that you haven't read and might have missed.
share|improve this answer
    
If it let's me retrieve new mail only, this is a clear accept. Thank! –  Szabolcs Jun 26 '12 at 20:58
    
@Szabolcs See my edit. –  rm -rf Jun 27 '12 at 8:35
    
Wow, that is really great! I am going to set up a separate email account for this---the volume of notifications is just too great! –  Szabolcs Jun 27 '12 at 9:51
    
While this is amazing, I think the JavaMail API must have changed since you posted this code, because getContent seems to return a MIME MultiPart now, instead of something that can be converted to a String. In particular, your Mathematica code doesn't seem to work (at least on my machine). –  Steve D Dec 19 '12 at 4:30
    
@SteveD Thanks for letting me know; I'll look into it, but I don't promise any immediate solutions. I actually don't know java all that much and this is in fact my first program in it (I learnt the basics in half a day just for this answer). Out of curiosity, does it work for you if you use the mail.jar that you get from the linked Wolfram blogpost? –  rm -rf Dec 19 '12 at 19:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.