This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 57a260600fbf5c1fa3c8ae282d188e6cc2146b2d Author: Benoit Tellier <[email protected]> AuthorDate: Mon Feb 7 17:29:19 2022 +0700 JAMES-3683 PerRecipientRateLimitMailet -> PerRecipientRateLimit & javadoc --- ...PerRecipientRateLimitMailetIntegrationTest.java | 2 +- ...mitMailet.scala => PerRecipientRateLimit.scala} | 43 +++++++++++++++++++++- ...tTest.scala => PerRecipientRateLimitTest.scala} | 22 +++++------ 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/PerRecipientRateLimitMailetIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/PerRecipientRateLimitMailetIntegrationTest.java index 9be73ed..ff58d57 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/PerRecipientRateLimitMailetIntegrationTest.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/PerRecipientRateLimitMailetIntegrationTest.java @@ -83,7 +83,7 @@ public class PerRecipientRateLimitMailetIntegrationTest { .putProcessor(ProcessorConfiguration.transport() .addMailet(MailetConfiguration.builder() .matcher(All.class) - .mailet(PerRecipientRateLimitMailet.class) + .mailet(PerRecipientRateLimit.class) .addProperty("duration", "60s") .addProperty("count", "1") .addProperty("size", "6K") diff --git a/server/mailet/rate-limiter/src/main/scala/org/apache/james/transport/mailets/PerRecipientRateLimitMailet.scala b/server/mailet/rate-limiter/src/main/scala/org/apache/james/transport/mailets/PerRecipientRateLimit.scala similarity index 64% rename from server/mailet/rate-limiter/src/main/scala/org/apache/james/transport/mailets/PerRecipientRateLimitMailet.scala rename to server/mailet/rate-limiter/src/main/scala/org/apache/james/transport/mailets/PerRecipientRateLimit.scala index 31e2d7f..a8b05a1 100644 --- a/server/mailet/rate-limiter/src/main/scala/org/apache/james/transport/mailets/PerRecipientRateLimitMailet.scala +++ b/server/mailet/rate-limiter/src/main/scala/org/apache/james/transport/mailets/PerRecipientRateLimit.scala @@ -50,7 +50,48 @@ case class RecipientKey(keyPrefix: Option[KeyPrefix], entityType: EntityType, ma }${entityType.asString()}_${mailAddress.asString()}" } -class PerRecipientRateLimitMailet @Inject()(rateLimiterFactory: RateLimiterFactory) extends GenericMailet { +/** + * <p><b>PerRecipientRateLimit</b> allows defining and enforcing rate limits for the recipients of matching emails.</p> + * + * <ul>This allows writing rules like: + * <li>A recipient can receive 10 emails per hour</li> + * <li>A recipient can receive 100 MB of emails per hour</li> + * </ul> + * + * <p>Depending on its position and the matcher it is being combined with, those rate limiting rules could be applied to + * submitted emails, received emails or emitted email being relayed to third parties.</p> + * + * <ul>Here are supported configuration parameters: + * <li><b>keyPrefix</b>: An optional key prefix to apply to rate limiting. Choose distinct values if you specify + * this mailet twice within your <code>mailetcontainer.xml</code> file. Defaults to none.</li> + * <li><b>exceededProcessor</b>: Processor to which emails whose rate is exceeded should be redirected to. Defaults to error. + * Use this to customize the behaviour upon exceeded rate.</li> + * <li><b>duration</b>: Duration during which the rate limiting shall be applied. Compulsory, must be a valid duration of at least one second. Supported units includes s (second), m (minute), h (hour), d (day).</li> + * <li><b>count</b>: Count of emails allowed for a given sender during duration. Optional, if unspecified this rate limit is not applied.</li> + * <li><b>size</b>: Size of emails allowed for a given sender during duration (each email count one time, regardless of recipient count). Optional, if unspecified this rate limit is not applied. Supported units : B ( 2^0 ), K ( 2^10 ), M ( 2^20 ), G ( 2^30 ), defaults to B.</li> + * </ul> + * + * <p>For instance, to apply all the examples given above:</p> + * + * <pre><code> + * <mailet matcher="All" class="PerRecipientRateLimit"> + * <keyPrefix>myPrefix</keyPrefix> + * <duration>1h</duration> + * <count>10</count> + * <size>100M</size> + * <exceededProcessor>tooMuchMails</exceededProcessor> + * </mailet> + * </code></pre> + * + * <p>Note that to use this extension you need to place the rate-limiter JAR in the <code>extensions-jars</code> folder + * and need to configure a viable option to invoke <code>RateLimiterFactory</code> which can be done by + * loading <code>org.apache.james.rate.limiter.memory.MemoryRateLimiterModule</code> Guice module within the + * <code>guice.extension.module</code> in <code>extensions.properties</code> configuration file. Note that other Rate + * limiter implementation might require extra configuration parameters within your mailet.</p> + * + * @param rateLimiterFactory Allows instantiations of the underlying rate limiters. + */ +class PerRecipientRateLimit @Inject()(rateLimiterFactory: RateLimiterFactory) extends GenericMailet { private var exceededProcessor: String = _ private var rateLimiters: Seq[PerRecipientRateLimiter] = _ diff --git a/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitMailetTest.scala b/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala similarity index 95% rename from server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitMailetTest.scala rename to server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala index f45002b..66ffc54 100644 --- a/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitMailetTest.scala +++ b/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala @@ -31,17 +31,17 @@ import org.mockito.{ArgumentCaptor, Mockito} import scala.jdk.CollectionConverters._ -class PerRecipientRateLimitMailetTest { +class PerRecipientRateLimitTest { - def testee(mailetConfig: MailetConfig) : PerRecipientRateLimitMailet = { - val mailet: PerRecipientRateLimitMailet = new PerRecipientRateLimitMailet(new MemoryRateLimiterFactory()) + def testee(mailetConfig: MailetConfig) : PerRecipientRateLimit = { + val mailet: PerRecipientRateLimit = new PerRecipientRateLimit(new MemoryRateLimiterFactory()) mailet.init(mailetConfig) mailet } @Test def rateLimitingShouldBeAppliedPerRecipient(): Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "1") @@ -72,7 +72,7 @@ class PerRecipientRateLimitMailetTest { @Test def rateLimitingShouldNotBeAppliedWhenDoNotHaveRecipient() : Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "1") @@ -90,7 +90,7 @@ class PerRecipientRateLimitMailetTest { @Test def rateLimitingShouldFlowToTheIntendedProcessor() : Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "1") @@ -122,7 +122,7 @@ class PerRecipientRateLimitMailetTest { @Test def rateLimitingShouldNOTBeAppliedPerSender() : Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "1") @@ -154,7 +154,7 @@ class PerRecipientRateLimitMailetTest { @Test def shouldRateLimitSizeOfEmails(): Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("size", "100K") @@ -200,7 +200,7 @@ class PerRecipientRateLimitMailetTest { def shouldRateLimitPerRecipient(): Unit = { val mailetContext = Mockito.spy(FakeMailContext.defaultContext) - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "1") @@ -251,7 +251,7 @@ class PerRecipientRateLimitMailetTest { @Test def shouldRateLimitedWhenAllRecipientsExceeded(): Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "1") @@ -284,7 +284,7 @@ class PerRecipientRateLimitMailetTest { @Disabled("atomicity problem. https://github.com/apache/james-project/pull/851#issuecomment-1020792286") @Test def mailetShouldSupportBothCountAndSize(): Unit = { - val mailet: PerRecipientRateLimitMailet = testee(FakeMailetConfig.builder() + val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() .mailetName("PerRecipientRateLimitMailet") .setProperty("duration", "20s") .setProperty("count", "2") --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
