private Stream<Mapping> recurseMapping(Stream<Mapping> nonRecursiveResult, User targetUser, int remainingLoops) throws ErrorMappingException, RecipientRewriteTableException { Mappings childMappings = getMappings(targetUser, remainingLoops - 1); if (childMappings.isEmpty()) { return nonRecursiveResult; } else { return childMappings.asStream(); } }
@Override public void removeMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException { Mappings map = getUserDomainMappings(source); if (map.size() > 1) { Mappings updatedMappings = map.remove(mapping); doUpdateMapping(source, updatedMappings.serialize()); } else { doRemoveMapping(source, mapping.asString()); } }
@GET @Path(DOMAIN_MAPPINGS) @ApiOperation(value = "Lists all domain mappings.") @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "Domain mappings.", responseContainer = "Map"), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public Map<String, List<String>> getAllMappings(Request request, Response response) throws RecipientRewriteTableException { return recipientRewriteTable.getAllMappings() .entrySet() .stream() .filter(mappingsEntry -> !mappingsEntry.getValue().isEmpty()) .filter(mappingsEntry -> mappingsEntry.getValue().contains(Mapping.Type.Domain)) .collect(Guavate.toImmutableMap( mappingsEntry -> mappingsEntry.getKey().getFixedDomain(), mappingsEntry -> toDomainList(mappingsEntry.getValue()) )); }
@Override protected Mappings mapAddress(String user, Domain domain) throws RecipientRewriteTableException { Mappings mapping = getMapping(user, domain, "selectExactMappings"); if (!mapping.isEmpty()) { return mapping; } return getMapping(user, domain, "selectMappings"); }
private void updateConfiguration(MappingSource source, Mappings oldMappings, Mappings updatedMappings) throws RecipientRewriteTableException { if (oldMappings != null) { removeMappingsFromConfig(source, oldMappings); } if (!updatedMappings.isEmpty()) { defaultConfiguration.addProperty("mapping", source.getFixedUser() + "@" + source.getFixedDomain() + "=" + updatedMappings.serialize()); } try { virtualUserTable.configure(defaultConfiguration); } catch (Exception e) { if (updatedMappings.size() > 0) { throw new RecipientRewriteTableException("Error update mapping", e); } } }
@GET @Path(SPECIFIC_MAPPING_PATH) @ApiOperation(value = "Lists mappings for specific domain.") @ApiImplicitParams({ @ApiImplicitParam(required = true, dataType = "string", name = FROM_DOMAIN, paramType = "path") }) @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "Domain mappings.", responseContainer = "List"), @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "Not existing mappings."), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public List<String> getMapping(Request request, Response response) throws RecipientRewriteTableException { MappingSource mappingSource = mappingSourceFrom(request); return Optional.ofNullable(recipientRewriteTable.getUserDomainMappings(mappingSource).select(Mapping.Type.Domain)) .filter(mappings -> !mappings.isEmpty()) .filter(mappings -> mappings.contains(Mapping.Type.Domain)) .map(this::toDomainList) .orElseThrow(() -> ErrorResponder.builder() .statusCode(HttpStatus.NOT_FOUND_404) .type(ErrorResponder.ErrorType.NOT_FOUND) .message(String.format("Cannot find mappings for %s", mappingSource.getFixedDomain())) .haltError()); }
@Override public void addMapping(MappingSource source, Mapping mapping) throws RecipientRewriteTableException { Mappings map = getUserDomainMappings(source); if (!map.isEmpty()) { Mappings updatedMappings = MappingsImpl.from(map).add(mapping).build(); doUpdateMapping(source, updatedMappings.serialize()); } else { doAddMapping(source, mapping.asString()); } }
@VisibleForTesting List<MailAddress> handleMappings(Mappings mappings, Mail mail, MailAddress recipient) { boolean isLocal = true; Map<Boolean, List<MailAddress>> mailAddressSplit = mappings.asStream() .map(mapping -> mapping.appendDomainIfNone(defaultDomainSupplier)) .map(Mapping::asMailAddress) .flatMap(OptionalUtils::toStream) .collect(Collectors.partitioningBy(mailAddress -> mailetContext.isLocalServer(mailAddress.getDomain()))); forwardToRemoteAddress(mail, recipient, mailAddressSplit.get(!isLocal)); return mailAddressSplit.get(isLocal); }
@GET @Path(ROOT_PATH) @ApiOperation(value = "getting groups list") @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public Set<String> listGroups(Request request, Response response) throws RecipientRewriteTableException { return Optional.ofNullable(recipientRewriteTable.getAllMappings()) .map(mappings -> mappings.entrySet().stream() .filter(e -> e.getValue().contains(Mapping.Type.Group)) .map(Map.Entry::getKey) .flatMap(source -> OptionalUtils.toStream(source.asMailAddress())) .map(MailAddress::asString) .collect(Guavate.toImmutableSortedSet())) .orElse(ImmutableSortedSet.of()); }
if (mappings.size() == 0) { return null; } else {
protected void removeMappingFromConfiguration(MappingSource source, String mapping, Type type) throws RecipientRewriteTableException { Mappings oldMappings = Optional.ofNullable(virtualUserTable.getUserDomainMappings(source)) .orElseThrow(() -> new RecipientRewriteTableException("Cannot remove from null mappings")); Mappings updatedMappings = oldMappings.remove(Mapping.of(type, mapping)); updateConfiguration(source, oldMappings, updatedMappings); }
private void removeMappingsFromConfig(MappingSource source, Mappings mappings) { List<String> stored = new ArrayList<>(); for (String c : defaultConfiguration.getStringArray("mapping")) { String mapping = source.getFixedUser() + "@" + source.getFixedDomain() + "=" + mappings.serialize(); if (!c.equalsIgnoreCase(mapping)) { stored.add(c); } } // clear old values defaultConfiguration.clear(); // add stored mappings for (String aStored : stored) { defaultConfiguration.addProperty("mapping", aStored); } } }
private boolean isRedirected(MailAddress recipient, String username) { LOGGER.debug("Unknown user {} check if it's an alias", username); try { Mappings targetString = recipientRewriteTable.getMappings(recipient.getLocalPart(), recipient.getDomain()); if (!targetString.isEmpty()) { return true; } } catch (ErrorMappingException e) { return true; } catch (RecipientRewriteTableException e) { LOGGER.info("Unable to access RecipientRewriteTable", e); return false; } return false; }
@GET @Path(ROOT_PATH + "/{" + GROUP_ADDRESS + "}") @ApiOperation(value = "listing group members") @ApiImplicitParams({ @ApiImplicitParam(required = true, dataType = "string", name = GROUP_ADDRESS, paramType = "path") }) @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class), @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The group is not an address"), @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The group does not exist"), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public ImmutableSortedSet<String> listGroupMembers(Request request, Response response) throws RecipientRewriteTableException { MailAddress groupAddress = parseMailAddress(request.params(GROUP_ADDRESS)); Mappings mappings = Optional.ofNullable(recipientRewriteTable.getUserDomainMappings(MappingSource.fromMailAddress(groupAddress))) .orElse(MappingsImpl.empty()) .select(Mapping.Type.Group); ensureNonEmptyMappings(mappings); return mappings .asStream() .map(Mapping::asMailAddress) .flatMap(OptionalUtils::toStream) .map(MailAddress::asString) .collect(Guavate.toImmutableSortedSet()); }
public void tearDown() throws Exception { Map<MappingSource, Mappings> mappings = virtualUserTable.getAllMappings(); if (mappings != null) { for (MappingSource key : virtualUserTable.getAllMappings().keySet()) { Mappings map = mappings.get(key); map.asStream() .forEach(Throwing.consumer(mapping -> virtualUserTable.removeMapping(key, mapping))); } } LifecycleUtil.dispose(virtualUserTable); }
@GET @Path(ROOT_PATH) @ApiOperation(value = "getting forwards list") @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public Set<String> listForwards(Request request, Response response) throws RecipientRewriteTableException { return Optional.ofNullable(recipientRewriteTable.getAllMappings()) .map(mappings -> mappings.entrySet().stream() .filter(e -> e.getValue().contains(Mapping.Type.Forward)) .map(Map.Entry::getKey) .flatMap(source -> OptionalUtils.toStream(source.asMailAddress())) .map(MailAddress::asString) .collect(Guavate.toImmutableSortedSet())) .orElse(ImmutableSortedSet.of()); }
private RrtExecutionResult executeRrtForRecipient(Mail mail, MailAddress recipient) { try { Mappings mappings = virtualTableStore.getMappings(recipient.getLocalPart(), recipient.getDomain()); if (mappings != null && !mappings.isEmpty()) { List<MailAddress> newMailAddresses = handleMappings(mappings, mail, recipient); return RrtExecutionResult.success(newMailAddresses); } return RrtExecutionResult.success(recipient); } catch (ErrorMappingException | RecipientRewriteTableException e) { LOGGER.warn("Could not rewrite recipient {}", recipient, e); return RrtExecutionResult.error(recipient); } }
@GET @Path(ROOT_PATH + "/{" + FORWARD_BASE_ADDRESS + "}") @ApiOperation(value = "listing forward destinations") @ApiImplicitParams({ @ApiImplicitParam(required = true, dataType = "string", name = FORWARD_BASE_ADDRESS, paramType = "path") }) @ApiResponses(value = { @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class), @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "The forward is not an address"), @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The forward does not exist"), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.") }) public ImmutableSet<ForwardDestinationResponse> listForwardDestinations(Request request, Response response) throws RecipientRewriteTableException { MailAddress baseAddress = parseMailAddress(request.params(FORWARD_BASE_ADDRESS)); Mappings mappings = Optional.ofNullable(recipientRewriteTable.getUserDomainMappings(MappingSource.fromMailAddress(baseAddress))) .orElse(MappingsImpl.empty()) .select(Mapping.Type.Forward); ensureNonEmptyMappings(mappings); return mappings.asStream() .map(mapping -> mapping.asMailAddress() .orElseThrow(() -> new IllegalStateException(String.format("Can not compute address for mapping %s", mapping.asString())))) .map(MailAddress::asString) .sorted() .map(ForwardDestinationResponse::new) .collect(Guavate.toImmutableSet()); }
private Mappings getMappings(User user, int mappingLimit) throws ErrorMappingException, RecipientRewriteTableException { // We have to much mappings throw ErrorMappingException to avoid // infinity loop if (mappingLimit == 0) { throw new TooManyMappingException("554 Too many mappings to process"); } Mappings targetMappings = mapAddress(user.getLocalPart(), user.getDomainPart().get()); try { return MappingsImpl.fromMappings( targetMappings.asStream() .flatMap(Throwing.function((Mapping target) -> convertAndRecurseMapping(user, target, mappingLimit)).sneakyThrow())); } catch (SkipMappingProcessingException e) { return MappingsImpl.empty(); } }