mirror of
https://github.com/moparisthebest/davmail
synced 2025-01-06 03:08:02 -05:00
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:
parent
1a5e963c1b
commit
c7d6607f40
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
89
src/java/davmail/exchange/DoubleDotInputStream.java
Normal file
89
src/java/davmail/exchange/DoubleDotInputStream.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
59
src/java/davmail/exchange/DoubleDotOutputStream.java
Normal file
59
src/java/davmail/exchange/DoubleDotOutputStream.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
67
src/test/davmail/exchange/TestDoubleDotInputStream.java
Normal file
67
src/test/davmail/exchange/TestDoubleDotInputStream.java
Normal 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));
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user