Index: perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm
===================================================================
--- perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm	(revision f798d022dd2f4b6ab1c7b51d133fc027b96517fc)
+++ perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm	(revision a957e9285b443c0e7c978318a7e67324b6085139)
@@ -132,6 +132,8 @@
 
     foreach my $jid ( $conn->getJIDs() ) {
+
+        next unless $conn->jidActive($jid) or $conn->tryReconnect($jid);
+
         my $client = $conn->getConnectionFromJID($jid);
-
         unless($client) {
             $conn->removeConnection($jid);
@@ -140,7 +142,5 @@
         my $status = $client->Process(0); # keep-alive
         if ( !defined($status) ) {
-            BarnOwl::error("Jabber account $jid disconnected!");
-            do_logout($jid);
-            next;
+            $conn->scheduleReconnect($jid);
         }
         if ($::shutdown) {
@@ -383,7 +383,9 @@
     }
 
-    if ( $conn->jidExists($jidStr) ) {
+    if ( $conn->jidActive($jidStr) ) {
         BarnOwl::error("Already logged in as $jidStr.");
         return;
+    } elsif ($conn->jidExists($jidStr)) {
+        return $conn->tryReconnect($jidStr, 1);
     }
 
@@ -453,4 +455,10 @@
                 BarnOwl::error( "Error in connect: " . join( " ", @result ) );
             } else {
+                $conn->setAuth(
+                    $jidStr,
+                    {   %{ $vars{jlogin_authhash} },
+                        password => $vars{jlogin_password}
+                    }
+                );
                 my $roster = $conn->getRosterFromJID($jidStr);
                 $roster->fetch();
@@ -463,5 +471,5 @@
                 $client->{fileno} = $client->getSocket()->fileno();
                 #queue_admin_msg("Connected to jabber as $fullJid ($client->{fileno})");
-                BarnOwl::add_dispatch($client->{fileno}, sub { $client->OwlProcess() });
+                BarnOwl::add_dispatch($client->{fileno}, sub { $client->OwlProcess($fullJid) });
 
                 # populate completion from roster.
Index: perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm
===================================================================
--- perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm	(revision 6b580b05f6e84a05297c835e3ff724e1e3187e1c)
+++ perl/modules/Jabber/lib/BarnOwl/Module/Jabber/Connection.pm	(revision a957e9285b443c0e7c978318a7e67324b6085139)
@@ -142,10 +142,22 @@
 sub OwlProcess {
     my $self = shift;
+    my $jid = shift || $self->{SESSION}->{FULLJID};
     my $status = $self->Process(0);
     if ( !defined($status) ) {
-        my $jid = $self->{SESSION}->{FULLJID};
-        BarnOwl::error("Jabber account $jid disconnected!");
-        BarnOwl::Module::Jabber::do_logout($jid);
+        $BarnOwl::Module::Jabber::conn->scheduleReconnect($jid);
     }
+}
+
+=head2 Disconnect
+
+Work around a bug in Net::Jabber::Client where Process' return status
+is not cleared on disconnect.
+
+=cut
+
+sub Disconnect {
+    my $self = shift;
+    delete $self->{PROCESSERROR};
+    return $self->SUPER::Disconnect(@_);
 }
 
Index: perl/modules/Jabber/lib/BarnOwl/Module/Jabber/ConnectionManager.pm
===================================================================
--- perl/modules/Jabber/lib/BarnOwl/Module/Jabber/ConnectionManager.pm	(revision 8ff511d084fa70be6a1515c8e3dcc3c1f9ba5763)
+++ perl/modules/Jabber/lib/BarnOwl/Module/Jabber/ConnectionManager.pm	(revision a957e9285b443c0e7c978318a7e67324b6085139)
@@ -41,4 +41,56 @@
       if $self->{$jidStr}->{Client};
     delete $self->{$jidStr};
+
+    return 1;
+}
+
+sub scheduleReconnect {
+    my $self = shift;
+    my $jidStr = shift;
+    return 0 unless exists $self->{$jidStr};
+    BarnOwl::admin_message(Jabber => "Disconnected from jabber account $jidStr");
+
+    BarnOwl::remove_dispatch($self->{$jidStr}->{Client}->{fileno}) if $self->{$jidStr}->{Client}->{fileno};
+    $self->{$jidStr}->{Client}->Disconnect()
+      if $self->{$jidStr}->{Client};
+
+    $self->{$jidStr}->{Status} = "reconnecting";
+    $self->{$jidStr}->{ReconnectBackoff} = 5;
+    $self->{$jidStr}->{ReconnectAt} = time + $self->{$jidStr}->{ReconnectBackoff};
+    return 1;
+}
+
+sub setAuth {
+    my $self = shift;
+    my $jidStr = shift;
+    $self->{$jidStr}->{Auth} = shift;
+}
+
+sub tryReconnect {
+    my $self = shift;
+    my $jidStr = shift;
+    my $force = shift;
+
+    return 0 unless exists $self->{$jidStr};
+    return 0 unless $self->{$jidStr}{Status} eq "reconnecting";
+    return 0 unless $force or (time > $self->{$jidStr}{ReconnectAt});
+
+    $self->{$jidStr}->{ReconnectBackoff} *= 2;
+    $self->{$jidStr}->{ReconnectBackoff} = 60*5
+        if $self->{$jidStr}->{ReconnectBackoff} > 60*5;
+    $self->{$jidStr}->{ReconnectAt} = time + $self->{$jidStr}->{ReconnectBackoff};
+
+    my $status = $self->{$jidStr}->{Client}->Connect;
+    return 0 unless $status;
+
+    my @result = $self->{$jidStr}->{Client}->AuthSend( %{ $self->{$jidStr}->{Auth} } );
+    if ( !@result || $result[0] ne 'ok' ) {
+        $self->removeConnection($jidStr);
+        BarnOwl::error( "Error in jabber reconnect: " . join( " ", @result ) );
+        return 0;
+    }
+
+    BarnOwl::admin_message(Jabber => "Reconnected to jabber as $jidStr");
+    $self->{$jidStr}{Status} = "available";
 
     return 1;
@@ -88,4 +140,10 @@
 }
 
+sub jidActive {
+    my $self = shift;
+    my $jidStr = shift;
+    return(exists $self->{$jidStr} and $self->{$jidStr}{Status} eq "available");
+}
+
 sub sidExists {
     my $self = shift;
@@ -110,5 +168,5 @@
     my $jid = shift;
     $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID');
-    return $self->{$jid}->{Client} if exists $self->{$jid};
+    return $self->{$jid}->{Client} if $self->jidActive($jid);
 }
 
@@ -127,5 +185,5 @@
     my $jid = shift;
     $jid = $jid->GetJID('full') if UNIVERSAL::isa($jid, 'Net::XMPP::JID');
-    return $self->{$jid}->{Roster} if exists $self->{$jid};
+    return $self->{$jid}->{Roster} if $self->jidExists($jid);
 }
 
