Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ protected Response handleMessageExists(POP3Session session, MessageMetaData data
if (args.getLineCount().isEmpty()) {
return handleSyntaxError();
}
InputStream content = getMessageContent(session, data);
InputStream in = new CountingBodyInputStream(new CRLFTerminatedInputStream(new ExtraDotInputStream(content)), args.getLineCount().get());
int lineCount = args.getLineCount().get();
InputStream content = lineCount == 0 ? getMessageHeaders(session, data) : getMessageContent(session, data);
InputStream in = new CountingBodyInputStream(new CRLFTerminatedInputStream(new ExtraDotInputStream(content)), lineCount);
return new POP3StreamResponse(POP3Response.OK_RESPONSE, "Message follows", in);
}

Expand Down Expand Up @@ -95,6 +96,10 @@ protected InputStream getMessageContent(POP3Session session, MessageMetaData dat
return session.getUserMailbox().getMessage(data.getUid());
}

protected InputStream getMessageHeaders(POP3Session session, MessageMetaData data) throws IOException {
return session.getUserMailbox().getMessageHeaders(data.getUid());
}

@Override
public Set<String> getImplementedCapabilities(POP3Session session) {
if (session.getHandlerState() == POP3Session.TRANSACTION) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ public interface Mailbox {
*/
InputStream getMessage(String uid) throws IOException;

/**
* Return only the headers as {@link InputStream} for the given <code>uid</code>.
* Implementations may override this for better performance (e.g. using FetchGroup.HEADERS).
* @exception IOException If message can not be found or is inaccessible
*/
default InputStream getMessageHeaders(String uid) throws IOException {
return getMessage(uid);
}

/**
* Return a immutable {@link List} which holds the {@link MessageMetaData}
* for all messages in the {@link Mailbox}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,24 @@ public InputStream getMessage(String uid) throws IOException {
}
}

@Override
public InputStream getMessageHeaders(String uid) throws IOException {
try {
MessageId messageId = messageIdFactory.fromString(uid);
Iterator<MessageResult> messages = messageIdManager.getMessage(messageId, FetchGroup.HEADERS, session).iterator();
if (messages.hasNext()) {
return messages.next().getHeaders().getInputStream();
} else {
LOGGER.warn("Removing {} from {} POP3 projection for user {} as it is not backed by a MailboxMessage",
uid, mailbox.getId().serialize(), session.getUser().asString());
Mono.from(metadataStore.remove(mailbox.getId(), messageId)).block();
throw new IOException("Message does not exist for uid " + uid);
}
} catch (MailboxException e) {
throw new IOException("Unable to retrieve message headers for uid " + uid, e);
}
}

@Override
public List<MessageMetaData> getMessages() {
return Flux.from(metadataStore.stat(mailbox.getId()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@
import com.google.common.collect.ImmutableList;

public class MailboxAdapter implements Mailbox {
private static final FetchGroup FULL_GROUP = FetchGroup.FULL_CONTENT;
private static final FetchGroup METADATA_GROUP = FetchGroup.MINIMAL;

private final MessageManager manager;
private final MailboxSession session;

Expand All @@ -58,7 +55,7 @@ public MailboxAdapter(MailboxManager mailboxManager, MessageManager manager, Mai
public InputStream getMessage(String uid) throws IOException {
try {
mailboxManager.startProcessingRequest(session);
Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), FULL_GROUP, session);
Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), FetchGroup.FULL_CONTENT, session);
if (results.hasNext()) {
return results.next().getFullContent().getInputStream();
} else {
Expand All @@ -71,11 +68,28 @@ public InputStream getMessage(String uid) throws IOException {
}
}

@Override
public InputStream getMessageHeaders(String uid) throws IOException {
try {
mailboxManager.startProcessingRequest(session);
Iterator<MessageResult> results = manager.getMessages(MessageUid.of(Long.parseLong(uid)).toRange(), FetchGroup.HEADERS, session);
if (results.hasNext()) {
return results.next().getHeaders().getInputStream();
} else {
throw new IOException("Message does not exist for uid " + uid);
}
} catch (MailboxException e) {
throw new IOException("Unable to retrieve message headers for uid " + uid, e);
} finally {
mailboxManager.endProcessingRequest(session);
}
}

@Override
public List<MessageMetaData> getMessages() throws IOException {
try {
mailboxManager.startProcessingRequest(session);
Iterator<MessageResult> results = manager.getMessages(MessageRange.all(), METADATA_GROUP, session);
Iterator<MessageResult> results = manager.getMessages(MessageRange.all(), FetchGroup.MINIMAL, session);
List<MessageMetaData> mList = new ArrayList<>();
while (results.hasNext()) {
MessageResult result = results.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,44 @@ void testKnownUserInboxWithMessages() throws Exception {
mailboxManager.deleteMailbox(mailboxPath, session);
}

@Test
void topWithZeroLinesShouldReturnOnlyHeaders() throws Exception {
finishSetUp(pop3Configuration);

pop3Client = new POP3Client();
InetSocketAddress bindedAddress = new ProtocolServerUtils(pop3Server).retrieveBindedAddress();
pop3Client.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort());

Username username = Username.of("topzero");
usersRepository.addUser(username, "password");

MailboxPath mailboxPath = MailboxPath.inbox(username);
MailboxSession session = mailboxManager.authenticate(username, "password").withoutDelegation();
mailboxManager.createMailbox(mailboxPath, session);
setupTestMails(session, mailboxManager.getMailbox(mailboxPath, session));

pop3Client.login("topzero", "password");
POP3MessageInfo[] entries = pop3Client.listMessages();

Reader reader = pop3Client.retrieveMessageTop(entries[0].number, 0);
assertThat(reader).isNotNull();

StringBuilder responseBody = new StringBuilder();
char[] buffer = new char[1024];
int n;
while ((n = reader.read(buffer)) != -1) {
responseBody.append(buffer, 0, n);
}
reader.close();

String response = responseBody.toString();
assertThat(response).contains("Return-path: return@test.com");
assertThat(response).contains("Subject: test");
assertThat(response).doesNotContain("Body Text POP3ServerTest.setupTestMails");

mailboxManager.deleteMailbox(mailboxPath, session);
}

@Test
void pop3SessionShouldTolerateConcurrentDeletes() throws Exception {
finishSetUp(pop3Configuration);
Expand Down