diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java
index 753e8c324f901eef4c03fe51ba6f51bb8f044311..5fd186d81edf8baa4678a1250b2ed1afdf0046a6 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxConstants.java
@@ -6,7 +6,7 @@ public interface MailboxConstants {
 	TransportId ID = new TransportId("org.briarproject.bramble.mailbox");
 
 
-	int POLLING_INTERVALL = 30 * 1000 ; // Scientifically chosen
+	int MIN_POLLING_INTERVALL = 30 * 1000 ; // Scientifically chosen
 	int MAX_LATENCY = 30 * 1000; // 30 seconds
 	int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
 	int MAX_MAILBOX_LATENCY = 604800000; // 1 Week
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxServiceImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxServiceImpl.java
index 7c9604cf85fba476f9bd5018ff7db8f35c6d8c5e..e6b408e53c07049cba07ac9a452a61eadeef32d8 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxServiceImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxServiceImpl.java
@@ -1,6 +1,5 @@
 package org.briarproject.bramble.mailbox;
 
-import org.briarproject.bramble.api.contact.Contact;
 import org.briarproject.bramble.api.contact.ContactId;
 import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.contact.ContactType;
@@ -13,7 +12,6 @@ import org.briarproject.bramble.api.event.Event;
 import org.briarproject.bramble.api.event.EventBus;
 import org.briarproject.bramble.api.event.EventListener;
 import org.briarproject.bramble.api.lifecycle.IoExecutor;
-import org.briarproject.bramble.api.lifecycle.ServiceException;
 import org.briarproject.bramble.api.mailbox.MailboxConstants;
 import org.briarproject.bramble.api.mailbox.MailboxInfo;
 import org.briarproject.bramble.api.mailbox.MailboxManager;
@@ -21,6 +19,7 @@ import org.briarproject.bramble.api.mailbox.MailboxService;
 import org.briarproject.bramble.api.plugin.ConnectionRegistry;
 import org.briarproject.bramble.api.plugin.LanTcpConstants;
 import org.briarproject.bramble.api.plugin.PluginManager;
+import org.briarproject.bramble.api.plugin.TorConstants;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
 import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
@@ -31,8 +30,11 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
 import org.briarproject.bramble.api.system.Scheduler;
 
 import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
@@ -44,8 +46,7 @@ import javax.inject.Inject;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.bramble.api.contact.ContactType.PRIVATE_MAILBOX;
-import static org.briarproject.bramble.api.mailbox.MailboxConstants.POLLING_INTERVALL;
+import static org.briarproject.bramble.api.mailbox.MailboxConstants.MIN_POLLING_INTERVALL;
 import static org.briarproject.bramble.util.LogUtils.logException;
 
 /**
@@ -64,12 +65,16 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 	private final PluginManager pluginManager;
 	private final MailboxManager mailboxManager;
 	private final TransportPropertyManager transportPropertyManager;
+	private SecureRandom secureRandom;
 
 
-	private volatile Future mailboxLanFuture;
+	private volatile Future mailboxFuture;
 	private volatile ContactId privateMailboxId = null;
 	private volatile AtomicBoolean hasPrivateMailbox = new AtomicBoolean(false);
 
+	private ConcurrentHashMap<TransportId, DuplexPlugin> activePlugins =
+			new ConcurrentHashMap<>();
+
 	@Inject
 	MailboxServiceImpl(@IoExecutor Executor ioExecutor, @Scheduler
 			ScheduledExecutorService scheduler, EventBus eventBus,
@@ -77,7 +82,8 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 			DatabaseComponent db,
 			ConnectionRegistry connectionRegistry,
 			PluginManager pluginManager, MailboxManager mailboxManager,
-			TransportPropertyManager transportPropertyManager) {
+			TransportPropertyManager transportPropertyManager,
+			SecureRandom secureRandom) {
 		this.ioExecutor = ioExecutor;
 		this.scheduler = scheduler;
 		this.eventBus = eventBus;
@@ -87,7 +93,7 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 		this.pluginManager = pluginManager;
 		this.mailboxManager = mailboxManager;
 		this.transportPropertyManager = transportPropertyManager;
-
+		this.secureRandom = secureRandom;
 	}
 
 	@Override
@@ -97,7 +103,7 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 
 		try {
 			PrivateMailbox mb = contactManager.getPrivateMailbox();
-			if (mb!=null)
+			if (mb != null)
 				privateMailboxId = mb.getId();
 		} catch (DbException e1) {
 			if (LOG.isLoggable(WARNING))
@@ -105,35 +111,61 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 		}
 		if (privateMailboxId != null)
 			hasPrivateMailbox.set(true);
-		
-		tryToRunLanMailboxFuture();
+
+		// Get Lan plugin if available
+		DuplexPlugin plugin =
+				(DuplexPlugin) pluginManager.getPlugin(LanTcpConstants.ID);
+
+		if (plugin != null && plugin.isRunning())
+			activePlugins.put(LanTcpConstants.ID, plugin);
+
+		// Get Tor plugin if available
+		plugin = (DuplexPlugin) pluginManager.getPlugin(TorConstants.ID);
+
+		if (plugin != null && plugin.isRunning())
+			activePlugins.put(TorConstants.ID, plugin);
+
+
+		mailboxFuture =
+				schedule(new ConnectMailboxesTask(MIN_POLLING_INTERVALL),
+						MIN_POLLING_INTERVALL);
+
 		this.eventBus.addListener(this);
 	}
 
+	private Future schedule(Runnable task, int delay) {
+		return scheduler
+				.schedule(() -> ioExecutor.execute(task), delay, MILLISECONDS);
+	}
+
 	@Override
 	public void eventOccurred(Event e) {
 		if (e instanceof TransportEnabledEvent) {
-			if (((TransportEnabledEvent) e).getTransportId()
-					.equals(LanTcpConstants.ID)) {
-				if (mailboxLanFuture == null || mailboxLanFuture.isCancelled())
-					tryToRunLanMailboxFuture();
+			TransportEnabledEvent tee = (TransportEnabledEvent) e;
+			if (tee.getTransportId().equals(LanTcpConstants.ID) ||
+					tee.getTransportId().equals(TorConstants.ID)) {
+				DuplexPlugin p =
+						(DuplexPlugin) pluginManager
+								.getPlugin(tee.getTransportId());
+				activePlugins.put(p.getId(), p);
 			}
 		}
 
 		if (e instanceof TransportDisabledEvent) {
-			if (((TransportDisabledEvent) e).getTransportId()
-					.equals(LanTcpConstants.ID)) {
-				if (mailboxLanFuture != null)
-					mailboxLanFuture.cancel(false);
+			if (activePlugins
+					.containsKey(
+							((TransportDisabledEvent) e).getTransportId())) {
+				activePlugins
+						.remove(((TransportDisabledEvent) e).getTransportId());
 			}
 		}
 
-		if (e instanceof ContactAddedEvent){
+		if (e instanceof ContactAddedEvent) {
 			if (hasPrivateMailbox.get())
 				return;
 			try {
 				PrivateMailbox mb = contactManager.getPrivateMailbox();
-				if (mb!=null)
+				if (mb != null)
 					privateMailboxId = mb.getId();
 			} catch (DbException e1) {
 				if (LOG.isLoggable(WARNING))
@@ -144,51 +176,36 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 		}
 	}
 
-	private void tryToRunLanMailboxFuture() {
-		//NOTE/TODO: Only using LAN connections for now
-		DuplexPlugin plugin =
-				(DuplexPlugin) pluginManager.getPlugin(LanTcpConstants.ID);
-		// TODO: Find a useful polling interval and randomize (should have
-		// a minimum polling interval)
-		if (plugin != null && plugin.isRunning())
-			mailboxLanFuture = schedule(
-					new ConnectMailboxesTask(LanTcpConstants.ID,
-							POLLING_INTERVALL, plugin), POLLING_INTERVALL);
-	}
-
-	private Future schedule(Runnable task, int delay) {
-		return scheduler
-				.schedule(() -> ioExecutor.execute(task), delay, MILLISECONDS);
-	}
-
 	private class ConnectMailboxesTask implements Runnable {
-		private TransportId transportId;
+		// TODO: Try to connect via Lan then Tor (this is debatable but
+		// surely useful for testing)
+		ArrayList<TransportId> transportOrder = new ArrayList<>(
+				Arrays.asList(LanTcpConstants.ID, TorConstants.ID));
+
 		private int delay;
-		private DuplexPlugin plugin;
-		private TransportProperties privateMailboxProperties = null;
-
-		private ConnectMailboxesTask(TransportId transportId,
-				int delay, DuplexPlugin plugin) {
-			this.transportId = transportId;
-			this.delay = delay;
-			this.plugin = plugin;
+
+		private ConnectMailboxesTask(int min_interval) {
+			this.delay = (int) (min_interval +
+					secureRandom.nextFloat() * min_interval);
 		}
 
 		private void reschedule() {
-			mailboxLanFuture = schedule(this, delay);
+			mailboxFuture = schedule(this, delay);
 		}
 
 
 		@Override
 		public void run() {
-			if (hasPrivateMailbox.get() &&
-					!connectionRegistry.isConnected(privateMailboxId)) {
-				try {
-					connectPrivateMailbox();
-				} catch (DbException e) {
-					logException(LOG, WARNING, e);
-					return;
-				}
+			// Wait for plugins to become available
+			if (activePlugins.isEmpty()) {
+				reschedule();
+			}
+
+			try {
+				connectPrivateMailbox();
+			} catch (DbException e) {
+				logException(LOG, WARNING, e);
+				return;
 			}
 
 			// Poll Contact mailboxes
@@ -211,64 +228,95 @@ public class MailboxServiceImpl implements MailboxService, EventListener {
 			}
 
 			for (MailboxInfo mailboxInfo : contactMailboxes) {
-				if (mailboxInfo.getMailboxId() == null)
+				if (connectionRegistry
+						.isConnected(mailboxInfo.getContactId()))
+					continue;
+
+				// If mailboxId == null the contact does not have their own mailbox
+				// but has been introduced to our mailbox
+				if (mailboxInfo.getMailboxId() == null) {
+					mailboxManager
+							.handleOwnerContactWithoutMailbox(mailboxInfo);
 					continue;
-				if (!connectionRegistry
-						.isConnected(mailboxInfo.getContactId())) {
-					TransportProperties mailboxTP =
-							contacts.get(mailboxInfo.getMailboxId());
-					if (mailboxTP == null)
-						throw new AssertionError();
-					ioExecutor.execute(
-							() -> connectContactMailbox(plugin,
-									mailboxInfo.getContactId(),
-									mailboxTP));
 				}
+
+				TransportProperties properties =
+						contacts.get(mailboxInfo.getMailboxId());
+
+				if (properties == null)
+					throw new AssertionError();
+
+				ioExecutor.execute(
+						() -> connectContactMailbox(mailboxInfo.getContactId(),
+								properties));
 			}
 
 			reschedule();
-
 		}
 
-		private void connectContactMailbox(DuplexPlugin plugin,
-				ContactId contactId,
-				TransportProperties transportProperties) {
-			DuplexTransportConnection mailBoxConn =
-					plugin.createConnection(transportProperties);
-			if (mailBoxConn != null)
-				mailboxManager.handleOutgoingContactMailboxConnection(
-						contactId, mailBoxConn,
-						transportId);
+		private void connectContactMailbox(ContactId contactId,
+				TransportProperties properties) {
+			for (TransportId transportId : transportOrder) {
+				if (!activePlugins.containsKey(transportId))
+					continue;
+
+				DuplexPlugin plugin = activePlugins.get(transportId);
+
+				DuplexTransportConnection conn =
+						plugin.createConnection(properties);
+
+				if (conn != null) {
+					if (LOG.isLoggable(INFO))
+						LOG.info("Contact mailbox connected");
+
+					mailboxManager.handleOutgoingContactMailboxConnection(
+							contactId, conn, transportId);
+				}
+			}
 		}
 
 		private void connectPrivateMailbox() throws DbException {
-			if (privateMailboxProperties == null) {
-				privateMailboxProperties = transportPropertyManager
-						.getRemoteProperties(privateMailboxId, transportId);
-			}
+			// Check if mailbox is available and if it is connected
+			if (!hasPrivateMailbox.get() ||
+					connectionRegistry.isConnected(privateMailboxId))
+				return;
 
-			if (LOG.isLoggable(INFO))
-				LOG.info("Connecting to private mailbox");
+			for (TransportId transportId : transportOrder) {
+				if (!activePlugins.containsKey(transportId))
+					continue;
+
+				DuplexPlugin plugin = activePlugins.get(transportId);
 
-			DuplexTransportConnection mailBoxConn =
-					plugin.createConnection(privateMailboxProperties);
+				TransportProperties properties = transportPropertyManager
+						.getRemoteProperties(privateMailboxId, transportId);
 
-			if (mailBoxConn != null) {
-				mailboxManager
-						.handleOutgoingPrivateMailboxConnection(
-								privateMailboxId, mailBoxConn,
-								transportId);
-			} else {
 				if (LOG.isLoggable(INFO))
-					LOG.info("Unable to connect to private mailbox");
+					LOG.info("Connecting to private mailbox");
+
+				DuplexTransportConnection conn =
+						plugin.createConnection(properties);
+
+
+				if (conn != null) {
+					if (LOG.isLoggable(INFO))
+						LOG.info("Connected to private mailbox");
+					mailboxManager
+							.handleOutgoingPrivateMailboxConnection(
+									privateMailboxId, conn,
+									transportId);
+					return;
+				}
 			}
+
+			if (LOG.isLoggable(INFO))
+				LOG.info("Unable to connect to private mailbox");
 		}
 	}
 
 	@Override
-	public void stopService() throws ServiceException {
-		if (mailboxLanFuture != null && !mailboxLanFuture.isCancelled())
-			mailboxLanFuture.cancel(true);
+	public void stopService() {
+		if (mailboxFuture != null && !mailboxFuture.isCancelled())
+			mailboxFuture.cancel(true);
 		eventBus.removeListener(this);
 	}
 }