From e9418ecae721a8099a2ccf6f15b274a4a6334949 Mon Sep 17 00:00:00 2001 From: pengzili Date: Fri, 30 Dec 2016 14:37:23 +0800 Subject: [PATCH 01/10] deal with html in multipart/related --- pom.xml | 13 ++++++++++-- .../mail/MockMockMessageHandlerFactory.java | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 88cfb5b..106c57d 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ - org.dstovall + com.jolira onejar-maven-plugin 1.4.4 @@ -95,7 +95,8 @@ onejar-maven-plugin.googlecode.com - http://onejar-maven-plugin.googlecode.com/svn/mavenrepo + + http://maven.aliyun.com/nexus/content/groups/public/ @@ -120,6 +121,14 @@ 2.6 + + + commons-io + commons-io + 2.2 + + + javax.mail mail diff --git a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java index e45ee0f..f1c6976 100644 --- a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java +++ b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java @@ -9,12 +9,14 @@ import org.subethamail.smtp.MessageHandler; import org.subethamail.smtp.MessageHandlerFactory; import org.subethamail.smtp.RejectException; +import org.apache.commons.io.IOUtils; import javax.mail.BodyPart; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeUtility; import java.io.*; import java.util.Properties; @@ -126,6 +128,9 @@ public void data(InputStream data) throws RejectException, IOException { BodyPart bodyPart = multipart.getBodyPart(i); String contentType = bodyPart.getContentType(); + contentType = contentType.replaceAll("\t|\r|\n", ""); + System.out.println(contentType); + if(contentType.matches("text/plain.*")) { mockMail.setBody(convertStreamToString(bodyPart.getInputStream())); @@ -134,6 +139,22 @@ else if(contentType.matches("text/html.*")) { mockMail.setBodyHtml(convertStreamToString(bodyPart.getInputStream())); } + else if(contentType.matches("multipart/related.*")){ + // compound documents + Multipart contentMulti = (Multipart)bodyPart.getContent(); + for (int j = 0; j < contentMulti.getCount(); j++){ + BodyPart subPart = contentMulti.getBodyPart(i); + String subContentType = subPart.getContentType(); + System.out.println(subContentType); + String encoding = "UTF-8"; + + if(subContentType.matches("text/html.*")){ + String bodyHtml = IOUtils.toString(MimeUtility.decode(subPart.getInputStream(), "quoted-printable"), "utf-8"); + mockMail.setBodyHtml(bodyHtml); + } + } + + } } } else if(messageContent instanceof InputStream) From d7bde0c1b639ac6967e33c362e4d76f1a2436c20 Mon Sep 17 00:00:00 2001 From: pengzili Date: Fri, 30 Dec 2016 18:23:16 +0800 Subject: [PATCH 02/10] add attachment support --- .../htmlbuilder/MailViewHtmlBuilder.java | 37 ++++++++++++++++--- src/main/java/com/mockmock/mail/MockMail.java | 18 +++++++++ .../mail/MockMockMessageHandlerFactory.java | 6 +++ .../java/com/mockmock/server/HttpServer.java | 7 ++++ 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java index 12915ef..5d78f23 100644 --- a/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java @@ -63,19 +63,44 @@ public String build() " \n"; } - if(mockMail.getBodyHtml() != null) + if(mockMail.getAttacheFileName() != null) { output += - "
\n" + - "

HTML body unformatted

\n" + - "
" + StringEscapeUtils.escapeHtml(mockMail.getBodyHtml()) + "
\n" + - "
\n"; + " \n"; + } + + if(mockMail.getBodyHtml() != null) + { +// output += +// "
\n" + +// "

HTML body unformatted

\n" + +// "
" + StringEscapeUtils.escapeHtml(mockMail.getBodyHtml()) + "
\n" + +// "
\n"; // also show a parsed version via an iframe + output += + ""; + output += "
\n" + "

HTML body formatted

\n" + - " \n" + "
"; } diff --git a/src/main/java/com/mockmock/mail/MockMail.java b/src/main/java/com/mockmock/mail/MockMail.java index 32739d7..16550ba 100644 --- a/src/main/java/com/mockmock/mail/MockMail.java +++ b/src/main/java/com/mockmock/mail/MockMail.java @@ -13,6 +13,8 @@ public class MockMail implements Comparable private String rawMail; private MimeMessage mimeMessage; private long receivedTime; + private byte[] attachment; + private String attacheFileName; public long getId() { @@ -113,4 +115,20 @@ public void setReceivedTime(long receivedTime) { this.receivedTime = receivedTime; } + + public byte[] getAttachment() { + return attachment; + } + + public void setAttachment(byte[] attachment) { + this.attachment = attachment; + } + + public String getAttacheFileName() { + return attacheFileName; + } + + public void setAttacheFileName(String attacheFileName) { + this.attacheFileName = attacheFileName; + } } diff --git a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java index f1c6976..f2b63af 100644 --- a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java +++ b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java @@ -154,6 +154,12 @@ else if(contentType.matches("multipart/related.*")){ } } + }else if(contentType.matches("application/octet-stream.*")){ + // attachment + String strFileName = MimeUtility.decodeText(bodyPart.getFileName()); + mockMail.setAttacheFileName(strFileName); + byte[] attachContent = IOUtils.toByteArray(bodyPart.getInputStream()); + mockMail.setAttachment(attachContent); } } } diff --git a/src/main/java/com/mockmock/server/HttpServer.java b/src/main/java/com/mockmock/server/HttpServer.java index 6738ee8..0a32872 100644 --- a/src/main/java/com/mockmock/server/HttpServer.java +++ b/src/main/java/com/mockmock/server/HttpServer.java @@ -23,6 +23,7 @@ public class HttpServer implements com.mockmock.server.Server private MailDetailHtmlHandler mailDetailHtmlHandler; private MailDeleteHandler mailDeleteHandler; private DeleteHandler deleteHandler; + private MailAttachmentHandler attachmentHandler; public void setPort(int port) { @@ -62,6 +63,7 @@ public void start() this.mailDetailHtmlHandler, this.mailDeleteHandler, this.deleteHandler, + this.attachmentHandler, resourceHandler }; HandlerList handlerList = new HandlerList(); @@ -105,6 +107,11 @@ public void setDeleteHandler(DeleteHandler deleteHandler) { this.deleteHandler = deleteHandler; } + @Autowired + private void setAttachmentHandler(MailAttachmentHandler attachmentHandler) { + this.attachmentHandler = attachmentHandler; + } + @Autowired public void setSettings(Settings settings) { this.settings = settings; From a565fd7af32479fd36f7782de166a09fd84f6504 Mon Sep 17 00:00:00 2001 From: pengzili Date: Fri, 30 Dec 2016 18:23:49 +0800 Subject: [PATCH 03/10] add attachment support --- .../mockmock/http/MailAttachmentHandler.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/main/java/com/mockmock/http/MailAttachmentHandler.java diff --git a/src/main/java/com/mockmock/http/MailAttachmentHandler.java b/src/main/java/com/mockmock/http/MailAttachmentHandler.java new file mode 100644 index 0000000..38f6be9 --- /dev/null +++ b/src/main/java/com/mockmock/http/MailAttachmentHandler.java @@ -0,0 +1,121 @@ +package com.mockmock.http; + +import com.mockmock.mail.MailQueue; +import com.mockmock.mail.MockMail; +import org.apache.commons.io.IOUtils; +import org.eclipse.jetty.server.Request; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.MimeTypeUtils; + +import javax.mail.internet.MimeUtility; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by Pengzili on 2016/12/30. + */ + +@Service +public class MailAttachmentHandler extends BaseHandler{ + + private String pattern = "^/attachment/([0-9]+)/?$"; + + private MailQueue mailQueue; + + @Override + public void handle(String target, Request request, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException { + + if(!isMatch(target)) + { + return; + } + + long mailId = getMailId(target); + if(mailId == 0) + { + return; + } + + MockMail mockMail = this.mailQueue.getById(mailId); + + if(mockMail == null) + { + return; + } + + if(mockMail.getBodyHtml() == null) + { + return; + } + + String fileName = mockMail.getAttacheFileName(); + String fileNameExt =fileName.substring(fileName.lastIndexOf(".")+1, fileName.length()); + String mimeType = "application/octet-stream"; + + if (fileNameExt.equals("pdf")){ + mimeType = "application/pdf"; + }else if(fileNameExt.equals("doc")){ + mimeType = "application/msword"; + }else if(fileNameExt.equals("xls")){ + mimeType = "application/vnd.ms-excel"; + } + + response.setContentType(mimeType); + response.setHeader("Content-Disposition", " attachment;filename="+ MimeUtility.encodeWord(mockMail.getAttacheFileName())); + response.getOutputStream().write(mockMail.getAttachment()); + response.setStatus(HttpServletResponse.SC_OK); + + request.setHandled(true); + + } + + /** + * Checks if this handler should be used for the given target + * @param target String + * @return boolean + */ + private boolean isMatch(String target) + { + return target.matches(pattern); + } + + /** + * Returns the mail id if it is part of the target + * @param target String + * @return long + */ + private long getMailId(String target) + { + Pattern compiledPattern = Pattern.compile(pattern); + + Matcher matcher = compiledPattern.matcher(target); + if(matcher.find()) + { + String result = matcher.group(1); + try + { + return Long.valueOf(result); + } + catch (NumberFormatException e) + { + return 0; + } + } + + return 0; + } + + @Autowired + public void setMailQueue(MailQueue mailQueue) { + this.mailQueue = mailQueue; + } +} From e69d6cf2f5669c44449630ada63bed5361959f8c Mon Sep 17 00:00:00 2001 From: pengzili Date: Fri, 30 Dec 2016 18:41:55 +0800 Subject: [PATCH 04/10] htmlbody in iframe use no scroll --- .../com/mockmock/htmlbuilder/MailViewHtmlBuilder.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java b/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java index 5d78f23..b9366de 100644 --- a/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java +++ b/src/main/java/com/mockmock/htmlbuilder/MailViewHtmlBuilder.java @@ -88,9 +88,9 @@ public String build() " if (document.getElementById){\n" + " if (iframeid && !window.opera){\n" + " if (iframeid.contentDocument && iframeid.contentDocument.body.offsetHeight){\n" + - " iframeid.height = iframeid.contentDocument.body.offsetHeight;\n" + + " iframeid.height = iframeid.contentDocument.body.offsetHeight + 40;\n" + " }else if(iframeid.Document && iframeid.Document.body.scrollHeight){\n" + - " iframeid.height = iframeid.Document.body.scrollHeight;\n" + + " iframeid.height = iframeid.Document.body.scrollHeight + 40;\n" + " }\n" + " }\n" + " }\n" + @@ -100,8 +100,10 @@ public String build() output += "
\n" + "

HTML body formatted

\n" + - " \n" + + "
\n" + "
"; } From 2e27eb6651e2413d910ad4c9efaf53009d187229 Mon Sep 17 00:00:00 2001 From: "pengzili@yeah.net" Date: Fri, 13 Jan 2017 23:25:02 +0800 Subject: [PATCH 05/10] updated one-jar dependency, GoogleCode has closed. --- pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pom.xml b/pom.xml index 106c57d..3a83589 100644 --- a/pom.xml +++ b/pom.xml @@ -92,13 +92,6 @@ - - - onejar-maven-plugin.googlecode.com - - http://maven.aliyun.com/nexus/content/groups/public/ - - From fb1d3a49c8a15bfa2bff74cdd2e35da9e9221133 Mon Sep 17 00:00:00 2001 From: pengzili Date: Fri, 9 Jun 2017 14:10:19 +0800 Subject: [PATCH 06/10] small fix --- .../java/com/mockmock/mail/MockMockMessageHandlerFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java index f2b63af..0e445a9 100644 --- a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java +++ b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java @@ -2,6 +2,7 @@ import com.google.common.eventbus.EventBus; import com.mockmock.Settings; +import org.apache.commons.io.IOUtils; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -9,7 +10,6 @@ import org.subethamail.smtp.MessageHandler; import org.subethamail.smtp.MessageHandlerFactory; import org.subethamail.smtp.RejectException; -import org.apache.commons.io.IOUtils; import javax.mail.BodyPart; import javax.mail.MessagingException; @@ -154,7 +154,7 @@ else if(contentType.matches("multipart/related.*")){ } } - }else if(contentType.matches("application/octet-stream.*")){ + } else if (contentType.matches("application/octet-stream.*") || contentType.matches("application/pdf.*")) { // attachment String strFileName = MimeUtility.decodeText(bodyPart.getFileName()); mockMail.setAttacheFileName(strFileName); From d65c173aaaed16d4b35296a1cb878f808ce6da88 Mon Sep 17 00:00:00 2001 From: pengzili Date: Wed, 30 May 2018 17:21:01 +0800 Subject: [PATCH 07/10] adapat to java 1.6 --- pom.xml | 4 ++-- src/main/java/com/mockmock/console/Parser.java | 4 ++-- src/main/java/com/mockmock/mail/MailQueue.java | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 3a83589..ae45c11 100644 --- a/pom.xml +++ b/pom.xml @@ -19,8 +19,8 @@ - ISO-8859-15 - ISO-8859-15 + UTF-8 + UTF-8 4.1.2.RELEASE diff --git a/src/main/java/com/mockmock/console/Parser.java b/src/main/java/com/mockmock/console/Parser.java index d836a4e..9821043 100644 --- a/src/main/java/com/mockmock/console/Parser.java +++ b/src/main/java/com/mockmock/console/Parser.java @@ -126,7 +126,7 @@ protected void parseFilterFromEmailAddressesOption(CommandLine cmd, Settings set { String input = cmd.getOptionValue("ff"); String[] emailAddresses = input.split(","); - settings.setFilterFromEmailAddresses(new HashSet<>(Arrays.asList(emailAddresses))); + settings.setFilterFromEmailAddresses(new HashSet(Arrays.asList(emailAddresses))); } } @@ -136,7 +136,7 @@ protected void parseFilterToEmailAddressesOption(CommandLine cmd, Settings setti { String input = cmd.getOptionValue("ft"); String[] emailAddresses = input.split(","); - settings.setFilterToEmailAddresses(new HashSet<>(Arrays.asList(emailAddresses))); + settings.setFilterToEmailAddresses(new HashSet(Arrays.asList(emailAddresses))); } } diff --git a/src/main/java/com/mockmock/mail/MailQueue.java b/src/main/java/com/mockmock/mail/MailQueue.java index 43ff309..177bdde 100644 --- a/src/main/java/com/mockmock/mail/MailQueue.java +++ b/src/main/java/com/mockmock/mail/MailQueue.java @@ -1,7 +1,6 @@ package com.mockmock.mail; import com.google.common.eventbus.Subscribe; -import com.mockmock.AppStarter; import com.mockmock.Settings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -13,7 +12,7 @@ @Service public class MailQueue { - private static ArrayList mailQueue = new ArrayList<>(); + private static ArrayList mailQueue = new ArrayList(); private Settings settings; From 5a48e28cd32736d933ede045a1f0f56e25785291 Mon Sep 17 00:00:00 2001 From: pengzili Date: Wed, 30 May 2018 17:23:11 +0800 Subject: [PATCH 08/10] adapat to java 1.6 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ae45c11..87d87b6 100644 --- a/pom.xml +++ b/pom.xml @@ -31,8 +31,8 @@ maven-compiler-plugin 2.3.2 - 1.7 - 1.7 + 1.6 + 1.6 From 5ae9aa44135fb44a4c8222086fa83f9e166ab76e Mon Sep 17 00:00:00 2001 From: pengzili <2059728+openmartin@users.noreply.github.com> Date: Thu, 12 Nov 2020 18:40:09 +0800 Subject: [PATCH 09/10] fix Quoted-printable soft line break --- src/main/java/com/mockmock/Settings.java | 4 ++-- .../com/mockmock/mail/MockMockMessageHandlerFactory.java | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mockmock/Settings.java b/src/main/java/com/mockmock/Settings.java index 890c505..af933b6 100644 --- a/src/main/java/com/mockmock/Settings.java +++ b/src/main/java/com/mockmock/Settings.java @@ -31,12 +31,12 @@ public class Settings /** * A set of "From" email addresses to filter */ - private Set filterFromEmailAddresses = new HashSet<>(); + private Set filterFromEmailAddresses = new HashSet(); /** * A set of "To" email addresses to filter */ - private Set filterToEmailAddresses = new HashSet<>(); + private Set filterToEmailAddresses = new HashSet(); /** * Path to the static folder containing the images, css and js diff --git a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java index 0e445a9..6e13630 100644 --- a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java +++ b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java @@ -149,7 +149,12 @@ else if(contentType.matches("multipart/related.*")){ String encoding = "UTF-8"; if(subContentType.matches("text/html.*")){ - String bodyHtml = IOUtils.toString(MimeUtility.decode(subPart.getInputStream(), "quoted-printable"), "utf-8"); + String originalBodyHtml = IOUtils.toString(subPart.getInputStream()); + String replacedBodyHtml = originalBodyHtml.replaceAll("(? Date: Fri, 13 Nov 2020 10:22:36 +0800 Subject: [PATCH 10/10] fix encoding --- .../java/com/mockmock/mail/MockMockMessageHandlerFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java index 6e13630..32dab70 100644 --- a/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java +++ b/src/main/java/com/mockmock/mail/MockMockMessageHandlerFactory.java @@ -149,10 +149,10 @@ else if(contentType.matches("multipart/related.*")){ String encoding = "UTF-8"; if(subContentType.matches("text/html.*")){ - String originalBodyHtml = IOUtils.toString(subPart.getInputStream()); + String originalBodyHtml = IOUtils.toString(subPart.getInputStream(), "utf-8"); String replacedBodyHtml = originalBodyHtml.replaceAll("(?