diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index f295d6dd9ba8bd0f0cc982292041f5f95c095239..cc7a0930926f102ff3ed2777b3a60759d91f365a 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -1133,7 +1133,10 @@ RingAccount::matches(const std::string &userName, const std::string &server) con
 
 std::string RingAccount::getFromUri() const
 {
-    return "<sip:" + dht_.getId().toString() + "@ring.dht>";
+    const std::string uri = "<sip:" + dht_.getId().toString() + "@ring.dht>";
+    if (not displayName_.empty())
+        return "\"" + displayName_ + "\" " + uri;
+    return uri;
 }
 
 std::string RingAccount::getToUri(const std::string& to) const
diff --git a/src/sip/sip_utils.cpp b/src/sip/sip_utils.cpp
index 2ff159d575d938a44e830c605d49cd5141e91911..c37674050f050665be547dc5b77fe799b8e8a2b3 100644
--- a/src/sip/sip_utils.cpp
+++ b/src/sip/sip_utils.cpp
@@ -101,58 +101,36 @@ createRouteSet(const std::string &route, pj_pool_t *hdr_pool)
     return route_set;
 }
 
-// FIXME: replace with regex
 std::string
-parseDisplayName(const char * buffer)
+parseDisplayName(const pjsip_name_addr* sip_name_addr)
 {
-    // Start in From: in short and long form
-    const char* from_header = strstr(buffer, "\nFrom: ");
-    if (!from_header)
-        from_header = strstr(buffer, "\nf: ");
-    if (!from_header)
-        return "";
+    if (not sip_name_addr->display.ptr or not sip_name_addr->display.slen)
+        return {};
 
-    std::string temp(from_header);
-
-    // Cut at end of line
-    temp = temp.substr(0, temp.find("\n", 1));
-
-    size_t begin_displayName = temp.find("\"");
-    size_t end_displayName;
-    if (begin_displayName != std::string::npos) {
-      // parse between quotes
-      end_displayName = temp.find("\"", begin_displayName + 1);
-      if (end_displayName == std::string::npos)
-          return "";
-    } else {
-      // parse without quotes
-      end_displayName = temp.find("<");
-      if (end_displayName != std::string::npos) {
-          begin_displayName = temp.find_first_not_of(" ", temp.find(":"));
-          if (begin_displayName == std::string::npos)
-              return "";
-
-          // omit trailing/leading spaces
-          begin_displayName++;
-          end_displayName--;
-          if (end_displayName == begin_displayName)
-              return "";
-      } else {
-          return "";
-      }
-    }
-
-    std::string displayName = temp.substr(begin_displayName + 1,
-                                          end_displayName - begin_displayName - 1);
+    std::string displayName {sip_name_addr->display.ptr,
+            static_cast<size_t>(sip_name_addr->display.slen)};
 
     // Filter out invalid UTF-8 characters to avoid getting kicked from D-Bus
-    if (not utf8_validate(displayName)) {
+    if (not utf8_validate(displayName))
         return utf8_make_valid(displayName);
-    }
 
     return displayName;
 }
 
+std::string
+parseDisplayName(const pjsip_from_hdr* header)
+{
+    // PJSIP return a pjsip_name_addr for To, From and Contact headers
+    return parseDisplayName(reinterpret_cast<pjsip_name_addr*>(header->uri));
+}
+
+std::string
+parseDisplayName(const pjsip_contact_hdr* header)
+{
+    // PJSIP return a pjsip_name_addr for To, From and Contact headers
+    return parseDisplayName(reinterpret_cast<pjsip_name_addr*>(header->uri));
+}
+
 void
 stripSipUriPrefix(std::string& sipUri)
 {
diff --git a/src/sip/sip_utils.h b/src/sip/sip_utils.h
index aa5df501f966ab027d578ad1bc18b74cd8ba2d9e..51030aea7816f3ea38e65e1b6148e4c9f6e866af 100644
--- a/src/sip/sip_utils.h
+++ b/src/sip/sip_utils.h
@@ -73,7 +73,9 @@ createRouteSet(const std::string &route, pj_pool_t *hdr_pool);
 
 void stripSipUriPrefix(std::string& sipUri);
 
-std::string parseDisplayName(const char * buffer);
+std::string parseDisplayName(const pjsip_name_addr* sip_name_addr);
+std::string parseDisplayName(const pjsip_from_hdr* header);
+std::string parseDisplayName(const pjsip_contact_hdr* header);
 
 std::string getHostFromUri(const std::string& sipUri);
 
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index 0331e5821a269020d0cc5856e21eece464c66d01..83f7791e20bc77da1b99b4f1038fd5482b24196b 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -1355,7 +1355,10 @@ std::string SIPAccount::getFromUri() const
         hostname = IpAddr(hostname).toString(false, true);
 #endif
 
-    return "<" + scheme + username + "@" + hostname + transport + ">";
+    const std::string uri = "<" + scheme + username + "@" + hostname + transport + ">";
+    if (not displayName_.empty())
+        return "\"" + displayName_ + "\" " + uri;
+    return uri;
 }
 
 std::string SIPAccount::getToUri(const std::string& username) const
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 1953497cb9b82721f9707fd308c14662d3025cbb..347a682d1a05340b25eb612c4461bfaf9a745cba 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -194,14 +194,16 @@ transaction_request_cb(pjsip_rx_data *rdata)
         RING_ERR("Missing From, To or Via fields");
         return PJ_FALSE;
     }
-    const pjsip_sip_uri *sip_to_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.to->uri);
-    const pjsip_sip_uri *sip_from_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.from->uri);
+
+    const auto sip_to_uri = reinterpret_cast<pjsip_sip_uri*>(pjsip_uri_get_uri(rdata->msg_info.to->uri));
+    const auto sip_from_uri = reinterpret_cast<pjsip_sip_uri*>(pjsip_uri_get_uri(rdata->msg_info.from->uri));
     const pjsip_host_port& sip_via = rdata->msg_info.via->sent_by;
 
     if (!sip_to_uri or !sip_from_uri or !sip_via.host.ptr) {
         RING_ERR("NULL uri");
         return PJ_FALSE;
     }
+
     std::string toUsername(sip_to_uri->user.ptr, sip_to_uri->user.slen);
     std::string toHost(sip_to_uri->host.ptr, sip_to_uri->host.slen);
     std::string viaHostname(sip_via.host.ptr, sip_via.host.slen);
@@ -225,7 +227,6 @@ transaction_request_cb(pjsip_rx_data *rdata)
     }
 
     const auto& account_id = account->getAccountID();
-    auto peerDisplayName = sip_utils::parseDisplayName(rdata->msg_info.msg_buf);
     pjsip_msg_body *body = rdata->msg_info.msg->body;
 
     if (method->id == PJSIP_OTHER_METHOD) {
@@ -286,7 +287,6 @@ transaction_request_cb(pjsip_rx_data *rdata)
         return PJ_FALSE;
     }
 
-
     if (not remote_user.empty() and not remote_hostname.empty())
         peerNumber = remote_user + "@" + remote_hostname;
 
@@ -324,6 +324,16 @@ transaction_request_cb(pjsip_rx_data *rdata)
     /* fallback on local address */
     if (not addrSdp) addrSdp = addrToUse;
 
+    // Try to obtain display name from From: header first, fallback on Contact:
+    auto peerDisplayName = sip_utils::parseDisplayName(rdata->msg_info.from);
+    if (peerDisplayName.empty()) {
+        if (auto hdr = static_cast<const pjsip_contact_hdr*>(pjsip_msg_find_hdr(rdata->msg_info.msg,
+                                                                                PJSIP_H_CONTACT,
+                                                                                nullptr))) {
+            peerDisplayName = sip_utils::parseDisplayName(hdr);
+        }
+    }
+
     call->setState(Call::ConnectionState::PROGRESSING);
     call->setPeerNumber(peerNumber);
     call->setPeerDisplayName(peerDisplayName);