Skip to content

Commit

Permalink
Problems with unicode in sent message (backport) #470
Browse files Browse the repository at this point in the history
Backport of #460:

Fixes trailing \r\n for IMAP msg.getContent()

SmtpConnection now strips the last \r\n before terminating dot of a
received message.

So for an IMAP plain text message, msg.getContent() equals to the sent
plain text content, without being forced to trim off '\r\n' from the received
content.

Note that messages retrieved with POP3 still have trailing '\r\n'.
  • Loading branch information
marcelmay committed Jul 30, 2022
1 parent 4fb9202 commit be61a6f
Show file tree
Hide file tree
Showing 21 changed files with 114 additions and 66 deletions.
16 changes: 8 additions & 8 deletions docs/index.html
Expand Up @@ -213,7 +213,7 @@ <h4>Test Your Sending Code</h4>
public void testSend() throws MessagingException {
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost",
"some subject", "some body"); // --- Place your sending code here instead
assertEquals("some body", GreenMailUtil.getBody(greenMail.getReceivedMessages()[0]));
assertEquals("some body", greenMail.getReceivedMessages()[0].getContent());
}
</code></pre><!-- @formatter:on -->

Expand Down Expand Up @@ -432,15 +432,15 @@ <h3 id="ex_junit_rule" class="anchor">Using JUnit4 rule based setup</h3>
<pre><code class="language-java"><!-- @formatter:off -->
/** [See code on GitHub](https://github.com/greenmail-mail-test/greenmail/tree/master/greenmail-core/src/test/java/com/icegreen/greenmail/examples/ExampleRuleTest.java) */
@Rule
public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.ALL);
public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP);

@Test
public void testSomething() {
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost", "subject", "body");
MimeMessage[] emails = greenMail.getReceivedMessages();
assertEquals(1, emails.length);
assertEquals("subject", emails[0].getSubject());
assertEquals("body", GreenMailUtil.getBody(emails[0]));
assertEquals("body", emails[0].getContent());
// ...
}
</code></pre><!-- @formatter:on -->
Expand All @@ -460,7 +460,7 @@ <h3 id="ex_junit_extension" class="anchor">Using JUnit5 extension</h3>
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost", "some subject", "some body");
final MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
final MimeMessage receivedMessage = receivedMessages[0];
assertEquals("some body", GreenMailUtil.getBody(receivedMessage));
assertEquals("some body", receivedMessage.getContent());
}
</code></pre><!-- @formatter:on -->

Expand All @@ -471,7 +471,7 @@ <h3 id="ex_send_simple" class="anchor">Testing your sending code (simple)</h3>
greenMail.start();
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost", "some subject",
"some body"); // --- Place your sending code here
assertEquals("some body", GreenMailUtil.getBody(greenMail.getReceivedMessages()[0]));
assertEquals("some body", greenMail.getReceivedMessages()[0].getContent());
greenMail.stop();
</code></pre><!-- @formatter:on -->

Expand All @@ -497,14 +497,14 @@ <h3 id="ex_send_adv" class="anchor">Testing your sending code (advanced)</h3>

// Simple message
assertEquals(subject, messages[0].getSubject());
assertEquals(body, GreenMailUtil.getBody(messages[0]).trim());
assertEquals(body, messages[0].getContent());

//if you send content as a 2 part multipart...
assertTrue(messages[1].getContent() instanceof MimeMultipart);
MimeMultipart mp = (MimeMultipart) messages[1].getContent();
assertEquals(2, mp.getCount());
assertEquals("body1", GreenMailUtil.getBody(mp.getBodyPart(0)).trim());
assertEquals("body2", GreenMailUtil.getBody(mp.getBodyPart(1)).trim());
assertEquals("body1", mp.getBodyPart(0).getContent());
assertEquals("body2", mp.getBodyPart(1).getContent());

greenMail.stop();
</code></pre><!-- @formatter:on -->
Expand Down
Expand Up @@ -80,11 +80,20 @@ public void println() {
out.flush();
}

public void print(String line) {
out.print(line);
}

public void print(Reader in) throws IOException {
StreamUtils.copy(in, out);
out.flush();
}

public void println(Reader in) throws IOException {
StreamUtils.copy(in, out);
println();
}

public String readLine() throws IOException {
return in.readLine();
}
Expand Down
Expand Up @@ -44,12 +44,11 @@ public void execute(Pop3Connection conn, Pop3State state,
StoredMessage msg = msgList.get(0);
String email = GreenMailUtil.getWholeMessage(msg.getMimeMessage());
conn.println("+OK");
conn.print(new StringReader(email));
conn.println();
conn.println(email);
conn.println(".");
msg.setFlag(Flags.Flag.SEEN, true);
} catch (Exception e) {
conn.println("-ERR " + e);
}
}
}
}
Expand Up @@ -107,7 +107,7 @@ public InputStream dotLimitedInputStream(byte[] initialContent) {

if (cbuf == CR_LF_DOT_CR && b == '\n') { // CRLF-DOT-CRLF
final byte[] buf = bos.toByteArray();
int maxLen = Math.min(bos.size(), bos.size() - 2 /* DOT + CR */);
int maxLen = Math.min(bos.size(), bos.size() - 4 /* CR + LF + DOT + CR */);
return new ByteArrayInputStream(buf, 0, maxLen);
} else if ((cbuf & 0xffffff) == CR_LF_DOT && b == '.') { // CR_LF_DOT and DOT => Skip dot once
// https://tools.ietf.org/html/rfc5321#section-4.5.2 :
Expand Down
Expand Up @@ -114,7 +114,10 @@ public static int getLineCount(String str) {
}

/**
* @return The content of an email (or a Part)
* @return The content part of an email (or a Part)
*
* Note: You might have to use MimeUtility.decodeText(contentPart)
* on the result to decode the (possibly) quoted-printable encoded special characters.
*/
public static String getBody(Part msg) {
String all = getWholeMessage(msg);
Expand Down Expand Up @@ -153,7 +156,7 @@ public static byte[] getHeaderAsBytes(Part part) {
}

/**
* @return same as {@link #getWholeMessage(jakarta.mail.Part)} }
* @return same as {@link #getWholeMessage(jakarta.mail.Part)}
*/
public static String toString(Part msg) {
return getWholeMessage(msg);
Expand Down
Expand Up @@ -9,19 +9,22 @@
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;

public class ExampleRuleTest {
@Rule
public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP_IMAP);

@Test
public void testSomething() throws MessagingException {
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost", "subject", "body");
public void testSomething() throws MessagingException, IOException {
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost", "subject", "content");
MimeMessage[] emails = greenMail.getReceivedMessages();
assertThat(emails.length).isEqualTo(1);
assertThat(emails[0].getSubject()).isEqualTo("subject");
assertThat(GreenMailUtil.getBody(emails[0])).isEqualTo("body");
assertThat(emails[0].getContentType()).isEqualTo("text/plain; charset=us-ascii");
assertThat(emails[0].getContent()).isEqualTo("content");
// ...
}
}
Expand Up @@ -36,14 +36,15 @@ public void testSend() throws MessagingException, IOException {

// Simple message
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(GreenMailUtil.getBody(messages[0]).trim()).isEqualTo(body);
assertThat(messages[0].getContentType()).isEqualTo("text/plain; charset=us-ascii");
assertThat(messages[0].getContent()).isEqualTo(body);

//if you send content as a 2 part multipart...
assertThat(messages[1].getContent() instanceof MimeMultipart).isTrue();
MimeMultipart mp = (MimeMultipart) messages[1].getContent();
assertThat(mp.getCount()).isEqualTo(2);
assertThat(GreenMailUtil.getBody(mp.getBodyPart(0)).trim()).isEqualTo("body1");
assertThat(GreenMailUtil.getBody(mp.getBodyPart(1)).trim()).isEqualTo("body2");
assertThat(mp.getBodyPart(0).getContent()).isEqualTo("body1");
assertThat(mp.getBodyPart(1).getContent()).isEqualTo("body2");
} finally {
greenMail.stop();
}
Expand Down
Expand Up @@ -3,19 +3,22 @@
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetupTest;
import javax.mail.MessagingException;
import org.junit.Test;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;

public class ExampleSendNoRuleSimpleTest {
@Test
public void testSend() {
public void testSend() throws MessagingException, IOException {
GreenMail greenMail = new GreenMail(ServerSetupTest.SMTP_IMAP); //uses test ports by default
try {
greenMail.start();
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost", "some subject",
"some body"); //replace this with your test message content
assertThat(GreenMailUtil.getBody(greenMail.getReceivedMessages()[0])).isEqualTo("some body");
assertThat((greenMail.getReceivedMessages()[0].getContent())).isEqualTo("some body");
} finally {
greenMail.stop();
}
Expand Down
Expand Up @@ -3,19 +3,22 @@
import com.icegreen.greenmail.junit.GreenMailRule;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetupTest;
import javax.mail.MessagingException;
import org.junit.Rule;
import org.junit.Test;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;

public class ExampleSendTest {
@Rule
public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.SMTP);

@Test
public void testSend() {
public void testSend() throws MessagingException, IOException {
GreenMailUtil.sendTextEmailTest("to@localhost", "from@localhost",
"some subject", "some body"); // --- Place your sending code here instead
assertThat(GreenMailUtil.getBody(greenMail.getReceivedMessages()[0])).isEqualTo("some body");
assertThat(greenMail.getReceivedMessages()[0].getContent()).isEqualTo("some body");
}
}
Expand Up @@ -38,7 +38,7 @@ public void testSendMailAndReceiveWithAuthDisabled() throws MessagingException,
MimeMessage[] emails = greenMail.getReceivedMessages();
assertThat(emails.length).isEqualTo(1);
assertThat(emails[0].getSubject()).isEqualTo(subject);
assertThat(GreenMailUtil.getBody(emails[0])).isEqualTo(body);
assertThat(emails[0].getContent()).isEqualTo(body);

greenMail.waitForIncomingEmail(5000, 1);

Expand Down
Expand Up @@ -58,19 +58,19 @@ public void testGetEmptyBodyAndHeader() throws Exception {
MimeMultipart mp = (MimeMultipart) retriever.getMessages(to)[0].getContent();
BodyPart bp;
bp = mp.getBodyPart(0);
assertThat(body).isEqualTo(GreenMailUtil.getBody(bp).trim());
assertThat(body).isEqualTo(GreenMailUtil.getBody(bp));
assertThat(
"Content-Type: text/plain; charset=us-ascii\r\n" +
"Content-Transfer-Encoding: 7bit").isEqualTo(
GreenMailUtil.getHeaders(bp).trim());

bp = mp.getBodyPart(1);
assertThat("AAEC").isEqualTo(GreenMailUtil.getBody(bp).trim());
assertThat("AAEC").isEqualTo(GreenMailUtil.getBody(bp));
assertThat(
"Content-Type: image/gif; name=testimage_filename\r\n" +
"Content-Transfer-Encoding: base64\r\n" +
"Content-Disposition: attachment; filename=testimage_filename\r\n" +
"Content-Description: testimage_description").isEqualTo(GreenMailUtil.getHeaders(bp).trim());
"Content-Description: testimage_description").isEqualTo(GreenMailUtil.getHeaders(bp));

ByteArrayOutputStream bout = new ByteArrayOutputStream();
GreenMailUtil.copyStream(bp.getInputStream(), bout);
Expand Down
Expand Up @@ -69,7 +69,7 @@ public void testRetrieveSimple() throws Exception {
Message[] messages = retriever.getMessages(to);
assertThat(messages.length).isEqualTo(1);
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(((String) messages[0].getContent()).trim()).isEqualTo(body);
assertThat(((String) messages[0].getContent())).isEqualTo(body);
}
}

Expand All @@ -86,7 +86,7 @@ public void testImapsReceive() throws Throwable {
Message[] messages = retriever.getMessages(to);
assertThat(messages.length).isEqualTo(1);
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(((String) messages[0].getContent()).trim()).isEqualTo(body);
assertThat(((String) messages[0].getContent())).isEqualTo(body);
}
}

Expand All @@ -109,7 +109,7 @@ public void testRetrieveSimpleWithNonDefaultPassword() throws Exception {
Message[] messages = retriever.getMessages(to, password);
assertThat(messages.length).isEqualTo(1);
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(((String) messages[0].getContent()).trim()).isEqualTo(body);
assertThat(((String) messages[0].getContent())).isEqualTo(body);
}
}

Expand All @@ -132,10 +132,10 @@ public void testRetrieveMultipart() throws Exception {
assertThat(mp.getCount()).isEqualTo(2);
BodyPart bp;
bp = mp.getBodyPart(0);
assertThat(GreenMailUtil.getBody(bp).trim()).isEqualTo(body);
assertThat(bp.getContent()).isEqualTo(body);

bp = mp.getBodyPart(1);
assertThat(GreenMailUtil.getBody(bp).trim()).isEqualTo("AAEC");
assertThat(GreenMailUtil.getBody(bp)).isEqualTo("AAEC");

ByteArrayOutputStream bout = new ByteArrayOutputStream();
GreenMailUtil.copyStream(bp.getInputStream(), bout);
Expand Down
Expand Up @@ -15,6 +15,7 @@
import com.icegreen.greenmail.user.UserException;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.Retriever;
import com.icegreen.greenmail.util.ServerSetup;
import com.icegreen.greenmail.util.ServerSetupTest;
import com.sun.mail.pop3.POP3Folder;
import com.sun.mail.pop3.POP3Store;
Expand All @@ -25,12 +26,12 @@

/**
* @author Wael Chatila
* @version $Id: $
* @since Jan 28, 2006
*/
public class Pop3ServerTest {
@Rule
public final GreenMailRule greenMail = new GreenMailRule(ServerSetupTest.ALL);
public final GreenMailRule greenMail = new GreenMailRule(new ServerSetup[]{
ServerSetupTest.SMTP, ServerSetupTest.SMTPS,
ServerSetupTest.POP3, ServerSetupTest.POP3S});

@Test
public void testPop3Capabillities() throws MessagingException, UserException {
Expand All @@ -57,12 +58,13 @@ public void testRetrieve() throws Exception {
try (Retriever retriever = new Retriever(greenMail.getPop3())) {
Message[] messages = retriever.getMessages(to);
assertThat(messages.length).isEqualTo(1);
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(GreenMailUtil.getBody(messages[0]).trim()).isEqualTo(body);
final Message message = messages[0];
assertThat(message.getSubject()).isEqualTo(subject);
assertThat(message.getContent().toString().trim()).isEqualTo(body);

// UID
POP3Folder f = (POP3Folder) messages[0].getFolder();
assertThat(f.getUID(messages[0])).isNotEqualTo("UNKNOWN");
POP3Folder f = (POP3Folder) message.getFolder();
assertThat(f.getUID(message)).isNotEqualTo("UNKNOWN");
}
}

Expand All @@ -79,7 +81,7 @@ public void testPop3sReceive() throws Throwable {
Message[] messages = retriever.getMessages(to);
assertThat(messages.length).isEqualTo(1);
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(GreenMailUtil.getBody(messages[0]).trim()).isEqualTo(body);
assertThat(messages[0].getContent().toString().trim()).isEqualTo(body);
}
}

Expand All @@ -102,7 +104,7 @@ public void testRetrieveWithNonDefaultPassword() throws Exception {
Message[] messages = retriever.getMessages(to, password);
assertThat(messages.length).isEqualTo(1);
assertThat(messages[0].getSubject()).isEqualTo(subject);
assertThat(GreenMailUtil.getBody(messages[0]).trim()).isEqualTo(body);
assertThat(messages[0].getContent().toString().trim()).isEqualTo(body);
}
}

Expand All @@ -127,10 +129,10 @@ public void testRetrieveMultipart() throws Exception {
assertThat(mp.getCount()).isEqualTo(2);
BodyPart bp;
bp = mp.getBodyPart(0);
assertThat(GreenMailUtil.getBody(bp).trim()).isEqualTo(body);
assertThat(bp.getContent()).isEqualTo(body);

bp = mp.getBodyPart(1);
assertThat(GreenMailUtil.getBody(bp).trim()).isEqualTo("AAEC");
assertThat(GreenMailUtil.getBody(bp)).isEqualTo("AAEC");

ByteArrayOutputStream bout = new ByteArrayOutputStream();
GreenMailUtil.copyStream(bp.getInputStream(), bout);
Expand Down

0 comments on commit be61a6f

Please sign in to comment.