diff --git a/src/main.rs b/src/main.rs
index bff47decec29e2162603b916a33569f4b6ad6d7d..9d9907673012ee0fe753a75241729dac1509ec71 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,24 +1,10 @@
 #![allow(unused_imports)]
 
 mod config;
+mod matrix;
 use crate::config::Config;
 
-use matrix_sdk::{
-    deserialized_responses::EncryptionInfo,
-    room::Room,
-    ruma::{
-        events::{
-            macros::EventContent, push_rules::PushRulesEvent, room::message::MessageEventContent,
-            room::topic::TopicEventContent, AnyRoomEvent, AnySyncRoomEvent, StateEvent,
-            SyncMessageEvent,
-        },
-        UserId,
-    },
-    Client, LoopCtrl, Result, SyncSettings, RoomInfo,
-};
-
-use matrix_sdk::ruma::{events::SyncStateEvent, Int, MilliSecondsSinceUnixEpoch};
-
+use matrix_sdk::Result;
 use std::convert::TryFrom;
 use std::path::Path;
 use std::{env, process::exit};
@@ -61,44 +47,7 @@ async fn main() -> Result<()> {
     let config_file = env::args().last().unwrap();
     println!("Using config file: {}", config_file);
     return match config::from_file(&config_file) {
-        Ok(config) => {
-            let alice = UserId::try_from(config.user_name)?;
-            let client = Client::new(config.homeserver_url)?;
-
-            // Login
-            client
-                .login(
-                    alice.localpart(),
-                    config.user_password.as_str(),
-                    None,
-                    Some(config.display_name.as_str()),
-                )
-                .await?;
-            println!("Logged as: {}", alice);
-
-            // Don't respond to old messages
-            client.sync_once(SyncSettings::default()).await?;
-
-            // https://docs.rs/ruma/0.4.0/ruma/events/enum.AnySyncMessageEvent.html
-            client
-                .register_event_handler(
-                    |ev: SyncMessageEvent<MessageEventContent>,
-                     room: Room,
-                     encryption_info: Option<EncryptionInfo>| async move {
-                        println!(
-                            "---\nROOM: {:?}\nENC: {:?}\nSME: {:?}",
-                            room, encryption_info, ev
-                        );
-                    },
-                )
-                .await;
-
-            println!("Entering sync loop");
-            let token = client.sync_token().await.unwrap();
-            let settings = SyncSettings::default().token(token);
-            client.sync(settings).await;
-            Ok(())
-        }
+        Ok(config) => matrix::connect_and_handle(config).await,
         Err(e) => panic!(
             "Failed to read config file '{}' with error: {}",
             config_file, e
diff --git a/src/matrix.rs b/src/matrix.rs
new file mode 100644
index 0000000000000000000000000000000000000000..74c4f69dbe672ded6611059011b54b5680c6dcad
--- /dev/null
+++ b/src/matrix.rs
@@ -0,0 +1,55 @@
+use crate::config::Config;
+use std::convert::TryFrom;
+
+use matrix_sdk::{
+    deserialized_responses::EncryptionInfo,
+    room::Room,
+    ruma::{
+        events::{
+            macros::EventContent, push_rules::PushRulesEvent, room::message::MessageEventContent,
+            room::topic::TopicEventContent, AnyRoomEvent, AnySyncRoomEvent, StateEvent,
+            SyncMessageEvent, SyncStateEvent,
+        },
+        Int, MilliSecondsSinceUnixEpoch, UserId,
+    },
+    Client, LoopCtrl, Result, RoomInfo, SyncSettings,
+};
+
+pub async fn connect_and_handle(config: Config) -> Result<()> {
+    let alice = UserId::try_from(config.user_name)?;
+    let client = Client::new(config.homeserver_url)?;
+
+    // Login
+    client
+        .login(
+            alice.localpart(),
+            config.user_password.as_str(),
+            None,
+            Some(config.display_name.as_str()),
+        )
+        .await?;
+    println!("Logged as: {}", alice);
+
+    // Don't respond to old messages
+    client.sync_once(SyncSettings::default()).await?;
+
+    // https://docs.rs/ruma/0.4.0/ruma/events/enum.AnySyncMessageEvent.html
+    client
+        .register_event_handler(
+            |ev: SyncMessageEvent<MessageEventContent>,
+             room: Room,
+             encryption_info: Option<EncryptionInfo>| async move {
+                println!(
+                    "---\nROOM: {:?}\nENC: {:?}\nSME: {:?}",
+                    room, encryption_info, ev
+                );
+            },
+        )
+        .await;
+
+    println!("Entering sync loop");
+    let token = client.sync_token().await.unwrap();
+    let settings = SyncSettings::default().token(token);
+    client.sync(settings).await;
+    Ok(())
+}