Coder Social home page Coder Social logo

cuba-platform / imap-addon Goto Github PK

View Code? Open in Web Editor NEW
6.0 8.0 2.0 1.57 MB

IMAP Integration CUBA component provides a readily available instrument that enables adding the capability to integrate email messaging into any application developed using CUBA Platform.

License: Apache License 2.0

Java 73.47% Groovy 12.76% XSLT 13.77%
cuba-platform cuba-component imap apache2

imap-addon's Introduction

IMAP

license Build Status

Overview

The IMAP-addon provides a readily available instrument for integrating email messaging into any CUBA-based application via the IMAP protocol. The main model of the component is designed to interact with incoming emails via Spring application events.

The component includes the following set of functionalities:

  • Integration between any IMAP servers and CUBA applications.
  • Basic API methods to work with the main email server functionalities:
    • Connecting to servers;
    • Retrieving and viewing emails;
    • Searching for emails;
    • Operating custom flags.
  • Predefined events for implementing custom business logic and processing various updates.
  • User interface for configuring IMAP connection settings and events.

See sample application using this component. See webinar on the CUBA Platform channel.

Installation

The add-on can be added to your project in one of the ways described below. Installation from the Marketplace is the simplest way. The last version of the add-on compatible with the used version of the platform will be installed. Also, you can install the add-on by coordinates choosing the required version of the add-on from the table.

In case you want to install the add-on by manual editing or by building from sources see the complete add-ons installation guide in CUBA Platform documentation.

From the Marketplace

  1. Open your application in CUBA Studio. Check the latest version of CUBA Studio on the CUBA Platform site.
  2. Go to CUBA -> Marketplace in the main menu.

marketplace

  1. Find the IMAP add-on there.

addons

  1. Click Install and apply the changes. The add-on corresponding to the used platform version will be installed.

By coordinates

  1. Open your application in CUBA Studio. Check the latest version of CUBA Studio on the CUBA Platform site.
  2. Go to CUBA -> Marketplace in the main menu.
  3. Click the icon in the upper-right corner.

by-coordinates

  1. Paste the add-on coordinates in the corresponding field as follows:

com.haulmont.addon.imap:imap-global:<add-on version>

where <add-on version> is compatible with the used version of the CUBA platform.

Platform Version Add-on Version
7.2.x 1.5.1
7.1.x 1.4.0
7.0.x 1.3.1
6.10.x 1.2.0
6.9.x 1.1.1
6.8.x 1.0.1
  1. Click Install and apply the changes. The add-on will be installed to your project.

Add-on Configuration

Before using the add-on do the following:

  1. Open app.properties file of your application and configure the following application properties:
#IMAP configuration
imap.encryption.key = HBXv3Q70IlmBMiW4EMyPHw==
imap.encryption.iv = DYOKud/GWV5boeGvmR/ttg==

#Enable scheduling
cuba.schedulingActive=true
  1. Run the application and go to Administration -> Scheduled tasks screen. Configure imap_ImapScheduler -> syncImap scheduled task.

Usage

Predefined Roles

IMAP Admin role - allows user to configure IMAP events.

Component Functionalities

IMAP Configuration

IMAP Configuration Browser is designed to add and manage mailboxes from which emails are retrieved. The browser is available from Menu: Administration → IMAP → IMAP Configuration.

IMAP Configuration Menu Item

Creating a new configuration is available by clicking the Create button.

Creating IMAP Configuration

IMAP Configuration Editor

IMAP Configuration Editor comprises two main sections to fill in: Basic and Advanced.

IMAP Configuration Editor

Basic

The Basic section enables to configure the main attributes for connecting to an email server via IMAP. The description of all fields is provided below.

  • Name: specify a name for connection.
  • Host: specify a host name or IP address of an email server.
  • Port: provide a port number to connect to an email server. The default value is 143.
  • Secure Connection: select an option for secure connection if required. Available values: STARTTLS, SSL/TLS.
  • Root Certificate: upload a client certificate if required.
  • Username: provide a username to connect to an email server.
  • Password: provide a user password to connect to an email server.

The Basic section comprises the Connect button. After providing all required information, use the button to upload a list of folders from the email server to work with.

Advanced

The Advanced section provides a set of additional options for connecting to an email server.

  • Custom Flag: specify a custom flag.
  • Use trash folder to remove emails: if checked, then it is possible to specify a trash folder of a current mailbox (the Trash Folder field becomes available). The setting works as follows: if an email is moved to the specified folder on the email server, EmailDeletedImapEvent occurs (for more details, see Event Types).
  • Use custom event generator class: if checked, it is possible to specify a custom class that defines additional logic for connecting to an IMAP server, handling events, etc. If the current setting is enabled, the Event Generator Class lookup field becomes available. To learn how to register a custom event generator class, please refer to Registering Custom IMAP Implementation Class.
  • Use proxy: if checked, proxy settings become available (see the description below).

Proxy Configuration

  • Proxy Host: provide a host name or IP address of a proxy server.
  • Proxy Port: provide a port to connect to a proxy server.
  • Use web proxy: if checked, web proxy is used.

Table of Folders

Once connection to the provided email server is successfully established, the table of folders becomes available.

Table of Folders

The table shows a list of folders from the email server you are connected to. In order to enable/disable some folders, use the checkboxes in the second column. If some folder is disabled, then messages from it are not retrieved.

For each folder you can select a set of IMAP events by using the Events table and register custom logic for them (for more details, please refer to Configuration).

IMAP Message Browser

All emails from connected mailboxes are displayed in IMAP Message Browser (available from Menu: Administration → IMAP → IMAP Message Browser).

IMAP Message Browser

Selecting an email and clicking View opens it for reading. Email Screen contains all general details of an email: date, author, subject, etc., and two tabs: Body and Attachments.

On the Body tab, the whole text of an email is displayed.

The Attachments tab comprises the table of attachments and the button to download required elements.

Attachments

Registering EventListeners to Interact with IMAP Events

In order to make your application react to IMAP events, you can register the @Component methods as Event listeners by using the @EventListener annotation. The example of how to set up an event listener is provided below.

import org.springframework.context.event.EventListener;

@Service(EmailReceiveService.NAME)
public class EmailReceiveServiceBean implements EmailReceiveService {

    @EventListener
    @Override
    public void receiveEmail(NewEmailImapEvent event) {
      // handles IMAP event
    }
}

Another option is to create @Component with a method having the required event type as the only parameter.

public class EmailReceiver {
    String NAME = "ceuia_EmailReceiver";

    public void receiveEmail(NewEmailImapEvent event) {
        // handle IMAP event
    }
}

Once it is done, the selected method (in the example, it is receiveEmail) should be registered on a particular folder for a given IMAP connection. This should be done at runtime using the IMAP configuration UI (see Creating Handlers for IMAP Events). After that, the method will be invoked every time, when the configured event occurs.

Creating Handlers for IMAP Events

After registering EventListeners, it is required to create handlers for IMAP events related to a particular folder and mailbox (for more information see IMAP Connection). The table of folders comprises several columns, each representing a certain event type (e.g. New, Seen, Replied, etc.). Clicking gear icons opens IMAP Folder Event Editor.

IMAP Folder Event Editor

There you can specify required beans and methods for them.

Event types

All events contain the ImapMessage object that can be used to determine where an event occurs (mailbox, folder, message).

The application component supports the following kinds of IMAP events:

  • NewEmailImapEvent is triggered for a folder having an event of the ImapEventType.NEW_EMAIL type enabled, when a new message appears in the folder on the IMAP server.
  • EmailSeenImapEvent is triggered for a folder having an event of the ImapEventType.EMAIL_SEEN type enabled, when a message is marked with the javax.mail.Flags.Flag.SEEN IMAP flag.
  • EmailAnsweredImapEvent is triggered for a folder having an event of the ImapEventType.NEW_ANSWER type enabled, when a message is replied (usually it happens when a message is marked with the javax.mail.Flags.Flag.ANSWERED IMAP flag).
  • EmailFlagChangedImapEvent is triggered for a folder having an event of the ImapEventType.FLAGS_UPDATED type enabled, when a standard or custom IMAP flag is changed for a message. The event contains a Map of all changed flags and their actual state (set or unset).
  • EmailDeletedImapEvent is triggered for a folder having an event of the ImapEventType.EMAIL_DELETED type enabled, when a message is completely deleted from a folder on the IMAP server side, it is not related to the IMAP flag javax.mail.Flags.Flag.DELETED. Such events are also triggered when a message is moved to a trash folder (if it is configured for a mailbox) on the server.
  • EmailMovedImapEvent is triggered for a folder having an event of the ImapEventType.EMAIL_MOVED type enabled, when a message is moved to another folder on the IMAP server. Note: the standard implementation tracks only folders which are selected in the ImapMailBox configuration, but does not count a trash folder, if one is configured.
  • NewThreadImapEvent is not implemented yet.

Using API

The component provides the following API to interact with the IMAP server:

  • ImapAPI methods:
    • Collection<ImapFolderDto> fetchFolders(ImapMailBox) — retrieves all folders preserving the tree structure.
    • Collection<ImapFolderDto> fetchFolders(ImapMailBox, String...) — retrieves folders with the specified names. The result is not structured as a tree.
    • List<ImapFolderDto> fetchMessage(ImapMessage) — fetches a single message using a reference.
    • void moveMessage(ImapMessage, String) — moves a message to a different folder on the IMAP server side.
    • void deleteMessage(ImapMessage) — deletes a message from a folder.
    • void setFlag(ImapMessage, ImapFlag, boolean) — sets or unsets a specified flag for a message.
  • ImapAttachmentsAPI methods:
    • Collection<ImapMessageAttachment> fetchAttachments(ImapMessage) — retrieves attachments included in a message. The result contains only meta data, no content.
    • InputStream openStream(ImapMessageAttachment) and byte[] loadFile(ImapMessageAttachment — retrieve the content of a message attachment.

Registering Custom IMAP Implementation Class

In order to configure custom logic for a specific mailbox (e.g for applying IMAP extensions and custom communication mechanisms), it is required to register a custom IMAP implementation class in the source code of your application. The example of how to register such class is given below.

@Component("demo_SimpleSingleFolderNewMessagesEventsGenerator")
public class SimpleSingleFolderNewMessagesEventsGenerator implements ImapEventsGenerator {
...
}

After registering a class implementing ImapEventsGenerator, it appears in the dropdown list of the Event Generator Class field in IMAP Configuration Editor (for more details, see IMAP Configuration Editor).

Event Generator Class Field

imap-addon's People

Contributors

desire456 avatar gorbunkov avatar mariodavid avatar nikitashchienko avatar oshiryaeva avatar shmaks0 avatar shmelev-haulmont avatar smianna avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

imap-addon's Issues

IllegalStateException when creating new IMAP configuration

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Click Create.
  3. Fill in the required fields and establish a connection.
  4. Click OK to save the changes.

ER: The created connection is saved and the user is redirected to IMAP Configuration Browser.
AR: The following error occurs:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.haulmont.addon.imap.entity.ImapFolderEvent-d88686d4-e240-d926-a2ea-545e5d4b3217 [new].
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:313)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:728)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1521)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1174)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:134)
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
	at com.haulmont.cuba.core.sys.TransactionImpl.commit(TransactionImpl.java:104)
	at com.haulmont.cuba.core.app.RdbmsStore.commit(RdbmsStore.java:423)
	at com.haulmont.cuba.core.app.DataManagerBean.commit(DataManagerBean.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.cuba.core.app.DataManagerBean$SecureDataManagerInvocationHandler.invoke(DataManagerBean.java:362)
	at com.sun.proxy.$Proxy322.commit(Unknown Source)
	at com.haulmont.cuba.core.app.DataServiceBean.commit(DataServiceBean.java:40)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
	at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:117)
	at sun.reflect.GeneratedMethodAccessor133.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
	at com.sun.proxy.$Proxy217.commit(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94)
	at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154)
	at com.sun.proxy.$Proxy30.commit(Unknown Source)
	at com.haulmont.cuba.client.sys.DataManagerClientImpl.commit(DataManagerClientImpl.java:96)
	at com.haulmont.cuba.gui.data.impl.GenericDataSupplier.commit(GenericDataSupplier.java:90)
	at com.haulmont.cuba.gui.data.impl.DsContextImpl.commit(DsContextImpl.java:165)
	at com.haulmont.cuba.gui.components.EditorWindowDelegate.commit(EditorWindowDelegate.java:283)
	at com.haulmont.cuba.web.gui.WebWindow$Editor.commitAndClose(WebWindow.java:1755)
	at com.haulmont.cuba.gui.components.AbstractEditor.commitAndClose(AbstractEditor.java:109)
	at com.haulmont.cuba.gui.components.EditorWindowDelegate$2.actionPerform(EditorWindowDelegate.java:102)
	at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:44)
	at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:36)
	at sun.reflect.GeneratedMethodAccessor228.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163)
	at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037)
	at com.vaadin.ui.Button.fireClick(Button.java:377)
	at com.haulmont.cuba.web.toolkit.ui.CubaButton.fireClick(CubaButton.java:54)
	at com.vaadin.ui.Button$1.click(Button.java:54)
	at sun.reflect.GeneratedMethodAccessor219.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:119)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:444)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:409)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1435)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:361)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:300)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:191)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107)
	at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

Folder event handlers are mixed up in some cases

Case for reproduce:
add new handler to the list and then without saving remove other or change ordering, warning about all handlers used appears and there are duplicates after save configuration

Custom IMAP implementation

Add ability to create custom implementation for IMAP for diferent IMAP servers.
There should be ability to select custom IMAP implementation in IMAP configuration.
By default there should be applied implementation for standart IMAP server.

put IMAP menu under Administration > IMAP

Hi,

i think the that "IMAP" menu is currently hanged directly under the root note is not optimal. I think it should be placed under administration due to the fact that it does not distinguish itself compared to something like "Email History". Also for non-administrators of the application these screens are not relevant.

I can send you a PR, but wanted to ask you about it before, so you can decide if it is a good idea.

Not all types of files can be downloaded

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Message Browser.
  2. Open an email that contains attachments (PDFs or images).
  3. Open the Attachments tab.
  4. Select an attachment and click Download Attachment

ER: The selected attachment is downloaded.
AR: Not all attachments can be downloaded. For example, images and pdf files are ignored, when *.DOC and *.DOCX files can be successfully downloaded.

Note: it is required to think about a list of supported formats, or to make a special setting where a user can provide this list him-/herself.

Fix folder names localization

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Create a configuration (it is required to connect to a mailbox that has folder names in Cyrillic).
  3. Click 'Connect'.

Expected Result: All folder names are localized properly.
Actual Result:
image

[IMAP Configuration Editor] Scroller works improperly

Preconditions:

  • An IMAP configuration should be created.

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Select the configuration and click Edit.
  3. Wait for the folder table to download.
  4. Try expanding several parent folders.

ER: There should be an ability to scroll the table. For example, if there are many parent folders, it is easier to navigate if scrolling is available.

AR: At first, a scroller does not appear at all, then it appears for the whole screen, and after that, for the table. See this GIF.

IMAP MailBox Configuration Edit - NPE at select Folder with incorrect connection

When creating a IMAP configuration and hit "Select Folder" before setting the proper connection, a NPE is thrown:

java.lang.NullPointerException
	at com.haulmont.addon.imap.core.ImapHelper.getStore(ImapHelper.java:132)
	at com.haulmont.addon.imap.api.Imap.fetchFolders(Imap.java:55)
	at com.haulmont.addon.imap.service.ImapAPIServiceBean.fetchFolders(ImapAPIServiceBean.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
	at...

Selection of folders should probably be enabled after a successful connection could be established.

IMAP folders caching

Currently folders of mailbox are cached somewhere in IMAP internal classes and actual list of folders can be retrieved only after restart. Need to investigate and configure properly

Add a progress bar to Email Viewer

When an email is downloading, a user should see progress results. For this purpose, add a progress bar at the top of the Email Viewer screen.

IllegalStateException when opening an email

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Message Browser
  2. Select an email
  3. Click View

Expected Result:
Details about the selected email are downloaded.

Actual Result:

17:11:55.743 ERROR c.h.c.w.g.e.impl.WebBackgroundWorker - Unhandled exception in background task
java.util.concurrent.ExecutionException: com.haulmont.cuba.core.global.RemoteException:
---
java.lang.IllegalStateException: Not connected
        at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:1.8.0_171]
        at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[na:1.8.0_171]
        at com.haulmont.cuba.web.gui.executors.impl.WebBackgroundWorker$WebTaskExecutor.handleDone(WebBackgroundWorker.java:273) ~[cuba-web-6.8.8.jar:6.8.8]
        at com.haulmont.cuba.web.gui.executors.impl.WebBackgroundWorker$WebTaskExecutor$1.lambda$done$0(WebBackgroundWorker.java:187) [cuba-web-6.8.8.jar:6.8.8]
        at com.vaadin.ui.UI.accessSynchronously(UI.java:1392) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.ui.UI$4.run(UI.java:1458) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_171]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_171]
        at com.vaadin.server.VaadinService.runPendingAccessTasks(VaadinService.java:1861) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.VaadinSession.unlock(VaadinSession.java:994) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:1824) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.VaadinService.accessSession(VaadinService.java:1790) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.VaadinSession.access(VaadinSession.java:1399) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.ui.UI.access(UI.java:1455) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.haulmont.cuba.web.gui.executors.impl.WebBackgroundWorker$WebTaskExecutor$1.done(WebBackgroundWorker.java:186) [cuba-web-6.8.8.jar:6.8.8]
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:384) ~[na:1.8.0_171]
        at java.util.concurrent.FutureTask.setException(FutureTask.java:251) ~[na:1.8.0_171]
        at java.util.concurrent.FutureTask.run(FutureTask.java:271) ~[na:1.8.0_171]
        at com.haulmont.cuba.web.gui.executors.impl.WebBackgroundWorker$WebTaskExecutor.lambda$startExecution$1(WebBackgroundWorker.java:371) ~[cuba-web-6.8.8.jar:6.8.8]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_171]
Caused by: com.haulmont.cuba.core.global.RemoteException: Not connected
        at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:129) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor184.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at com.sun.proxy.$Proxy268.fetchAttachments(Unknown Source) ~[na:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94) ~[na:na]
        at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154) ~[cuba-web-6.8.8.jar:6.8.8]
        at com.sun.proxy.$Proxy61.fetchAttachments(Unknown Source) ~[na:na]
        at com.haulmont.addon.imap.web.imapmessage.ImapMessageEdit$InitAttachmentTask.run(ImapMessageEdit.java:123) ~[imap-web-0.1-SNAPSHOT.jar:na]
        at com.haulmont.addon.imap.web.imapmessage.ImapMessageEdit$InitAttachmentTask.run(ImapMessageEdit.java:113) ~[imap-web-0.1-SNAPSHOT.jar:na]
        at com.haulmont.cuba.web.gui.executors.impl.WebBackgroundWorker$WebTaskExecutor.call(WebBackgroundWorker.java:205) ~[cuba-web-6.8.8.jar:6.8.8]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_171]
        ... 4 common frames omitted

Error saving IMAP Configuration

Hi,

I constantly get an error when I try to save a Configuration. I am connecting to a gmail account. The connection works fine and loads the folders. I then click the OK button and get the following error.

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.haulmont.addon.imap.entity.ImapFolder-e3745499-e463-3de1-07b9-4cb5723bbd1a [new].
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:313)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:728)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1521)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1174)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:134)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at com.haulmont.cuba.core.sys.TransactionImpl.commit(TransactionImpl.java:104)
at com.haulmont.cuba.core.app.RdbmsStore.commit(RdbmsStore.java:423)
at com.haulmont.cuba.core.app.DataManagerBean.commit(DataManagerBean.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.haulmont.cuba.core.app.DataManagerBean$SecureDataManagerInvocationHandler.invoke(DataManagerBean.java:362)
at com.sun.proxy.$Proxy326.commit(Unknown Source)
at com.haulmont.cuba.core.app.DataServiceBean.commit(DataServiceBean.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:117)
at sun.reflect.GeneratedMethodAccessor144.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy82.commit(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94)
at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154)
at com.sun.proxy.$Proxy223.commit(Unknown Source)
at com.haulmont.cuba.client.sys.DataManagerClientImpl.commit(DataManagerClientImpl.java:96)
at com.haulmont.cuba.gui.data.impl.GenericDataSupplier.commit(GenericDataSupplier.java:90)
at com.haulmont.cuba.gui.data.impl.DsContextImpl.commit(DsContextImpl.java:165)
at com.haulmont.cuba.gui.components.EditorWindowDelegate.commit(EditorWindowDelegate.java:283)
at com.haulmont.cuba.web.gui.WebWindow$Editor.commitAndClose(WebWindow.java:1755)
at com.haulmont.cuba.gui.components.AbstractEditor.commitAndClose(AbstractEditor.java:109)
at com.haulmont.cuba.gui.components.EditorWindowDelegate$2.actionPerform(EditorWindowDelegate.java:102)
at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:44)
at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:36)
at sun.reflect.GeneratedMethodAccessor184.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163)
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037)
at com.vaadin.ui.Button.fireClick(Button.java:377)
at com.haulmont.cuba.web.toolkit.ui.CubaButton.fireClick(CubaButton.java:54)
at com.vaadin.ui.Button$1.click(Button.java:54)
at sun.reflect.GeneratedMethodAccessor195.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:119)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:444)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:409)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1435)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:361)
at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:300)
at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:191)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107)
at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73)
at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Support for CUBA 6.8.x

Since warnings appear when trying to use the addon in a CUBA app with version 6.8.x it would be great if you update the component to the 6.8.x line.

I could send you a PR, but i'm not sure if you want to release a version for 6.7.x - therefore i thought i will write a issue.

Change field with button to PickerField

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Click Create.
  3. Tick the Use trash folder for removal checkbox in the Advanced section.

The Name of folder to use the trash bin field is implemented as a combination of a button and a simple field (see the attached figure below). Instead of this, the Simple PickerField component should be used (for more details, please refer to CUBA Sampler).

default

[IMAP Configuration] Make Secure Connection field mandatory

It is required to make the Secure Connection field in IMAP Configuration Editor (Menu: Administration → IMAP → IMAP Configuration → Create) mandatory because if a value is not provided and the user tries to connect, the following error occurs:

14:58:44.647 ERROR c.h.a.i.w.i.ImapMailBoxEdit - Connection Error
com.haulmont.addon.imap.exception.ImapException: [javax.mail.MessagingException]Read timed out
        at com.haulmont.addon.imap.api.Imap.fetchFolders(Imap.java:105) ~[na:na]
        at com.haulmont.addon.imap.service.ImapAPIServiceBean.fetchFolders(ImapAPIServiceBean.java:52) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor298.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:117) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor167.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at com.sun.proxy.$Proxy265.fetchFolders(Unknown Source) ~[na:na]
        at sun.reflect.GeneratedMethodAccessor303.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94) ~[na:na]
        at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154) ~[cuba-web-6.8.7.jar:6.8.7]
        at com.sun.proxy.$Proxy61.fetchFolders(Unknown Source) ~[na:na]
        at com.haulmont.addon.imap.web.imapmailbox.helper.FolderRefresher.refreshFolders(FolderRefresher.java:44) ~[imap-web-0.1-SNAPSHOT.jar:na]
        at com.haulmont.addon.imap.web.imapmailbox.ImapMailBoxEdit.checkTheConnection(ImapMailBoxEdit.java:105) ~[imap-web-0.1-SNAPSHOT.jar:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:92) [cuba-gui-6.8.7.jar:6.8.7]
        at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:44) [cuba-web-6.8.7.jar:6.8.7]
        at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:36) [cuba-web-6.8.7.jar:6.8.7]
        at sun.reflect.GeneratedMethodAccessor252.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.ui.Button.fireClick(Button.java:377) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.haulmont.cuba.web.toolkit.ui.CubaButton.fireClick(CubaButton.java:54) ~[cuba-web-6.8.7.jar:6.8.7]
        at com.vaadin.ui.Button$1.click(Button.java:54) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at sun.reflect.GeneratedMethodAccessor254.invoke(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
        at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:119) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:444) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:409) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1435) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:361) ~[vaadin-server-7.7.13.cuba.9.jar:7.7.13.cuba.9]
        at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:300) ~[cuba-web-6.8.7.jar:6.8.7]
        at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:191) ~[cuba-web-6.8.7.jar:6.8.7]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[servlet-api.jar:na]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.23]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-websocket.jar:8.5.23]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.23]
        at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
        at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:107) ~[cuba-web-6.8.7.jar:6.8.7]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[catalina.jar:8.5.23]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) ~[catalina.jar:8.5.23]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) ~[catalina.jar:8.5.23]
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650) ~[catalina.jar:8.5.23]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) ~[catalina.jar:8.5.23]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) ~[catalina.jar:8.5.23]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) ~[tomcat-coyote.jar:8.5.23]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-coyote.jar:8.5.23]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-coyote.jar:8.5.23]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) ~[tomcat-coyote.jar:8.5.23]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:8.5.23]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_171]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:8.5.23]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_171]

[IMAP Configuration] Events for the first folder are duplicated

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Click Create.
  3. Fill in the required fields.
  4. Click the Connect button

ER: Once the connection is successfully established, folders should appear in the corresponding table, they all should be active and all events should be enabled for each folder.
AR: Events for the first folder are duplicated for several times (my guess is that the number of duplicates for each event corresponds to the number of folders).
default

[IMAP Connection] Add Refresh button to folders table

It is required to add the Refresh action button to the table of folders, because there is no need to download all folders every time a configuration is edited (currently, it takes over a minute and this amount of waiting time is absolutely unacceptable).

Improve localization of attachment titles

Preconditions:

  • Create a connection with the imap.yandex.ru host.

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Message Browser.
  2. Open an email that contains an attachment with a title is in Cyrillic.
  3. Open the Attachments tab.

Expected Result: Cyrillic letters are displayed properly.
Actual Result:
image

Improve downloading speed

Currently, the elements listed below are downloaded very slowly:

  1. The table of folders in IMAP Configuration Editor (Menu: Administration → IMAP → IMAP Configuration → Edit).
  2. Email bodies (Menu: Administration → IMAP → IMAP Message Browser → View).
  3. Emails (Menu: Administration → IMAP → IMAP Message Browser).

[IMAP Message Browser] Only messages from enabled folders should be shown

Preconditions:

  • An IMAP configuration should be created in the system.
  • Several folders should be active (it is easier to check when only one or two are enabled).

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Message Browser.
    ER: All emails from the active folders are displayed.
  2. Open Menu: Administration → IMAP → IMAP Configuration.
  3. Edit the configuration.
  4. Enable one or two other folders and disable those ones that were active previously.
  5. Open Menu: Administration → IMAP → IMAP Message Browser.
  6. Click the Search button in the Filter area.
    ER: Only emails from active folders are displayed.
    AR: All emails from both active and previously active folders are shown.

Bottom of "IMAP Configuration Edit" page is not visible

Bottom of "IMAP Configuration Edit" page with folders and events configuration blocks is not visible in case of low resolution screens. Wrapping entire layout with scrolling breaks the folders table rendering for first connection (only first row is visible).

Optimisation of IMAP communications

  1. parallel & forkJoin -> explicit executors
  2. avoid extra fetch of message in newMessagesTask
  3. make scheduler ticks more frequently
  4. check for modifications from IMAP

@Component EventListener is not found

When i tried to create an EventListener, the first thing that i tried was to create a Spring Bean via @component. Just like that:

@Component("app_myListener")
public class MyListener {

    @EventListener
    public void doIt(NewEmailImapEvent myEvent) {
        //do your stuff
    }
}

But in the UI it was not picked up and therefore not selectable. Only when I created a Service with a corresponding Service Interface it worked perfectly.

I think it has to do with the fact, that the Lookup mechanism searches for all methods in the interfaces the bean implements (perhaps this is even CUBA core logic). Perhaps you can just confirm that a Service has to be used. Would be totally ok for me. But if i'm just doing something wrong here, you might point me into the right direction.

Thx

Table names too long for Oracle RDBMS

When I look into the Entities there are Table names like

  • IMAPCOMPONENT_IMAP_SIMPLE_AUTHENTICATION (40 chars)
  • IMAPCOMPONENT_IMAP_MESSAGE_ATTACHMENT (37 chars)

These table names will not work for the Oracle RDBMS. As the name has to globally be defined via the @Table annotation, it is not easily possible to change that afterwards. So perhaps it makes sense to now (even before supporting other RDBMS like Oracle) change the prefix so that you'll not bounce against this 32 chars limit of oracle afterwards.

IMAP Configuration changes

  • Rename 'IMAP MailBox editor' to 'IMAP Configuration editor'
  • Rename 'Cuba custom flag to mark and filter messages' to 'Custom flag' and add description notification
  • Add description to 'Update slice size' field
  • Move options 'Custom flag' and 'Update slice size' to 'Advanced' collpsed groupbox

IMAP configuration is not saved without refreshing table of folders

Preconditions:

  • An IMAP configuration should be created.

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Select the configuration.
  3. Click Edit.
  4. Click OK.

Expected Result:
There is no need to connect to an email server again because now there is the Refresh button available on the screen. If some changes were made, they should be saved just by clicking the OK button.

Actual Result: The system expects the connection to an email server (the corresponding notification is displayed) even if no changes were made. There is a workaround for this issue — to refresh the table of folders. After that, IMAP Configuration Editor is closed by clicking OK. However, this method is nor obvious, neither user-friendly.

[IMAP Configuration] Add ability to specify configuration name

It is required to add the Configuration Name field to the Basic section of IMAP Configuration Editor. This field should be mandatory.

Also, this attribute should be added as a column to the table in IMAP Message Browser.
This is necessary for better understanding to which mailbox each message belongs, because some connections may have similar folder names.

[IMAP Connection] Add items for disabling and enabling folders to context menu

  1. Open Menu: Administration → IMAP → IMAP Configuration.
  2. Create/Edit a configuration.

In the context menu (opened by right-clicking the checkbox that activates a folder), add the following options:

  • Enable — enables only a selected folder.
  • Enable with Children — enables a selected folder and its children.
  • Disable — disables only a selected folder.
  • Disable with Children — disabled a selected folder and its children.

Viewing Email doesn't work

Hi,

I'm trying out the latest version of this add-on and I cannot view emails. No errors are thrown and noting seems to appear in the logs it just sits there waiting. I cannot view either from the Demo screen or the IMAP Message Browser screen which doesn't open at all.

Very rarely will any new messages appear in the Demo screen.

I am using a Gmail account in my testing.

[Email Viewer][Cosmetics] Size of attachments table should be fixed

Steps to reproduce:

  1. Open Menu: Administration → IMAP → IMAP Message Browser.
  2. View an email.
  3. Go to the Attachments tab.

ER: The table displayed on the Attachments tab should be of the same size as the first column in the field group (see the figure below).

default

AR: The table size is not fixed at all and changes when changing the size of columns (see this GIF).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.