0

I am trying to set up JavaMail to read emails that have been received via smtp on a CentOS 7 server with postfix and mailx installed and functioning properly. I created a POJO named TestEmail.java that contains a method named read(). A Spring MVC controller instantiates TestEmail.java and calls the read.() method, but this call is throwing the following error:

javax.mail.NoSuchProviderException: Invalid protocol: null  

I have read other postings about this error, including this one and this one. But the other postings relate to sending email. My error is related to reading received email. So this new post is different.

Here is the method that is throwing the error:

public void read(){
    //lookup the java mail session
    InitialContext ic;
    try {
        ic = new InitialContext();
        String snName = "java:comp/env/mail/Session";
        Session session = (Session)ic.lookup(snName);
        //Get a Store object from the Session, then connect to the mail server using the Store object’s connect() method. You must supply a mail server name, a mail user name, and a password.
        Store store = session.getStore();
        store.connect("mail.smtp.host", "someuser", "somepassword"); 
        //Get the default folder, then get the INBOX folder:
        Folder folder = store.getDefaultFolder();
        folder = folder.getFolder("INBOX"); 
        //It is efficient to read the Message objects (which represent messages on the server) into an array:
        Message[] messages = folder.getMessages();
        int num_msgs = messages.length;
        System.out.println("num_msgs is: "+num_msgs);
    } 
    catch (NamingException e) {e.printStackTrace();} 
    catch (MessagingException me){me.printStackTrace();}
}

I added the following as the very last node in web.xml:

<resource-ref>
  <description>
    Resource reference to a factory for javax.mail.Session
    instances that may be used for sending electronic mail
    messages, preconfigured to connect to the appropriate
    SMTP server.
  </description>
  <res-ref-name>
    mail/Session
  </res-ref-name>
  <res-type>
    javax.mail.Session
  </res-type>
  <res-auth>
    Container
  </res-auth>
</resource-ref>  

And I added the following line to /opt/tomcat/conf/context.xml:

<Resource name="mail/Session" auth="Container" type="javax.mail.Session" mail.smtp.host="localhost"/>

The line in the stack trace that refers to calling the read() method above is:

at some.package.SomeController.processSomeForm(SomeController.java:277)  

Here is the complete stack trace:

javax.mail.NoSuchProviderException: Invalid protocol: null
    at javax.mail.Session.getProvider(Session.java:455)
    at javax.mail.Session.getStore(Session.java:553)
    at javax.mail.Session.getStore(Session.java:533)
    at javax.mail.Session.getStore(Session.java:519)
    at mainpackage.TestEmail.read(TestEmail.java:91)
    at some.package.SomeController.processSomeForm(SomeController.java:277)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.github.dandelion.datatables.core.web.filter.DatatablesFilter.doFilter(DatatablesFilter.java:73)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.github.dandelion.datatables.extras.servlet2.filter.DatatablesFilter.doFilter(DatatablesFilter.java:71)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
sessionID is: 24FA856A1F66FEC2E282693662BE0BB0  
Community
  • 1
  • 1
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • The code are you using is taken from any example? Makes sense to use a protocol like imap or pop3 for reading emails. – Leandro Carracedo Jan 08 '15 at 03:25
  • @PatrickLC The server only has SMTP installed. Lemme see if I can find where the code came from. – CodeMed Jan 08 '15 at 03:27
  • @PatrickLC The code is a mix from different sources because I could not find a good `SMTP` example. Note that **all emails on my devbox are sent to and from localhost only**. This is not a production machine, but it is running `CentOS 7`. Also, I did find the `javamail` `smtp` `api` here: https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html – CodeMed Jan 08 '15 at 03:34
  • @PatrickLC That gives `javax.mail.NoSuchProviderException: invalid provider` – CodeMed Jan 08 '15 at 03:51
  • Really sorry, time to sleep for me, After getting the session and before getting the store, try to include: Properties props = session.getProperties(); props.put("mail.store.protocol", "imap"); – Leandro Carracedo Jan 08 '15 at 03:57
  • @PatrickLC Progress? That gives: `com.sun.mail.util.MailConnectException: Couldn't connect to host, port: mail.smtp.host, 143; timeout -1; nested exception is: java.net.UnknownHostException: mail.smtp.host` – CodeMed Jan 08 '15 at 04:02
  • I think now i understand more your scenario, check: http://stackoverflow.com/questions/3127075/parse-inbox-in-postfix-using-java – Leandro Carracedo Jan 08 '15 at 04:02
  • @PatrickLC I read your link and all nested links. The server only has `postfix` and `mailx`, so I do not think it can do `imap`. When I googled `postfix imap`, the results were tutorials for mixed installations with `postfix`/`dovecot`/etc. This server might only have one or two email addresses, and all emails will be automatically managed by an app to import/export data with other systems, etc. I have imagined it could do that with `smtp` only. I would hate to have to reconfigure the server. I can send/receive `smtp` email at the command line using the `mailx` command. – CodeMed Jan 08 '15 at 04:33
  • Maybe you could find a way to parse the messages by yourself, if you are working with mailx, check if the messages are being stored and then parse them inside your app: https://java.net/projects/javamail/pages/MboxStore – Leandro Carracedo Jan 08 '15 at 16:55
  • @PatrickLC Thank you. I may indeed resort to that. I have written lots of parsing programs like that in the past. I am reading the link you sent, but I want to spend at least some more time researching a more elegant solution. My app is already extremely complex. I hope to reduce the amount of code that I need to maintain over the long run. I am using `smtp` instead of `imap` in part because i want to make it harder for hackers to get at the email contents. – CodeMed Jan 08 '15 at 18:48

0 Answers0