Java™ - Retrieve Contents of an Email Remotely with Gmail SMTPS

in #utopian-io7 years ago (edited)

What Will I Learn?

In this tutorial, I will continue my previous lesson about how to manipulate email via Java™ application that all classes are available in the javax.mail package. Previously we already know how to send an email with attachments, now we will try to retrieve and read all existing emails on our Gmail account.

  • Java™ I/O Stream
  • Java™ Mail
  • Java™ Functional Interfaces

Requirements

  • Any current JDK.
  • IntelliJ IDEA Community.
  • Target google account.
    Before we get started, make sure to change the Allow less secure apps: ON setting on the target account here.
    Untitled 019.png

Difficulty

  • Basic

Tutorial Contents

  1. Prepare Connection To the Target Folder

    In this case, we will retrieve and read all emails in the Inbox folder.

    
       public static void retrieve(String username, String password) {
           Session session = Session.getDefaultInstance(GMAIL);
           try {
               Store store = session.getStore("imaps");
               store.connect(GMAIL.getProperty("mail.smtp.host"), username, password);
               Folder inbox = store.getFolder("Inbox");
               inbox.open(Folder.READ_ONLY);
               /*
                * Right now, the folder is ready
                */
               {
                   inbox.getMessages();
               }
               inbox.close(false);
               store.close();
           }
           catch(Throwable e) { e.printStackTrace(); }
       }
       
  2. Read Headers of Email

    We will read From, To, Cc, Bcc and the Subject of Email.

    
       private static void print(Part part) throws Throwable {
           if(part instanceof Message) {
               Message message = (Message) part;
               // From
               System.out.println("From: [" + print(message.getFrom()) + "]");
               // To
               System.out.println("  To: [" + print(message.getRecipients(Message.RecipientType.TO)) + "]");
               // CC
               System.out.println("  Cc: [" + print(message.getRecipients(Message.RecipientType.CC)) + "]");
               // BCC
               System.out.println(" Bbc: [" + print(message.getRecipients(Message.RecipientType.BCC)) + "]");
               // Subject
               System.out.println("Subject: " + message.getSubject());
           }
       }
       
       private static String print(Address[] accounts) {
           if(accounts == null) return "";
           StringBuilder plain = new StringBuilder(accounts[0].toString());
           for(int i = 0, n = accounts.length; ++i < n;)
               plain.append(";" + accounts[i]);
           return plain.toString();
       }
       
  3. Define Functions for Handling Any Types of Message Bodies

    We will handle the type of message bodies: image, multipart and plain string as the default. Next, we will try to handle the other types.
    The content of an email (usually known as Part) is available in various formats:

    • As a DataHandler - using the getDataHandler() method. The content of a Part is also available through a javax.activation.DataHandler object. The DataHandler object allows clients to discover the operations available on the content, and to instantiate the appropriate component to perform those operations.
    • As an InputStream - using the getInputStream() method. Any mail-specific encodings are decoded before this stream is returned.
    • As a Java Object - using the getContent() method. This method returns the content as a Java object. The returned object is of course dependent on the content itself. In particular, a multipart Part's content is always a Multipart or subclass thereof. That is, getContent() on a multipart type Part will always return a Multipart (or subclass) object.
      References
      • javax.mail.Part - The common base interface for Messages and BodyParts.
      • javax.mail.Multipart - The container that holds multiple body parts. Multipart provides methods to retrieve and set its subparts.
      • javax.mail.internet.MimeMultipart - An implementation of the abstract Multipart class that uses MIME conventions for the multipart data.
    
       private static final Map<String, Function<Object, Void>> FUNCTIONS = new java.util.HashMap<>();
       private static final String IMG_JPEG = "image/jpeg";
       private static final String MULTIPART = "multipart/*";
       
       static {
           //Default action
           FUNCTIONS.put(null, content -> {
               System.out.println(content);
               return null;
           });
           FUNCTIONS.put(MULTIPART, content -> {
               Multipart multiPart;
               try { multiPart = (Multipart) content; }
               catch(Throwable e) {
                   System.out.println("Parsing content was unsuccessful");
                   e.printStackTrace();
                   return null;
               }
               int i, n;
               try {
                   n = multiPart.getCount();
               } catch(Throwable e) {
                   System.out.println("Getting count of this content was unsuccessful");
                   n = 0;
               }
               for(i = 0; i < n; i++)
                   try { print(multiPart.getBodyPart(i)); }
                   catch(Throwable e) { e.printStackTrace(); }
               return null;
           });
           FUNCTIONS.put(IMG_JPEG, content -> {
               InputStream in;
               try { in = (InputStream) content; }
               catch(Throwable e) {
                   System.out.println("Parsing content was unsuccessful");
                   e.printStackTrace();
                   return null;
               }
               final byte[] BYTES = new byte[2048];
               System.out.println("Enter image path and name of this current content: ");
               String name;
               try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
                   if((name = reader.readLine()) == null || name.length() < 1)
                       throw new UnsupportedOperationException("Name should not be empty");
               } catch(Throwable e) {
                   System.out.println("Scanning name was unsuccessful");
                   e.printStackTrace();
                   return null;
               }
               try(FileOutputStream writer = new FileOutputStream(name)) {
                   for(int length; ; writer.write(BYTES, 0, length))
                       if((length = in.read(BYTES)) < 0)
                           break;
               } catch(Throwable e) { e.printStackTrace(); }
               return null;
           });
       }
       
       private static void print(Part part) throws Throwable {
           if(part instanceof Message) {
               Message message = (Message) part;
               System.out.println("From: [" + print(message.getFrom()) + "]");
               System.out.println("  To: [" + print(message.getRecipients(Message.RecipientType.TO)) + "]");
               System.out.println("  Cc: [" + print(message.getRecipients(Message.RecipientType.CC)) + "]");
               System.out.println(" Bbc: [" + print(message.getRecipients(Message.RecipientType.BCC)) + "]");
               System.out.println("Subject: " + message.getSubject());
           }
           /*
            * Additional logic
            */
           if(part.isMimeType("text/plain") || part.isMimeType("message/rfc822"))
               FUNCTIONS.get(null).apply(part.getContent());
           else if(part.isMimeType(MULTIPART))
               FUNCTIONS.get(MULTIPART).apply(part.getContent());
           else if(part.isMimeType(IMG_JPEG) || part.getContentType().contains("image/"))
               FUNCTIONS.get(IMG_JPEG).apply(part.getContent());
           else {
               Object content = part.getContent();
               if(content instanceof InputStream) {
                   InputStream in = (InputStream) content;
                   for(int c; (c = in.read()) > -1; )
                       System.out.write(c);
               } else
                   System.out.println(content.toString());
               System.out.println("*** THE END ***");
           }
           
       }
       

Testing

Main


public static void main(String[] args) {
    String username = "rezanas************";
    String password = "*******************";
    retrieve(username, password);
}

public static void retrieve(String username, String password) {
    Session session = Session.getDefaultInstance(GMAIL);
    try {
        Store store = session.getStore("imaps");
        store.connect(GMAIL.getProperty("mail.smtp.host"), username, password);
        Folder inbox = store.getFolder("Inbox");
        inbox.open(Folder.READ_ONLY);
        /*
         * Listen input from the user
         */
        String line;
        int i = 0, n = inbox.getMessageCount();
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
            do {
                print(inbox.getMessage(n -= (i + 1)));
                System.out.print("To stop, type \"0\" (zero) or type any positive number to jump: ");
                line = reader.readLine();
                try{ i = Integer.parseInt(line); }
                catch(Throwable e) { i = 0; }
            }
            while(!line.equals("0"));
        }
        inbox.close(false);
        store.close();
    }
    catch(Throwable e) { e.printStackTrace(); }
}

Result
Untitled 001.png

Final Source Code


public class Mail {
    public static void main(String[] args) {
        String username = "rezanas***********";
        String password = "******************";
        retrieve(username, password);
    }
    
    public static void retrieve(String username, String password) {
        Session session = Session.getDefaultInstance(GMAIL);
        try {
            Store store = session.getStore("imaps");
            store.connect(GMAIL.getProperty("mail.smtp.host"), username, password);
            Folder inbox = store.getFolder("Inbox");
            inbox.open(Folder.READ_ONLY);
            String line;
            int i = 0, n = inbox.getMessageCount();
            try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
                do {
                    print(inbox.getMessage(n -= (i + 1)));
                    System.out.print("To stop, type \"0\" (zero) or type any positive number to jump: ");
                    line = reader.readLine();
                    try{ i = Integer.parseInt(line); }
                    catch(Throwable e) { i = 0; }
                }
                while(!line.equals("0"));
            }
            inbox.close(false);
            store.close();
        }
        catch(Throwable e) { e.printStackTrace(); }
    }
    
    private static final Map<String, Function<Object, Void>> FUNCTIONS = new java.util.HashMap<>();
    private static final String IMG_JPEG = "image/jpeg";
    private static final String MULTIPART = "multipart/*";
    
    static {
        //Default action
        FUNCTIONS.put(null, content -> {
            System.out.println(content);
            return null;
        });
        FUNCTIONS.put(MULTIPART, content -> {
            Multipart multiPart;
            try { multiPart = (Multipart) content; }
            catch(Throwable e) {
                System.out.println("Parsing content was unsuccessful");
                e.printStackTrace();
                return null;
            }
            int i, n;
            try {
                n = multiPart.getCount();
            } catch(Throwable e) {
                System.out.println("Getting count of this content was unsuccessful");
                n = 0;
            }
            for(i = 0; i < n; i++)
                try { print(multiPart.getBodyPart(i)); }
                catch(Throwable e) { e.printStackTrace(); }
            return null;
        });
        FUNCTIONS.put(IMG_JPEG, content -> {
            InputStream in;
            try { in = (InputStream) content; }
            catch(Throwable e) {
                System.out.println("Parsing content was unsuccessful");
                e.printStackTrace();
                return null;
            }
            final byte[] BYTES = new byte[2048];
            System.out.println("Enter image path and name of this current content: ");
            String name;
            try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
                if((name = reader.readLine()) == null || name.length() < 1)
                    throw new UnsupportedOperationException("Name should not be empty");
            } catch(Throwable e) {
                System.out.println("Scanning name was unsuccessful");
                e.printStackTrace();
                return null;
            }
            try(FileOutputStream writer = new FileOutputStream(name)) {
                for(int length; ; writer.write(BYTES, 0, length))
                    if((length = in.read(BYTES)) < 0)
                        break;
            } catch(Throwable e) { e.printStackTrace(); }
            return null;
        });
    }
    
    private static void print(Part part) throws Throwable {
        if(part instanceof Message) {
            Message message = (Message) part;
            System.out.println("From: [" + print(message.getFrom()) + "]");
            System.out.println("  To: [" + print(message.getRecipients(Message.RecipientType.TO)) + "]");
            System.out.println("  Cc: [" + print(message.getRecipients(Message.RecipientType.CC)) + "]");
            System.out.println(" Bbc: [" + print(message.getRecipients(Message.RecipientType.BCC)) + "]");
            System.out.println("Subject: " + message.getSubject());
        }
        if(part.isMimeType("text/plain") || part.isMimeType("message/rfc822"))
            FUNCTIONS.get(null).apply(part.getContent());
        else if(part.isMimeType(MULTIPART))
            FUNCTIONS.get(MULTIPART).apply(part.getContent());
        else if(part.isMimeType(IMG_JPEG) || part.getContentType().contains("image/"))
            FUNCTIONS.get(IMG_JPEG).apply(part.getContent());
        else {
            Object content = part.getContent();
            if(content instanceof InputStream) {
                InputStream in = (InputStream) content;
                for(int c; (c = in.read()) > -1; )
                    System.out.write(c);
            } else
                System.out.println(content.toString());
            System.out.println("*** THE END ***");
        }
    }
    
    private static String print(Address[] accounts) {
        if(accounts == null) return "";
        StringBuilder plain = new StringBuilder(accounts[0].toString());
        for(int i = 0, n = accounts.length; ++i < n;)
            plain.append(";" + accounts[i]);
        return plain.toString();
    }
}

Untitled 001.png

Thank you!

Share with Heart.


Curriculum



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Hi! I am a robot. I just upvoted you! I found similar content that readers might be interested in:
https://docs.oracle.com/javaee/6/api/javax/mail/Part.html

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

Hey @murez-nst I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x