Major refactoring: use straight inpustream instead of reader everywhere

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1175 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-07-12 16:35:46 +00:00
parent 1a5e963c1b
commit c7d6607f40
12 changed files with 366 additions and 176 deletions

View File

@ -18,6 +18,7 @@
*/
package davmail;
import davmail.exception.DavMailException;
import davmail.exchange.ExchangeSession;
import davmail.ui.tray.DavGatewayTray;
import org.apache.commons.codec.binary.Base64;
@ -35,9 +36,74 @@ public class AbstractConnection extends Thread {
INITIAL, LOGIN, USER, PASSWORD, AUTHENTICATED, STARTMAIL, RECIPIENT, MAILDATA
}
protected static class LineReaderInputStream extends PushbackInputStream {
final String encoding;
/**
* @inheritDoc
*/
protected LineReaderInputStream(InputStream in, String encoding) {
super(in);
if (encoding == null) {
this.encoding = "ASCII";
} else {
this.encoding = encoding;
}
}
public String readLine() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b;
while ((b = read()) > -1) {
if (b == '\r') {
int next = read();
if (next != '\n') {
unread(next);
}
break;
} else if (b == '\n') {
break;
}
baos.write(b);
}
return new String(baos.toByteArray(), encoding);
}
/**
* Read byteSize bytes from inputStream, return content as String.
* @param byteSize content size
* @return content
* @throws IOException on error
*/
public String readContentAsString(int byteSize) throws IOException {
return new String(readContent(byteSize), encoding);
}
/**
* Read byteSize bytes from inputStream, return content as byte array.
* @param byteSize content size
* @return content
* @throws IOException on error
*/
public byte[] readContent(int byteSize) throws IOException {
byte[] buffer = new byte[byteSize];
int startIndex = 0;
int count = 0;
while (count >= 0 && startIndex < byteSize) {
count = in.read(buffer, startIndex, byteSize - startIndex);
startIndex += count;
}
if (startIndex < byteSize) {
throw new DavMailException("EXCEPTION_END_OF_STREAM");
}
return buffer;
}
}
protected final Socket client;
protected BufferedReader in;
protected LineReaderInputStream in;
protected OutputStream os;
// user name and password initialized through connection
protected String userName;
@ -70,12 +136,7 @@ public class AbstractConnection extends Thread {
super(name + '-' + clientSocket.getPort());
this.client = clientSocket;
try {
if (encoding == null) {
//noinspection IOResourceOpenedButNotSafelyClosed
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
} else {
in = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
}
in = new LineReaderInputStream(client.getInputStream(), encoding);
os = new BufferedOutputStream(client.getOutputStream());
} catch (IOException e) {
close();

View File

@ -91,21 +91,7 @@ public class CaldavConnection extends AbstractConnection {
} catch (NumberFormatException e) {
throw new DavMailException("EXCEPTION_INVALID_CONTENT_LENGTH", contentLength);
}
char[] buffer = new char[size];
StringBuilder builder = new StringBuilder();
int actualSize = in.read(buffer);
builder.append(buffer, 0, actualSize);
if (actualSize < 0) {
throw new DavMailException("EXCEPTION_END_OF_STREAM");
}
// dirty hack to ensure full content read
// TODO : replace with a dedicated reader
while (builder.toString().getBytes("UTF-8").length < size) {
actualSize = in.read(buffer);
builder.append(buffer, 0, actualSize);
}
String content = builder.toString();
String content = in.readContentAsString(size);
if (wireLogger.isDebugEnabled()) {
wireLogger.debug("< " + content);
}

View File

@ -0,0 +1,89 @@
/*
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
* Copyright (C) 2010 Mickael Guessant
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package davmail.exchange;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
/**
* Replace double dot lines with single dot in input stream.
* A line with a single dot means end of stream
*/
public class DoubleDotInputStream extends PushbackInputStream {
int[] buffer = new int[4];
int index = -1;
/**
* @inheritDoc
*/
public DoubleDotInputStream(InputStream in) {
super(in, 3);
}
/**
* Push current byte to buffer and read next byte.
*
* @param currentByte current byte
* @return next byte
* @throws IOException on error
*/
protected int readNextByte() throws IOException {
int b = super.read();
buffer[++index] = b;
return b;
}
@Override
public int read() throws IOException {
int b = super.read();
if (b == '\r') {
// \r\n
if (readNextByte() == '\n') {
// \r\n.
if (readNextByte() == '.') {
// \r\n.\r
if (readNextByte() == '\r') {
// \r\n.\r\n
if (readNextByte() == '\n') {
// end of stream
index = -1;
b = -1;
}
// \r\n..
} else if (buffer[index] == '.') {
// \r\n..\r
if ((readNextByte()) == '\r') {
// replace double dot
buffer[--index] = '\r';
}
}
}
}
// push back characters
if (index >= 0) {
while(index >= 0) {
unread(buffer[index--]);
}
}
}
return b;
}
}

View File

@ -0,0 +1,59 @@
/*
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
* Copyright (C) 2010 Mickael Guessant
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package davmail.exchange;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Replace single dot lines with double dot.
*/
public class DoubleDotOutputStream extends FilterOutputStream {
enum State {
CR, CRLF, CRLFDOT
}
State currentState;
/**
* @inheritDoc
*/
public DoubleDotOutputStream(OutputStream out) {
super(out);
}
@Override
public void write(int b) throws IOException {
if (currentState == null && b == '\r') {
currentState = State.CR;
} else if (currentState == State.CR && b == '\n') {
currentState = State.CRLF;
} else if (currentState == State.CRLF && b == '.') {
currentState = State.CRLFDOT;
} else if (currentState == State.CRLFDOT && b == '\r') {
out.write('.');
currentState = null;
} else {
currentState = null;
}
out.write(b);
}
}

View File

@ -35,7 +35,9 @@ import org.htmlcleaner.CommentToken;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
@ -473,7 +475,7 @@ public abstract class ExchangeSession {
* @param messageBody mail body
* @throws IOException when unable to create message
*/
public abstract void createMessage(String folderPath, String messageName, HashMap<String, String> properties, String messageBody) throws IOException;
public abstract void createMessage(String folderPath, String messageName, HashMap<String, String> properties, byte[] messageBody) throws IOException;
/**
* Update given properties on message.
@ -496,11 +498,10 @@ public abstract class ExchangeSession {
/**
* Send message to recipients, properties contains bcc recipients and other non MIME flags.
*
* @param properties additional message properties
* @param messageBody MIME message body
* @throws IOException on error
*/
public abstract void sendMessage(HashMap<String, String> properties, String messageBody) throws IOException;
public abstract void sendMessage(byte[] messageBody) throws IOException;
/**
* Create message MIME body reader.
@ -906,67 +907,25 @@ public abstract class ExchangeSession {
* @param reader message stream
* @throws IOException on error
*/
public void sendMessage(List<String> recipients, BufferedReader reader) throws IOException {
String line = reader.readLine();
StringBuilder mailBuffer = new StringBuilder();
StringBuilder recipientBuffer = new StringBuilder();
boolean inHeader = true;
boolean inRecipientHeader = false;
while (!".".equals(line)) {
// Exchange 2007 : skip From: header
if ((inHeader && line.length() >= 5)) {
String prefix = line.substring(0, 5).toLowerCase();
if ("from:".equals(prefix)) {
line = reader.readLine();
}
}
public void sendMessage(List<String> rcptToRecipients, MimeMessage mimeMessage) throws IOException, MessagingException {
// Exchange 2007 : skip From: header
mimeMessage.removeHeader("from");
if (inHeader && line.length() == 0) {
inHeader = false;
}
inRecipientHeader = inRecipientHeader && line.startsWith(" ");
if ((inHeader && line.length() >= 3) || inRecipientHeader) {
String prefix = line.substring(0, 3).toLowerCase();
if ("to:".equalsIgnoreCase(prefix) || "cc:".equalsIgnoreCase(prefix) || inRecipientHeader) {
inRecipientHeader = true;
recipientBuffer.append(line);
}
}
String nextLine = reader.readLine();
mailBuffer.append(line);
if (!".".equals(nextLine)) {
mailBuffer.append((char) 13).append((char) 10);
}
line = nextLine;
}
// remove visible recipients from list
List<String> visibleRecipients = new ArrayList<String>();
for (String recipient : recipients) {
if (recipientBuffer.indexOf(recipient) >= 0) {
visibleRecipients.add(recipient);
Set<String> visibleRecipients = new HashSet<String>();
Address[] recipients = mimeMessage.getAllRecipients();
for (Address address:recipients) {
visibleRecipients.add(address.toString());
}
for (String recipient : rcptToRecipients) {
if (!visibleRecipients.contains(recipient)) {
mimeMessage.addRecipient(javax.mail.Message.RecipientType.BCC, new InternetAddress(recipient));
}
}
recipients.removeAll(visibleRecipients);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mimeMessage.writeTo(baos);
StringBuilder bccBuffer = new StringBuilder();
for (String recipient : recipients) {
if (bccBuffer.length() > 0) {
bccBuffer.append(',');
}
bccBuffer.append('<');
bccBuffer.append(recipient);
bccBuffer.append('>');
}
String bcc = bccBuffer.toString();
HashMap<String, String> properties = new HashMap<String, String>();
if (bcc.length() > 0) {
properties.put("bcc", bcc);
}
sendMessage(properties, mailBuffer.toString());
sendMessage(baos.toByteArray());
}
/**

View File

@ -1407,7 +1407,7 @@ public class DavExchangeSession extends ExchangeSession {
* @throws IOException when unable to create message
*/
@Override
public void createMessage(String folderPath, String messageName, HashMap<String, String> properties, String messageBody) throws IOException {
public void createMessage(String folderPath, String messageName, HashMap<String, String> properties, byte[] messageBody) throws IOException {
String messageUrl = URIUtil.encodePathQuery(getFolderPath(folderPath) + '/' + messageName + ".EML");
PropPatchMethod patchMethod;
List<DavConstants> davProperties = buildProperties(properties);
@ -1434,7 +1434,7 @@ public class DavExchangeSession extends ExchangeSession {
putmethod.setRequestHeader("Translate", "f");
try {
// use same encoding as client socket reader
putmethod.setRequestEntity(new ByteArrayRequestEntity(messageBody.getBytes()));
putmethod.setRequestEntity(new ByteArrayRequestEntity(messageBody));
int code = httpClient.executeMethod(putmethod);
if (code != HttpStatus.SC_OK && code != HttpStatus.SC_CREATED) {
@ -1495,10 +1495,10 @@ public class DavExchangeSession extends ExchangeSession {
* @inheritDoc
*/
@Override
public void sendMessage(HashMap<String, String> properties, String messageBody) throws IOException {
public void sendMessage(byte[] messageBody) throws IOException {
String messageName = UUID.randomUUID().toString();
createMessage("Drafts", messageName, properties, messageBody);
createMessage("Drafts", messageName, null, messageBody);
String tempUrl = draftsUrl + '/' + messageName + ".EML";
MoveMethod method = new MoveMethod(URIUtil.encodePath(tempUrl), URIUtil.encodePath(sendmsgUrl), true);

View File

@ -162,17 +162,10 @@ public class EwsExchangeSession extends ExchangeSession {
}
@Override
public void createMessage(String folderPath, String messageName, HashMap<String, String> properties, String messageBody) throws IOException {
public void createMessage(String folderPath, String messageName, HashMap<String, String> properties, byte[] messageBody) throws IOException {
EWSMethod.Item item = new EWSMethod.Item();
item.type = "Message";
String bcc = properties.get("bcc");
if (bcc != null) {
properties.remove("bcc");
// put bcc header back into mime body, Exchange will handle it on send
item.mimeContent = Base64.encodeBase64(("bcc: "+bcc+ "\r\n" +messageBody).getBytes());
} else {
item.mimeContent = Base64.encodeBase64(messageBody.getBytes());
}
item.mimeContent = Base64.encodeBase64(messageBody);
Set<FieldUpdate> fieldUpdates = buildProperties(properties);
if (!properties.containsKey("draft")) {
@ -204,23 +197,13 @@ public class EwsExchangeSession extends ExchangeSession {
}
@Override
public void sendMessage(HashMap<String, String> properties, String messageBody) throws IOException {
public void sendMessage(byte[] messageBody) throws IOException {
EWSMethod.Item item = new EWSMethod.Item();
item.type = "Message";
String bcc = properties.get("bcc");
if (bcc != null) {
properties.remove("bcc");
// put bcc header back into mime body, Exchange will handle it on send
item.mimeContent = Base64.encodeBase64(("bcc: "+bcc+ "\r\n" +messageBody).getBytes());
} else {
item.mimeContent = Base64.encodeBase64(messageBody.getBytes());
}
item.mimeContent = Base64.encodeBase64(messageBody);
Set<FieldUpdate> fieldUpdates = buildProperties(properties);
item.setFieldUpdates(fieldUpdates);
CreateItemMethod createItemMethod = new CreateItemMethod(MessageDisposition.SendAndSaveCopy, getFolderId(SENT), item);
executeMethod(createItemMethod);
}
/**

View File

@ -419,20 +419,12 @@ public class ImapConnection extends AbstractConnection {
}
int size = Integer.parseInt(nextToken);
sendClient("+ send literal data");
char[] buffer = new char[size];
int index = 0;
int count = 0;
while (count >= 0 && index < size) {
count = in.read(buffer, index, size - index);
if (count >= 0) {
index += count;
}
}
byte[] buffer = in.readContent(size);
// empty line
readClient();
String messageName = UUID.randomUUID().toString();
session.createMessage(folderName, messageName, properties, new String(buffer));
session.createMessage(folderName, messageName, properties, buffer);
sendClient(commandId + " OK APPEND completed");
} else if ("idle".equalsIgnoreCase(command) && imapIdleDelay > 0) {
sendClient("+ idling ");
@ -441,7 +433,7 @@ public class ImapConnection extends AbstractConnection {
DavGatewayTray.resetIcon();
try {
int count = 0;
while (!in.ready()) {
while (in.available() == 0) {
if (++count >= imapIdleDelay) {
count = 0;
List<Long> previousImapUidList = currentFolder.getImapUidList();

View File

@ -21,18 +21,22 @@ package davmail.smtp;
import davmail.AbstractConnection;
import davmail.BundleMessage;
import davmail.exception.DavMailException;
import davmail.exchange.DoubleDotInputStream;
import davmail.exchange.ExchangeSessionFactory;
import davmail.ui.tray.DavGatewayTray;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.SharedByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
/**
* Dav Gateway smtp connection implementation
@ -48,6 +52,7 @@ public class SmtpConnection extends AbstractConnection {
super(SmtpConnection.class.getSimpleName(), clientSocket, null);
}
@Override
public void run() {
String line;
@ -146,7 +151,15 @@ public class SmtpConnection extends AbstractConnection {
sendClient("354 Start mail input; end with <CRLF>.<CRLF>");
try {
session.sendMessage(recipients, in);
// read message in buffer
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DoubleDotInputStream doubleDotInputStream = new DoubleDotInputStream(in);
int b;
while ((b = doubleDotInputStream.read()) >= 0) {
baos.write(b);
}
MimeMessage mimeMessage = new MimeMessage(null, new SharedByteArrayInputStream(baos.toByteArray()));
session.sendMessage(recipients, mimeMessage);
state = State.AUTHENTICATED;
sendClient("250 Queued mail for delivery");
} catch (Exception e) {

View File

@ -59,11 +59,10 @@ public class AbstractExchangeSessionTestCase extends AbstractDavMailTestCase {
return mimeMessage;
}
protected String getMimeBody(MimeMessage mimeMessage) throws IOException, MessagingException {
protected byte[] getMimeBody(MimeMessage mimeMessage) throws IOException, MessagingException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mimeMessage.writeTo(baos);
byte[] content = baos.toByteArray();
return new String(content);
return baos.toByteArray();
}
}

View File

@ -0,0 +1,67 @@
/*
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
* Copyright (C) 2010 Mickael Guessant
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package davmail.exchange;
import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Test double dot input stream.
*/
public class TestDoubleDotInputStream extends TestCase {
static final String END_OF_STREAM = "\r\n.\r\n";
protected String doubleDotRead(String value) throws IOException {
DoubleDotInputStream doubleDotInputStream = new DoubleDotInputStream(new ByteArrayInputStream(value.getBytes()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b;
while ((b = doubleDotInputStream.read()) != -1) {
baos.write(b);
}
return new String(baos.toByteArray());
}
public void testSimple() throws IOException {
String value = "simple test";
assertEquals(value, doubleDotRead(value + END_OF_STREAM));
}
public void testNoEof() throws IOException {
String value = "simple test";
assertEquals(value, doubleDotRead(value));
}
public void testMultiLine() throws IOException {
String value = "simple test\r\nsecond line";
assertEquals(value, doubleDotRead(value+END_OF_STREAM));
}
public void testDoubleDot() throws IOException {
String value = "simple test\r\n..\r\nsecond line";
assertEquals(value.replaceAll("\\.\\.", "."), doubleDotRead(value+END_OF_STREAM));
}
public void testDoubleDotEnd() throws IOException {
String value = "simple test\r\n..";
assertEquals(value.replaceAll("\\.\\.", "."), doubleDotRead(value+END_OF_STREAM));
assertEquals("..", doubleDotRead(".."+END_OF_STREAM));
}
}

View File

@ -21,6 +21,7 @@ package davmail.smtp;
import davmail.AbstractDavMailTestCase;
import davmail.DavGateway;
import davmail.Settings;
import davmail.exchange.DoubleDotOutputStream;
import davmail.exchange.ExchangeSession;
import davmail.exchange.ExchangeSessionFactory;
import org.apache.commons.codec.binary.Base64;
@ -78,14 +79,6 @@ public class TestSmtp extends AbstractDavMailTestCase {
return new String(baos.toByteArray(), "ASCII");
}
protected String readFullAnswer(String prefix) throws IOException {
String line = readLine();
while (!line.startsWith(prefix)) {
line = readLine();
}
return line;
}
@Override
public void setUp() throws IOException {
super.setUp();
@ -95,43 +88,26 @@ public class TestSmtp extends AbstractDavMailTestCase {
clientSocket = new Socket("localhost", Settings.getIntProperty("davmail.smtpPort"));
socketOutputStream = new BufferedOutputStream(clientSocket.getOutputStream());
socketInputStream = new BufferedInputStream(clientSocket.getInputStream());
String banner = readLine();
assertNotNull(banner);
String credentials = (char) 0+Settings.getProperty("davmail.username")+ (char) 0 +Settings.getProperty("davmail.password");
writeLine("AUTH PLAIN " + new String(new Base64().encode(credentials.getBytes())));
assertEquals("235 OK Authenticated", readLine());
}
if (session == null) {
session = ExchangeSessionFactory.getInstance(Settings.getProperty("davmail.username"), Settings.getProperty("davmail.password"));
}
}
public void testBanner() throws IOException {
String banner = readLine();
assertNotNull(banner);
}
public void testLogin() throws IOException {
String credentials = (char) 0+Settings.getProperty("davmail.username")+ (char) 0 +Settings.getProperty("davmail.password");
writeLine("AUTH PLAIN " + new String(new Base64().encode(credentials.getBytes())));
assertEquals("235 OK Authenticated", readLine());
}
public void testSendMessage() throws IOException, MessagingException, InterruptedException {
String body = "Test message\r\n" +
"Special characters: éèçà\r\n" +
"Chinese: "+((char)0x604F)+((char)0x7D59);
MimeMessage mimeMessage = new MimeMessage((Session) null);
mimeMessage.addHeader("To", Settings.getProperty("davmail.to"));
mimeMessage.setText(body, "UTF-8");
//mimeMessage.setHeader("Content-Transfer-Encoding", "8bit");
mimeMessage.setSubject("Test subject");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mimeMessage.writeTo(baos);
byte[] content = baos.toByteArray();
public void sendAndCheckMessage(MimeMessage mimeMessage) throws IOException, MessagingException, InterruptedException {
writeLine("MAIL FROM:"+session.getEmail());
readLine();
writeLine("RCPT TO:"+Settings.getProperty("davmail.to"));
readLine();
writeLine("DATA");
assertEquals("354 Start mail input; end with <CRLF>.<CRLF>", readLine());
mimeMessage.writeTo(socketOutputStream);
mimeMessage.writeTo(new DoubleDotOutputStream(socketOutputStream));
writeLine("");
writeLine(".");
assertEquals("250 Queued mail for delivery", readLine());
@ -141,29 +117,35 @@ public class TestSmtp extends AbstractDavMailTestCase {
assertEquals(1, messages.size());
ExchangeSession.Message message = messages.get(0);
message.getMimeMessage().writeTo(System.out);
assertEquals(body, (String) message.getMimeMessage().getDataHandler().getContent());
assertEquals(mimeMessage.getDataHandler().getContent(), (String) message.getMimeMessage().getDataHandler().getContent());
}
public void testBccMessage() throws IOException, MessagingException {
public void testSendMessage() throws IOException, MessagingException, InterruptedException {
String body = "Test message\r\n" +
"Special characters: éèçà\r\n" +
"Chinese: "+((char)0x604F)+((char)0x7D59);
MimeMessage mimeMessage = new MimeMessage((Session) null);
mimeMessage.addHeader("To", Settings.getProperty("davmail.to"));
mimeMessage.setSubject("Test subject");
mimeMessage.setText(body, "UTF-8");
sendAndCheckMessage(mimeMessage);
}
public void testBccMessage() throws IOException, MessagingException, InterruptedException {
MimeMessage mimeMessage = new MimeMessage((Session) null);
mimeMessage.addHeader("to", Settings.getProperty("davmail.to"));
mimeMessage.setText("Test message");
mimeMessage.setSubject("Test subject");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mimeMessage.writeTo(baos);
byte[] content = baos.toByteArray();
writeLine("MAIL FROM:"+session.getEmail());
readLine();
writeLine("RCPT TO:"+Settings.getProperty("davmail.to"));
readLine();
writeLine("RCPT TO:"+Settings.getProperty("davmail.bcc"));
readLine();
writeLine("DATA");
assertEquals("354 Start mail input; end with <CRLF>.<CRLF>", readLine());
writeLine(new String(content));
writeLine(".");
assertEquals("250 Queued mail for delivery", readLine());
mimeMessage.setText("Test message");
sendAndCheckMessage(mimeMessage);
}
public void testDotMessage() throws IOException, MessagingException, InterruptedException {
String body = "First line\r\n.\r\nSecond line";
MimeMessage mimeMessage = new MimeMessage((Session) null);
mimeMessage.addHeader("to", Settings.getProperty("davmail.to"));
mimeMessage.setSubject("Test subject");
mimeMessage.setText(body);
sendAndCheckMessage(mimeMessage);
}
public void testQuit() throws IOException {