Skip to content

Commit

Permalink
JAMES-1854 VirtualHosting should be managed by UsersRepository
Browse files Browse the repository at this point in the history
  • Loading branch information
chibenwa committed Nov 18, 2016
1 parent f719e2f commit b4a31c7
Show file tree
Hide file tree
Showing 16 changed files with 98 additions and 62 deletions.
Expand Up @@ -22,6 +22,7 @@
import java.util.Iterator;

import org.apache.james.user.api.model.User;
import org.apache.mailet.MailAddress;

/**
* Interface for a repository of users. A repository represents a logical
Expand Down Expand Up @@ -127,4 +128,13 @@ public interface UsersRepository {
*/
boolean supportVirtualHosting() throws UsersRepositoryException;

/**
* Returns username to be used for a given MailAddress
*
* @param mailAddress
* @return Username used by James for this mailAddress
* @throws UsersRepositoryException
*/
String getUser(MailAddress mailAddress) throws UsersRepositoryException;

}
Expand Up @@ -51,6 +51,7 @@
import org.apache.james.util.retry.DoublingRetrySchedule;
import org.apache.james.util.retry.api.RetrySchedule;
import org.apache.james.util.retry.naming.ldap.RetryingLdapContext;
import org.apache.mailet.MailAddress;
import org.slf4j.Logger;

/**
Expand Down Expand Up @@ -761,4 +762,9 @@ public boolean supportVirtualHosting() {
return false;
}


@Override
public String getUser(MailAddress mailAddress) throws UsersRepositoryException {
return mailAddress.getLocalPart();
}
}
Expand Up @@ -30,6 +30,7 @@
import org.apache.james.user.api.AlreadyExistInUsersRepositoryException;
import org.apache.james.user.api.UsersRepository;
import org.apache.james.user.api.UsersRepositoryException;
import org.apache.mailet.MailAddress;
import org.slf4j.Logger;

public abstract class AbstractUsersRepository implements UsersRepository, LogEnabled, Configurable {
Expand Down Expand Up @@ -132,4 +133,13 @@ public boolean supportVirtualHosting() {
* If an error occurred
*/
protected abstract void doAddUser(String username, String password) throws UsersRepositoryException;

@Override
public String getUser(MailAddress mailAddress) throws UsersRepositoryException {
if (supportVirtualHosting()) {
return mailAddress.print();
} else {
return mailAddress.getLocalPart();
}
}
}
Expand Up @@ -23,12 +23,16 @@
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.commons.lang.NotImplementedException;
import org.apache.james.domainlist.api.mock.SimpleDomainList;
import org.apache.james.lifecycle.api.LifecycleUtil;
import org.apache.james.user.api.AlreadyExistInUsersRepositoryException;
import org.apache.james.user.api.UsersRepository;
import org.apache.james.user.api.UsersRepositoryException;
import org.apache.james.user.api.model.User;
import org.apache.mailet.MailAddress;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -299,6 +303,25 @@ public void updateUserShouldThrowWhenAUserIsNoMoreInRepository() throws UsersRep
usersRepository.updateUser(user);
}

@Test
public void virtualHostedUsersRepositoryShouldUseFullMailAddressAsUsername() throws Exception {
usersRepository.setEnableVirtualHosting(true);

// Some implementations do not support changing virtual hosting value
Assume.assumeTrue(usersRepository.supportVirtualHosting());

assertThat(usersRepository.getUser(new MailAddress("local@domain"))).isEqualTo("local@domain");
}

@Test
public void nonVirtualHostedUsersRepositoryShouldUseLocalPartAsUsername() throws Exception {
usersRepository.setEnableVirtualHosting(false);

// Some implementations do not support changing virtual hosting value
Assume.assumeFalse(usersRepository.supportVirtualHosting());

assertThat(usersRepository.getUser(new MailAddress("local@domain"))).isEqualTo("local");
}

protected void disposeUsersRepository() throws UsersRepositoryException {
LifecycleUtil.dispose(this.usersRepository);
Expand Down
Expand Up @@ -258,16 +258,11 @@ public boolean isLocalUser(String name) {
@Override
public boolean isLocalEmail(MailAddress mailAddress) {
if (mailAddress != null) {
String userName = mailAddress.toString().toLowerCase();
if (!isLocalServer(mailAddress.getDomain().toLowerCase())) {
return false;
}
try {
if (!localusers.supportVirtualHosting()) {
userName = mailAddress.getLocalPart().toLowerCase();
}
return localusers.contains(userName);

return localusers.contains(localusers.getUser(mailAddress));
} catch (UsersRepositoryException e) {
log("Unable to access UsersRepository", e);
}
Expand Down
Expand Up @@ -84,17 +84,7 @@ public void service(Mail mail) throws MessagingException {
private void doService(Mail mail) throws MessagingException {

final MailAddress sender = mail.getSender();
String username;
try {
if (usersRepository.supportVirtualHosting()) {
username = sender.toString();
}
else {
username = sender.getLocalPart();
}
} catch (UsersRepositoryException e) {
throw new MessagingException(e.getMessage());
}
String username = retrieveUser(sender);

final MailboxSession session;
try {
Expand Down Expand Up @@ -140,6 +130,14 @@ private void doService(Mail mail) throws MessagingException {

}

private String retrieveUser(MailAddress sender) throws MessagingException {
try {
return usersRepository.getUser(sender);
} catch (UsersRepositoryException e) {
throw new MessagingException(e.getMessage());
}
}

/* (non-Javadoc)
* @see org.apache.mailet.base.GenericMailet#init()
*/
Expand Down
Expand Up @@ -79,11 +79,14 @@ private void append(MimeMessage mail, String user, String folder, MailboxSession
} finally {
session.close();
try {
mailboxManager.logout(session, true);
} catch (MailboxException e) {
throw new MessagingException("Can logout from mailbox", e);
try {
mailboxManager.logout(session, true);
} catch (MailboxException e) {
throw new MessagingException("Can logout from mailbox", e);
}
} finally {
mailboxManager.endProcessingRequest(session);
}
mailboxManager.endProcessingRequest(session);
}
}

Expand All @@ -93,7 +96,7 @@ private void appendMessageToMailbox(MimeMessage mail, MailboxSession session, Ma
}
final MessageManager mailbox = mailboxManager.getMailbox(path, session);
if (mailbox == null) {
throw new MessagingException("Mailbox for user " + session.getUser().getUserName() + " was not found on this server.");
throw new MessagingException("Mailbox " + path + " for user " + session.getUser().getUserName() + " was not found on this server.");
}
mailbox.appendMessage(new MimeMessageInputStream(mail), new Date(), session, IS_RECENT, FLAGS);
}
Expand Down
Expand Up @@ -94,11 +94,7 @@ public void storeMail(MailAddress sender, MailAddress recipient, Mail mail) thro

private String computeUsername(MailAddress recipient) throws MessagingException {
try {
if (usersRepository.supportVirtualHosting()) {
return recipient.toString();
} else {
return recipient.getLocalPart();
}
return usersRepository.getUser(recipient);
} catch (UsersRepositoryException e) {
log.error("Unable to access UsersRepository", e);
return recipient.toString();
Expand Down
Expand Up @@ -180,20 +180,19 @@ protected void handleFailure(MailAddress recipient, Mail aMail, Exception ex) th
}

protected void storeMessageInbox(MailAddress mailAddress, MimeMessage message) throws MessagingException {
sievePoster.post("mailbox://" + mailAddress + "/", message);
sievePoster.post("mailbox://" + retrieveUserNameUsedForScriptStorage(mailAddress) + "/", message);
}

public String retrieveUserNameUsedForScriptStorage(MailAddress m) {
public String retrieveUserNameUsedForScriptStorage(MailAddress mailAddress) {
try {
if (usersRepos.supportVirtualHosting()) {
return m.toString();
return mailAddress.print();
} else {
return m.getLocalPart() + "@localhost";
return mailAddress.getLocalPart() + "@localhost";
}
} catch (UsersRepositoryException e) {
log.error("Unable to access UsersRepository", e);
return m.getLocalPart() + "@localhost";

return mailAddress.getLocalPart() + "@localhost";
}
}
}
Expand Up @@ -26,6 +26,7 @@
import org.apache.james.transport.mailets.jsieve.Poster;
import org.apache.james.user.api.UsersRepository;
import org.apache.james.user.api.UsersRepositoryException;
import org.apache.mailet.MailAddress;

public class SievePoster implements Poster {

Expand Down Expand Up @@ -86,10 +87,7 @@ private String parseUser(String url, int startOfUser, int endOfUser, String host
String user = url.substring(startOfUser, endOfUser).toLowerCase();
// Check if we should use the full email address as username
try {
if (usersRepos.supportVirtualHosting()) {
return user + "@" + host;
}
return user;
return usersRepos.getUser(new MailAddress(user, host));
} catch (UsersRepositoryException e) {
throw new MessagingException("Unable to accessUsersRepository", e);
}
Expand Down
Expand Up @@ -112,12 +112,7 @@ protected long getUsed(MailAddress recipient, Mail _) throws MessagingException
try {
// see if we need use the full email address as username or not.
// See JAMES-1197
if (localUsers.supportVirtualHosting()) {
username = recipient.toString().toLowerCase(Locale.US);
}
else {
username = recipient.getLocalPart().toLowerCase(Locale.US);
}
username = localUsers.getUser(recipient).toLowerCase(Locale.US);
}
catch (UsersRepositoryException e) {
throw new MessagingException("Unable to access UsersRepository", e);
Expand Down
Expand Up @@ -72,6 +72,8 @@
@RunWith(Parameterized.class)
public class LocalDeliveryTest {

public static final String RECEIVER_DOMAIN_COM = "receiver@domain.com";

public static class Parameter {
private final UsersRepository usersRepository;
private final MailboxManager mailboxManager;
Expand Down Expand Up @@ -163,6 +165,7 @@ public void mailShouldBeWellDeliveredByDefaultToUserWhenVirtualHostingIsTurnedOn
MessageManager messageManager = mock(MessageManager.class);

when(parameter.getUsersRepository().supportVirtualHosting()).thenReturn(true);
when(parameter.getUsersRepository().getUser(new MailAddress(username))).thenReturn(username);
doThrow(new ScriptNotFoundException()).when(parameter.getSieveRepository()).getActive(username);
when(parameter.getMailboxManager().getMailbox(eq(inbox), any(MailboxSession.class))).thenReturn(messageManager);
when(parameter.getUser().getUserName()).thenReturn(username);
Expand All @@ -183,6 +186,8 @@ public void mailShouldBeWellDeliveredByDefaultToUserWhenVirtualHostingIsTurnedOf
MailboxPath inbox = new MailboxPath("#private", username, "INBOX");
MessageManager messageManager = mock(MessageManager.class);
when(parameter.getUsersRepository().supportVirtualHosting()).thenReturn(false);
when(parameter.getUsersRepository().getUser(new MailAddress("receiver@localhost"))).thenReturn(username);
when(parameter.getUsersRepository().getUser(new MailAddress(RECEIVER_DOMAIN_COM))).thenReturn(username);
doThrow(new ScriptNotFoundException()).when(parameter.getSieveRepository()).getActive(username);
when(parameter.getMailboxManager().getMailbox(eq(inbox), any(MailboxSession.class))).thenReturn(messageManager);
when(parameter.getUser().getUserName()).thenReturn(username);
Expand All @@ -200,7 +205,7 @@ private Mail createMail() throws MessagingException, IOException {
MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
message.setSubject("Subject");
message.setSender(new InternetAddress("sender@any.com"));
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("receiver@domain.com"));
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(RECEIVER_DOMAIN_COM));
MimeMultipart multipart = new MimeMultipart();
MimeBodyPart scriptPart = new MimeBodyPart();
scriptPart.setDataHandler(
Expand Down
Expand Up @@ -118,6 +118,7 @@ public void setUp() throws Exception {
@Test
public void mailShouldBeWellDeliveredByDefaultToUserWhenVirtualHostingIsTurnedOn() throws Exception {
when(usersRepository.supportVirtualHosting()).thenReturn(true);
when(usersRepository.getUser(new MailAddress(RECEIVER_DOMAIN_COM))).thenReturn(RECEIVER_DOMAIN_COM);
when(resourceLocator.get(RECEIVER_DOMAIN_COM)).thenThrow(new ScriptNotFoundException());
final MessageManager messageManager = prepareMessageManagerOn(new MailboxPath("#private", RECEIVER_DOMAIN_COM, "INBOX"));

Expand All @@ -129,6 +130,7 @@ public void mailShouldBeWellDeliveredByDefaultToUserWhenVirtualHostingIsTurnedOn
@Test
public void mailShouldBeWellDeliveredByDefaultToUserWhenvirtualHostingIsTurnedOff() throws Exception {
when(usersRepository.supportVirtualHosting()).thenReturn(false);
when(usersRepository.getUser(new MailAddress("receiver@localhost"))).thenReturn("receiver");
when(resourceLocator.get("receiver")).thenThrow(new ScriptNotFoundException());
final MessageManager messageManager = prepareMessageManagerOn(INBOX);

Expand Down Expand Up @@ -964,6 +966,7 @@ private void prepareTestUsingScript(final String script) throws Exception {

private void prepareTestUsingScriptAndDates(String script, DateTime scriptCreationDate, DateTime scriptExecutionDate) throws Exception {
when(usersRepository.supportVirtualHosting()).thenReturn(false);
when(usersRepository.getUser(new MailAddress("receiver@localhost"))).thenReturn("receiver");
when(resourceLocator.get("//receiver@localhost/sieve")).thenReturn(new ResourceLocator.UserSieveInformation(scriptCreationDate,
scriptExecutionDate,
ClassLoader.getSystemResourceAsStream(script)));
Expand Down
Expand Up @@ -79,24 +79,22 @@ public void setUp() throws Exception {

@Test
public void storeMailShouldUseFullMailAddressWhenSupportsVirtualHosting() throws Exception {
when(usersRepository.supportVirtualHosting()).thenReturn(true);

MailAddress sender = MailAddressFixture.ANY_AT_JAMES;
MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES;
when(usersRepository.getUser(recipient)).thenReturn(recipient.print());
FakeMail mail = FakeMail.builder()
.mimeMessage(mimeMessage)
.build();
testee.storeMail(sender, recipient, mail);

verify(mailboxAppender).append(any(MimeMessage.class), eq(recipient.toString()), eq(FOLDER));
verify(mailboxAppender).append(any(MimeMessage.class), eq(recipient.print()), eq(FOLDER));
}

@Test
public void storeMailShouldUseLocalPartWhenSupportsVirtualHosting() throws Exception {
when(usersRepository.supportVirtualHosting()).thenReturn(false);

MailAddress sender = MailAddressFixture.ANY_AT_JAMES;
MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES;
when(usersRepository.getUser(recipient)).thenReturn(recipient.getLocalPart());
FakeMail mail = FakeMail.builder()
.mimeMessage(mimeMessage)
.build();
Expand All @@ -107,10 +105,9 @@ public void storeMailShouldUseLocalPartWhenSupportsVirtualHosting() throws Excep

@Test
public void storeMailShouldUseFullMailAddressWhenErrorReadingUsersRepository() throws Exception {
when(usersRepository.supportVirtualHosting()).thenThrow(new UsersRepositoryException("Any message"));

MailAddress sender = MailAddressFixture.ANY_AT_JAMES;
MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES;
when(usersRepository.getUser(recipient)).thenThrow(new UsersRepositoryException("Any message"));
FakeMail mail = FakeMail.builder()
.mimeMessage(mimeMessage)
.build();
Expand Down
Expand Up @@ -187,6 +187,7 @@ public void consumeOptionShouldNotGhostTheMailByDefault() throws Exception {
@Test
public void folderParameterShouldIndicateDestinationFolder() throws Exception {
when(parameter.getUsersRepository().supportVirtualHosting()).thenReturn(true);
when(parameter.getUsersRepository().getUser(new MailAddress(USER))).thenReturn(USER);
when(parameter.getMailboxManager().getMailbox(eq(JUNK_VIRTUAL_HOSTING), any(MailboxSession.class))).thenReturn(messageManager);
when(parameter.getUser().getUserName()).thenReturn(USER);

Expand All @@ -200,6 +201,7 @@ public void folderParameterShouldIndicateDestinationFolder() throws Exception {
@Test
public void folderParameterShouldBeInboxByDefault() throws Exception {
when(parameter.getUsersRepository().supportVirtualHosting()).thenReturn(true);
when(parameter.getUsersRepository().getUser(new MailAddress(USER))).thenReturn(USER);
when(parameter.getMailboxManager().getMailbox(eq(INBOX), any(MailboxSession.class))).thenReturn(messageManager);
when(parameter.getUser().getUserName()).thenReturn(USER);

Expand All @@ -212,6 +214,8 @@ public void folderParameterShouldBeInboxByDefault() throws Exception {
@Test
public void folderParameterShouldWorkWhenVirtualHostingIsTurnedOff() throws Exception {
when(parameter.getUsersRepository().supportVirtualHosting()).thenReturn(false);
when(parameter.getUsersRepository().getUser(new MailAddress(USER_LOCAL_PART + "@localhost"))).thenReturn(USER_LOCAL_PART);
when(parameter.getUsersRepository().getUser(new MailAddress(USER))).thenReturn(USER_LOCAL_PART);
when(parameter.getMailboxManager().getMailbox(eq(JUNK), any(MailboxSession.class))).thenReturn(messageManager);
when(parameter.getUser().getUserName()).thenReturn(USER_LOCAL_PART);

Expand Down

0 comments on commit b4a31c7

Please sign in to comment.