Java tutorial
// (c) Alexandre Fenyo 2012, 2013, 2014, 2015, 2016 - alex@fenyo.net - http://fenyo.net - GPLv3 licensed package net.fenyo.mail4hotspot.service; import java.io.IOException; import java.util.Properties; import javax.mail.*; import javax.mail.Address; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.NoSuchProviderException; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.net.ssl.*; import org.apache.commons.lang3.ArrayUtils; import net.fenyo.mail4hotspot.domain.*; import net.fenyo.mail4hotspot.tools.GenericTools; // pour rajouter un certificat au keystore global : // on va dans le rept contenant le keystore global cacerts : // cd "/cygdrive/c/Program Files/Java/jdk1.7.0_01/jre/lib/security" // on rajouter un password : // c:/Program\ Files/Java/jdk1.7.0_01/jre/bin/keytool.exe -protected -storepasswd -keystore cacerts // on rajouter le certif l'aide de ce password : // c:/Program\ Files/Java/jdk1.7.0_01/jre/bin/keytool.exe -importcert -file cyrus-CAcert.pem -alias rsi -storepass PASSWORD -keystore cacerts // si on ne prcisait pas le keystore, un nouveau serait cr : C:\Documents and Settings\fenyo.C01078599\.keystore ///usr/lib/cyrus/bin/deliver -e -r fenyo fenyo //From: fenyo //To: fenyo //Subject: zefpozekfze // //test //From: John Doe <example@example.com> //MIME-Version: 1.0 //Content-Type: multipart/mixed; // boundary="XXXXboundary text" // //This is a multipart message in MIME format. // //--XXXXboundary text //Content-Type: text/plain // //this is the body text // //--XXXXboundary text //Content-Type: text/plain; //Content-Disposition: attachment; // filename="test.txt" // //this is the attachment text // //--XXXXboundary text-- //MIME-Version: 1.0 //Content-Type: multipart/mixed; boundary=frontier // //This is a message with multiple parts in MIME format. //--frontier //Content-Type: text/plain // //This is the body of the message. //--frontier //Content-Type: application/octet-stream //Content-Transfer-Encoding: base64 // //PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg //Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg= //--frontier-- // Subject: =?iso-8859-1?Q?=A1Hola,_se=F1or!?= // correspond Subject: Hola, seor! // http://en.wikipedia.org/wiki/MIME //MIME-Version: 1.0 //From: Nathaniel Borenstein //Subject: A multipart example //Content-Type: multipart/mixed; // boundary=unique-boundary-1 // //This is the preamble area of a multipart message. Mail readers //that understand multipart format should ignore this preamble. // //If you are reading this text, you might want to consider //changing to a mail reader that understands how to properly //display multipart messages. //--unique-boundary-1 // //Some text appears here... //[Note that the preceding blank line means //no header fields were given and this is text, //with charset US ASCII. It could have been //done with explicit typing as in the next part.] //--unique-boundary-1 //Content-type: text/plain; charset=US-ASCII // //This could have been part of the previous part, but illustrates //explicit versus implicit typing of body parts. // //--unique-boundary-1 //Content-Type: multipart/parallel; boundary=unique-boundary-2 // //--unique-boundary-2 //Content-Type: audio/basic //Content-Transfer-Encoding: base64 // //... base64-encoded 8000 Hz single-channel u-law-format audio data //goes here ... // //--unique-boundary-2 //Content-Type: image/gif //Content-Transfer-Encoding: Base64 // //... base64-encoded image data goes here ... // //--unique-boundary-2-- // //--unique-boundary-1 //Content-type: text/richtext // //This is richtext.Isn't it //cool? // //--unique-boundary-1 //Content-Type: message/rfc822 // //From: (name in US-ASCII) //Subject: (subject in US-ASCII) //Content-Type: Text/plain; charset=ISO-8859-1 //Content-Transfer-Encoding: Quoted-printable // //... Additional text in ISO-8859-1 goes here ... // //--unique-boundary-1-- public class MailManager { protected final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(getClass()); private javax.mail.Session session = null; private Store store = null; private Folder inbox = null; private Message[] messages = null; private Transport transport = null; public MailManager() { } private void connectToOutgoingServer(final String protocol, final String host, final int port, final String username, final String password) throws MessagingException { final Properties prop = new Properties(); prop.setProperty("mail.mime.address.strict", "false"); // prop.put("mail.smtp.auth", "true"); mais a laisse useAuth false prop.put("mail.smtp.starttls.enable", "true"); prop.setProperty("mail.debug", "true"); session = javax.mail.Session.getInstance(prop, null); session.setDebugOut(System.out); //session.setDebug(false); session.setDebug(true); transport = session.getTransport(protocol); transport.connect(host, username, password); } private void connectToServer(final String protocol, final String host, final int port, final String username, final String password) throws MessagingException { final Properties prop = new Properties(); prop.setProperty("mail.mime.address.strict", "false"); // prop.setProperty(" mail.debug", "true"); session = javax.mail.Session.getInstance(prop, null); //session.setDebugOut(System.out); //session.setDebug(false); // session.setDebug(true); store = session.getStore(protocol); store.connect(host, port, username, password); inbox = store.getDefaultFolder().getFolder("INBOX"); inbox.open(Folder.READ_ONLY); messages = inbox.getMessages(); } public Message[] getMessages() { return messages; } public String getMessageContentString(final Message message) throws IOException, MessagingException { final Object content = message.getContent(); if (String.class.isInstance(content)) // content-type: text/{plain, html, etc.} // prfrer isMimeType(...) getContentType().equals(...) car getContentType() peut contenir aussi le charset et renvoyer une string comme suit : << text/html; charset="us-ascii" >> if (message.isMimeType("text/html")) return GenericTools.html2Text((String) content); else if (message.isMimeType("text/plain")) return (String) content; else { log.warn("message content-type not handled: " + message.getContentType() + " -> downgrading to String"); return (String) content; } else if (MimeMultipart.class.isInstance(content)) { boolean mixed = false; if (message.isMimeType("multipart/mixed")) mixed = true; else if (message.isMimeType("multipart/alternative")) mixed = false; else { log.warn("multipart content-type not handled: " + message.getContentType() + " -> downgrading to multipart/mixed"); mixed = true; } return getMultipartContentString((MimeMultipart) content, mixed); } else { log.warn("invalid message content type and class: " + content.getClass().toString() + " - " + message.getContentType()); return ""; } } private String getMultipartContentString(final MimeMultipart multipart, final boolean mixed) throws IOException, MessagingException { // content-type: multipart/mixed ou multipart/alternative final StringBuffer selected_content = new StringBuffer(); for (int i = 0; i < multipart.getCount(); i++) { final BodyPart body_part = multipart.getBodyPart(i); final Object content = body_part.getContent(); final String content_string; if (String.class.isInstance(content)) if (body_part.isMimeType("text/html")) content_string = GenericTools.html2Text((String) content); else if (body_part.isMimeType("text/plain")) content_string = (String) content; else { log.warn("body part content-type not handled: " + body_part.getContentType() + " -> downgrading to String"); content_string = (String) content; } else if (MimeMultipart.class.isInstance(content)) { boolean part_mixed = false; if (body_part.isMimeType("multipart/mixed")) part_mixed = true; else if (body_part.isMimeType("multipart/alternative")) part_mixed = false; else { log.warn("body part content-type not handled: " + body_part.getContentType() + " -> downgrading to multipart/mixed"); part_mixed = true; } content_string = getMultipartContentString((MimeMultipart) content, part_mixed); } else { log.warn("invalid body part content type and class: " + content.getClass().toString() + " - " + body_part.getContentType()); content_string = ""; } if (mixed == false) { // on slectionne la premire part non vide - ce n'est pas forcment la meilleure alternative, mais comment diffrentiel un text/plain d'une pice jointe d'un text/plain du corps du message, accompagnant un text/html du mme corps ??? if (selected_content.length() == 0) selected_content.append(content_string); } else { if (selected_content.length() > 0 && content_string.length() > 0) selected_content.append("\r\n---\r\n"); selected_content.append(content_string); } } return selected_content.toString(); } private void connectToSMTPServer(final String host, final int port, final String username, final String password) throws MessagingException { connectToOutgoingServer("smtp", host, port, username, password); } private void connectToSMTPsServer(final String host, final int port, final String username, final String password) throws MessagingException { connectToOutgoingServer("smtps", host, port, username, password); } private void connectToPop3SSLServer(final String host, final int port, final String username, final String password) throws MessagingException { connectToServer("pop3s", host, port, username, password); } private void connectToPop3Server(final String host, final int port, final String username, final String password) throws MessagingException { connectToServer("pop3", host, port, username, password); } private void connectToImapServer(final String host, final int port, final String username, final String password) throws MessagingException { connectToServer("imap", host, port, username, password); } private void connectToImapSSLServer(final String host, final int port, final String username, final String password) throws MessagingException { connectToServer("imaps", host, port, username, password); } public void connectToProvider(final Account.Provider provider, final String username, final String password) throws MessagingException { // il faut rajouter dans le client AOL puis tester l'algo de la marque if (provider == Account.Provider.AOL) connectToPop3SSLServer("pop.aol.com.", 995, username, password); // GMail test OK pour la rception avec l'algo de la marque // en production : en imap - pour tester : en pop // if (provider == Account.Provider.GMAIL) connectToPop3SSLServer("pop.gmail.com.", 995, username, password); // protocole version 2 : rception OK if (provider == Account.Provider.GMAIL) connectToImapSSLServer("imap.gmail.com.", 993, username, password); // HotMail inclut outlook.com et live.com // HotMail test OK pour la rception avec l'algo de la marque // protocole version 2 : rception OK // if (provider == Account.Provider.HOTMAIL) connectToPop3SSLServer("pop3.live.com.", 995, username, password); if (provider == Account.Provider.HOTMAIL) connectToImapSSLServer("imap-mail.outlook.com.", 993, username, password); // YahooMail test OK pour la rception avec l'algo de la marque // MARCHE PAS EN AUTOMATIQUE en POP3S (le password n'est pas pris ou reconnu, l'change login/passwd semble planter car le passwd est envoy sans attendre le OK de la commande du login) // => ont fait en POP3 //if (provider == Account.Provider.YAHOO) connectToPop3Server("pop.mail.yahoo.com.", 110, username, password); // protocole version 2 : rception OK (corrige en passant de pop imaps) if (provider == Account.Provider.YAHOO) connectToImapSSLServer("imap.mail.yahoo.com.", 993, username, password); // OperaMail correspond FastMail // OperaMail test OK pour la rception avec l'algo de la marque // protocole version 2 : rception OK if (provider == Account.Provider.OPERAMAIL) connectToImapSSLServer("mail.messagingengine.com.", 993, username, password); if (provider == Account.Provider.TESTIMAPLOCALHOST) connectToImapServer("localhost", 143, username, password); if (provider == Account.Provider.TESTIMAPRSI) connectToImapServer("10.69.60.6", 143, username, password); if (provider == Account.Provider.TESTPOPLOCALHOST) connectToPop3Server("localhost", 110, username, password); if (provider == Account.Provider.TESTPOPRSI) connectToPop3Server("10.69.60.6", 110, username, password); } public void connectToRelay(final Account.Provider provider, final String username, final String password) throws MessagingException { // il faut rajouter dans le client AOL puis tester if (provider == Account.Provider.AOL) connectToSMTPsServer("pop.aol.com.", 465, username, password); // test OK // protocole version 2 : retester // mission : "DEBUG SMTP: useEhlo true, useAuth false" et version de JavaMail regarder (1.5.4 : https://java.net/projects/javamail/pages/Home) // et regarder les spcificits de JavaMail pour les diffrents providers : https://java.net/projects/javamail/pages/Home et " Q: How do I access Yahoo! Mail with JavaMail? " sur http://www.oracle.com/technetwork/java/javamail/faq/index.html#yahoomail // voir aussi l'exemple ici : https://community.oracle.com/thread/2350165?tstart=0 // protocole version 2 : test OK if (provider == Account.Provider.GMAIL) connectToSMTPsServer("smtp.gmail.com.", 465, username, password); // test OK // protocole version 2 : test OK // if (provider == Account.Provider.HOTMAIL) connectToSMTPServer("smtp.live.com.", 25, username, password); if (provider == Account.Provider.HOTMAIL) connectToSMTPServer("smtp-mail.outlook.com.", 25, username, password); // test OK // protocole version 2 : test OK if (provider == Account.Provider.YAHOO) connectToSMTPsServer("smtp.mail.yahoo.com.", 465, username, password); // protocole version 2 : test OK if (provider == Account.Provider.OPERAMAIL) connectToSMTPsServer("mail.messagingengine.com.", 995, username, password); // ICI } public void disconnect() throws MessagingException { try { if (inbox != null) inbox.close(false); } finally { if (store != null) store.close(); } } public void disconnectRelay() throws MessagingException { if (transport != null) transport.close(); } public void sendMessage(Address from_addr, Address[] to_addr, Address[] cc_addr, String subject, String content) throws MessagingException { final MimeMessage msg = new MimeMessage(session); msg.setFrom(from_addr); msg.setRecipients(Message.RecipientType.TO, to_addr); if (cc_addr.length > 0) msg.setRecipients(Message.RecipientType.CC, cc_addr); msg.setSubject(subject, "UTF-8"); msg.setContent(content, "text/plain"); transport.sendMessage(msg, ArrayUtils.addAll(to_addr, cc_addr)); } // marche uniquement pour les connexions HTTPs, pas pour pop3s ni smtps public static void trustSSL() { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } }; // c'est un pb de scurit, il faudrait mettre jour les certifs racine et supprimer le all-trusting trust manager // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { System.out.println("Can not install the all-trusting trust manager"); } } // http://javamail.kenai.com/nonav/javadocs/ // http://code.google.com/p/tubesrus/source/browse/trunk/src/tubesrus/beans/MailManager.java?spec=svn88&r=88 public static void main(String[] args) throws NoSuchProviderException, MessagingException { System.out.println("Salut"); // trustSSL(); /* final Properties props = new Properties(); props.put("mail.smtp.host", "my-mail-server"); props.put("mail.from", "me@example.com"); javax.mail.Session session = javax.mail.Session.getInstance(props, null); try { MimeMessage msg = new MimeMessage(session); msg.setFrom(); msg.setRecipients(Message.RecipientType.TO, "you@example.com"); msg.setSubject("JavaMail hello world example"); msg.setSentDate(new Date()); msg.setText("Hello, world!\n"); Transport.send(msg); } catch (MessagingException mex) { System.out.println("send failed, exception: " + mex); }*/ final Properties props = new Properties(); //props.put("mail.host", "10.69.60.6"); //props.put("mail.user", "fenyo"); //props.put("mail.from", "fenyo@fenyo.net"); //props.put("mail.transport.protocol", "smtps"); //props.put("mail.store.protocol", "pop3s"); // [javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], // javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], // javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc], // javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], // javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc], // javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc]] // final Provider[] providers = session.getProviders(); javax.mail.Session session = javax.mail.Session.getInstance(props, null); session.setDebug(true); //session.setDebug(false); // final Store store = session.getStore("pop3s"); // store.connect("10.69.60.6", 995, "fenyo", "PASSWORD"); // final Store store = session.getStore("imaps"); // store.connect("10.69.60.6", 993, "fenyo", "PASSWORD"); // System.out.println(store.getDefaultFolder().getMessageCount()); //final Store store = session.getStore("pop3"); final Store store = session.getStore("pop3s"); //final Store store = session.getStore("imaps"); // store.addStoreListener(new StoreListener() { // public void notification(StoreEvent e) { // String s; // if (e.getMessageType() == StoreEvent.ALERT) // s = "ALERT: "; // else // s = "NOTICE: "; // System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: " + s + e.getMessage()); // } // }); //store.connect("10.69.60.6", 110, "fenyo", "PASSWORD"); store.connect("pop.gmail.com", 995, "alexandre.fenyo@gmail.com", "PASSWORD"); //store.connect("localhost", 110, "alexandre.fenyo@yahoo.com", "PASSWORD"); //store.connect("localhost", 995, "fenyo@live.fr", "PASSWORD"); //store.connect("localhost", 995, "thisisatestforalex@aol.fr", "PASSWORD"); // final Folder[] folders = store.getPersonalNamespaces(); // for (Folder f : folders) { // System.out.println("Folder: " + f.getMessageCount()); // final Folder g = f.getFolder("INBOX"); // g.open(Folder.READ_ONLY); // System.out.println(" g:" + g.getMessageCount()); // } final Folder inbox = store.getDefaultFolder().getFolder("INBOX"); inbox.open(Folder.READ_ONLY); System.out.println("nmessages: " + inbox.getMessageCount()); final Message[] messages = inbox.getMessages(); for (Message message : messages) { System.out.println("message:"); System.out.println(" size: " + message.getSize()); try { if (message.getFrom() != null) System.out.println(" From: " + message.getFrom()[0]); } catch (final Exception ex) { System.out.println(ex.toString()); } System.out.println(" content-type: " + message.getContentType()); System.out.println(" disposition: " + message.getDisposition()); System.out.println(" description: " + message.getDescription()); System.out.println(" filename: " + message.getFileName()); System.out.println(" line count: " + message.getLineCount()); System.out.println(" message number: " + message.getMessageNumber()); System.out.println(" subject: " + message.getSubject()); try { if (message.getAllRecipients() != null) for (Address address : message.getAllRecipients()) System.out.println(" address: " + address); } catch (final Exception ex) { System.out.println(ex.toString()); } } for (Message message : messages) { System.out.println("-----------------------------------------------------"); Object content; try { content = message.getContent(); if (javax.mail.Multipart.class.isInstance(content)) { System.out.println("CONTENT OBJECT CLASS: MULTIPART"); final javax.mail.Multipart multipart = (javax.mail.Multipart) content; System.out.println("multipart content type: " + multipart.getContentType()); System.out.println("multipart count: " + multipart.getCount()); for (int i = 0; i < multipart.getCount(); i++) { System.out.println(" multipart body[" + i + "]: " + multipart.getBodyPart(i)); BodyPart part = multipart.getBodyPart(i); System.out.println(" content-type: " + part.getContentType()); } } else if (String.class.isInstance(content)) { System.out.println("CONTENT IS A STRING: {" + content + "}"); } else { System.out.println("CONTENT OBJECT CLASS: " + content.getClass().toString()); } } catch (IOException e) { e.printStackTrace(); } } store.close(); } }