diff --git a/src/call.cpp b/src/call.cpp
index 892832c1a21849de3d854e13561d488b716f11f4..01b2ed5df0c5b919764df2adca357bfa919ce4c4 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -430,11 +430,8 @@ Call::onTextMessage(std::map<std::string, std::string>&& messages)
 #ifdef ENABLE_PLUGIN
     auto& pluginChatManager = Manager::instance().getJamiPluginManager().getChatServicesManager();
     if (pluginChatManager.hasHandlers()) {
-        pluginChatManager.publishMessage(std::make_shared<JamiMessage>(getAccountId(),
-                                            getPeerNumber(),
-                                            true,
-                                            messages,
-                                            false));
+        pluginChatManager.publishMessage(
+            std::make_shared<JamiMessage>(getAccountId(), getPeerNumber(), true, messages, false));
     }
 #endif
     Manager::instance().incomingMessage(getCallId(), getPeerNumber(), messages);
@@ -474,8 +471,9 @@ Call::addSubCall(Call& subcall)
         subcall.sendTextMessage(msg.first, msg.second);
 
     subcall.addStateListener(
-        [sub = subcall.weak(),
-         parent = weak()](Call::CallState new_state, Call::ConnectionState new_cstate, int code) {
+        [sub = subcall.weak(), parent = weak()](Call::CallState new_state,
+                                                Call::ConnectionState new_cstate,
+                                                int /* code */) {
             runOnMainThread([sub, parent, new_state, new_cstate]() {
                 if (auto p = parent.lock()) {
                     if (auto s = sub.lock()) {
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index e1586cd6cae2499f836b2746f9eea662ec7c1dad..1895e02a92e5da45266e21159f20e197a4ad979a 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -794,19 +794,14 @@ JamiAccount::SIPStartCall(SIPCall& call, const IpAddr& target)
     std::string targetStr = getToUri(target.toString(true));
     pj_str_t pjTarget = sip_utils::CONST_PJ_STR(targetStr);
 
-    pj_str_t pjContact;
-    {
-        auto transport = call.getTransport();
-        pjContact = getContactHeader(transport ? transport->get() : nullptr);
-    }
+    auto contact = getContactHeader(call.getTransport());
+    auto pjContact = sip_utils::CONST_PJ_STR(contact);
 
-    JAMI_DBG("contact header: %.*s / %s -> %s / %.*s",
-             (int) pjContact.slen,
-             pjContact.ptr,
+    JAMI_DBG("contact header: %s / %s -> %s / %s",
+             contact.c_str(),
              from.c_str(),
              toUri.c_str(),
-             (int) pjTarget.slen,
-             pjTarget.ptr);
+             targetStr.c_str());
 
     auto local_sdp = call.getSDP().getLocalSdpSession();
     pjsip_dialog* dialog {nullptr};
@@ -3058,32 +3053,26 @@ JamiAccount::setMessageDisplayed(const std::string& conversationUri,
     return true;
 }
 
-pj_str_t
-JamiAccount::getContactHeader(pjsip_transport* t)
+std::string
+JamiAccount::getContactHeader(SipTransport* sipTransport)
 {
     std::string quotedDisplayName = "\"" + displayName_ + "\" " + (displayName_.empty() ? "" : " ");
-    if (t) {
-        auto* td = reinterpret_cast<tls::AbstractSIPTransport::TransportData*>(t);
+    std::ostringstream contact;
+
+    if (auto transport = sipTransport->get()) {
+        auto* td = reinterpret_cast<tls::AbstractSIPTransport::TransportData*>(transport);
         auto address = td->self->getLocalAddress().toString(true);
-        bool reliable = t->flag & PJSIP_TRANSPORT_RELIABLE;
-
-        contact_.slen = pj_ansi_snprintf(contact_.ptr,
-                                         PJSIP_MAX_URL_SIZE,
-                                         "%s<sips:%s%s%s;transport=%s>",
-                                         quotedDisplayName.c_str(),
-                                         id_.second->getId().toString().c_str(),
-                                         (address.empty() ? "" : "@"),
-                                         address.c_str(),
-                                         reliable ? "tls" : "dtls");
+        bool reliable = transport->flag & PJSIP_TRANSPORT_RELIABLE;
+
+        contact << quotedDisplayName << "<sips:" << id_.second->getId().toString()
+                << (address.empty() ? "" : "@") << address
+                << (reliable ? ";transport=tls>" : ";transport=dtls");
     } else {
         JAMI_ERR("getContactHeader: no SIP transport provided");
-        contact_.slen = pj_ansi_snprintf(contact_.ptr,
-                                         PJSIP_MAX_URL_SIZE,
-                                         "%s<sips:%s@ring.dht>",
-                                         quotedDisplayName.c_str(),
-                                         id_.second->getId().toString().c_str());
+        contact << quotedDisplayName << "<sips:" << id_.second->getId().toString() << "@ring.dht>";
     }
-    return contact_;
+
+    return contact.str();
 }
 
 /* contacts */
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index 5e2d50754efcadcba6c27b0a6d24309479bd68a6..0587a2a37afad5a6f5a54b0d1ed50b3896c958d3 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -251,9 +251,9 @@ public:
 
     /**
      * Get the contact header for
-     * @return pj_str_t The contact header based on account information
+     * @return The contact header based on account information
      */
-    pj_str_t getContactHeader(pjsip_transport* = nullptr) override;
+    std::string getContactHeader(SipTransport* transport = nullptr) override;
 
     /* Returns true if the username and/or hostname match this account */
     MatchRank matches(std::string_view username, std::string_view hostname) const override;
@@ -804,8 +804,6 @@ private:
      */
     pjsip_host_port via_addr_ {};
 
-    char contactBuffer_[PJSIP_MAX_URL_SIZE] {};
-    pj_str_t contact_ {contactBuffer_, 0};
     pjsip_transport* via_tp_ {nullptr};
 
     std::unique_ptr<DhtPeerConnector> dhtPeerConnector_;
diff --git a/src/jamidht/sync_channel_handler.cpp b/src/jamidht/sync_channel_handler.cpp
index 3cff8e4530169c9b98c39edfa51293712a751b91..6adb88073a21d45682d03f4f8211d8b54b78cfa0 100644
--- a/src/jamidht/sync_channel_handler.cpp
+++ b/src/jamidht/sync_channel_handler.cpp
@@ -50,7 +50,7 @@ SyncChannelHandler::connect(const DeviceId& deviceId, const std::string&, Connec
 }
 
 bool
-SyncChannelHandler::onRequest(const DeviceId& deviceId, const std::string& name)
+SyncChannelHandler::onRequest(const DeviceId& deviceId, const std::string& /* name */)
 {
     auto cert = tls::CertificateStore::instance().getCertificate(deviceId.toString());
     auto acc = account_.lock();
diff --git a/src/sip/sip_utils.cpp b/src/sip/sip_utils.cpp
index 5821bd346be9841979879fbcad2eda7bcaa6186f..edfed41bed70672a15e4895ad70fdf7276a26396 100644
--- a/src/sip/sip_utils.cpp
+++ b/src/sip/sip_utils.cpp
@@ -174,12 +174,17 @@ getHostFromUri(std::string_view uri)
 }
 
 void
-addContactHeader(pj_str_t contact_str, pjsip_tx_data* tdata)
+addContactHeader(const std::string& contactHdr, pjsip_tx_data* tdata)
 {
+    if (contactHdr.empty()) {
+        JAMI_WARN("Contact header won't be added (empty string)");
+        return;
+    }
+    auto pjContact = sip_utils::CONST_PJ_STR(contactHdr);
     pjsip_contact_hdr* contact = pjsip_contact_hdr_create(tdata->pool);
     contact->uri = pjsip_parse_uri(tdata->pool,
-                                   contact_str.ptr,
-                                   contact_str.slen,
+                                   pjContact.ptr,
+                                   pjContact.slen,
                                    PJSIP_PARSE_URI_AS_NAMEADDR);
     // remove old contact header (if present)
     pjsip_msg_find_remove_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
@@ -189,7 +194,7 @@ addContactHeader(pj_str_t contact_str, pjsip_tx_data* tdata)
 void
 addUserAgentHeader(const std::string& userAgent, pjsip_tx_data* tdata)
 {
-    if (tdata == nullptr)
+    if (tdata == nullptr or userAgent.empty())
         return;
 
     auto pjUserAgent = CONST_PJ_STR(userAgent);
@@ -224,8 +229,8 @@ getPeerUserAgent(const pjsip_rx_data* rdata)
 
     constexpr auto USER_AGENT_STR = CONST_PJ_STR("User-Agent");
     if (auto uaHdr = (pjsip_generic_string_hdr*) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
-                                                                   &USER_AGENT_STR,
-                                                                   nullptr)) {
+                                                                            &USER_AGENT_STR,
+                                                                            nullptr)) {
         return as_view(uaHdr->hvalue);
     }
     return {};
diff --git a/src/sip/sip_utils.h b/src/sip/sip_utils.h
index 31e58ca793e943460621f5eca1fec1d3fd77dca7..9b72323fac12754fbdd1bf2c941fc40fb2276c96 100644
--- a/src/sip/sip_utils.h
+++ b/src/sip/sip_utils.h
@@ -96,7 +96,7 @@ std::string parseDisplayName(const pjsip_contact_hdr* header);
 
 std::string_view getHostFromUri(std::string_view sipUri);
 
-void addContactHeader(pj_str_t contactStr, pjsip_tx_data* tdata);
+void addContactHeader(const std::string& contact, pjsip_tx_data* tdata);
 void addUserAgentHeader(const std::string& userAgent, pjsip_tx_data* tdata);
 std::string_view getPeerUserAgent(const pjsip_rx_data* rdata);
 void logMessageHeaders(const pjsip_hdr* hdr_list);
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index ca2750ce78ec7fe4a5cefea20038baaa6f2c2397..f501adaae6b7e1c9b90439c6218ab6f7f357bc66 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -146,8 +146,6 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
     , receivedParameter_("")
     , rPort_(-1)
     , via_addr_()
-    , contactBuffer_()
-    , contact_ {contactBuffer_, 0}
     , contactRewriteMethod_(2)
     , allowIPAutoRewrite_(true)
     , contactOverwritten_(false)
@@ -451,13 +449,10 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
         return false;
     }
 
-    pj_str_t pjContact = getContactHeader(transport->get());
-    JAMI_DBG("contact header: %.*s / %s -> %s",
-             (int) pjContact.slen,
-             pjContact.ptr,
-             from.c_str(),
-             toUri.c_str());
+    std::string contact = getContactHeader(transport);
+    JAMI_DBG("contact header: %s / %s -> %s", contact.c_str(), from.c_str(), toUri.c_str());
 
+    pj_str_t pjContact = sip_utils::CONST_PJ_STR(contact);
     auto local_sdp = isEmptyOffersEnabled() ? nullptr : call->getSDP().getLocalSdpSession();
 
     pjsip_dialog* dialog {nullptr};
@@ -881,8 +876,7 @@ SIPAccount::setPushNotificationToken(const std::string& pushDeviceToken)
         return;
 
     deviceKey_ = pushDeviceToken;
-    pj_bzero(contact_.ptr, sizeof(contact_));
-    contact_.slen = 0;
+    contact_.clear();
 
     if (enabled_)
         doUnregister([&](bool /* transport_free */) { doRegister(); });
@@ -890,7 +884,7 @@ SIPAccount::setPushNotificationToken(const std::string& pushDeviceToken)
 
 void
 SIPAccount::pushNotificationReceived(const std::string& from,
-                                     const std::map<std::string, std::string>& data)
+                                     const std::map<std::string, std::string>&)
 {
     JAMI_WARN("[SIP Account %s] pushNotificationReceived: %s", getAccountID().c_str(), from.c_str());
 
@@ -1099,7 +1093,8 @@ SIPAccount::sendRegister()
     const std::string& received(getReceivedParameter());
 
     // Get the contact header
-    const pj_str_t pjContact(getContactHeader());
+    std::string contact = getContactHeader();
+    pj_str_t pjContact = sip_utils::CONST_PJ_STR(contact);
 
     JAMI_DBG("Using contact header %.*s in registration", (int) pjContact.slen, pjContact.ptr);
 
@@ -1568,17 +1563,17 @@ SIPAccount::getServerUri() const
     return "<" + scheme + host + transport + ">";
 }
 
-pj_str_t
-SIPAccount::getContactHeader(pjsip_transport* t)
+std::string
+SIPAccount::getContactHeader(SipTransport* sipTransport)
 {
-    if (contact_.slen and contactOverwritten_)
+    if (not contact_.empty() and contactOverwritten_)
         return contact_;
 
-    if (!t && transport_)
-        t = transport_->get();
-    if (!t) {
+    if (not sipTransport && transport_)
+        sipTransport = transport_.get();
+    if (not sipTransport) {
         JAMI_ERR("Transport not created yet");
-        return {nullptr, 0};
+        return {};
     }
 
     // The transport type must be specified, in our case START_OTHER refers to stun transport
@@ -1591,7 +1586,7 @@ SIPAccount::getContactHeader(pjsip_transport* t)
     std::string address;
     pj_uint16_t port;
 
-    link_.findLocalAddressFromTransport(t, transportType, hostname_, address, port);
+    link_.findLocalAddressFromTransport(sipTransport->get(), transportType, hostname_, address, port);
 
     if (getUPnPActive() and getUPnPIpAddress()) {
         address = getUPnPIpAddress().toString();
@@ -1603,7 +1598,11 @@ SIPAccount::getContactHeader(pjsip_transport* t)
         port = publishedPort_;
         JAMI_DBG("Using published address %s and port %d", address.c_str(), port);
     } else if (stunEnabled_) {
-        auto success = link_.findLocalAddressFromSTUN(t, &stunServerName_, stunPort_, address, port);
+        auto success = link_.findLocalAddressFromSTUN(sipTransport->get(),
+                                                      &stunServerName_,
+                                                      stunPort_,
+                                                      address,
+                                                      port);
         if (not success)
             emitSignal<DRing::ConfigurationSignal::StunStatusFailed>(getAccountID());
         setPublishedAddress({address});
@@ -1628,55 +1627,48 @@ SIPAccount::getContactHeader(pjsip_transport* t)
 
     const char* scheme = "sip";
     const char* transport = "";
-    if (PJSIP_TRANSPORT_IS_SECURE(t)) {
+    if (PJSIP_TRANSPORT_IS_SECURE(sipTransport->get())) {
         scheme = "sips";
         transport = ";transport=tls";
     }
 
     std::string quotedDisplayName = displayName_.empty() ? "" : "\"" + displayName_ + "\" ";
-    contact_.slen
-        = printContactHeader(contact_.ptr, quotedDisplayName, scheme, address, port, transport);
+    contact_ = printContactHeader(quotedDisplayName, scheme, address, port, transport);
     return contact_;
 }
 
-int
-SIPAccount::printContactHeader(char* data,
-                               const std::string& displayName,
+std::string
+SIPAccount::printContactHeader(const std::string& displayName,
                                const char* scheme,
                                const std::string& address,
                                pj_uint16_t port,
                                const char* transport)
 {
-    if (deviceKey_.empty()) {
-        return pj_ansi_snprintf(data,
-                                PJSIP_MAX_URL_SIZE,
-                                CONTACT_HEADER_WITHOUT_PN,
-                                displayName.c_str(),
-                                scheme,
-                                username_.c_str(),
-                                (username_.empty() ? "" : "@"),
-                                address.c_str(),
-                                port,
-                                transport);
-    } else {
-        return pj_ansi_snprintf(data,
-                                PJSIP_MAX_URL_SIZE,
-                                CONTACT_HEADER_WITH_PN,
-                                displayName.c_str(),
-                                scheme,
-                                username_.c_str(),
-                                (username_.empty() ? "" : "@"),
-                                address.c_str(),
-                                port,
-                                transport,
+    // This method generates SIP contact header field, with push
+    // notification parameters if any.
+    // Example without push notification:
+    // John Doe<sips:jdoe@10.10.10.10:5060;transport=tls>
+    // Example with push notification:
+    // John Doe<sips:jdoe@10.10.10.10:5060;transport=tls;pn-provider=XXX;pn-param=YYY;pn-prid=ZZZ>
+
+    std::ostringstream contact;
+
+    contact << displayName << "<" << scheme << ":" << username_ << (username_.empty() ? "" : "@")
+            << address << ":" << port << transport;
+
+    if (not deviceKey_.empty()) {
+        contact
 #if defined(__ANDROID__) || defined(ANDROID)
-                                PN_FCM,
+            << "pn-provider=" << PN_FCM
 #elif defined(__Apple__)
-                                PN_APNS,
+            << "pn-provider=" << PN_APNS
 #endif
-                                "",
-                                deviceKey_.c_str());
+            << "pn-param=;"
+            << "pn-prid=" << deviceKey_;
     }
+    contact << ">";
+
+    return contact.str();
 }
 
 pjsip_host_port
@@ -2007,9 +1999,10 @@ SIPAccount::checkNATAddress(pjsip_regc_cbparam* param, pj_pool_t* pool)
     setPublishedAddress(IpAddr(via_addrstr));
 
     /* Compare received and rport with the URI in our registration */
+    auto pjContact = sip_utils::CONST_PJ_STR(getContactHeader());
     const pj_str_t STR_CONTACT = {(char*) "Contact", 7};
     pjsip_contact_hdr* contact_hdr = (pjsip_contact_hdr*)
-        pjsip_parse_hdr(pool, &STR_CONTACT, contact_.ptr, contact_.slen, nullptr);
+        pjsip_parse_hdr(pool, &STR_CONTACT, pjContact.ptr, pjContact.slen, nullptr);
     pj_assert(contact_hdr != nullptr);
     pjsip_sip_uri* uri = (pjsip_sip_uri*) contact_hdr->uri;
     pj_assert(uri != nullptr);
@@ -2106,21 +2099,21 @@ SIPAccount::checkNATAddress(pjsip_regc_cbparam* param, pj_pool_t* pool)
             transport_param = ";transport=tls";
         }
 
-        char* tmp = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
-        int len = printContactHeader(tmp, "", scheme, via_addrstr, rport, transport_param);
+        auto tmp = printContactHeader("", scheme, via_addrstr, rport, transport_param);
 
-        if (len < 1) {
-            JAMI_ERR("URI too long");
+        if (tmp.empty()) {
+            JAMI_ERR("Invalid contact header");
             return false;
         }
 
-        pj_str_t tmp_str = {tmp, len};
-        pj_strncpy_with_null(&contact_, &tmp_str, PJSIP_MAX_URL_SIZE);
+        // Update
+        contact_ = std::move(tmp);
+        pjContact = sip_utils::CONST_PJ_STR(contact_);
     }
 
     if (contactRewriteMethod_ == 2 && regc_ != nullptr) {
         contactOverwritten_ = true;
-        pjsip_regc_update_contact(regc_, 1, &contact_);
+        pjsip_regc_update_contact(regc_, 1, &pjContact);
 
         /*  Perform new registration at the next registration cycle */
     }
diff --git a/src/sip/sipaccount.h b/src/sip/sipaccount.h
index c3d473b1908da6e9edc8747989e31021ae06dc85..c71d6c4d05cdbdb43a3933ed644441b491ae16c2 100644
--- a/src/sip/sipaccount.h
+++ b/src/sip/sipaccount.h
@@ -69,9 +69,6 @@ class SIPAccount : public SIPAccountBase
 {
 public:
     constexpr static const char* const ACCOUNT_TYPE = "SIP";
-    constexpr static const char* const CONTACT_HEADER_WITH_PN
-        = "%s<%s:%s%s%s:%d%s;pn-provider=%s;pn-param=%s;pn-prid=%s>";
-    constexpr static const char* const CONTACT_HEADER_WITHOUT_PN = "%s<%s:%s%s%s:%d%s>";
     constexpr static const char* const PN_FCM = "fcm";
     constexpr static const char* const PN_APNS = "apns";
 
@@ -348,9 +345,9 @@ public:
 
     /**
      * Get the contact header for
-     * @return pj_str_t The contact header based on account information
+     * @return The contact header based on account information
      */
-    pj_str_t getContactHeader(pjsip_transport* = nullptr) override;
+    std::string getContactHeader(SipTransport* transport = nullptr) override;
 
     std::string getServiceRoute() const { return serviceRoute_; }
 
@@ -613,12 +610,11 @@ private:
     /**
      * Print contact header in certain format
      */
-    int printContactHeader(char* data,
-                           const std::string& displayName,
-                           const char* scheme,
-                           const std::string& address,
-                           pj_uint16_t port,
-                           const char* transport);
+    std::string printContactHeader(const std::string& displayName,
+                                   const char* scheme,
+                                   const std::string& address,
+                                   pj_uint16_t port,
+                                   const char* transport);
 
     /**
      * Resolved IP of hostname_ (for registration)
@@ -750,8 +746,7 @@ private:
      */
     std::string upnpIpAddr_;
 
-    char contactBuffer_[PJSIP_MAX_URL_SIZE];
-    pj_str_t contact_;
+    std::string contact_;
     int contactRewriteMethod_;
     bool allowIPAutoRewrite_;
     /* Undocumented feature in pjsip, this can == 2 */
diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp
index a71979d6252c4115eacd6c9e2da713662e3a222e..498561e7e50d3f1176215f6153b6b2c2a39c65c5 100644
--- a/src/sip/sipaccountbase.cpp
+++ b/src/sip/sipaccountbase.cpp
@@ -458,7 +458,7 @@ SIPAccountBase::getIceOptions() const noexcept
 void
 SIPAccountBase::onTextMessage(const std::string& id,
                               const std::string& from,
-                              const std::string& deviceId,
+                              const std::string& /* deviceId */,
                               const std::map<std::string, std::string>& payloads)
 {
     JAMI_DBG("Text message received from %s, %zu part(s)", from.c_str(), payloads.size());
@@ -476,7 +476,8 @@ SIPAccountBase::onTextMessage(const std::string& id,
 #ifdef ENABLE_PLUGIN
     auto& pluginChatManager = Manager::instance().getJamiPluginManager().getChatServicesManager();
     if (pluginChatManager.hasHandlers()) {
-        pluginChatManager.publishMessage(std::make_shared<JamiMessage>(accountID_, from, true, payloads, false));
+        pluginChatManager.publishMessage(
+            std::make_shared<JamiMessage>(accountID_, from, true, payloads, false));
     }
 #endif
     emitSignal<DRing::ConfigurationSignal::IncomingAccountMessage>(accountID_, from, id, payloads);
diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h
index e5d571fe712d49e51687782627cba8762b79c483..67837d113e7432a35134ee85f9bef5021356643f 100644
--- a/src/sip/sipaccountbase.h
+++ b/src/sip/sipaccountbase.h
@@ -216,9 +216,9 @@ public:
 
     /**
      * Get the contact header for
-     * @return pj_str_t The contact header based on account information
+     * @return The contact header based on account information
      */
-    virtual pj_str_t getContactHeader(pjsip_transport* = nullptr) = 0;
+    virtual std::string getContactHeader(SipTransport* transport = nullptr) = 0;
 
     virtual std::string getToUri(const std::string& username) const = 0;
 
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index fc0cccd0a19619ca3d8ab618761f1e9a82bce1a2..5b134a62ff8a3056e4208f996161311bd1f893d0 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -420,9 +420,15 @@ SIPCall::generateMediaPorts()
 }
 
 void
-SIPCall::setContactHeader(pj_str_t contact)
+SIPCall::setContactHeader(const std::string& contact)
 {
-    pj_strcpy(&contactHeader_, &contact);
+    contactHeader_ = contact;
+}
+
+const std::string&
+SIPCall::getContactHeader() const
+{
+    return contactHeader_;
 }
 
 void
@@ -437,6 +443,12 @@ SIPCall::setTransport(const std::shared_ptr<SipTransport>& t)
     if (not t) {
         return;
     }
+    auto account = getSIPAccount();
+    if (not account) {
+        JAMI_ERR("[call:%s] No account detected", getCallId().c_str());
+    }
+
+    setContactHeader(account->getContactHeader(transport_.get()));
 
     if (isSrtpEnabled() and not transport_->isSecure()) {
         JAMI_WARN("[call:%s] Crypto (SRTP) is negotiated over an un-encrypted signaling channel",
@@ -701,9 +713,7 @@ SIPCall::terminateSipSession(int status)
             if (tdata) {
                 auto account = getSIPAccount();
                 if (account) {
-                    sip_utils::addContactHeader(account->getContactHeader(
-                                                    transport_ ? transport_->get() : nullptr),
-                                                tdata);
+                    sip_utils::addContactHeader(contactHeader_, tdata);
                     // Add user-agent header
                     sip_utils::addUserAgentHeader(account->getUserAgentName(), tdata);
                 } else {
@@ -750,8 +760,6 @@ SIPCall::answer()
         Manager::instance().sipVoIPLink().createSDPOffer(inviteSession_.get());
     }
 
-    setContactHeader(account->getContactHeader(transport_ ? transport_->get() : nullptr));
-
     pjsip_tx_data* tdata;
     if (!inviteSession_->last_answer)
         throw std::runtime_error("Should only be called for initial answer");
@@ -765,15 +773,16 @@ SIPCall::answer()
         != PJ_SUCCESS)
         throw std::runtime_error("Could not init invite request answer (200 OK)");
 
-    // contactStr must stay in scope as long as tdata
-    if (contactHeader_.slen) {
-        JAMI_DBG("[call:%s] Answering with contact header: %.*s",
-                 getCallId().c_str(),
-                 (int) contactHeader_.slen,
-                 contactHeader_.ptr);
-        sip_utils::addContactHeader(contactHeader_, tdata);
+    if (contactHeader_.empty()) {
+        throw std::runtime_error("Cant answer with an invalid contact header");
     }
 
+    JAMI_DBG("[call:%s] Answering with contact header: %s",
+             getCallId().c_str(),
+             contactHeader_.c_str());
+
+    sip_utils::addContactHeader(contactHeader_, tdata);
+
     // Add user-agent header
     sip_utils::addUserAgentHeader(account->getUserAgentName(), tdata);
 
@@ -879,8 +888,6 @@ SIPCall::answer(const std::vector<DRing::MediaMap>& mediaList)
         }
     }
 
-    setContactHeader(account->getContactHeader(transport_ ? transport_->get() : nullptr));
-
     if (!inviteSession_->last_answer)
         throw std::runtime_error("Should only be called for initial answer");
 
@@ -896,14 +903,16 @@ SIPCall::answer(const std::vector<DRing::MediaMap>& mediaList)
         != PJ_SUCCESS)
         throw std::runtime_error("Could not init invite request answer (200 OK)");
 
-    if (contactHeader_.slen) {
-        JAMI_DBG("[call:%s] Answering with contact header: %.*s",
-                 getCallId().c_str(),
-                 (int) contactHeader_.slen,
-                 contactHeader_.ptr);
-        sip_utils::addContactHeader(contactHeader_, tdata);
+    if (contactHeader_.empty()) {
+        throw std::runtime_error("Cant answer with an invalid contact header");
     }
 
+    JAMI_DBG("[call:%s] Answering with contact header: %s",
+             getCallId().c_str(),
+             contactHeader_.c_str());
+
+    sip_utils::addContactHeader(contactHeader_, tdata);
+
     // Add user-agent header
     sip_utils::addUserAgentHeader(account->getUserAgentName(), tdata);
 
@@ -990,7 +999,7 @@ SIPCall::answerMediaChangeRequest(const std::vector<DRing::MediaMap>& mediaList)
         return;
     }
 
-    if (contactHeader_.slen) {
+    if (not contactHeader_.empty()) {
         sip_utils::addContactHeader(contactHeader_, tdata);
     }
 
@@ -2501,7 +2510,7 @@ SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* r
                                  NULL,
                                  &tdata)
         != PJ_SUCCESS) {
-        JAMI_ERR("Could not create initial answer OK");
+        JAMI_ERR("[call:%s] Could not create initial answer OK", getCallId().c_str());
         return !PJ_SUCCESS;
     }
 
@@ -2514,11 +2523,15 @@ SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* r
         return !PJ_SUCCESS;
     }
 
-    // ContactStr must stay in scope as long as tdata
-    sip_utils::addContactHeader(getSIPAccount()->getContactHeader(getTransport()->get()), tdata);
+    if (contactHeader_.empty()) {
+        JAMI_ERR("[call:%s] Contact header is empty!", getCallId().c_str());
+        return !PJ_SUCCESS;
+    }
+
+    sip_utils::addContactHeader(contactHeader_, tdata);
 
     if (pjsip_inv_send_msg(inviteSession_.get(), tdata) != PJ_SUCCESS) {
-        JAMI_ERR("Could not send msg OK");
+        JAMI_ERR("[call:%s] Could not send msg OK", getCallId().c_str());
         return !PJ_SUCCESS;
     }
 
@@ -3029,8 +3042,7 @@ SIPCall::merge(Call& call)
     sdp_ = std::move(subcall.sdp_);
     peerHolding_ = subcall.peerHolding_;
     upnp_ = std::move(subcall.upnp_);
-    std::copy_n(subcall.contactBuffer_, PJSIP_MAX_URL_SIZE, contactBuffer_);
-    pj_strcpy(&contactHeader_, &subcall.contactHeader_);
+    contactHeader_ = std::move(subcall.contactHeader_);
     localAudioPort_ = subcall.localAudioPort_;
     localVideoPort_ = subcall.localVideoPort_;
     peerUserAgent_ = subcall.peerUserAgent_;
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index d0c1a5465c2a3dfb7418eb382eedaad77cc66edc..1860a1d0805ac1a698186030d2026720a47d0ebc 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -219,7 +219,8 @@ public:
     void onMediaNegotiationComplete();
     // End fo SiPVoipLink events
 
-    void setContactHeader(pj_str_t contact);
+    void setContactHeader(const std::string& contact);
+    const std::string& getContactHeader() const;
 
     void setTransport(const std::shared_ptr<SipTransport>& t);
 
@@ -432,8 +433,7 @@ private:
 
     std::string peerRegisteredName_ {};
 
-    char contactBuffer_[PJSIP_MAX_URL_SIZE] {};
-    pj_str_t contactHeader_ {contactBuffer_, 0};
+    std::string contactHeader_ {};
 
     std::shared_ptr<jami::upnp::Controller> upnp_;
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index b82c6b4e5eb9ab6c741b696394eafad313ebc697..85301860e0d18282cfd8cf944891e87c9a54863d 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -560,7 +560,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
         return PJ_FALSE;
     }
 
-    sip_utils::addContactHeader(account->getContactHeader(transport->get()), tdata);
+    sip_utils::addContactHeader(call->getContactHeader(), tdata);
     if (pjsip_inv_send_msg(call->inviteSession_.get(), tdata) != PJ_SUCCESS) {
         JAMI_ERR("Could not send msg RINGING");
         return PJ_FALSE;