diff --git a/exec/binkit.js b/exec/binkit.js
index 2076956a6b4be38e0ca814ec3b8468170d34721c..6e060379caac0bc20fc515ee76578733d8fa6779 100644
--- a/exec/binkit.js
+++ b/exec/binkit.js
@@ -10,8 +10,8 @@
  * 2) Will not check in a zone-specified directory for the default
  *    zone.  That is, if the default zone is zone 1, and the outbound
  *    is "/path/to/outbound", it will not correctly handle the case
- *    where there is a "/path/to/outbound.001" directory.  The
- *    behaviour in this case is undefined and likely to be bad.
+ *    where there is a "/path/to/outbound.001" directory.
+ * 3) The domain is always 'fidonet'
  * 
  * See FTS-5005 for details.
  */
@@ -31,7 +31,7 @@ function lock_flow(file, csy)
 	 * Race-safe version...
 	 * 1) If date is "too old", pick a random time in the future.
 	 * 2) Set the file date to that random time.
-	 * 3) Wait one second.
+	 * 3) Wait one second (there's still an unlikely race here)
 	 * 4) If the file date is the random time you chose, set the date
 	 *    to now and take "ownership" of the file.
 	 */
@@ -91,15 +91,135 @@ function unlock_flow(locks)
 	}
 }
 
+/*
+ * Given a list of addresses to rescan, calls
+ * bp.addFile() for any pending file transfers.
+ */
+function add_outbound_files(addrs, bp)
+{
+	addrs.forEach(function(addr) {
+		log(LOG_DEBUG, "Adding outbound files for "+addr);
+		// Find all possible flow files for the remote.
+		var allfiles = directory(bp.cb_data.binkit_scfg.outbound.replace(/[\\\/]$/)+addr.flo_outbound(bp.default_zone, bp.default_domain)+'*');
+		// Parse flow files and call addFile() tracking what to do on success.
+		allfiles.forEach(function(file) {
+			var flo;
+			var line;
+			var action;
+			var i;
+			var fnchars = '0123456789abcdefghijklmnopqrstuvwxyz';
+			var fname;
+
+			switch(file_getext(file).toLowerCase()) {
+				case '.flo':
+				case '.ilo':
+				case '.hlo':
+				case '.clo':
+				case '.dlo':
+					flo = new File(file);
+					if (!flo.open("r")) {
+						log(LOG_ERROR, "Unable to open FLO file '"+flo.name+"'.");
+						break;
+					}
+					if (bp.cb_data.binkit_flow_contents[flo.name] === undefined)
+						bp.cb_data.binkit_flow_contents[flo.name] = [];
+					while((line = flo.readln(2048))) {
+						switch(line.charAt(0)) {
+							case '#':
+								if (bp.addFile(line.substr(1)))
+									bp.cb_data.binkit_file_actions[flo.name] = 'TRUNCATE';
+								bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
+								break;
+							case '^':
+							case '-':
+								if (bp.addFile(line.substr(1)))
+									bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
+								bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
+								break;
+							case '~':
+							case '!':
+								break;
+							case '@':
+								line = line.substr(1);
+								if (bp.addFile(line))
+									bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
+								break;
+							default:
+								if (bp.addFile(line))
+									bp.cb_data.binkit_flow_contents[flo.name].push(line.substr(1));
+								break;
+						}
+					}
+					flo.close();
+					break;
+				case '.out':
+				case '.iut':
+				case '.hut':
+				case '.cut':
+				case '.dut':
+					fname = '';
+					for (i=0; i<8; i++)
+						fname += fnchars[random(fnchars.length)];
+					fname += '.pkt';
+					if (bp.addFile(file, fname))
+						bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
+					break;
+				case '.rep':
+					fname = '';
+					for (i=0; i<8; i++)
+						fname += fnchars[random(fnchars.length)];
+					fname += '.rep';
+					if (bp.addFile(file, fname))
+						bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
+					break;
+				default:
+					log(LOG_WARNING, "Unsupported flow file type '"+file+"'.");
+					break;
+			}
+		});
+	});
+}
+
 function callout_auth_cb(mode, bp)
 {
 	/*
-	 * TODO: Add all outgoing mail for all authenticated addresses.
-	 * This is tricky since we need to only use addresses that are
-	 * configured with the single password we sent.  The multiple
-	 * password extension (FRL-1013) was withdrawn, so we can't do
-	 * that.
+	 * Loop through remote addresses, building a list of the ones with
+	 * the same password (if we used an empty password, no other nodes
+	 * are allowed)
 	 */
+	var addrs = [];
+
+	if (bp.cb_data.binkitpw === undefined)
+		addrs.push(bp.binkit_to_addr);
+	else {
+		bp.remote_addrs.forEach(function(addr) {
+			if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
+				if (bp.cb_data.binkitcfg.node[addr].pw === bp.cb_data.binkitpw)
+					addrs.push(addr);
+			}
+			else
+				log(LOG_DEBUG, "Unconfigured address "+addr);
+		});
+	}
+
+	add_outbound_files(addrs);
+}
+
+/*
+ * Delete completed flo files.
+ */
+function callout_tx_callback(fname, bp)
+{
+	var j;
+
+	Object.keys(bp.bp.cb_data.binkit_flow_contents).forEach(function(flo) {
+		if (file_exists(flo)) {
+			while ((j = bp.cb_data.binkit_flow_contents[flo].indexOf(fname)) !== -1)
+				bp.cb_data.binkit_flow_contents[flo].splice(j, 1);
+			if (bp.cb_data.binkit_flow_contents[flo].length == 0)
+				file_remove(flo);
+		}
+	});
 }
 
 function callout_rx_callback(fname, bp)
@@ -127,39 +247,82 @@ function callout_want_callback(fobj, fsize, fdate, offset, bp)
 	return this.file.ACCEPT;
 }
 
+function callout_done(bp)
+{
+	var f;
+
+	bp.sent_files.forEach(function(file) {
+		if (bp.cb_data.binkit_file_actions[file] !== undefined) {
+			switch(bp.cb_data.binkit_file_actions[file]) {
+				case 'TRUNCATE':
+					f = new File(file);
+					if (f.truncate())
+						log(LOG_INFO, "Truncated '"+f.name+"'.");
+					else
+						log(LOG_ERROR, "Unable to truncate '"+f.name+"'.");
+					break;
+				case 'DELETE':
+					if (file_remove(file))
+						log(LOG_INFO, "Removed '"+file+"'.");
+					else
+						log(LOG_ERROR, "Unable to remove '"+file+"'.");
+			}
+		}
+	});
+
+	// TODO: update incomplete flow files...
+}
+
 function callout(addr, scfg)
 {
-	/*
-	 * TODO: We can force 5D stuff here by adding a "fidonet" argument
-	 * in parse_addr()
-	 */
-	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1);
-	var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, callout_rx_callback);
+	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
+	var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, callout_rx_callback, callout_tx_callback);
+	var port;
+	var f;
 
 	log(LOG_INFO, "Callout to "+addr+" started.");
-	// Force debug mode for now...
+	bp.cb_data = {
+		binkitcfg:new BinkITCfg(),
+		binkit_to_addr:addr,
+		binkit_scfg:scfg,
+		binkit_file_actions:{},
+		binkit_flow_contents:{},
+	};
+	if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
+		bp.cb_data.binkitpw = bp.cb_data.binkitcfg.node[addr].pass;
+		port = bp.cb_data.binkitcfg.node[addr].port;
+		bp.require_md5 = !(bp.cb_data.binkitcfg.node[addr].nomd5);
+	}
+	// TODO: Force debug mode for now...
 	bp.debug = true;
 	bp.default_zone = myaddr.zone;
 	bp.default_domain = myaddr.domain;
 	bp.want_callback = callout_want_callback;
-	bp.rx_callback = callout_rx_callback;
 
 	// We won't add files until the auth finishes...
-	/*
-	 * TODO: We're currently using the packet password... this is not
-	 * only not a good idea, it's a BAD idea since the session password
-	 * is not transmitted in the clear but packet passwords are.
-	 */
+	bp.connect(addr, bp.cb_data.binkitpw, callout_auth_cb, port);
+
+	callout_done(bp);
+
+	// TODO: Some real .try information...
+	f = new File(bp.cb_data.binkit_scfg.outbound.replace(/[\\\/]$/)+addr.flo_outbound(bp.default_zone, bp.default_domain)+'.try');
+	if (f.open("w")) {
+		f.writeln("Callout complete.");
+		f.close();
+	}
+	else {
+		log(LOG_ERROR, "Unable to create .try file '"+f.name+"'.");
+	}
 }
 
 function run_one_outbound_dir(dir, scfg)
 {
-	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1);
+	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
 	var flow_files;
 	var lock_files;
-	var addr;
 	var ext;
 	var i;
+	var ran = {};
 
 	log(LOG_DEBUG, "Running outbound dir "+dir);
 
@@ -192,6 +355,8 @@ function run_one_outbound_dir(dir, scfg)
 
 	function check_flavour(wildcard, typename)
 	{
+		var addr;
+
 		while (!js.terminated) {
 			flow_files = directory(dir+wildcard);
 			if (flow_files.length == 0)
@@ -199,12 +364,14 @@ function run_one_outbound_dir(dir, scfg)
 			flow_file_loop:
 			for (i=0; i<flow_files.length; i++) {
 				try {
-					addr = FIDO.parse_flo_file_path(flow_files[i], myaddr.zone);
+					addr = FIDO.parse_flo_file_path(flow_files[i], myaddr.zone, 'fidonet');
 				}
 				catch(addr_e) {
 					log(LOG_WARNING, addr_e+" when checking '"+flow_files[i]+"' (default zone: "+myaddr.zone+")");
 					continue;
 				}
+				if (ran[addr] !== undefined)
+					continue;
 				ext = file_getext(flow_files[i]);
 
 				// Ensure this is the "right" outbound (file case, etc)
@@ -245,14 +412,8 @@ function run_one_outbound_dir(dir, scfg)
 			if (i<flow_files.length) {
 				log(LOG_DEBUG, "Attempting callout for file "+flow_files[i]);
 				// Use a try/catch to ensure we clean up the lock files.
-				try {
-					callout(flow_files[i], scfg);
-				}
-				catch(callout_e) {
-					log(LOG_DEBUG, "Unlocking after exception in callout.");
-					unlock_flow(lock_files);
-					throw(callout_e);
-				}
+				callout(addr, scfg);
+				ran[addr] = true;
 				unlock_flow(lock_files);
 			}
 			else {