Author: kmorin Date: 2014-05-21 21:52:19 +0200 (Wed, 21 May 2014) New Revision: 87 Url: http://forge.codelutin.com/projects/faxtomail/repository/revisions/87 Log: refs #4657 [TECH] Int?\195?\169gration EDI transfert du fichier par un cron (?\195?\160 tester) ajout de la colonne quantit?\195?\169 de devis dans la popup de calcul des quantit?\195?\169s Added: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/EDIManagementJob.java trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java Removed: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/MailFilterJob.java Modified: trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java trunk/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/QuantitiesByRangeUIHandler.java trunk/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailApplicationListener.java Modified: trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java =================================================================== --- trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java 2014-05-21 19:30:41 UTC (rev 86) +++ trunk/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java 2014-05-21 19:52:19 UTC (rev 87) @@ -204,8 +204,8 @@ && email.getClient() != null && email.getDemandType() != null && email.getProjectReference() != null) { - email.setDemandStatus(DemandStatus.IN_PROGRESS); - transmitDemandToEdi(email); + email.setDemandStatus(DemandStatus.TRANSMITTED_TO_EDI); +// transmitDemandToEdi(email); } History history; @@ -239,18 +239,29 @@ return result; } + public void transmitPendingDemandsToEdi() { + EmailTopiaDao dao = getPersistenceContext().getEmailDao(); + + List<Email> toTransmitToEdi = dao.forDemandStatusEquals(DemandStatus.TRANSMITTED_TO_EDI).findAll(); + for (Email email : toTransmitToEdi) { + transmitDemandToEdi(email); + } + } + /** * Generate txt file to send demand to EDI system. * * @param email email to send */ protected void transmitDemandToEdi(Email email) { - Preconditions.checkArgument(email.getDemandStatus() == DemandStatus.IN_PROGRESS); + Preconditions.checkArgument(email.getDemandStatus() == DemandStatus.TRANSMITTED_TO_EDI); if (CollectionUtils.isEmpty(email.getRangeRow())) { return; } + //TODO kmorin 20140521 maybe check if the file is not being read + // get output file with pattern name depending on date Date now = serviceContext.getNow(); File ediDirectory = getApplicationConfig().getEdiDirectory(); Modified: trunk/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/QuantitiesByRangeUIHandler.java =================================================================== --- trunk/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/QuantitiesByRangeUIHandler.java 2014-05-21 19:30:41 UTC (rev 86) +++ trunk/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/QuantitiesByRangeUIHandler.java 2014-05-21 19:52:19 UTC (rev 87) @@ -67,6 +67,10 @@ newTableCellRender(Range.class), RangeTableModel.RANGE_COLUMN); addIntegerColumnToModel(columnModel, + RangeTableModel.QUOTATION_QUANTITY_COLUMN, + null, + table); + addIntegerColumnToModel(columnModel, RangeTableModel.PRODUCT_QUANTITY_COLUMN, null, table); Modified: trunk/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties =================================================================== --- trunk/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties 2014-05-21 19:30:41 UTC (rev 86) +++ trunk/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties 2014-05-21 19:52:19 UTC (rev 87) @@ -1,3 +1,5 @@ +\ |\ = +\:= X= application.action.create.error= application.error.ui.business.warning= Modified: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailApplicationListener.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailApplicationListener.java 2014-05-21 19:30:41 UTC (rev 86) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/FaxToMailApplicationListener.java 2014-05-21 19:52:19 UTC (rev 87) @@ -27,6 +27,8 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; +import com.franciaflex.faxtomail.web.job.EDIManagementJob; +import com.franciaflex.faxtomail.web.job.MailFilterJob; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.CronScheduleBuilder; @@ -76,25 +78,40 @@ data.put(MailFilterJob.SERVICE_CONTEXT, serviceContext); - JobDetail job = JobBuilder.newJob(MailFilterJob.class) - .usingJobData(data) - .withIdentity("faxToMailJobs", "job1") - .build(); + JobDetail mailFilteringJob = JobBuilder.newJob(MailFilterJob.class) + .usingJobData(data) + .withIdentity("faxToMailJobs", "mailFilteringJob") + .build(); + JobDetail ediManagementJob = JobBuilder.newJob(EDIManagementJob.class) + .usingJobData(data) + .withIdentity("faxToMailJobs", "ediManagementJob") + .build(); + try { Trigger trigger = TriggerBuilder - .newTrigger() - .withIdentity("mailFiltering", "trigger1") -// .withSchedule(CronScheduleBuilder.cronSchedule("* 0/1 * * * ?")) - .withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?")) - .build(); + .newTrigger() + .withIdentity("mailFiltering", "mailFilteringTrigger") +// .withSchedule(CronScheduleBuilder.cronSchedule("* 0/1 * * * ?")) + .withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?")) + .build(); Scheduler scheduler = new StdSchedulerFactory().getScheduler(); scheduler.start(); - scheduler.scheduleJob(job, trigger); + scheduler.scheduleJob(mailFilteringJob, trigger); - log.debug("scheduler launched"); + trigger = TriggerBuilder + .newTrigger() + .withIdentity("ediManagement", "ediManagementTrigger") + .withSchedule(CronScheduleBuilder.cronSchedule("* 0/5 * * * ?")) + .build(); + scheduler = new StdSchedulerFactory().getScheduler(); + scheduler.start(); + scheduler.scheduleJob(ediManagementJob, trigger); + + log.debug("schedulers launched"); + } catch (SchedulerException e) { log.error("Error while launching the mail filter job", e); } Deleted: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/MailFilterJob.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/MailFilterJob.java 2014-05-21 19:30:41 UTC (rev 86) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/MailFilterJob.java 2014-05-21 19:52:19 UTC (rev 87) @@ -1,350 +0,0 @@ -package com.franciaflex.faxtomail.web; - -/* - * #%L - * FaxToMail :: Web - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2014 Franciaflex, Code Lutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - -import static org.nuiton.i18n.I18n.t; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.Enumeration; -import java.util.List; -import java.util.Properties; - -import javax.activation.DataHandler; -import javax.activation.DataSource; -import javax.mail.Address; -import javax.mail.BodyPart; -import javax.mail.Flags; -import javax.mail.Folder; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Part; -import javax.mail.Session; -import javax.mail.Store; -import javax.mail.URLName; -import javax.mail.internet.ContentType; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; -import javax.mail.internet.MimeUtility; - -import org.apache.commons.io.Charsets; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.Decorator; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; - -import com.franciaflex.faxtomail.persistence.entities.Attachment; -import com.franciaflex.faxtomail.persistence.entities.AttachmentFile; -import com.franciaflex.faxtomail.persistence.entities.AttachmentImpl; -import com.franciaflex.faxtomail.persistence.entities.DemandStatus; -import com.franciaflex.faxtomail.persistence.entities.Email; -import com.franciaflex.faxtomail.persistence.entities.EmailAccount; -import com.franciaflex.faxtomail.persistence.entities.EmailImpl; -import com.franciaflex.faxtomail.persistence.entities.MailFolder; -import com.franciaflex.faxtomail.services.DecoratorService; -import com.franciaflex.faxtomail.services.FaxToMailServiceContext; -import com.franciaflex.faxtomail.services.service.CompanyService; -import com.franciaflex.faxtomail.services.service.EmailService; -import com.franciaflex.faxtomail.services.service.MailFolderService; - -/** - * @author Kevin Morin (Code Lutin) - * @since x.x - */ -public class MailFilterJob implements Job { - - private static final Log log = LogFactory.getLog(MailFilterJob.class); - - public static final String SERVICE_CONTEXT = "serviceContext"; - - protected FaxToMailServiceContext serviceContext; - - //TODO kmorin 20140414 handle imap protocol - @Override - public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { - serviceContext = (FaxToMailServiceContext) jobExecutionContext.getMergedJobDataMap().get(SERVICE_CONTEXT); - - CompanyService companyService = serviceContext.newService(CompanyService.class); - Collection<EmailAccount> emailAccounts = companyService.getEmailAccounts(); - - for (EmailAccount account : emailAccounts) { - if ("pop3".equals(account.getProtocol().toLowerCase())) { - checkEmailsOnPop3(account); - } - } - } - - /** - * Checks the emails of the account - * @param account - */ - public void checkEmailsOnPop3(EmailAccount account) { - Properties properties = new Properties(); - properties.setProperty("mail.store.protocol", "pop3"); - properties.setProperty("mail.pop3.host", account.getHost()); - properties.setProperty("mail.pop3.user", account.getLogin()); - - Session session = Session.getInstance(properties); - Store store = null; - Folder defaultFolder = null; - Folder inbox = null; - - try { - store = session.getStore(new URLName("pop3://" + account.getHost())); - store.connect(account.getLogin(), account.getPassword()); - defaultFolder = store.getDefaultFolder(); - inbox = defaultFolder.getFolder("INBOX"); - checkEmailsOfFolder(inbox); - - } catch (Exception e) { - log.error("Error while getting emails from the mailbox", e); - - } finally { - close(inbox); - close(defaultFolder); - try { - if (store != null && store.isConnected()) { - store.close(); - } - } catch (MessagingException e) { - log.error("Error while closing the store", e); - } - } - - } - - protected void close(Folder folder) { - if (folder != null && folder.isOpen()) { - try { - // TODO 20140414 kmorin close(true) in production - folder.close(false); // false -> On n'efface pas les messages marqués DELETED - - } catch (Exception e) { - log.error("Error while closing the folder", e); - } - } - } - - /** - * Check the emails of teh folder, create the emails in the database and delete the email in the folder - * @param folder the folder to check - */ - protected void checkEmailsOfFolder(Folder folder) { - try { - folder.open(Folder.READ_WRITE); - - int count = folder.getMessageCount(); - int unread = folder.getUnreadMessageCount(); - - log.debug(count + " messages, " + unread + " unread"); - - EmailService emailService = serviceContext.newService(EmailService.class); - - for (int i = 0 ; i < count ; i++) { - Email email = new EmailImpl(); - emailService.saveEmail(email, null); - - int messageNumber = count - i; - Message message = folder.getMessage(messageNumber); - - Charset charset = getCharset(message); - - List<String> modifiedProperties = new ArrayList<>(); - -// log.debug("Object: " + message.getSubject()); -// email.s(message.getSubject()); -// modifiedProperties.add(Email.PROPERTY_OBJECT); - - Address[] addresses = message.getFrom(); - if (addresses != null && addresses.length > 0) { - email.setSender(addresses[0].toString()); - modifiedProperties.add(Email.PROPERTY_SENDER); - } - - List<Address> recipients = new ArrayList<>(); - Address[] toRecipients = message.getRecipients(Message.RecipientType.TO); - if (toRecipients != null) { - recipients.addAll(Arrays.asList(toRecipients)); - } - Address[] ccRecipients = message.getRecipients(Message.RecipientType.CC); - if (ccRecipients != null) { - recipients.addAll(Arrays.asList(ccRecipients)); - } - - for (Address address : recipients) { - String recipient = address.toString(); - MailFolder mailFolder = serviceContext.newService(MailFolderService.class).getFolderForRecipient(recipient); - - log.debug("\tTo : " + address + " -> " + (mailFolder != null ? mailFolder.getName() : "none")); - - if (mailFolder != null) { - email.setRecipient(recipient); - email.setMailFolder(mailFolder); - modifiedProperties.add(Email.PROPERTY_RECIPIENT); - modifiedProperties.add(Email.PROPERTY_MAIL_FOLDER); - break; - } - } - - Date receivedDate = message.getReceivedDate(); - if (receivedDate == null) { - receivedDate = message.getSentDate(); - } - email.setReceptionDate(receivedDate); - modifiedProperties.add(Email.PROPERTY_RECEPTION_DATE); - - Date now = new Date(); - - DecoratorService decoratorService = serviceContext.newService(DecoratorService.class); - Decorator<Date> dateDecorator = decoratorService.getDecoratorByType(Date.class, DecoratorService.DATE); - String projectRef = t("faxtomail.email.projectReference.default", dateDecorator.toString(now)); - email.setProjectReference(projectRef); - modifiedProperties.add(Email.PROPERTY_PROJECT_REFERENCE); - - email.setDemandStatus(DemandStatus.UNTREATED); - modifiedProperties.add(Email.PROPERTY_DEMAND_STATUS); - - StringBuilder emailSource = new StringBuilder(); - Enumeration<String> headerLines = ((MimeMessage)message).getAllHeaderLines(); - while (headerLines.hasMoreElements()) { - String headerLine = headerLines.nextElement(); - emailSource.append(headerLine).append("\n"); - } - String originalContent = IOUtils.toString(message.getInputStream(), charset); - emailSource.append("\n").append(originalContent); - email.setOriginalEmail(emailSource.toString()); - - if (message.isMimeType("multipart/*")) { - decomposeMultipartEmail(message, email, emailService); -// } else { -// String content = IOUtils.toString(message.getInputStream(), charset); -// email.setPlainContent(content); - } - - emailService.saveEmail(email, null, modifiedProperties.toArray(new String[modifiedProperties.size()])); - - message.setFlag(Flags.Flag.DELETED, true); - } - log.debug("End of emails"); - - } catch (Exception e) { - log.error("Error while reading the emails", e); - } - } - - /** - * Decompose a multipart part. - * - sets the email content if the part contains a text bodypart - * - adds attachments to the email - * - * @param part the part to decompose - * @param email the email object to fill with the attachments or content - * @param emailService email service - * @throws Exception - */ - protected void decomposeMultipartEmail(Part part, Email email, EmailService emailService) throws Exception { - DataSource dataSource = part.getDataHandler().getDataSource(); - MimeMultipart mimeMultipart = new MimeMultipart(dataSource); - int multiPartCount = mimeMultipart.getCount(); - - for (int j = 0; j < multiPartCount; j++) { - BodyPart bp = mimeMultipart.getBodyPart(j); - Charset charset = getCharset(bp); - - // if it is a text part, the,n this is the email content - String disposition = bp.getDisposition(); - if (bp.isMimeType("text/*") && !Part.ATTACHMENT.equals(disposition)) { -// String content = IOUtils.toString(bp.getInputStream(), charset); -// if (bp.isMimeType("text/plain")) { -// email.setPlainContent(content); -// } else { -// email.setHtmlContent(content); -// } - - // if it is multipart part, decompose it - } else if (bp.isMimeType("multipart/*")) { - decomposeMultipartEmail(bp, email, emailService); - - // else, this is an attachment - } else { - String fileName = bp.getFileName(); - if (fileName == null) { - String[] headers = bp.getHeader("Content-ID"); - if (headers == null) { - break; - } - fileName = headers[0]; - // remove the guillemets between the id - fileName = fileName.replaceFirst("^<(.*)>$", "$1"); - } - - try { - fileName = MimeUtility.decodeText(fileName); - log.debug("FileName : " + fileName); - } catch (UnsupportedEncodingException ex) { - // don't care, use filename raw value - if (log.isWarnEnabled()) { - log.warn("Can't debug email file name", ex); - } - } - - File dir = new File(FileUtils.getTempDirectory(), email.getTopiaId()); - if (!dir.exists()) { - dir.mkdir(); - } - File file = new File(dir, fileName); - FileOutputStream fos = new FileOutputStream(file); - - DataHandler dh = bp.getDataHandler(); - dh.writeTo(fos); - - Attachment attachment = new AttachmentImpl(); - attachment.setAddedByUser(false); - AttachmentFile attachmentFile = emailService.getAttachmentFileFromStream(dh.getInputStream()); - attachmentFile.setFilename(dh.getName()); - attachment.setOriginalFile(attachmentFile); - - email.addAttachment(attachment); - } - } - } - - protected Charset getCharset(Part part) throws MessagingException { - ContentType contentType = new ContentType(part.getContentType()); - String charsetName = contentType.getParameter("charset"); - Charset charset = Charsets.toCharset(charsetName); - return charset; - } -} Added: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/EDIManagementJob.java =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/EDIManagementJob.java (rev 0) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/EDIManagementJob.java 2014-05-21 19:52:19 UTC (rev 87) @@ -0,0 +1,57 @@ +package com.franciaflex.faxtomail.web.job; + +/* + * #%L + * FaxToMail :: Web + * $Id: MailFilterJob.java 82 2014-05-20 14:25:32Z echatellier $ + * $HeadURL: https://svn.codelutin.com/faxtomail/trunk/faxtomail-ui-web/src/main/java/com... $ + * %% + * Copyright (C) 2014 Franciaflex, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.franciaflex.faxtomail.services.FaxToMailServiceContext; +import com.franciaflex.faxtomail.services.service.EmailService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * @author Kevin Morin (Code Lutin) + * @since x.x + */ +public class EDIManagementJob implements Job { + + private static final Log log = LogFactory.getLog(EDIManagementJob.class); + + public static final String SERVICE_CONTEXT = "serviceContext"; + + protected FaxToMailServiceContext serviceContext; + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + serviceContext = (FaxToMailServiceContext) jobExecutionContext.getMergedJobDataMap().get(SERVICE_CONTEXT); + + EmailService emailService = serviceContext.newService(EmailService.class); + emailService.transmitPendingDemandsToEdi(); + + //TODO kmorin 20140521 check in the transfert table if new command number arrived + } + +} Copied: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java (from rev 84, trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/MailFilterJob.java) =================================================================== --- trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java (rev 0) +++ trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java 2014-05-21 19:52:19 UTC (rev 87) @@ -0,0 +1,350 @@ +package com.franciaflex.faxtomail.web.job; + +/* + * #%L + * FaxToMail :: Web + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2014 Franciaflex, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import static org.nuiton.i18n.I18n.t; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Enumeration; +import java.util.List; +import java.util.Properties; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.mail.Address; +import javax.mail.BodyPart; +import javax.mail.Flags; +import javax.mail.Folder; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Part; +import javax.mail.Session; +import javax.mail.Store; +import javax.mail.URLName; +import javax.mail.internet.ContentType; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.internet.MimeUtility; + +import org.apache.commons.io.Charsets; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.Decorator; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import com.franciaflex.faxtomail.persistence.entities.Attachment; +import com.franciaflex.faxtomail.persistence.entities.AttachmentFile; +import com.franciaflex.faxtomail.persistence.entities.AttachmentImpl; +import com.franciaflex.faxtomail.persistence.entities.DemandStatus; +import com.franciaflex.faxtomail.persistence.entities.Email; +import com.franciaflex.faxtomail.persistence.entities.EmailAccount; +import com.franciaflex.faxtomail.persistence.entities.EmailImpl; +import com.franciaflex.faxtomail.persistence.entities.MailFolder; +import com.franciaflex.faxtomail.services.DecoratorService; +import com.franciaflex.faxtomail.services.FaxToMailServiceContext; +import com.franciaflex.faxtomail.services.service.CompanyService; +import com.franciaflex.faxtomail.services.service.EmailService; +import com.franciaflex.faxtomail.services.service.MailFolderService; + +/** + * @author Kevin Morin (Code Lutin) + * @since x.x + */ +public class MailFilterJob implements Job { + + private static final Log log = LogFactory.getLog(MailFilterJob.class); + + public static final String SERVICE_CONTEXT = "serviceContext"; + + protected FaxToMailServiceContext serviceContext; + + //TODO kmorin 20140414 handle imap protocol + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + serviceContext = (FaxToMailServiceContext) jobExecutionContext.getMergedJobDataMap().get(SERVICE_CONTEXT); + + CompanyService companyService = serviceContext.newService(CompanyService.class); + Collection<EmailAccount> emailAccounts = companyService.getEmailAccounts(); + + for (EmailAccount account : emailAccounts) { + if ("pop3".equals(account.getProtocol().toLowerCase())) { + checkEmailsOnPop3(account); + } + } + } + + /** + * Checks the emails of the account + * @param account + */ + public void checkEmailsOnPop3(EmailAccount account) { + Properties properties = new Properties(); + properties.setProperty("mail.store.protocol", "pop3"); + properties.setProperty("mail.pop3.host", account.getHost()); + properties.setProperty("mail.pop3.user", account.getLogin()); + + Session session = Session.getInstance(properties); + Store store = null; + Folder defaultFolder = null; + Folder inbox = null; + + try { + store = session.getStore(new URLName("pop3://" + account.getHost())); + store.connect(account.getLogin(), account.getPassword()); + defaultFolder = store.getDefaultFolder(); + inbox = defaultFolder.getFolder("INBOX"); + checkEmailsOfFolder(inbox); + + } catch (Exception e) { + log.error("Error while getting emails from the mailbox", e); + + } finally { + close(inbox); + close(defaultFolder); + try { + if (store != null && store.isConnected()) { + store.close(); + } + } catch (MessagingException e) { + log.error("Error while closing the store", e); + } + } + + } + + protected void close(Folder folder) { + if (folder != null && folder.isOpen()) { + try { + // TODO 20140414 kmorin close(true) in production + folder.close(false); // false -> On n'efface pas les messages marqués DELETED + + } catch (Exception e) { + log.error("Error while closing the folder", e); + } + } + } + + /** + * Check the emails of teh folder, create the emails in the database and delete the email in the folder + * @param folder the folder to check + */ + protected void checkEmailsOfFolder(Folder folder) { + try { + folder.open(Folder.READ_WRITE); + + int count = folder.getMessageCount(); + int unread = folder.getUnreadMessageCount(); + + log.debug(count + " messages, " + unread + " unread"); + + EmailService emailService = serviceContext.newService(EmailService.class); + + for (int i = 0 ; i < count ; i++) { + Email email = new EmailImpl(); + emailService.saveEmail(email, null); + + int messageNumber = count - i; + Message message = folder.getMessage(messageNumber); + + Charset charset = getCharset(message); + + List<String> modifiedProperties = new ArrayList<>(); + +// log.debug("Object: " + message.getSubject()); +// email.s(message.getSubject()); +// modifiedProperties.add(Email.PROPERTY_OBJECT); + + Address[] addresses = message.getFrom(); + if (addresses != null && addresses.length > 0) { + email.setSender(addresses[0].toString()); + modifiedProperties.add(Email.PROPERTY_SENDER); + } + + List<Address> recipients = new ArrayList<>(); + Address[] toRecipients = message.getRecipients(Message.RecipientType.TO); + if (toRecipients != null) { + recipients.addAll(Arrays.asList(toRecipients)); + } + Address[] ccRecipients = message.getRecipients(Message.RecipientType.CC); + if (ccRecipients != null) { + recipients.addAll(Arrays.asList(ccRecipients)); + } + + for (Address address : recipients) { + String recipient = address.toString(); + MailFolder mailFolder = serviceContext.newService(MailFolderService.class).getFolderForRecipient(recipient); + + log.debug("\tTo : " + address + " -> " + (mailFolder != null ? mailFolder.getName() : "none")); + + if (mailFolder != null) { + email.setRecipient(recipient); + email.setMailFolder(mailFolder); + modifiedProperties.add(Email.PROPERTY_RECIPIENT); + modifiedProperties.add(Email.PROPERTY_MAIL_FOLDER); + break; + } + } + + Date receivedDate = message.getReceivedDate(); + if (receivedDate == null) { + receivedDate = message.getSentDate(); + } + email.setReceptionDate(receivedDate); + modifiedProperties.add(Email.PROPERTY_RECEPTION_DATE); + + Date now = new Date(); + + DecoratorService decoratorService = serviceContext.newService(DecoratorService.class); + Decorator<Date> dateDecorator = decoratorService.getDecoratorByType(Date.class, DecoratorService.DATE); + String projectRef = t("faxtomail.email.projectReference.default", dateDecorator.toString(now)); + email.setProjectReference(projectRef); + modifiedProperties.add(Email.PROPERTY_PROJECT_REFERENCE); + + email.setDemandStatus(DemandStatus.UNTREATED); + modifiedProperties.add(Email.PROPERTY_DEMAND_STATUS); + + StringBuilder emailSource = new StringBuilder(); + Enumeration<String> headerLines = ((MimeMessage)message).getAllHeaderLines(); + while (headerLines.hasMoreElements()) { + String headerLine = headerLines.nextElement(); + emailSource.append(headerLine).append("\n"); + } + String originalContent = IOUtils.toString(message.getInputStream(), charset); + emailSource.append("\n").append(originalContent); + email.setOriginalEmail(emailSource.toString()); + + if (message.isMimeType("multipart/*")) { + decomposeMultipartEmail(message, email, emailService); +// } else { +// String content = IOUtils.toString(message.getInputStream(), charset); +// email.setPlainContent(content); + } + + emailService.saveEmail(email, null, modifiedProperties.toArray(new String[modifiedProperties.size()])); + + message.setFlag(Flags.Flag.DELETED, true); + } + log.debug("End of emails"); + + } catch (Exception e) { + log.error("Error while reading the emails", e); + } + } + + /** + * Decompose a multipart part. + * - sets the email content if the part contains a text bodypart + * - adds attachments to the email + * + * @param part the part to decompose + * @param email the email object to fill with the attachments or content + * @param emailService email service + * @throws Exception + */ + protected void decomposeMultipartEmail(Part part, Email email, EmailService emailService) throws Exception { + DataSource dataSource = part.getDataHandler().getDataSource(); + MimeMultipart mimeMultipart = new MimeMultipart(dataSource); + int multiPartCount = mimeMultipart.getCount(); + + for (int j = 0; j < multiPartCount; j++) { + BodyPart bp = mimeMultipart.getBodyPart(j); + Charset charset = getCharset(bp); + + // if it is a text part, the,n this is the email content + String disposition = bp.getDisposition(); + if (bp.isMimeType("text/*") && !Part.ATTACHMENT.equals(disposition)) { +// String content = IOUtils.toString(bp.getInputStream(), charset); +// if (bp.isMimeType("text/plain")) { +// email.setPlainContent(content); +// } else { +// email.setHtmlContent(content); +// } + + // if it is multipart part, decompose it + } else if (bp.isMimeType("multipart/*")) { + decomposeMultipartEmail(bp, email, emailService); + + // else, this is an attachment + } else { + String fileName = bp.getFileName(); + if (fileName == null) { + String[] headers = bp.getHeader("Content-ID"); + if (headers == null) { + break; + } + fileName = headers[0]; + // remove the guillemets between the id + fileName = fileName.replaceFirst("^<(.*)>$", "$1"); + } + + try { + fileName = MimeUtility.decodeText(fileName); + log.debug("FileName : " + fileName); + } catch (UnsupportedEncodingException ex) { + // don't care, use filename raw value + if (log.isWarnEnabled()) { + log.warn("Can't debug email file name", ex); + } + } + + File dir = new File(FileUtils.getTempDirectory(), email.getTopiaId()); + if (!dir.exists()) { + dir.mkdir(); + } + File file = new File(dir, fileName); + FileOutputStream fos = new FileOutputStream(file); + + DataHandler dh = bp.getDataHandler(); + dh.writeTo(fos); + + Attachment attachment = new AttachmentImpl(); + attachment.setAddedByUser(false); + AttachmentFile attachmentFile = emailService.getAttachmentFileFromStream(dh.getInputStream()); + attachmentFile.setFilename(dh.getName()); + attachment.setOriginalFile(attachmentFile); + + email.addAttachment(attachment); + } + } + } + + protected Charset getCharset(Part part) throws MessagingException { + ContentType contentType = new ContentType(part.getContentType()); + String charsetName = contentType.getParameter("charset"); + Charset charset = Charsets.toCharset(charsetName); + return charset; + } +} Property changes on: trunk/faxtomail-ui-web/src/main/java/com/franciaflex/faxtomail/web/job/MailFilterJob.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native