{"action":"created","comment":{"url":"https://api.github.com/repos/linagora/james-project/pulls/comments/89054252","pull_request_review_id":9604365,"id":89054252,"diff_hunk":"@@ -0,0 +1,309 @@\n+/****************************************************************\n+ * Licensed to the Apache Software Foundation (ASF) under one   *\n+ * or more contributor license agreements.  See the NOTICE file *\n+ * distributed with this work for additional information        *\n+ * regarding copyright ownership.  The ASF licenses this file   *\n+ * to you under the Apache License, Version 2.0 (the            *\n+ * \"License\"); you may not use this file except in compliance   *\n+ * with the License.  You may obtain a copy of the License at   *\n+ *                                                              *\n+ *   http://www.apache.org/licenses/LICENSE-2.0                 *\n+ *                                                              *\n+ * Unless required by applicable law or agreed to in writing,   *\n+ * software distributed under the License is distributed on an  *\n+ * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *\n+ * KIND, either express or implied.  See the License for the    *\n+ * specific language governing permissions and limitations      *\n+ * under the License.                                           *\n+ ****************************************************************/\n+\n+package org.apache.james.transport.mailets;\n+\n+import java.util.List;\n+\n+import javax.mail.MessagingException;\n+import javax.mail.internet.AddressException;\n+import javax.mail.internet.MimeMessage;\n+\n+import org.apache.james.domainlist.api.DomainList;\n+import org.apache.james.domainlist.api.DomainListException;\n+import org.apache.james.rrt.api.RecipientRewriteTable;\n+import org.apache.james.rrt.api.RecipientRewriteTable.ErrorMappingException;\n+import org.apache.james.rrt.api.RecipientRewriteTableException;\n+import org.apache.james.rrt.lib.Mapping;\n+import org.apache.james.rrt.lib.Mappings;\n+import org.apache.mailet.Mail;\n+import org.apache.mailet.MailAddress;\n+import org.apache.mailet.MailetContext;\n+import org.apache.mailet.MailetContext.LogLevel;\n+\n+import com.google.common.annotations.VisibleForTesting;\n+import com.google.common.base.Function;\n+import com.google.common.base.Optional;\n+import com.google.common.base.Preconditions;\n+import com.google.common.base.Predicate;\n+import com.google.common.collect.FluentIterable;\n+import com.google.common.collect.ImmutableList;\n+\n+/**\n+ * Abstract base class which should get extended by classes which handle mapping\n+ * operations based on RecipientRewriteTable implementations\n+ */\n+public class RecipientRewriteTableProcessor {\n+    private final org.apache.james.rrt.api.RecipientRewriteTable virtualTableStore;\n+    private final DomainList domainList;\n+\n+    private static final Predicate<MappingData> recipientWithError = new Predicate<MappingData>() {\n+        @Override\n+        public boolean apply(MappingData mappingData) {\n+            return mappingData.getRecipientWithError().isPresent();\n+        }\n+    };\n+\n+    private static final Predicate<MappingData> recipientWithoutError = new Predicate<MappingData>() {\n+        @Override\n+        public boolean apply(MappingData mappingData) {\n+            return mappingData.getNewMappings().isPresent();\n+        }\n+    };\n+\n+    private static final Predicate<Mapping> noneDomain = new Predicate<Mapping>() {\n+        @Override\n+        public boolean apply(Mapping address) {\n+            return !address.hasDomain();\n+        }\n+    };\n+\n+    private static final Predicate<Mapping> haveDomain = new Predicate<Mapping>() {\n+        @Override\n+        public boolean apply(Mapping address) {\n+            return address.hasDomain();\n+        }\n+    };\n+\n+    private static final Function<MappingData, List<MailAddress>> mailAddressesFromMappingData = new Function<RecipientRewriteTableProcessor.MappingData, List<MailAddress>>() {\n+        @Override\n+        public List<MailAddress> apply(MappingData mappingData) {\n+            return mappingData.getNewMappings()\n+                .or(mappingData.getRecipientWithError()\n+                    .or(ImmutableList.<MailAddress>of()));\n+        }\n+    };\n+\n+    private static final Function<Optional<MailAddress>, MailAddress> mailAddressFromOptional = new Function<Optional<MailAddress>, MailAddress>() {\n+        @Override\n+        public MailAddress apply(Optional<MailAddress> mailAddress) {\n+            return mailAddress.get();\n+        }\n+    };\n+\n+    private static final Predicate<Optional<MailAddress>> mailAddressPresent = new Predicate<Optional<MailAddress>>() {\n+        @Override\n+        public boolean apply(Optional<MailAddress> mailAddress) {\n+            return mailAddress.isPresent();\n+        }\n+    };\n+\n+    private static final Function<Mapping, Optional<MailAddress>> mailAddressFromMapping = new Function<Mapping, Optional<MailAddress>>() {\n+        @Override\n+        public Optional<MailAddress> apply(Mapping addressMapping) {\n+            try {\n+                return Optional.of(new MailAddress(addressMapping.asString()));\n+            } catch (AddressException e) {\n+                return Optional.absent();\n+            }\n+        }\n+    };\n+\n+    public RecipientRewriteTableProcessor(RecipientRewriteTable virtualTableStore, DomainList domainList) {\n+        this.virtualTableStore = virtualTableStore;\n+        this.domainList = domainList;\n+    }\n+\n+    public void processMail(Mail mail, MailetContext mailetContext) throws MessagingException{\n+        ImmutableList<MappingData> mappingDatas = convertToMappingDatas(mail, mailetContext);\n+\n+        ImmutableList<MailAddress> newRecipients = filterRecipients(mappingDatas, recipientWithoutError);\n+\n+        ImmutableList<MailAddress> errorMailAddresses = filterRecipients(mappingDatas, recipientWithError);\n+\n+        if (!errorMailAddresses.isEmpty()) {\n+            mailetContext.sendMail(mail.getSender(), errorMailAddresses, mail.getMessage(), Mail.ERROR);\n+        }\n+\n+        if (newRecipients.isEmpty()) {\n+            mail.setState(Mail.GHOST);\n+        }\n+\n+        mail.setRecipients(newRecipients);\n+    }\n+\n+    private ImmutableList<MailAddress> filterRecipients(ImmutableList<MappingData> mappingDatas, Predicate<MappingData> filterCondition) {\n+        return FluentIterable.from(mappingDatas)\n+            .filter(filterCondition)\n+            .transformAndConcat(mailAddressesFromMappingData)\n+            .toList();\n+    }\n+\n+    private ImmutableList<MappingData> convertToMappingDatas(Mail mail, MailetContext mailetContext) {\n+        return FluentIterable.from(mail.getRecipients())\n+            .transform(convertToMappingData(mail, mailetContext))\n+            .toList();\n+    }\n+\n+    @VisibleForTesting\n+    List<MailAddress> handleMappings(Mappings mappings, MailAddress sender, MailAddress recipient, MimeMessage message,\n+                                                  MailetContext context, DomainList domainList) throws MessagingException {\n+        ImmutableList<Mapping> addressMappingWithoutDomains = getAddressWithNoDomain(mappings, domainList);\n+\n+        ImmutableList<Mapping> newAddressMappings = convertToNewMappings(mappings, addressMappingWithoutDomains);\n+\n+        ImmutableList<MailAddress> mailAddresses = buildMailAddressFromMappingAddress(newAddressMappings);\n+\n+        forwardToRemoteAddress(sender, recipient, message, mailAddresses, context);\n+\n+        return getLocalAddresses(mailAddresses, context);\n+    }\n+\n+    private ImmutableList<Mapping> convertToNewMappings(final Mappings mappings,\n+            ImmutableList<Mapping> addressWithoutDomains) {\n+        return FluentIterable.from(mappings)\n+            .filter(haveDomain)\n+            .append(addressWithoutDomains)\n+            .toList();\n+    }\n+\n+    private ImmutableList<MailAddress> getLocalAddresses(ImmutableList<MailAddress> mailAddresses,\n+            final MailetContext context) {\n+        return FluentIterable.from(mailAddresses)\n+            .filter(isLocalServer(context))\n+            .toList();\n+    }\n+\n+    private ImmutableList<MailAddress> buildMailAddressFromMappingAddress(ImmutableList<Mapping> newMappings) {\n+        return FluentIterable.from(newMappings)\n+            .transform(mailAddressFromMapping)\n+            .filter(mailAddressPresent)\n+            .transform(mailAddressFromOptional)\n+            .toList();\n+    }\n+\n+    private ImmutableList<Mapping> getAddressWithNoDomain(Mappings mappings, DomainList domainList) throws MessagingException {\n+        ImmutableList<Mapping> addressWithoutDomains = FluentIterable.from(mappings)\n+            .filter(noneDomain)\n+            .toList();\n+        \n+        if (!addressWithoutDomains.isEmpty()) {\n+            final String defaultDomain = getDefaultDomain(domainList);\n+\n+            return FluentIterable.from(addressWithoutDomains)\n+                .transform(appendDefaultDomain(defaultDomain))\n+                .toList();\n+        }\n+        return ImmutableList.of();\n+    }\n+\n+    private Function<MailAddress, MappingData> convertToMappingData(final Mail mail, final MailetContext mailetContext) {\n+        return new Function<MailAddress, RecipientRewriteTableProcessor.MappingData>() {\n+            @Override\n+            public MappingData apply(MailAddress recipient) {\n+                Preconditions.checkNotNull(recipient);\n+                List<MailAddress> originMailAddresses = ImmutableList.of(recipient);\n+                try {\n+                    Mappings mappings = virtualTableStore.getMappings(recipient.getLocalPart(), recipient.getDomain());\n+\n+                    if (mappings != null) {\n+                        List<MailAddress> newMailAddresses = handleMappings(mappings, mail.getSender(), recipient, mail.getMessage(), mailetContext, domainList);\n+                        return new MappingData(Optional.of(newMailAddresses), Optional.<List<MailAddress>>absent());\n+                    }\n+                } catch (ErrorMappingException e) {\n+                    mailetContext.log(LogLevel.INFO, \"Error while process mail.\", e);\n+                    return new MappingData(Optional.<List<MailAddress>>absent(), Optional.<List<MailAddress>>of(originMailAddresses));\n+                } catch (RecipientRewriteTableException e) {\n+                    mailetContext.log(LogLevel.INFO, \"Error while process mail.\", e);\n+                    return new MappingData(Optional.<List<MailAddress>>absent(), Optional.<List<MailAddress>>of(originMailAddresses));\n+                } catch (MessagingException e) {\n+                    mailetContext.log(LogLevel.INFO, \"Error while process mail.\", e);\n+                    return new MappingData(Optional.<List<MailAddress>>absent(), Optional.<List<MailAddress>>of(originMailAddresses));\n+                }\n+                return new MappingData(Optional.<List<MailAddress>>of(originMailAddresses), Optional.<List<MailAddress>>absent());\n+            }\n+        };\n+    }\n+\n+    private Function<Mapping, Mapping> appendDefaultDomain(final String defaultDomain) {\n+        return new Function<Mapping, Mapping>() {\n+            @Override\n+            public Mapping apply(Mapping address) {\n+                return address.appendDomain(defaultDomain);\n+            }\n+        };\n+    }\n+\n+    private Predicate<MailAddress> isLocalServer(final MailetContext context) {\n+        return new Predicate<MailAddress>() {\n+            @Override\n+            public boolean apply(MailAddress mailAddress) {\n+                return context.isLocalServer(mailAddress.getDomain());\n+            }\n+        };\n+    }\n+\n+    private Predicate<MailAddress> isNotLocalServer(final MailetContext context) {\n+        return new Predicate<MailAddress>() {\n+            @Override\n+            public boolean apply(MailAddress mailAddress) {\n+                return !context.isLocalServer(mailAddress.getDomain());\n+            }\n+        };\n+    }\n+\n+    private void forwardToRemoteAddress(MailAddress sender, MailAddress recipient, MimeMessage message, ImmutableList<MailAddress> mailAddresses, final MailetContext context) throws MessagingException {\n+        ImmutableList<MailAddress> remoteAddress = FluentIterable.from(mailAddresses)\n+            .filter(isNotLocalServer(context))\n+            .toList();\n+\n+        if (!remoteAddress.isEmpty()) {\n+            StringBuilder logBuffer = new StringBuilder(128);\n+            try {\n+                context.sendMail(sender, remoteAddress, message);\n+                logBuffer.append(\"Mail for \")\n+                    .append(recipient).append(\" forwarded to \")\n+                    .append(remoteAddress);\n+            } catch (MessagingException ex) {\n+                logBuffer.append(\"Error forwarding mail to \")\n+                    .append(remoteAddress)\n+                    .append(\"attempting local delivery\");\n+            }\n+            context.log(LogLevel.INFO, logBuffer.toString());\n+","path":"server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java","position":279,"original_position":279,"commit_id":"45c5c02ae385b51645f5c4bf981357e6b4bb63df","original_commit_id":"45c5c02ae385b51645f5c4bf981357e6b4bb63df","user":{"login":"chibenwa","id":6928740,"avatar_url":"https://avatars.githubusercontent.com/u/6928740?v=3","gravatar_id":"","url":"https://api.github.com/users/chibenwa","html_url":"https://github.com/chibenwa","followers_url":"https://api.github.com/users/chibenwa/followers","following_url":"https://api.github.com/users/chibenwa/following{/other_user}","gists_url":"https://api.github.com/users/chibenwa/gists{/gist_id}","starred_url":"https://api.github.com/users/chibenwa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chibenwa/subscriptions","organizations_url":"https://api.github.com/users/chibenwa/orgs","repos_url":"https://api.github.com/users/chibenwa/repos","events_url":"https://api.github.com/users/chibenwa/events{/privacy}","received_events_url":"https://api.github.com/users/chibenwa/received_events","type":"User","site_admin":false},"body":"extra line","created_at":"2016-11-22T07:16:40Z","updated_at":"2016-11-22T07:16:40Z","html_url":"https://github.com/linagora/james-project/pull/430#discussion_r89054252","pull_request_url":"https://api.github.com/repos/linagora/james-project/pulls/430","_links":{"self":{"href":"https://api.github.com/repos/linagora/james-project/pulls/comments/89054252"},"html":{"href":"https://github.com/linagora/james-project/pull/430#discussion_r89054252"},"pull_request":{"href":"https://api.github.com/repos/linagora/james-project/pulls/430"}}},"pull_request":{"url":"https://api.github.com/repos/linagora/james-project/pulls/430","id":88014007,"html_url":"https://github.com/linagora/james-project/pull/430","diff_url":"https://github.com/linagora/james-project/pull/430.diff","patch_url":"https://github.com/linagora/james-project/pull/430.patch","issue_url":"https://api.github.com/repos/linagora/james-project/issues/430","number":430,"state":"open","locked":false,"title":"MAILET-Refactor: RecipientRewriteTable","user":{"login":"quynhn","id":296170,"avatar_url":"https://avatars.githubusercontent.com/u/296170?v=3","gravatar_id":"","url":"https://api.github.com/users/quynhn","html_url":"https://github.com/quynhn","followers_url":"https://api.github.com/users/quynhn/followers","following_url":"https://api.github.com/users/quynhn/following{/other_user}","gists_url":"https://api.github.com/users/quynhn/gists{/gist_id}","starred_url":"https://api.github.com/users/quynhn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quynhn/subscriptions","organizations_url":"https://api.github.com/users/quynhn/orgs","repos_url":"https://api.github.com/users/quynhn/repos","events_url":"https://api.github.com/users/quynhn/events{/privacy}","received_events_url":"https://api.github.com/users/quynhn/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-10-05T04:17:01Z","updated_at":"2016-11-22T07:28:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3f4e1a099034f95cb82fb670d80eadbdd8897253","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/linagora/james-project/pulls/430/commits","review_comments_url":"https://api.github.com/repos/linagora/james-project/pulls/430/comments","review_comment_url":"https://api.github.com/repos/linagora/james-project/pulls/comments{/number}","comments_url":"https://api.github.com/repos/linagora/james-project/issues/430/comments","statuses_url":"https://api.github.com/repos/linagora/james-project/statuses/45c5c02ae385b51645f5c4bf981357e6b4bb63df","head":{"label":"quynhn:MAILET-Refactor-RecipientRewriteTable","ref":"MAILET-Refactor-RecipientRewriteTable","sha":"45c5c02ae385b51645f5c4bf981357e6b4bb63df","user":{"login":"quynhn","id":296170,"avatar_url":"https://avatars.githubusercontent.com/u/296170?v=3","gravatar_id":"","url":"https://api.github.com/users/quynhn","html_url":"https://github.com/quynhn","followers_url":"https://api.github.com/users/quynhn/followers","following_url":"https://api.github.com/users/quynhn/following{/other_user}","gists_url":"https://api.github.com/users/quynhn/gists{/gist_id}","starred_url":"https://api.github.com/users/quynhn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quynhn/subscriptions","organizations_url":"https://api.github.com/users/quynhn/orgs","repos_url":"https://api.github.com/users/quynhn/repos","events_url":"https://api.github.com/users/quynhn/events{/privacy}","received_events_url":"https://api.github.com/users/quynhn/received_events","type":"User","site_admin":false},"repo":{"id":58912828,"name":"james-project","full_name":"quynhn/james-project","owner":{"login":"quynhn","id":296170,"avatar_url":"https://avatars.githubusercontent.com/u/296170?v=3","gravatar_id":"","url":"https://api.github.com/users/quynhn","html_url":"https://github.com/quynhn","followers_url":"https://api.github.com/users/quynhn/followers","following_url":"https://api.github.com/users/quynhn/following{/other_user}","gists_url":"https://api.github.com/users/quynhn/gists{/gist_id}","starred_url":"https://api.github.com/users/quynhn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quynhn/subscriptions","organizations_url":"https://api.github.com/users/quynhn/orgs","repos_url":"https://api.github.com/users/quynhn/repos","events_url":"https://api.github.com/users/quynhn/events{/privacy}","received_events_url":"https://api.github.com/users/quynhn/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/quynhn/james-project","description":"Mirror of Apache James Project","fork":true,"url":"https://api.github.com/repos/quynhn/james-project","forks_url":"https://api.github.com/repos/quynhn/james-project/forks","keys_url":"https://api.github.com/repos/quynhn/james-project/keys{/key_id}","collaborators_url":"https://api.github.com/repos/quynhn/james-project/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/quynhn/james-project/teams","hooks_url":"https://api.github.com/repos/quynhn/james-project/hooks","issue_events_url":"https://api.github.com/repos/quynhn/james-project/issues/events{/number}","events_url":"https://api.github.com/repos/quynhn/james-project/events","assignees_url":"https://api.github.com/repos/quynhn/james-project/assignees{/user}","branches_url":"https://api.github.com/repos/quynhn/james-project/branches{/branch}","tags_url":"https://api.github.com/repos/quynhn/james-project/tags","blobs_url":"https://api.github.com/repos/quynhn/james-project/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/quynhn/james-project/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/quynhn/james-project/git/refs{/sha}","trees_url":"https://api.github.com/repos/quynhn/james-project/git/trees{/sha}","statuses_url":"https://api.github.com/repos/quynhn/james-project/statuses/{sha}","languages_url":"https://api.github.com/repos/quynhn/james-project/languages","stargazers_url":"https://api.github.com/repos/quynhn/james-project/stargazers","contributors_url":"https://api.github.com/repos/quynhn/james-project/contributors","subscribers_url":"https://api.github.com/repos/quynhn/james-project/subscribers","subscription_url":"https://api.github.com/repos/quynhn/james-project/subscription","commits_url":"https://api.github.com/repos/quynhn/james-project/commits{/sha}","git_commits_url":"https://api.github.com/repos/quynhn/james-project/git/commits{/sha}","comments_url":"https://api.github.com/repos/quynhn/james-project/comments{/number}","issue_comment_url":"https://api.github.com/repos/quynhn/james-project/issues/comments{/number}","contents_url":"https://api.github.com/repos/quynhn/james-project/contents/{+path}","compare_url":"https://api.github.com/repos/quynhn/james-project/compare/{base}...{head}","merges_url":"https://api.github.com/repos/quynhn/james-project/merges","archive_url":"https://api.github.com/repos/quynhn/james-project/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/quynhn/james-project/downloads","issues_url":"https://api.github.com/repos/quynhn/james-project/issues{/number}","pulls_url":"https://api.github.com/repos/quynhn/james-project/pulls{/number}","milestones_url":"https://api.github.com/repos/quynhn/james-project/milestones{/number}","notifications_url":"https://api.github.com/repos/quynhn/james-project/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/quynhn/james-project/labels{/name}","releases_url":"https://api.github.com/repos/quynhn/james-project/releases{/id}","deployments_url":"https://api.github.com/repos/quynhn/james-project/deployments","created_at":"2016-05-16T07:35:33Z","updated_at":"2016-05-16T07:35:44Z","pushed_at":"2016-11-22T06:56:50Z","git_url":"git://github.com/quynhn/james-project.git","ssh_url":"git@github.com:quynhn/james-project.git","clone_url":"https://github.com/quynhn/james-project.git","svn_url":"https://github.com/quynhn/james-project","homepage":null,"size":14829,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"linagora:master","ref":"master","sha":"b5daadd1d8eb76e06d5b909ade9d4678160cdeb4","user":{"login":"linagora","id":1230365,"avatar_url":"https://avatars.githubusercontent.com/u/1230365?v=3","gravatar_id":"","url":"https://api.github.com/users/linagora","html_url":"https://github.com/linagora","followers_url":"https://api.github.com/users/linagora/followers","following_url":"https://api.github.com/users/linagora/following{/other_user}","gists_url":"https://api.github.com/users/linagora/gists{/gist_id}","starred_url":"https://api.github.com/users/linagora/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linagora/subscriptions","organizations_url":"https://api.github.com/users/linagora/orgs","repos_url":"https://api.github.com/users/linagora/repos","events_url":"https://api.github.com/users/linagora/events{/privacy}","received_events_url":"https://api.github.com/users/linagora/received_events","type":"Organization","site_admin":false},"repo":{"id":39182136,"name":"james-project","full_name":"linagora/james-project","owner":{"login":"linagora","id":1230365,"avatar_url":"https://avatars.githubusercontent.com/u/1230365?v=3","gravatar_id":"","url":"https://api.github.com/users/linagora","html_url":"https://github.com/linagora","followers_url":"https://api.github.com/users/linagora/followers","following_url":"https://api.github.com/users/linagora/following{/other_user}","gists_url":"https://api.github.com/users/linagora/gists{/gist_id}","starred_url":"https://api.github.com/users/linagora/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linagora/subscriptions","organizations_url":"https://api.github.com/users/linagora/orgs","repos_url":"https://api.github.com/users/linagora/repos","events_url":"https://api.github.com/users/linagora/events{/privacy}","received_events_url":"https://api.github.com/users/linagora/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/linagora/james-project","description":"Mirror of Apache James Project","fork":true,"url":"https://api.github.com/repos/linagora/james-project","forks_url":"https://api.github.com/repos/linagora/james-project/forks","keys_url":"https://api.github.com/repos/linagora/james-project/keys{/key_id}","collaborators_url":"https://api.github.com/repos/linagora/james-project/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/linagora/james-project/teams","hooks_url":"https://api.github.com/repos/linagora/james-project/hooks","issue_events_url":"https://api.github.com/repos/linagora/james-project/issues/events{/number}","events_url":"https://api.github.com/repos/linagora/james-project/events","assignees_url":"https://api.github.com/repos/linagora/james-project/assignees{/user}","branches_url":"https://api.github.com/repos/linagora/james-project/branches{/branch}","tags_url":"https://api.github.com/repos/linagora/james-project/tags","blobs_url":"https://api.github.com/repos/linagora/james-project/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/linagora/james-project/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/linagora/james-project/git/refs{/sha}","trees_url":"https://api.github.com/repos/linagora/james-project/git/trees{/sha}","statuses_url":"https://api.github.com/repos/linagora/james-project/statuses/{sha}","languages_url":"https://api.github.com/repos/linagora/james-project/languages","stargazers_url":"https://api.github.com/repos/linagora/james-project/stargazers","contributors_url":"https://api.github.com/repos/linagora/james-project/contributors","subscribers_url":"https://api.github.com/repos/linagora/james-project/subscribers","subscription_url":"https://api.github.com/repos/linagora/james-project/subscription","commits_url":"https://api.github.com/repos/linagora/james-project/commits{/sha}","git_commits_url":"https://api.github.com/repos/linagora/james-project/git/commits{/sha}","comments_url":"https://api.github.com/repos/linagora/james-project/comments{/number}","issue_comment_url":"https://api.github.com/repos/linagora/james-project/issues/comments{/number}","contents_url":"https://api.github.com/repos/linagora/james-project/contents/{+path}","compare_url":"https://api.github.com/repos/linagora/james-project/compare/{base}...{head}","merges_url":"https://api.github.com/repos/linagora/james-project/merges","archive_url":"https://api.github.com/repos/linagora/james-project/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/linagora/james-project/downloads","issues_url":"https://api.github.com/repos/linagora/james-project/issues{/number}","pulls_url":"https://api.github.com/repos/linagora/james-project/pulls{/number}","milestones_url":"https://api.github.com/repos/linagora/james-project/milestones{/number}","notifications_url":"https://api.github.com/repos/linagora/james-project/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/linagora/james-project/labels{/name}","releases_url":"https://api.github.com/repos/linagora/james-project/releases{/id}","deployments_url":"https://api.github.com/repos/linagora/james-project/deployments","created_at":"2015-07-16T07:04:59Z","updated_at":"2016-10-24T06:34:26Z","pushed_at":"2016-11-22T07:06:40Z","git_url":"git://github.com/linagora/james-project.git","ssh_url":"git@github.com:linagora/james-project.git","clone_url":"https://github.com/linagora/james-project.git","svn_url":"https://github.com/linagora/james-project","homepage":null,"size":19719,"stargazers_count":6,"watchers_count":6,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":23,"forks":9,"open_issues":23,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/linagora/james-project/pulls/430"},"html":{"href":"https://github.com/linagora/james-project/pull/430"},"issue":{"href":"https://api.github.com/repos/linagora/james-project/issues/430"},"comments":{"href":"https://api.github.com/repos/linagora/james-project/issues/430/comments"},"review_comments":{"href":"https://api.github.com/repos/linagora/james-project/pulls/430/comments"},"review_comment":{"href":"https://api.github.com/repos/linagora/james-project/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/linagora/james-project/pulls/430/commits"},"statuses":{"href":"https://api.github.com/repos/linagora/james-project/statuses/45c5c02ae385b51645f5c4bf981357e6b4bb63df"}}}}
{"actor":{"display_login":"chibenwa"}}