[mireka] r195 committed - -load balanced sending to smarthosts...

15 views
Skip to first unread message

mir...@googlecode.com

unread,
Oct 14, 2013, 11:28:01 AM10/14/13
to mir...@googlegroups.com
Revision: 195
Author: hont...@flyordie.com
Date: Mon Oct 14 15:27:30 2013 UTC
Log: -load balanced sending to smarthosts
-SubEthaSMTP upgrade
-there is now a default ClientFactory which is automatically injected into
configuration classes if no other instance is supplied explicitly.
http://code.google.com/p/mireka/source/detail?r=195

Added:
/trunk/setup/doc/basic-configuration/relayhost.html
/trunk/src/mireka/transmission/immediate/IndirectImmediateSender.java
/trunk/src/mireka/transmission/immediate/Upstream.java
/trunk/test/mireka/transmission/immediate/UpstreamTest.java
Deleted:
/trunk/setup/doc/basic-configuration/null-client.html
/trunk/src/mireka/transmission/immediate/NullClientImmediateSender.java
Modified:
/trunk/lib/runtime/subethasmtp-UNVERSIONED.jar
/trunk/setup/conf/mireka.js
/trunk/setup/conf/submission/queues.js
/trunk/setup/doc/index.html
/trunk/setup/lib/configuration.js
/trunk/src/mireka/smtp/client/BackendServer.java
/trunk/src/mireka/transmission/immediate/DirectImmediateSender.java

=======================================
--- /dev/null
+++ /trunk/setup/doc/basic-configuration/relayhost.html Mon Oct 14 15:27:30
2013 UTC
@@ -0,0 +1,85 @@
+<html>
+ <head>
+ <title>Sending all outgoing mails via another server</title>
+ <link rel="stylesheet" type="text/css" href="../doc.css" />
+ </head>
+
+ <body>
+ <h1>Sending all outgoing mails via another server</h1>
+
+<p>Mireka can be configured to send all outgoing mail through another
server.
+The other server is usually the so called <i>smarthost</i>. This is useful
for
+example if the local network connects to the internet through a dynamic IP
+address.
+<p>
+In contrast to proxy mode, Mireka in this case waits until it
+completely receives the incoming mail, stores it, and forwards them later,
+usually within a few milliseconds. Mireka tries to send to the configured
+smarthost (or smarthosts, see later), and if is not successful, it try it
again
+later, up to the configured duration.
+<p><i>NOTE:
+If it turns out that the mail cannot be relayed for some reason, then
Mireka
+sends a Delivery Status Notification mail back to the original sender.
However,
+if the original sender is not a local user, this bounce mail must also go
through
+the smarthost. If the smarthost is inaccessible for an extended time,
Mireka
+will give up, and delete the DSN mail too. Depending on the importance of
the
+mails this can be a dangerous situation because the mail is accepted but
+neither the mail is delivered, nor the user is notified. To prevent this,
+configure appropriate retry intervals and regularly monitor the mail error
logs.
+</i><p>
+
+<p>First edit <code>mireka.js</code> and configure the value of the
+<code>backendServer</code> variable. For example if the smarthost is
+<code>myisp.example.com</code>, listens on port 587, and requires
authentication,
+then your configuration should look like this:
+<p class="code">...
+backendServer = setup(BackendServer, {
+ host: "<span class="relevant">myisp.example.com</span>",
+ <span class="relevant">port: 587,</span>
+ <span class="relevant">user: "mycompany",</span>
+ <span class="relevant">password: "CHANGEIT",</span>
+});
+...</p>
+
+<p>Note: you can define more than one backend servers, and reference them
later.
+
+<p>Next, edit <code>submission/queues.js</code> and uncomment the indirect
+sender definition.
+Your configuration should look like this:
+<p class="code">...
+immediateSender = setup(<span
class="relevant">IndirectImmediateSender</span>, {
+ mailToHostTransmitter: mailToHostTransmitter,
+ <span class="relevant">backendServer: backendServer</span>,
+});
+...</p>
+
+<h3>Load balancing</h3>
+It is also possible to use more than one smarthosts. Mireka provides basic
load
+balancing using the <code>weight</code> and <code>backup</code> properties
of backend servers. For example:
+
+<p class="code">...
+upstream = setup(Upstream, {
+ servers: [
+ setup(BackendServer, {
+ host: "smtp1.example.com",
+ <span class="relevant">weight: 60,</span>
+ }),
+ setup(BackendServer, {
+ host: "smtp2.example.com",
+ <span class="relevant">weight: 40,</span>
+ }),
+ setup(BackendServer, {
+ host: "backup.example.com",
+ <span class="relevant">backup: true,</span>
+ }),
+ ],
+});
+immediateSender = setup(IndirectImmediateSender, {
+ mailToHostTransmitter: mailToHostTransmitter,
+ <span class="relevant">upstream: upstream,</span>
+});
+...</p>
+
+
+ </body>
+</html>
=======================================
--- /dev/null
+++ /trunk/src/mireka/transmission/immediate/IndirectImmediateSender.java
Mon Oct 14 15:27:30 2013 UTC
@@ -0,0 +1,154 @@
+package mireka.transmission.immediate;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.concurrent.NotThreadSafe;
+
+import mireka.smtp.SendException;
+import mireka.smtp.client.BackendServer;
+import mireka.smtp.client.SmtpClient;
+import mireka.transmission.Mail;
+import mireka.transmission.immediate.host.MailToHostTransmitter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * IndirectImmediateSender synchronously sends all mails through other SMTP
+ * servers specified in the configuration, typically to a smarthost,
instead of
+ * sending the mail directly to the SMTP servers of the recipients. It
tries all
+ * listed smarthosts until a working one is found. The smarthost will in
turn
+ * transmit the mail to remote domains. This is useful for example if a
network
+ * is behind a dynamic IP address, considering that dynamic IP addresses
are
+ * frequently rejected by SMTP servers.
+ * <p>
+ * If a smart host name resolves to more than one IP addresses, than only
the
+ * first one is used.
+ * <p>
+ * Instead of specifying a single smarthost, an Upstream with more servers
can
+ * also be supplied and Mireka will distribute outgoing mails like a
simple load
+ * balancer.
+ */
+@NotThreadSafe
+public class IndirectImmediateSender implements ImmediateSender {
+ private final Logger logger = LoggerFactory
+ .getLogger(IndirectImmediateSender.class);
+ private MailToHostTransmitter mailToHostTransmitter;
+ private Upstream upstream = new Upstream();
+
+ @Override
+ public boolean singleDomainOnly() {
+ return false;
+ }
+
+ /**
+ * Transmits mail to a smart host.
+ *
+ * @throws PostponeException
+ * if transmission to all of the hosts must be postponed,
+ * because all of them are assumed to be busy at this
moment.
+ */
+ @Override
+ public void send(Mail mail) throws SendException,
+ RecipientsWereRejectedException, IllegalArgumentException,
+ PostponeException {
+
+ // a PostponeException does not prevent successful delivery using
+ // another host, but it must be saved so if there are no more
hosts then
+ // this exception instance will be rethrown.
+ PostponeException lastPostponeException = null;
+ // if there is a host which failed, but which should be retried
later,
+ // then a following unrecoverable DNS exception on another host may
+ // not prevent delivery, so this temporary exception will be
returned
+ SendException lastRetryableException = null;
+ // an unrecoverable DNS exception may not prevent delivery (to
another
+ // host), so the function will continue, but it must be
+ // saved, because maybe there is no more host.
+ SendException lastUnrecoverableDnsException = null;
+ List<BackendServer> servers = upstream.orderedServerList();
+ logger.debug("Trying backends in this order: {}", servers);
+ for (BackendServer server : servers) {
+ SmtpClient client;
+ try {
+ client = server.createClient();
+ } catch (SendException e) {
+ if (e.errorStatus().shouldRetry())
+ lastRetryableException = e;
+ else
+ lastUnrecoverableDnsException = e;
+ logger.debug("Looking up address of MTA {} failed,
continuing "
+ + "with the next MTA if one is available: {}",
server,
+ e.getMessage());
+ continue;
+ }
+
+ try {
+ mailToHostTransmitter.transmit(mail, client);
+ return;
+ } catch (PostponeException e) {
+ lastPostponeException = e;
+ logger.debug("Sending to SMTP host {} must be postponed, "
+ + "continuing with the next "
+ + "smart host if one is available: {}",
+ client.getMtaAddress(), e.getMessage());
+ } catch (SendException e) {
+ if (e.errorStatus().shouldRetry()) {
+ // lastSendException = e;
+ lastRetryableException = e;
+ logger.debug("Sending to SMTP host {} failed, "
+ + "continuing with the next "
+ + "smart host if one is available: {}",
+ client.getMtaAddress(), e.getMessage());
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // at this point it is known that the transmission was not
successful
+
+ if (lastRetryableException != null)
+ throw lastRetryableException;
+ if (lastPostponeException != null) {
+ // there is at least one host successfully found in DNS but
have not
+ // tried
+ throw lastPostponeException;
+ }
+ if (lastUnrecoverableDnsException == null)
+ throw new RuntimeException(); // impossible, but prevents
warning
+ // an unrecoverable DNS exception
+ throw lastUnrecoverableDnsException;
+ }
+
+ /** @category GETSET **/
+ public MailToHostTransmitter getMailToHostTransmitter() {
+ return mailToHostTransmitter;
+ }
+
+ /** @category GETSET **/
+ public void setMailToHostTransmitter(
+ MailToHostTransmitter mailToHostTransmitter) {
+ this.mailToHostTransmitter = mailToHostTransmitter;
+ }
+
+ /**
+ * Sets the upstream to the supplied single server.
+ *
+ * @category GETSET
+ **/
+ public void setBackendServer(BackendServer server) {
+ upstream.setServers(Arrays.asList(server));
+ }
+
+ /** @category GETSET **/
+ public Upstream getUpstream() {
+ return upstream;
+ }
+
+ /** @category GETSET **/
+ public void setUpstream(Upstream upstream) {
+ this.upstream = upstream;
+ }
+
+}
=======================================
--- /dev/null
+++ /trunk/src/mireka/transmission/immediate/Upstream.java Mon Oct 14
15:27:30 2013 UTC
@@ -0,0 +1,85 @@
+package mireka.transmission.immediate;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import mireka.smtp.client.BackendServer;
+
+/**
+ * An Upstream is a load balanced set of BackendServers. A specific server
is
+ * selected randomly but considering its weight and whether it is a backup
or
+ * primary server.
+ */
+public class Upstream {
+ private List<BackendServer> servers;
+
+ public List<BackendServer> orderedServerList() {
+ List<BackendServer> shuffledServers = new ArrayList<>();
+ shuffledServers.addAll(shuffle(getPrimaryServers()));
+ shuffledServers.addAll(shuffle(getBackupServers()));
+ return shuffledServers;
+ }
+
+ private List<BackendServer> getPrimaryServers() {
+ List<BackendServer> result = new ArrayList<>();
+ for (BackendServer server : servers) {
+ if (!server.isBackup())
+ result.add(server);
+ }
+ return result;
+ }
+
+ private List<BackendServer> getBackupServers() {
+ List<BackendServer> result = new ArrayList<>();
+ for (BackendServer server : servers) {
+ if (server.isBackup())
+ result.add(server);
+ }
+ return result;
+ }
+
+ private List<BackendServer> shuffle(List<BackendServer> servers) {
+ List<BackendServer> shuffledList = new ArrayList<>();
+ List<BackendServer> remainingServers = new ArrayList<>(servers);
+ if (remainingServers.isEmpty())
+ return Collections.emptyList();
+ while (remainingServers.size() > 1) {
+ int iSelected = selectFrom(remainingServers);
+ BackendServer selected = remainingServers.remove(iSelected);
+ shuffledList.add(selected);
+ }
+ shuffledList.add(remainingServers.get(0));
+ return shuffledList;
+ }
+
+ private int selectFrom(List<BackendServer> servers) {
+ double drawnNumber = Math.random() * totalWeight(servers);
+ double weigthsUntilNow = 0;
+ for (int i = 0; i < servers.size(); i++) {
+ BackendServer sender = servers.get(i);
+ weigthsUntilNow += sender.getWeight();
+ if (drawnNumber < weigthsUntilNow)
+ return i;
+ }
+ return servers.size() - 1;
+ }
+
+ private double totalWeight(List<BackendServer> servers) {
+ double total = 0;
+ for (BackendServer server : servers) {
+ total += server.getWeight();
+ }
+ return total;
+ }
+
+ /** @category GETSET **/
+ public List<BackendServer> getServers() {
+ return servers;
+ }
+
+ /** @category GETSET **/
+ public void setServers(List<BackendServer> servers) {
+ this.servers = servers;
+ }
+}
=======================================
--- /dev/null
+++ /trunk/test/mireka/transmission/immediate/UpstreamTest.java Mon Oct 14
15:27:30 2013 UTC
@@ -0,0 +1,65 @@
+package mireka.transmission.immediate;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import mireka.smtp.client.BackendServer;
+
+import org.junit.Test;
+
+public class UpstreamTest {
+
+ private BackendServer server66 = new BackendServer();
+ private BackendServer server33 = new BackendServer();
+ private BackendServer backupServer66 = new BackendServer();
+ private BackendServer backupServer33 = new BackendServer();
+
+ public UpstreamTest() {
+ server66.setWeight(66);
+ server66.setHost("server66");
+ server33.setWeight(33);
+ server33.setHost("server33");
+ backupServer66.setWeight(66);
+ backupServer66.setBackup(true);
+ backupServer66.setHost("backup66");
+ backupServer33.setWeight(33);
+ backupServer33.setBackup(true);
+ backupServer33.setHost("backup33");
+ }
+
+ @Test
+ public void testOrderedServerList() {
+ testList(server66, server33, backupServer66, backupServer33);
+ testList(backupServer33, server33, backupServer66, server66);
+ }
+
+ private void testList(BackendServer... server) {
+ Upstream upstream = new Upstream();
+ upstream.setServers(Arrays.asList(server));
+ int[] counters = new int[4];
+ for (int i = 0; i < 1000; i++) {
+ List<BackendServer> list = upstream.orderedServerList();
+ System.out.println(list);
+ if (list.get(0) == server66)
+ counters[0]++;
+ if (list.get(1) == server33)
+ counters[1]++;
+ if (list.get(2) == backupServer66)
+ counters[2]++;
+ if (list.get(3) == backupServer33)
+ counters[3]++;
+ assertTrue(list.get(2) == backupServer66
+ || list.get(3) == backupServer66);
+ assertTrue(list.get(2) == backupServer33
+ || list.get(3) == backupServer33);
+ }
+ assertTrue(counters[0] > 600);
+ assertTrue(counters[1] > 600);
+ assertTrue(counters[2] > 600);
+ assertTrue(counters[3] > 600);
+ System.out.println(Arrays.toString(counters));
+ }
+
+}
=======================================
--- /trunk/setup/doc/basic-configuration/null-client.html Thu May 9
22:39:28 2013 UTC
+++ /dev/null
@@ -1,58 +0,0 @@
-<html>
- <head>
- <title>Null client: sending all mails via another server</title>
- <link rel="stylesheet" type="text/css" href="../doc.css" />
- </head>
-
- <body>
- <h1>Null client: sending all mails via another server</h1>
-
-<p>Mireka can be configured to be a null client, which means that it sends
all
-outgoing mail through another server. The other server is the so called
-<i>smart host</i>. This is useful for example if the local network
connects to the
-internet through a dynamic IP address.
-<p>
-In contrast to proxy mode, Mireka, acting as a null client, waits until it
-completely receives the incoming mail, stores it, and forwards them later,
-usually within a few milliseconds. Mireka tries all configured smart
-hosts, and if none of them is accessible, than it tries them again later,
up to
-the configured duration.
-<p><i>NOTE:
-If it turns out that the mail cannot be forwarded for some reason, then
Mireka
-sends a Delivery Status Notification mail back to the original sender.
However,
-if the original sender is not a local user, this bounce mail must also go
through
-the smart host. If the smart host is inaccessible for an extended time,
Mireka
-will give up, and delete the DSN mail too. Depending on the importance of
the
-mails this can be a dangerous situation because the mail is accepted but
-neither the mail is neither delivered, nor the user is notified. To
prevent this,
-configure appropriate retry intervals and regularly monitor the mail error
logs.
-</i><p>
-
-<p>First edit <code>mireka.js</code> and configure the value of the
<code>backendServer</code>
-variable. For example if the smarthost is <code>myisp.example.com</code>,
-listens on port 587, and requires authentication, then your configuration
should
-look like this:
-<p class="code">...
-backendServer = setup(BackendServer, {
- host: "<span class="relevant">myisp.example.com</span>",
- <span class="relevant">port: 587,</span>
- <span class="relevant">user: "mycompany",</span>
- <span class="relevant">password: "CHANGEIT",</span>
- clientFactory: clientFactory
-});
-...</p>
-
-<p>Note: you can define more than one smart hosts.
-
-<p>Next, edit <code>submission/queues.js</code> and uncomment the null
client
-sender definition.
-Your configuraton should look like this:
-<p class="code">...
-immediateSender = setup(<span
class="relevant">NullClientImmediateSender</span>, {
- mailToHostTransmitter: mailToHostTransmitter,
- <span class="relevant">smartHosts: [ backendServer ]</span>,
-});
-...</p>
-
- </body>
-</html>
=======================================
--- /trunk/src/mireka/transmission/immediate/NullClientImmediateSender.java
Thu May 9 22:39:28 2013 UTC
+++ /dev/null
@@ -1,136 +0,0 @@
-package mireka.transmission.immediate;
-
-import java.util.List;
-
-import javax.annotation.concurrent.NotThreadSafe;
-
-import mireka.smtp.SendException;
-import mireka.smtp.client.BackendServer;
-import mireka.smtp.client.SmtpClient;
-import mireka.transmission.Mail;
-import mireka.transmission.immediate.host.MailToHostTransmitter;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * NullClientImmediateSender synchronously sends a mail to a smart host,
trying
- * all listed smart hosts until a working one is found. The smart host
will in
- * turn transmit the mail to remote domains. This is useful for example if
a
- * network is behind a dynamic IP address, considering that dynamic IP
addresses
- * are frequently rejected by SMTP servers.
- * <p>
- * If a smart host name resolves to more than one IP addresses, than only
the
- * first one is used.
- */
-@NotThreadSafe
-public class NullClientImmediateSender implements ImmediateSender {
- private final Logger logger = LoggerFactory
- .getLogger(NullClientImmediateSender.class);
- private MailToHostTransmitter mailToHostTransmitter;
- private List<BackendServer> smartHosts;
-
- @Override
- public boolean singleDomainOnly() {
- return false;
- }
-
- /**
- * Transmits mail to a smart host.
- *
- * @throws PostponeException
- * if transmission to all of the hosts must be postponed,
- * because all of them are assumed to be busy at this
moment.
- */
- @Override
- public void send(Mail mail) throws SendException,
- RecipientsWereRejectedException, IllegalArgumentException,
- PostponeException {
-
- // a PostponeException does not prevent successful delivery using
- // another host, but it must be saved so if there are no more
hosts then
- // this exception instance will be rethrown.
- PostponeException lastPostponeException = null;
- // if there is a host which failed, but which should be retried
later,
- // then a following unrecoverable DNS exception on another host may
- // not prevent delivery, so this temporary exception will be
returned
- SendException lastRetryableException = null;
- // an unrecoverable DNS exception may not prevent delivery (to
another
- // host), so the function will continue, but it must be
- // saved, because maybe there is no more host.
- SendException lastUnrecoverableDnsException = null;
- for (BackendServer smartHost : smartHosts) {
- SmtpClient client;
- try {
- client = smartHost.createClient();
- } catch (SendException e) {
- if (e.errorStatus().shouldRetry())
- lastRetryableException = e;
- else
- lastUnrecoverableDnsException = e;
- logger.debug(
- "Looking up address of MTA " + smartHost.toString()
- + " failed, continuing with the next MTA "
- + "if one is available: ", e.getMessage());
- continue;
- }
-
- try {
- mailToHostTransmitter.transmit(mail, client);
- return;
- } catch (PostponeException e) {
- lastPostponeException = e;
- logger.debug("Sending to SMTP host " +
client.getMtaAddress()
- + " must be postponed, continuing with the next "
- + "smart host if one is available: " +
e.getMessage());
- } catch (SendException e) {
- if (e.errorStatus().shouldRetry()) {
- // lastSendException = e;
- lastRetryableException = e;
- logger.debug(
- "Sending to SMTP host " +
client.getMtaAddress()
- + " failed, continuing with the next "
- + "smart host if one is available: ",
- e.getMessage());
- } else {
- throw e;
- }
- }
- }
-
- // at this point it is known that the transmission was not
successful
-
- if (lastRetryableException != null)
- throw lastRetryableException;
- if (lastPostponeException != null) {
- // there is at least one host successfully found in DNS but
have not
- // tried
- throw lastPostponeException;
- }
- if (lastUnrecoverableDnsException == null)
- throw new RuntimeException(); // impossible, but prevents
warning
- // an unrecoverable DNS exception
- throw lastUnrecoverableDnsException;
- }
-
- /** @category GETSET **/
- public MailToHostTransmitter getMailToHostTransmitter() {
- return mailToHostTransmitter;
- }
-
- /** @category GETSET **/
- public void setMailToHostTransmitter(
- MailToHostTransmitter mailToHostTransmitter) {
- this.mailToHostTransmitter = mailToHostTransmitter;
- }
-
- /** @category GETSET **/
- public List<BackendServer> getSmartHosts() {
- return smartHosts;
- }
-
- /** @category GETSET **/
- public void setSmartHosts(List<BackendServer> smartHosts) {
- this.smartHosts = smartHosts;
- }
-}
=======================================
--- /trunk/lib/runtime/subethasmtp-UNVERSIONED.jar Thu May 9 22:39:28 2013
UTC
+++ /trunk/lib/runtime/subethasmtp-UNVERSIONED.jar Mon Oct 14 15:27:30 2013
UTC
Binary file, no diff available.
=======================================
--- /trunk/setup/conf/mireka.js Sat May 11 16:55:14 2013 UTC
+++ /trunk/setup/conf/mireka.js Mon Oct 14 15:27:30 2013 UTC
@@ -28,7 +28,7 @@
Default SMTP client factory, it specifies the properties of the
outgoing SMTP connections.
*/
-clientFactory = setup(ClientFactory, {
+clientFactory = setupDefault(ClientFactory, {
helo: helo,
// bind: "192.0.2.0",
});
@@ -43,7 +43,6 @@
//port: 587,
//user: "office-server",
//password: "CHANGEIT",
- clientFactory: clientFactory,
});

/*
=======================================
--- /trunk/setup/conf/submission/queues.js Sat May 11 16:55:14 2013 UTC
+++ /trunk/setup/conf/submission/queues.js Mon Oct 14 15:27:30 2013 UTC
@@ -55,15 +55,14 @@
});

immediateSender = setup(DirectImmediateSender, {
- clientFactory: clientFactory,
- mailToHostTransmitter: mailToHostTransmitter
+ mailToHostTransmitter: mailToHostTransmitter,
});

-/* uncomment to send all outgoing mails through a smart host */
+/* uncomment to send all outgoing mails through a smarthost */
/*
-immediateSender = setup(NullClientImmediateSender, {
+immediateSender = setup(IndirectImmediateSender, {
mailToHostTransmitter: mailToHostTransmitter,
- smartHosts: [ backendServer ],
+ backendServer: backendServer,
});
*/

=======================================
--- /trunk/setup/doc/index.html Thu May 9 22:39:28 2013 UTC
+++ /trunk/setup/doc/index.html Mon Oct 14 15:27:30 2013 UTC
@@ -34,7 +34,7 @@
<li><a href="basic-configuration/forward.html">Specifying forwarding</a>
<li><a href="basic-configuration/mailing-list.html">Defining a simple
mailing list</a>
<li><a href="basic-configuration/proxy.html">Using as proxy</a>
- <li><a href="basic-configuration/null-client.html">Null client: sending
all mails via another server</a>
+ <li><a href="basic-configuration/relayhost.html">Sending all mails via
another server (smarthost)</a>
<li><a href="basic-configuration/authenticate-by-ip.html">Authenticate by
IP address</a>
<li><a href="basic-configuration/sendmail.html">Sendmail command on
Linux</a>
</ul>
=======================================
--- /trunk/setup/lib/configuration.js Thu May 9 22:39:28 2013 UTC
+++ /trunk/setup/lib/configuration.js Mon Oct 14 15:27:30 2013 UTC
@@ -109,9 +109,9 @@
}

/*
- * Makes the object available for injection. These object are used as
default
- * values for those properties of the configuration objects that which are
- * marked with an @Inject annotation .
+ * Makes the object available for injection. The object will be used as a
default
+ * value for configuration object properties which are marked with an
@Inject
+ * annotation.
*/
function useAsDefault(object) {
configuration.addInjectableObject(object);
=======================================
--- /trunk/src/mireka/smtp/client/BackendServer.java Thu May 9 22:39:28
2013 UTC
+++ /trunk/src/mireka/smtp/client/BackendServer.java Mon Oct 14 15:27:30
2013 UTC
@@ -6,11 +6,18 @@
import java.net.UnknownHostException;
import java.util.regex.Pattern;

+import javax.inject.Inject;
+
import mireka.smtp.EnhancedStatus;
import mireka.smtp.SendException;
+import mireka.transmission.immediate.Upstream;

import org.subethamail.smtp.client.PlainAuthenticator;

+/**
+ * BackendServer specifies another SMTP server which is used as a proxy
target
+ * or smarthost. It may be part of an {@link Upstream}.
+ */
public class BackendServer {
private static final String IPV6_PREFIX = "[IPv6:";
private static final Pattern dottedQuad = Pattern
@@ -43,6 +50,14 @@
private int port = 25;
private String user;
private String password;
+ /**
+ * {@link BackendServer#setWeight}
+ */
+ private double weight = 1;
+ /**
+ * {@link BackendServer#setBackup}
+ */
+ private boolean backup = false;

/**
*
@@ -74,7 +89,7 @@

@Override
public String toString() {
- return "BackendServer [" + host + ":" + port + "]";
+ return host + ":" + port;
}

/**
@@ -150,6 +165,7 @@
return clientFactory;
}

+ @Inject
public void setClientFactory(ClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
@@ -196,4 +212,36 @@
this.password = password;
}

+ /**
+ * @category GETSET
+ */
+ public double getWeight() {
+ return weight;
+ }
+
+ /**
+ * Relative weight of the server in an Upstream. Default is 1.
+ *
+ * @category GETSET
+ */
+ public void setWeight(double weight) {
+ this.weight = weight;
+ }
+
+ /**
+ * @category GETSET
+ */
+ public boolean isBackup() {
+ return backup;
+ }
+
+ /**
+ * True indicates that the server should only be used in an Upstream
if all
+ * non-backup servers failed. Default is false.
+ *
+ * @category GETSET
+ */
+ public void setBackup(boolean backup) {
+ this.backup = backup;
+ }
}
=======================================
--- /trunk/src/mireka/transmission/immediate/DirectImmediateSender.java Thu
May 9 22:39:28 2013 UTC
+++ /trunk/src/mireka/transmission/immediate/DirectImmediateSender.java Mon
Oct 14 15:27:30 2013 UTC
@@ -2,6 +2,8 @@

import java.net.InetAddress;

+import javax.inject.Inject;
+
import mireka.address.AddressLiteral;
import mireka.address.Domain;
import mireka.address.DomainPart;
@@ -228,6 +230,7 @@
}

/** @category GETSET **/
+ @Inject
public void setClientFactory(ClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
Reply all
Reply to author
Forward
0 new messages