diff --git a/Ring/Ring.xcodeproj/project.pbxproj b/Ring/Ring.xcodeproj/project.pbxproj
index 0e0389be657c42853c664fb6d9ebfc4e9e4a0c56..38947b0e373e717b15c8597c44da8a0dc556f5cb 100644
--- a/Ring/Ring.xcodeproj/project.pbxproj
+++ b/Ring/Ring.xcodeproj/project.pbxproj
@@ -183,6 +183,9 @@
 		56BBC9D41EDC7A6D00CDAF8B /* libargon2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56BBC9D31EDC7A6D00CDAF8B /* libargon2.a */; };
 		56BBC9DF1EDDC9D300CDAF8B /* LookupNameResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9DE1EDDC9D300CDAF8B /* LookupNameResponse.m */; };
 		56C715FF1F0D36C600770048 /* ContactsAdapter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 56C715FE1F0D36C600770048 /* ContactsAdapter.mm */; };
+		62A88D371F6C2ED400F8AB18 /* PresenceAdapterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A88D361F6C2ED400F8AB18 /* PresenceAdapterDelegate.swift */; };
+		62A88D391F6C323500F8AB18 /* PresenceAdapter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62A88D381F6C323500F8AB18 /* PresenceAdapter.mm */; };
+		62A88D3B1F6C3ACC00F8AB18 /* PresenceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A88D3A1F6C3ACC00F8AB18 /* PresenceService.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -406,6 +409,10 @@
 		56C715FE1F0D36C600770048 /* ContactsAdapter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContactsAdapter.mm; sourceTree = "<group>"; };
 		56C716001F0D36D900770048 /* ContactsAdapterDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsAdapterDelegate.swift; sourceTree = "<group>"; };
 		56C716021F0D466100770048 /* ContactsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsService.swift; sourceTree = "<group>"; };
+		62A88D351F6C2E5F00F8AB18 /* PresenceAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PresenceAdapter.h; sourceTree = "<group>"; };
+		62A88D361F6C2ED400F8AB18 /* PresenceAdapterDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceAdapterDelegate.swift; sourceTree = "<group>"; };
+		62A88D381F6C323500F8AB18 /* PresenceAdapter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PresenceAdapter.mm; sourceTree = "<group>"; };
+		62A88D3A1F6C3ACC00F8AB18 /* PresenceService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenceService.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -553,6 +560,8 @@
 				56C716001F0D36D900770048 /* ContactsAdapterDelegate.swift */,
 				1A5DC01D1F355DA70075E8EF /* ContactsAdapterDelegate.swift */,
 				1A5DC01F1F355DCF0075E8EF /* ContactsService.swift */,
+				62A88D361F6C2ED400F8AB18 /* PresenceAdapterDelegate.swift */,
+				62A88D3A1F6C3ACC00F8AB18 /* PresenceService.swift */,
 			);
 			path = Services;
 			sourceTree = "<group>";
@@ -583,6 +592,8 @@
 				1A5DC00D1F3559070075E8EF /* ContactsAdapter.mm */,
 				563AEC741EA66487003A5641 /* AccountCreation */,
 				563AEC731EA6627F003A5641 /* NameRegistration */,
+				62A88D351F6C2E5F00F8AB18 /* PresenceAdapter.h */,
+				62A88D381F6C323500F8AB18 /* PresenceAdapter.mm */,
 			);
 			path = Bridging;
 			sourceTree = "<group>";
@@ -1270,6 +1281,7 @@
 				1A3D28A71F0EB9DB00B524EE /* Bool+String.swift in Sources */,
 				5516C29F1E71CEFF009D3D2D /* AccountModelHelper.swift in Sources */,
 				1ABE07D31F0D8FE800D36361 /* Storyboards.swift in Sources */,
+				62A88D3B1F6C3ACC00F8AB18 /* PresenceService.swift in Sources */,
 				1A2D18E51F29197100B2C785 /* MessageAccessoryView.swift in Sources */,
 				1A2D18C61F29180700B2C785 /* ConversationModel.swift in Sources */,
 				56308BA71EA00E5700660275 /* NameRegistrationResponse.m in Sources */,
@@ -1289,6 +1301,7 @@
 				1A2041861F1EA19600C08435 /* CreateAccountViewController.swift in Sources */,
 				1A2D18C21F29180700B2C785 /* AccountCredentialsModel.swift in Sources */,
 				1A2D18FF1F29352D00B2C785 /* MeViewModel.swift in Sources */,
+				62A88D391F6C323500F8AB18 /* PresenceAdapter.mm in Sources */,
 				1A2D18B71F29164700B2C785 /* SmartlistViewModel.swift in Sources */,
 				04399AAE1D1C304300E99CD9 /* Utils.mm in Sources */,
 				56BBC9A31ED714DF00CDAF8B /* ConversationsService.swift in Sources */,
@@ -1316,6 +1329,7 @@
 				1A2D19011F29353A00B2C785 /* MeDetailViewModel.swift in Sources */,
 				1A2D18A41F27EF5200B2C785 /* AppCoordinator.swift in Sources */,
 				1A2D18C31F29180700B2C785 /* AccountModel.swift in Sources */,
+				62A88D371F6C2ED400F8AB18 /* PresenceAdapterDelegate.swift in Sources */,
 				1A2D18EB1F29197100B2C785 /* MessageViewModel.swift in Sources */,
 				02B22DFF1DF755DB000358C9 /* AccountsService.swift in Sources */,
 				1A5DC0421F3567DF0075E8EF /* ContactRequestsCoordinator.swift in Sources */,
diff --git a/Ring/Ring/AppDelegate.swift b/Ring/Ring/AppDelegate.swift
index 2c4c76c9b126acbe68eedbd3a682978f2c08fd65..6deb2d7830e053db795efccb3f64a10e6e833e2e 100644
--- a/Ring/Ring/AppDelegate.swift
+++ b/Ring/Ring/AppDelegate.swift
@@ -27,8 +27,6 @@ import RxSwift
 import Chameleon
 import Contacts
 
-import Contacts
-
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {
 
@@ -38,13 +36,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     private let nameService = NameService(withNameRegistrationAdapter: NameRegistrationAdapter())
     private let conversationsService = ConversationsService(withMessageAdapter: MessagesAdapter())
     private let contactsService = ContactsService(withContactsAdapter: ContactsAdapter())
+    private let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter())
 
     public lazy var injectionBag: InjectionBag = {
         return InjectionBag(withDaemonService: self.daemonService,
                             withAccountService: self.accountService,
                             withNameService: self.nameService,
                             withConversationService: self.conversationsService,
-                            withContactsService: self.contactsService)
+                            withContactsService: self.contactsService,
+                            withPresenceService: self.presenceService)
     }()
     private lazy var appCoordinator: AppCoordinator = {
         return AppCoordinator(with: self.injectionBag)
@@ -77,12 +77,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
             if let currentAccount = self.accountService.currentAccount {
                 self.contactsService.loadContacts(withAccount: currentAccount)
                 self.contactsService.loadContactRequests(withAccount: currentAccount)
+                self.presenceService.subscribeBuddies(withAccount: currentAccount, withContacts: self.contactsService.contacts.value)
             }
-            self.window?.rootViewController = self.appCoordinator.rootViewController
-            self.window?.makeKeyAndVisible()
-            self.appCoordinator.start()
         }.disposed(by: self.disposeBag)
 
+        self.window?.rootViewController = self.appCoordinator.rootViewController
+        self.window?.makeKeyAndVisible()
+        self.appCoordinator.start()
+
         return true
     }
 
diff --git a/Ring/Ring/Bridging/PresenceAdapter.h b/Ring/Ring/Bridging/PresenceAdapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9423d97c4ca3ee6a9f7ec06739cda23f84ccb46
--- /dev/null
+++ b/Ring/Ring/Bridging/PresenceAdapter.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol PresenceAdapterDelegate;
+
+@interface PresenceAdapter : NSObject
+
+@property (class, nonatomic, weak) id <PresenceAdapterDelegate> delegate;
+
+- (void)subscribeBuddyWithURI:(NSString*)uri WithAccountId:(NSString*)accountId WithFlag:(BOOL)flag;
+
+@end
diff --git a/Ring/Ring/Bridging/PresenceAdapter.mm b/Ring/Ring/Bridging/PresenceAdapter.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6648e76ee52726c928f67eb5a20de6a11614458b
--- /dev/null
+++ b/Ring/Ring/Bridging/PresenceAdapter.mm
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+#import "PresenceAdapter.h"
+#import "Utils.h"
+#import "dring/presencemanager_interface.h"
+#import "Ring-Swift.h"
+
+using namespace DRing;
+
+@implementation PresenceAdapter
+
+// Static delegate that will receive the propagated daemon events
+static id <PresenceAdapterDelegate> _delegate;
+
+#pragma mark Init
+
+- (id)init {
+    if (self = [super init]) {
+        [self registerPresenceHandlers];
+    }
+    return self;
+}
+
+#pragma mark -
+
+#pragma mark Callbacks registration
+
+- (void)registerPresenceHandlers {
+    std::map<std::string, std::shared_ptr<CallbackWrapperBase>> presenceHandlers;
+
+    // Incoming buddy notification
+    presenceHandlers.insert(exportable_callback<PresenceSignal::NewBuddyNotification>([&](const std::string& account_id,
+                                                                                      const std::string& uri,
+                                                                                      int status,
+                                                                                      const std::string& lineStatus) {
+        if(PresenceAdapter.delegate) {
+            NSString* accountId = [NSString stringWithUTF8String:account_id.c_str()];
+            NSString* uriString = [NSString stringWithUTF8String:uri.c_str()];
+            NSString* lineStatusString = [NSString stringWithUTF8String:lineStatus.c_str()];
+
+            [PresenceAdapter.delegate newBuddyNotificationWithAccountId:accountId withUri:uriString withStatus:(NSInteger)status withLineStatus:lineStatusString];
+        }
+    }));
+
+    registerPresHandlers(presenceHandlers);
+}
+
+#pragma mark -
+
+- (void)subscribeBuddyWithURI:(NSString*)uri WithAccountId:(NSString*)accountId WithFlag:(BOOL)flag {
+    DRing::subscribeBuddy(std::string([accountId UTF8String]), std::string([uri UTF8String]), (bool)flag);
+}
+
+#pragma mark PresenceAdapterDelegate
+
++ (id <PresenceAdapterDelegate>)delegate {
+    return _delegate;
+}
+
++ (void) setDelegate:(id<PresenceAdapterDelegate>)delegate {
+    _delegate = delegate;
+}
+
+#pragma mark -
+
+@end
diff --git a/Ring/Ring/Bridging/Ring-Bridging-Header.h b/Ring/Ring/Bridging/Ring-Bridging-Header.h
index 657359142aa34b1210fca00dcdc64cc084125931..a1af5df7c4445f9e1996e88edcaf44c81205687c 100644
--- a/Ring/Ring/Bridging/Ring-Bridging-Header.h
+++ b/Ring/Ring/Bridging/Ring-Bridging-Header.h
@@ -32,3 +32,4 @@
 #import "MessagesAdapter.h"
 #import "Chameleon/Chameleon.h"
 #import "ContactsAdapter.h"
+#import "PresenceAdapter.h"
diff --git a/Ring/Ring/Coordinators/InjectionBag.swift b/Ring/Ring/Coordinators/InjectionBag.swift
index 10188aad501f2d31afbb21d03f03287654b4c0dd..5c003c8571921510632426710c0040348c6a1439 100644
--- a/Ring/Ring/Coordinators/InjectionBag.swift
+++ b/Ring/Ring/Coordinators/InjectionBag.swift
@@ -28,17 +28,20 @@ class InjectionBag {
     let nameService: NameService
     let conversationsService: ConversationsService
     let contactsService: ContactsService
+    let presenceService: PresenceService
 
     init (withDaemonService daemonService: DaemonService,
           withAccountService accountService: AccountsService,
           withNameService nameService: NameService,
           withConversationService conversationService: ConversationsService,
-          withContactsService contactsService: ContactsService) {
+          withContactsService contactsService: ContactsService,
+          withPresenceService presenceService: PresenceService) {
         self.daemonService = daemonService
         self.accountService = accountService
         self.nameService = nameService
         self.conversationsService = conversationService
         self.contactsService = contactsService
+        self.presenceService = presenceService
     }
 
 }
diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
index ce8fc613ffe1295585f5fc47e5f6dfa4dd661ef6..841b27087515faaf8dd44de2e44eace749630380 100644
--- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
@@ -30,6 +30,26 @@ class ConversationViewModel: ViewModel {
      */
     private let log = SwiftyBeaver.self
 
+    //Services
+    private let conversationsService: ConversationsService
+    private let accountService: AccountsService
+    private let nameService: NameService
+    private let contactsService: ContactsService
+    private let presenceService: PresenceService
+    private let injectionBag: InjectionBag
+
+    required init(with injectionBag: InjectionBag) {
+        self.injectionBag = injectionBag
+        self.accountService = injectionBag.accountService
+        self.conversationsService = injectionBag.conversationsService
+        self.nameService = injectionBag.nameService
+        self.contactsService = injectionBag.contactsService
+        self.presenceService = injectionBag.presenceService
+
+        dateFormatter.dateStyle = .medium
+        hourFormatter.dateFormat = "HH:mm"
+    }
+
     var conversation: ConversationModel! {
         didSet {
             //Create observable from sorted conversations and flatMap them to view models
@@ -50,20 +70,34 @@ class ConversationViewModel: ViewModel {
 
             let contact = self.contactsService.contact(withRingId: self.conversation.recipientRingId)
 
-            if let contact = contact {
+	    if let contact = contact {
                 self.inviteButtonIsAvailable.onNext(!contact.confirmed)
             }
             self.contactsService.contactStatus.subscribe(onNext: { contact in
                 self.inviteButtonIsAvailable.onNext(!contact.confirmed)
             }).disposed(by: self.disposeBag)
 
+            // subscribe to presence updates for the conversation's associated contact
+            self.presenceService
+                .sharedResponseStream
+                .filter({ presenceUpdateEvent in
+                    return presenceUpdateEvent.eventType == ServiceEventType.presenceUpdated
+                        && presenceUpdateEvent.getEventInput(.uri) == contact?.ringId
+                })
+                .subscribe(onNext: { [unowned self] presenceUpdateEvent in
+                    if let uri: String = presenceUpdateEvent.getEventInput(.uri) {
+                        self.contactPresence.onNext(self.presenceService.contactPresence[uri]!)
+                    }
+                })
+                .disposed(by: disposeBag)
+
             if let contactUserName = contact?.userName {
                 self.userName.onNext(contactUserName)
             } else {
 
                 let recipientRingId = self.conversation.recipientRingId
 
-                //Return an observer for the username lookup
+                // Return an observer for the username lookup
                 self.nameService.usernameLookupStatus
                     .filter({ lookupNameResponse in
                         return lookupNameResponse.address != nil &&
@@ -101,25 +135,10 @@ class ConversationViewModel: ViewModel {
     var messages: Observable<[MessageViewModel]>!
 
     var userName = BehaviorSubject(value: "")
-    var inviteButtonIsAvailable = BehaviorSubject(value: true)
-
-    //Services
-    private let conversationsService: ConversationsService
-    private let accountService: AccountsService
-    private let nameService: NameService
-    private let contactsService: ContactsService
-    private let injectionBag: InjectionBag
 
-    required init(with injectionBag: InjectionBag) {
-        self.injectionBag = injectionBag
-        self.accountService = injectionBag.accountService
-        self.conversationsService = injectionBag.conversationsService
-        self.nameService = injectionBag.nameService
-        self.contactsService = injectionBag.contactsService
+    var inviteButtonIsAvailable = BehaviorSubject(value: true)
 
-        dateFormatter.dateStyle = .medium
-        hourFormatter.dateFormat = "HH:mm"
-    }
+    var contactPresence = BehaviorSubject(value: false)
 
     var unreadMessages: String {
        return self.unreadMessagesCount.description
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
index 12082a6f9a7f5cd0fb2c7c0f568418b3f92d7e10..76c96e87bfa7121e01078042080f96a4f1555dc1 100644
--- a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.swift
@@ -30,6 +30,7 @@ class ConversationCell: UITableViewCell, NibReusable {
     @IBOutlet weak var newMessagesLabel: UILabel!
     @IBOutlet weak var lastMessageDateLabel: UILabel!
     @IBOutlet weak var lastMessagePreviewLabel: UILabel!
+    @IBOutlet weak var presenceIndicator: UIView!
 
     override func setSelected(_ selected: Bool, animated: Bool) {
         super.setSelected(selected, animated: animated)
diff --git a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib
index a82c301ea75eb6599b07f9b812b8c7a65ecf3a81..f5e558f555bfe56fdecbbf040a0ee3a623b9c7cb 100644
--- a/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib
+++ b/Ring/Ring/Features/Conversations/SmartList/Cells/ConversationCell.xib
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F2073" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina4_7" orientation="portrait">
         <adaptation id="fullscreen"/>
     </device>
@@ -15,7 +15,7 @@
             <rect key="frame" x="0.0" y="0.0" width="358" height="76"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
             <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
-                <rect key="frame" x="0.0" y="0.0" width="358" height="75.5"/>
+                <rect key="frame" x="0.0" y="0.0" width="358" height="76"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
                     <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_contact_picture" translatesAutoresizingMaskIntoConstraints="NO" id="pFB-Jn-TNP">
@@ -32,19 +32,19 @@
                         </userDefinedRuntimeAttributes>
                     </imageView>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Yesterday" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7Yv-cC-LKx">
-                        <rect key="frame" x="281.5" y="30.5" width="60.5" height="14.5"/>
+                        <rect key="frame" x="281" y="31" width="61" height="15"/>
                         <fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
                         <color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
                         <nil key="highlightedColor"/>
                     </label>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Name" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2fJ-Wf-1e0">
-                        <rect key="frame" x="60" y="8" width="217.5" height="39"/>
+                        <rect key="frame" x="60" y="8" width="217" height="39"/>
                         <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
                         <nil key="textColor"/>
                         <nil key="highlightedColor"/>
                     </label>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Preview" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eug-ak-r49">
-                        <rect key="frame" x="60" y="51" width="217.5" height="17"/>
+                        <rect key="frame" x="60" y="51" width="217" height="17"/>
                         <fontDescription key="fontDescription" type="system" pointSize="14"/>
                         <nil key="textColor"/>
                         <nil key="highlightedColor"/>
@@ -76,14 +76,29 @@
                             </userDefinedRuntimeAttribute>
                         </userDefinedRuntimeAttributes>
                     </view>
+                    <view clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" translatesAutoresizingMaskIntoConstraints="NO" id="Fpi-20-ZYV" userLabel="Presence Indicator">
+                        <rect key="frame" x="42" y="44" width="14" height="14"/>
+                        <color key="backgroundColor" red="0.0" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="14" id="0m2-aN-1GT"/>
+                            <constraint firstAttribute="width" constant="14" id="m3b-My-KNY"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
+                                <integer key="value" value="6"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
                 </subviews>
                 <constraints>
                     <constraint firstItem="2fJ-Wf-1e0" firstAttribute="leading" secondItem="pFB-Jn-TNP" secondAttribute="trailing" constant="4" id="2NV-6m-dri"/>
                     <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="7Yv-cC-LKx" secondAttribute="bottom" constant="8" id="2O6-wC-voj"/>
                     <constraint firstItem="eug-ak-r49" firstAttribute="leading" secondItem="pFB-Jn-TNP" secondAttribute="trailing" constant="4" id="9ah-Ed-RlY"/>
                     <constraint firstItem="pFB-Jn-TNP" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="9mO-5E-3lA"/>
+                    <constraint firstItem="Fpi-20-ZYV" firstAttribute="bottom" secondItem="pFB-Jn-TNP" secondAttribute="bottom" id="BMe-Il-GoN"/>
                     <constraint firstItem="7Yv-cC-LKx" firstAttribute="leading" secondItem="2fJ-Wf-1e0" secondAttribute="trailing" constant="4" id="BzU-Ya-2ME"/>
                     <constraint firstItem="JTE-eF-Y5s" firstAttribute="trailing" secondItem="pFB-Jn-TNP" secondAttribute="trailing" id="MgK-cd-QXM"/>
+                    <constraint firstItem="Fpi-20-ZYV" firstAttribute="trailing" secondItem="pFB-Jn-TNP" secondAttribute="trailing" id="Oav-3c-X7k"/>
                     <constraint firstAttribute="trailing" secondItem="7Yv-cC-LKx" secondAttribute="trailing" constant="16" id="UOx-Og-IuZ"/>
                     <constraint firstItem="JTE-eF-Y5s" firstAttribute="top" secondItem="pFB-Jn-TNP" secondAttribute="top" id="W3A-IX-eXJ"/>
                     <constraint firstItem="7Yv-cC-LKx" firstAttribute="top" relation="greaterThanOrEqual" secondItem="H2p-sc-9uM" secondAttribute="top" constant="8" id="Wei-7X-4zv"/>
@@ -101,6 +116,7 @@
                 <outlet property="nameLabel" destination="2fJ-Wf-1e0" id="0Mb-yC-vh6"/>
                 <outlet property="newMessagesIndicator" destination="JTE-eF-Y5s" id="9kR-8x-Zpk"/>
                 <outlet property="newMessagesLabel" destination="P5S-4k-0yx" id="WlA-Z8-sNC"/>
+                <outlet property="presenceIndicator" destination="Fpi-20-ZYV" id="RL9-sx-sBF"/>
                 <outlet property="profileImage" destination="pFB-Jn-TNP" id="zuf-CZ-9wL"/>
             </connections>
             <point key="canvasLocation" x="70" y="-92"/>
diff --git a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
index a56fd6f0b0ace4c8f16cae9236b1569ce22320b4..4c23e9e9447ea29216d7712a473ac5ae2003808e 100644
--- a/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
+++ b/Ring/Ring/Features/Conversations/SmartList/SmartlistViewController.swift
@@ -117,12 +117,22 @@ class SmartlistViewController: UIViewController, StoryboardBased, ViewModelBased
 
                 let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ConversationCell.self)
 
-                item.userName.asObservable().observeOn(MainScheduler.instance).bind(to: cell.nameLabel.rx.text).disposed(by: self.disposeBag)
+                item.userName.asObservable()
+                    .observeOn(MainScheduler.instance)
+                    .bind(to: cell.nameLabel.rx.text)
+                    .disposed(by: self.disposeBag)
+
                 cell.newMessagesLabel.text = item.unreadMessages
                 cell.lastMessageDateLabel.text = item.lastMessageReceivedDate
                 cell.newMessagesIndicator.isHidden = item.hideNewMessagesLabel
                 cell.lastMessagePreviewLabel.text = item.lastMessage
 
+                item.contactPresence.asObservable()
+                    .observeOn(MainScheduler.instance)
+                    .map { value in !value }
+                    .bind(to: cell.presenceIndicator.rx.isHidden)
+                    .disposed(by: self.disposeBag)
+
                 return cell
         }
 
diff --git a/Ring/Ring/Services/PresenceAdapterDelegate.swift b/Ring/Ring/Services/PresenceAdapterDelegate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1f97df75b1ea4259eb73d502d009f3a2c17f47d8
--- /dev/null
+++ b/Ring/Ring/Services/PresenceAdapterDelegate.swift
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+@objc protocol PresenceAdapterDelegate {
+    func newBuddyNotification(withAccountId accountId: String,
+                              withUri uri: String,
+                              withStatus status: Int,
+                              withLineStatus lineStatus: String)
+}
diff --git a/Ring/Ring/Services/PresenceService.swift b/Ring/Ring/Services/PresenceService.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c318df8967307f5ae9643d22feb4851fae2c5f75
--- /dev/null
+++ b/Ring/Ring/Services/PresenceService.swift
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ */
+
+import SwiftyBeaver
+import RxSwift
+
+class PresenceService {
+
+    fileprivate let presenceAdapter: PresenceAdapter
+    fileprivate let log = SwiftyBeaver.self
+    var contactPresence: [String: Bool]
+
+    fileprivate let disposeBag = DisposeBag()
+    fileprivate let responseStream = PublishSubject<ServiceEvent>()
+    var sharedResponseStream: Observable<ServiceEvent>
+
+    init(withPresenceAdapter presenceAdapter: PresenceAdapter) {
+        self.responseStream.disposed(by: disposeBag)
+        self.sharedResponseStream = responseStream.share()
+        self.contactPresence = [String: Bool]()
+        self.presenceAdapter = presenceAdapter
+        PresenceAdapter.delegate = self
+    }
+
+    func subscribeBuddies(withAccount account: AccountModel, withContacts contacts: [ContactModel]) {
+        for contact in contacts {
+            subscribeBuddy(withAccountId: account.id,
+                           withUri: contact.ringId,
+                           withFlag: true)
+        }
+    }
+
+    func subscribeBuddy(withAccountId accountId: String,
+                        withUri uri: String,
+                        withFlag flag: Bool) {
+        presenceAdapter.subscribeBuddy(withURI: uri, withAccountId: accountId, withFlag: flag)
+        contactPresence[uri] = false
+    }
+}
+
+extension PresenceService: PresenceAdapterDelegate {
+    func newBuddyNotification(withAccountId accountId: String,
+                              withUri uri: String,
+                              withStatus status: Int,
+                              withLineStatus lineStatus: String) {
+        contactPresence[uri] = status > 0 ? true : false
+
+        /*
+         The subscriber is intended to query the contactPresence dictionary
+         with the contact's ringId
+         */
+        var event = ServiceEvent(withEventType: .presenceUpdated)
+        event.addEventInput(.uri, value: uri)
+        self.responseStream.onNext(event)
+
+        log.debug("newBuddyNotification: uri=\(uri), status=\(status)")
+    }
+}
diff --git a/Ring/Ring/Services/ServiceEvent.swift b/Ring/Ring/Services/ServiceEvent.swift
index 0e40e8662fabac4d03a44b3711e4de13a7bf1420..836d4b7bf1eb4a5773500ccc954148d14fd48f95 100644
--- a/Ring/Ring/Services/ServiceEvent.swift
+++ b/Ring/Ring/Services/ServiceEvent.swift
@@ -28,6 +28,7 @@ enum ServiceEventType {
     case accountAdded
     case accountsChanged
     case registrationStateChanged
+    case presenceUpdated
 }
 
 /**
@@ -37,6 +38,8 @@ enum ServiceEventInput {
     case id
     case state
     case registrationState
+    case uri
+    case presenceStatus
 }
 
 /**