This is an automated email from the git hooks/post-receive script. New commit to branch develop-1.1.x in repository faxtomail. See https://gitlab.nuiton.org/codelutin/faxtomail.git commit f99710cf4625416be22298f1a9f495ff54f73891 Author: jcouteau <couteau@codelutin.com> Date: Thu Mar 17 15:18:51 2022 +0100 Rendu html correct pour les réponses --- .../faxtomail/services/service/EmailService.java | 14 ++++ .../services/service/EmailServiceImpl.java | 85 ++++++++++++++++++++++ .../ui/swing/actions/OpenReplyAction.java | 1 + .../demande/replies/DemandRepliesUIHandler.java | 1 + .../ui/swing/content/reply/ReplyFormUIHandler.java | 47 ++++++++++-- .../ui/swing/content/reply/ReplyFormUIModel.java | 12 +++ .../faxtomail/ui/swing/util/FaxToMailUIUtil.java | 22 ++++++ .../i18n/faxtomail-ui-swing_fr_FR.properties | 1 + 8 files changed, 177 insertions(+), 6 deletions(-) diff --git a/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java b/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java index 0b55ee08..7f8c89d4 100644 --- a/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java +++ b/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailService.java @@ -44,6 +44,7 @@ import com.franciaflex.faxtomail.services.service.exceptions.FolderNotReadableEx import com.franciaflex.faxtomail.services.service.exceptions.InvalidClientException; import com.franciaflex.faxtomail.services.service.imports.ArchiveImportResult; import com.itextpdf.text.DocumentException; +import org.apache.commons.httpclient.URIException; import org.apache.commons.mail.EmailException; import org.nuiton.util.pagination.PaginationParameter; import org.nuiton.util.pagination.PaginationResult; @@ -189,4 +190,17 @@ public interface EmailService extends FaxToMailService { * @throws IOException */ Attachment convertHTMLToPdf(List<Attachment> attachments, List<String> content, String name) throws IOException; + + /** + * + * WARNING, must call deleteTempAttachmentFiles afterwards so temp directory does not grow indefinitely ! + * Could not be integrated in this method as on transfer, it deletes attachment before really using it + * + * @param attachments list of attachments that might be present in c + * @param contentList email html content + * @return email html content with attachments and inline attachments curated + */ + String extractHtmlContent(List<Attachment> attachments, List<String> contentList) throws URIException; + + void deleteTempAttachmentFiles(List<Attachment> attachments); } diff --git a/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java b/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java index 55ea1d28..65781b0f 100644 --- a/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java +++ b/faxtomail-service/src/main/java/com/franciaflex/faxtomail/services/service/EmailServiceImpl.java @@ -102,6 +102,7 @@ import gui.ava.html.Html2Image; import gui.ava.html.renderer.ImageRenderer; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.Predicate; +import org.apache.commons.httpclient.URIException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; @@ -2377,4 +2378,88 @@ public class EmailServiceImpl extends FaxToMailServiceSupport implements EmailSe return result; } + + /** + * + * WARNING, must call deleteTempAttachmentFiles afterwards so temp directory does not grow indefinitely ! + * Could not be integrated in this method as on transfer, it deletes attachment before really using it + * + * @param attachments list of attachments that might be present in c + * @param contentList email html content + * @return email html content with attachments and inline attachments curated + */ + public String extractHtmlContent(List<Attachment> attachments, List<String> contentList) throws URIException { + + + List<String> contents = new ArrayList<>(); + + if (contentList != null) { + for (String content : contentList) { + content = content.replaceAll("<meta (.*?)>(</meta>)?", ""); + // remove the images whose sources are on the filesystem of the sender (yes, it happens...) + // cf #6996 + content = content.replaceAll("(\\w+)=([\"'])file://.*?([\"'])", ""); + + for (Attachment attachment : attachments) { + String key = attachment.getContentId(); + if (key == null) { + key = attachment.getOriginalFileName(); + } + + // get file content + AttachmentFile attachmentFile = attachment.getOriginalFile(); + if (attachmentFile != null) { + File file = attachmentFile.getFile(); + + // replace the inline attachments with the extracted attachment file url + // match les patterns: + // <td background="cid:bg.gif" height="52"> + // <img border=0 src="cid:bg.gif" /> + // <img src='cid:5e9ef859-ea65-4f9b-a9fa-30d4a2c5837c' + content = content.replaceAll("(\\w+)=([\"'])cid:" + Pattern.quote(key) + "([\"'])", "$1=$2" + file.toURI() + "$3"); + + if (log.isDebugEnabled()) { + log.debug("Mapping attachment id " + key + " to file " + file.toURI()); + } + } + } + + // remove the remaining cids whose attachment is not in the email (yes, it happens) + // cf #6996 + content = content.replaceAll("(\\w+)=([\"'])cid:.*?([\"'])", ""); + + // on reformate les urls pour supprimer les caractères qui vont pas (ex espaces) + // cf #7740 + String defaultImageIfMalformedUrl = serviceContext.getApplicationConfig().getDefaultImageIfMalformedUrl(); + content = FaxToMailServiceUtils.encodeImageSourcesInEmail(content, defaultImageIfMalformedUrl); + + //On remplace les font-size:0 pour éviter les font-size too small + //cf #10123 + content = content.replace("font-size:0", "font-size:1"); + + + content = content.replaceAll("(.+) width=([\"])(.+)([\"])", "$1"); + content = content.replaceAll("(.+) width=(['])(.+)(['])", "$1"); + content = content.replaceAll("(.+) height=([\"])(.+)([\"])", "$1"); + content = content.replaceAll("(.+) height=(['])(.+)(['])", "$1"); + content = content.replaceAll("(style=\\\")([a-zA-Z0-9:;\\.\\s\\(\\)\\-\\,]*)(\\\")", "$1$3"); + content = content.replaceAll("(style=\\\')([a-zA-Z0-9:;\\.\\s\\(\\)\\-\\,]*)(\\\')", "$1$3"); + content = content.replace(" ", ""); + + contents.add(content); + } + } + + return StringUtils.join(contents, "<hr/>"); + } + + public void deleteTempAttachmentFiles(List<Attachment> attachments) { + for (Attachment attachment : attachments) { + AttachmentFile attachmentFile = attachment.getOriginalFile(); + if (attachmentFile != null) { + File file = attachmentFile.getFile(); + file.delete(); + } + } + } } diff --git a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/actions/OpenReplyAction.java b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/actions/OpenReplyAction.java index 50cc47ec..2a905118 100644 --- a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/actions/OpenReplyAction.java +++ b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/actions/OpenReplyAction.java @@ -87,6 +87,7 @@ public class OpenReplyAction extends AbstractFaxToMailAction<DemandeUIModel, Dem replyModel.setReadonly(true); replyModel.setReadSentDate(reply.getSentDate()); replyModel.setSubject(message.getSubject()); + replyModel.setForward(false); replyModel.setTo(StringUtils.join(message.getRecipients(MimeMessage.RecipientType.TO), " ; ")); replyModel.setFrom(message.getFrom()[0].toString()); if (ArrayUtils.isNotEmpty(message.getRecipients(MimeMessage.RecipientType.CC))) { diff --git a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/replies/DemandRepliesUIHandler.java b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/replies/DemandRepliesUIHandler.java index 895dddf4..c7868b9a 100644 --- a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/replies/DemandRepliesUIHandler.java +++ b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/demande/replies/DemandRepliesUIHandler.java @@ -207,6 +207,7 @@ public class DemandRepliesUIHandler extends AbstractToolbarPopupHandler<DemandeU replyModel.setOriginalDemand(ui.getModel()); replyModel.setReadSentDate(reply.getSentDate()); replyModel.setSubject(t("faxtomail.reply.forwardsubject", message.getSubject())); + replyModel.setForward(true); if (message.isMimeType("multipart/*")) { decomposeMultipartEmail(message, replyModel); diff --git a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIHandler.java b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIHandler.java index f1ef5559..37f66ce2 100644 --- a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIHandler.java +++ b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIHandler.java @@ -29,6 +29,7 @@ import com.franciaflex.faxtomail.persistence.entities.AttachmentFile; import com.franciaflex.faxtomail.persistence.entities.AttachmentFileImpl; import com.franciaflex.faxtomail.persistence.entities.AttachmentImpl; import com.franciaflex.faxtomail.persistence.entities.MailFolder; +import com.franciaflex.faxtomail.services.FaxToMailServiceContext; import com.franciaflex.faxtomail.services.service.ldap.Contact; import com.franciaflex.faxtomail.ui.swing.actions.AddAttachmentToReplyAction; import com.franciaflex.faxtomail.ui.swing.content.demande.DemandeUIModel; @@ -43,17 +44,20 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.application.swing.util.Cancelable; +import org.nuiton.validator.bean.AbstractValidator; import org.nuiton.validator.bean.simple.SimpleBeanValidator; import javax.swing.ComboBoxEditor; import javax.swing.JComboBox; import javax.swing.JComponent; +import javax.swing.JEditorPane; import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.JTextPane; import java.awt.Component; import java.awt.Dimension; +import java.awt.Font; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -77,6 +81,8 @@ public class ReplyFormUIHandler extends AbstractFaxToMailUIHandler<ReplyFormUIMo protected AddAttachmentToReplyAction addAttachmentToReplyAction; + private static final String CONTENT_SEPARATOR = "<br/><br/>----------------<br/><br/>"; + @Override public void beforeInit(ReplyFormUI ui) { super.beforeInit(ui); @@ -107,7 +113,8 @@ public class ReplyFormUIHandler extends AbstractFaxToMailUIHandler<ReplyFormUIMo DemandeUIModel demand = (DemandeUIModel) evt.getNewValue(); ReplyFormUIModel model = (ReplyFormUIModel) evt.getSource(); - List<DemandeUIModel> models = new ArrayList<>(demand.getGroupedDemandes()); + List<DemandeUIModel> models = new ArrayList<DemandeUIModel>(); + models.addAll(demand.getGroupedDemandes()); for (DemandeUIModel demandeUIModel : models) { // remove newline character (cf #6960) @@ -129,11 +136,34 @@ public class ReplyFormUIHandler extends AbstractFaxToMailUIHandler<ReplyFormUIMo model.setSubject(t("faxtomail.reply.subject", demand.getSubject())); - String plainContent = StringUtils.join(demand.getPlainContent(), "\n\n----------------\n\n"); - String quotedReply = t("faxtomail.reply.message", - decorate(demand.getReceptionDate()), - demand.getSender(), - plainContent != null ? plainContent.replaceAll("\n", "\n> ") : ""); + String quotedText = ""; + String plainContent = StringUtils.join(demand.getPlainContent(), CONTENT_SEPARATOR); + try(FaxToMailServiceContext serviceContext = getContext().newServiceContext()) { + String htmlContent = serviceContext.getEmailService().extractHtmlContent(demand.getAttachment(), demand.getHtmlContent()); + if (plainContent != null && !plainContent.isEmpty()) { + quotedText = plainContent.replaceAll("\n", "<br/> "); + } else { + quotedText = htmlContent; + } + } catch (IOException eee){ + log.error("Error setting maxAttachmentLength",eee); + } + + String quotedReply; + if (model.isForward()) { + quotedReply = FaxToMailUIUtil.getQuotedForwardContent( + demand.getSubject(), + decorate(demand.getReceptionDate()), + demand.getSender(), + demand.getRecipient(), + demand.getCcRecipients(), + quotedText); + } else { + quotedReply = FaxToMailUIUtil.getQuotedReplyContent( + decorate(demand.getReceptionDate()), + demand.getSender(), + quotedText); + } model.setMessage(quotedReply); String recipient = demand.getRecipient(); @@ -223,6 +253,11 @@ public class ReplyFormUIHandler extends AbstractFaxToMailUIHandler<ReplyFormUIMo @Override public void onCloseUI() { + try(FaxToMailServiceContext serviceContext = getContext().newServiceContext()) { + serviceContext.getEmailService().deleteTempAttachmentFiles(getModel().getOriginalDemand().getAttachment()); + } catch (IOException eee){ + log.error("Error deleting temp files",eee); + } } @Override diff --git a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIModel.java b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIModel.java index d3af493d..4a33050b 100644 --- a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIModel.java +++ b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/content/reply/ReplyFormUIModel.java @@ -62,6 +62,7 @@ public class ReplyFormUIModel extends AbstractSerializableBean { public static final String PROPERTY_READONLY = "readonly"; public static final String PROPERTY_EDITABLE = "editable"; public static final String PROPERTY_READ_SENT_DATE = "readSentDate"; + public static final String PROPERTY_FORWARD = "forward"; protected Contact contact; protected String to; @@ -74,6 +75,7 @@ public class ReplyFormUIModel extends AbstractSerializableBean { protected long maxAttachmentLength = 0; protected long totalAttachmentLength = 0; protected boolean valid = true; + protected boolean forward; /** Flag pour marquer les champs non editables dans le cas d'une lecture d'une réponse déjà envoyée. */ protected boolean readonly = false; @@ -368,4 +370,14 @@ public class ReplyFormUIModel extends AbstractSerializableBean { public List<String> getSenderAllowedAddresses() { return senderAllowedAddresses; } + + public boolean isForward() { + return forward; + } + + public void setForward(boolean forward) { + Object oldValue = isForward(); + this.forward = forward; + firePropertyChange(PROPERTY_FORWARD, oldValue, forward); + } } diff --git a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/util/FaxToMailUIUtil.java b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/util/FaxToMailUIUtil.java index 82ba0318..d0c7d871 100644 --- a/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/util/FaxToMailUIUtil.java +++ b/faxtomail-ui-swing/src/main/java/com/franciaflex/faxtomail/ui/swing/util/FaxToMailUIUtil.java @@ -905,4 +905,26 @@ public final class FaxToMailUIUtil extends ApplicationUIUtil { return textPane; } + public static String getQuotedReplyContent(String receptionDate, String sender, String originalEmail) { + String quotedReply = t("faxtomail.reply.message", + receptionDate, + sender, + originalEmail); + return quotedReply; + } + + public static String getQuotedForwardContent(String subject, String receptionDate, String sender, + String recipient, String ccRecipient, String originalEmail) { + String recipients = t("faxtomail.reply.label.to") + " " + recipient; + if (StringUtils.isNotBlank(ccRecipient)) { + recipients += "<br/>" + t("faxtomail.reply.label.cc") + " " + ccRecipient; + } + return t("faxtomail.forward.message", + subject, + receptionDate, + sender, + recipients, + originalEmail); + } + } diff --git a/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties b/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties index 77f8d74c..257e0704 100644 --- a/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties +++ b/faxtomail-ui-swing/src/main/resources/i18n/faxtomail-ui-swing_fr_FR.properties @@ -222,6 +222,7 @@ faxtomail.demandeList.table.header.waitingState.tip=État attente faxtomail.demandeList.title=Liste des éléments faxtomail.demandeList.totalCount=Nombre de demandes \: faxtomail.email.content.attachment.unnamed=Pièce-jointe %s +faxtomail.forward.message=\nLe %1$s, %2$s a écrit \:\n> %3$s faxtomail.historyList.action.tip=Historique faxtomail.historyList.text=Historique (%s) faxtomail.historyList.title=Historique -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.