diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index bc3163de2ee28dc57a8f81a38f41916b97c5327e..05ec6a4d2bcffbfcc5a92de22e77c6d41ee055df 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -371,7 +371,6 @@ JamiAccount::newIncomingCall(const std::string& from,
                     std::weak_ptr<SIPCall> wcall = call;
                     call->setPeerUri(RING_URI_PREFIX + from);
                     call->setPeerNumber(from);
-
                     call->updateDetails(details);
                     return call;
                 }
@@ -568,8 +567,7 @@ JamiAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::
             requestSIPConnection(toUri, deviceId);
         };
 
-    for (auto it = sipConns_.begin(); it != sipConns_.end(); ++it) {
-        auto& [key, value] = *it;
+    for (auto& [key, value] : sipConns_) {
         if (key.first != toUri)
             continue;
         if (value.empty())
@@ -1729,6 +1727,7 @@ JamiAccount::handlePendingCall(PendingCall& pc, bool incoming)
     if (!transport)
         throw std::runtime_error("transport creation failed");
 
+    transport->setAccount(shared());
     call->setTransport(transport);
 
     if (incoming) {
@@ -3735,9 +3734,9 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket,
     SipConnectionKey key(peerId, deviceId);
     auto it = sipConns_.find(key);
     if (it == sipConns_.end())
-        it = sipConns_.insert(it, std::make_pair(key, std::vector<SipConnection> {}));
+        it = sipConns_.emplace(key, std::vector<SipConnection> {}).first;
     auto& connections = it->second;
-    auto conn = std::find_if(connections.begin(), connections.end(), [socket](auto v) {
+    auto conn = std::find_if(connections.begin(), connections.end(), [&](auto v) {
         return v.channel == socket;
     });
     if (conn != connections.end()) {
@@ -3773,6 +3772,7 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket,
         shared->callConnectionClosed(key.second, false);
     };
     auto sip_tr = link_.sipTransportBroker->getChanneledTransport(socket, std::move(onShutdown));
+    sip_tr->setAccount(shared());
     // Store the connection
     connections.emplace_back(SipConnection {sip_tr, socket});
     JAMI_WARN("New SIP channel opened with %s", deviceId.to_c_str());
diff --git a/src/sip/siptransport.h b/src/sip/siptransport.h
index 9ccd4e51b31c9b43c4bd6c8a7a4872823c303f87..2472a8f3e627a6c9a192450060d2a7a8c2afa576 100644
--- a/src/sip/siptransport.h
+++ b/src/sip/siptransport.h
@@ -19,8 +19,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
  */
 
-#ifndef SIPTRANSPORT_H_
-#define SIPTRANSPORT_H_
+#pragma once
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -53,6 +52,7 @@ struct Certificate;
 namespace jami {
 
 class ChannelSocket;
+class SIPAccountBase;
 using onShutdownCb = std::function<void(void)>;
 
 struct TlsListener
@@ -115,6 +115,12 @@ public:
 
     void setIsIceTransport() { isIceTransport_ = true; }
     void setIsChanneledTransport() { isChanneledTransport_ = true; }
+    inline void setAccount(const std::shared_ptr<SIPAccountBase>& account) {
+        account_ = account;
+    }
+    inline const std::weak_ptr<SIPAccountBase>& getAccount() const {
+        return account_;
+    }
 
     uint16_t getTlsMtu();
 
@@ -125,8 +131,9 @@ private:
 
     std::unique_ptr<pjsip_transport, decltype(deleteTransport)&> transport_;
     std::shared_ptr<TlsListener> tlsListener_;
-    std::map<uintptr_t, SipTransportStateCallback> stateListeners_;
     std::mutex stateListenersMutex_;
+    std::map<uintptr_t, SipTransportStateCallback> stateListeners_;
+    std::weak_ptr<SIPAccountBase> account_ {};
 
     bool connected_ {false};
     bool isIceTransport_ {false};
@@ -202,5 +209,3 @@ private:
 };
 
 } // namespace jami
-
-#endif // SIPTRANSPORT_H_
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index d4010ce66d03c95bf36c57db37faa507348fca21..0ef2be8782a38b0a461cd6da3a209fe02f00f4de 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -165,6 +165,12 @@ try_respond_stateless(pjsip_endpoint* endpt,
     return !PJ_SUCCESS;
 }
 
+template <typename T>
+bool is_uninitialized(std::weak_ptr<T> const& weak) {
+    using wt = std::weak_ptr<T>;
+    return !weak.owner_before(wt{}) && !wt{}.owner_before(weak);
+}
+
 static pj_bool_t
 transaction_request_cb(pjsip_rx_data* rdata)
 {
@@ -213,19 +219,32 @@ transaction_request_cb(pjsip_rx_data* rdata)
         peerNumber = sip_utils::stripSipUriPrefix(std::string_view(tmp, length));
     }
 
-    auto account(
-        Manager::instance().sipVoIPLink().guessAccount(toUsername, viaHostname, remote_hostname));
-    if (!account) {
-        JAMI_ERR("NULL account");
+    auto transport = Manager::instance().sipVoIPLink().sipTransportBroker->addTransport(
+        rdata->tp_info.transport);
+
+    std::shared_ptr<SIPAccountBase> account;
+    // If transport account is default-constructed, guessing account is allowed
+    const auto& waccount = transport ? transport->getAccount() : std::weak_ptr<SIPAccountBase>{};
+    if (is_uninitialized(waccount)) {
+        account = Manager::instance().sipVoIPLink().guessAccount(toUsername, viaHostname, remote_hostname);
+        if (not account)
+            return PJ_FALSE;
+        if (not transport and not ::strcmp(account->getAccountType(), SIPAccount::ACCOUNT_TYPE)) {
+            if (not (transport = std::static_pointer_cast<SIPAccount>(account)->getTransport())) {
+                JAMI_ERR("No suitable transport to answer this call.");
+                return PJ_FALSE;
+            }
+            JAMI_WARN("Using transport from account.");
+        }
+    } else if (!(account = waccount.lock())) {
+        JAMI_ERR("Dropping SIP request: account is expired.");
         return PJ_FALSE;
     }
 
-    const auto& account_id = account->getAccountID();
     pjsip_msg_body* body = rdata->msg_info.msg->body;
 
     if (method->id == PJSIP_OTHER_METHOD) {
-        pj_str_t* str = &method->name;
-        std::string_view request(str->ptr, str->slen);
+        std::string_view request = sip_utils::as_view(method->name);
 
         if (request.find("NOTIFY") != std::string_view::npos) {
             if (body and body->data) {
@@ -245,7 +264,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
                     // According to rfc3842
                     // urgent messages are optional
                     if (ret >= 2)
-                        emitSignal<DRing::CallSignal::VoiceMailNotify>(account_id,
+                        emitSignal<DRing::CallSignal::VoiceMailNotify>(account->getAccountID(),
                                                                        newCount,
                                                                        oldCount,
                                                                        urgentCount);
@@ -334,36 +353,21 @@ transaction_request_cb(pjsip_rx_data* rdata)
         }
     }
 
-    auto transport = Manager::instance().sipVoIPLink().sipTransportBroker->addTransport(
-        rdata->tp_info.transport);
     auto call = account->newIncomingCall(std::string(remote_user),
                                          {{"AUDIO_ONLY", (hasVideo ? "false" : "true")}},
                                          transport);
     if (!call) {
         return PJ_FALSE;
     }
+    call->setTransport(transport);
 
     // JAMI_DBG("transaction_request_cb viaHostname %s toUsername %s addrToUse %s addrSdp %s
     // peerNumber: %s" , viaHostname.c_str(), toUsername.c_str(), addrToUse.toString().c_str(),
     // addrSdp.toString().c_str(), peerNumber.c_str());
 
-    // Append PJSIP transport to the broker's SipTransport list
-    if (!transport) {
-        if (not ::strcmp(account->getAccountType(), SIPAccount::ACCOUNT_TYPE)) {
-            JAMI_WARN("Using transport from account.");
-            transport = std::static_pointer_cast<SIPAccount>(account)->getTransport();
-        }
-        if (!transport) {
-            JAMI_ERR("No suitable transport to answer this call.");
-            return PJ_FALSE;
-        }
-    }
-    call->setTransport(transport);
-
     // FIXME : for now, use the same address family as the SIP transport
     auto family = pjsip_transport_type_get_af(
         pjsip_transport_get_type_from_flag(transport->get()->flag));
-    IpAddr addrToUse = ip_utils::getInterfaceAddr(account->getLocalInterface(), family);
 
     IpAddr addrSdp;
     if (account->getUPnPActive()) {
@@ -373,12 +377,12 @@ transaction_request_cb(pjsip_rx_data* rdata)
     } else {
         addrSdp = account->isStunEnabled() or (not account->getPublishedSameasLocal())
                       ? account->getPublishedIpAddress()
-                      : addrToUse;
+                      : ip_utils::getInterfaceAddr(account->getLocalInterface(), family);
     }
 
     /* fallback on local address */
     if (not addrSdp)
-        addrSdp = addrToUse;
+        addrSdp = ip_utils::getInterfaceAddr(account->getLocalInterface(), family);
 
     // Try to obtain display name from From: header first, fallback on Contact:
     auto peerDisplayName = sip_utils::parseDisplayName(rdata->msg_info.from);
@@ -506,7 +510,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
 
     call->setState(Call::ConnectionState::RINGING);
 
-    Manager::instance().incomingCall(*call, account_id);
+    Manager::instance().incomingCall(*call, account->getAccountID());
 
     if (replaced_dlg) {
         // Get the INVITE session associated with the replaced dialog.
@@ -737,25 +741,8 @@ SIPVoIPLink::guessAccount(std::string_view userName,
     std::shared_ptr<SIPAccountBase> IP2IPAccount;
     MatchRank best = MatchRank::NONE;
 
-    // DHT accounts
-    for (const auto& account : Manager::instance().getAllAccounts<JamiAccount>()) {
-        if (!account)
-            continue;
-        const MatchRank match(account->matches(userName, server));
-
-        // return right away if this is a full match
-        if (match == MatchRank::FULL) {
-            return account;
-        } else if (match > best) {
-            best = match;
-            result = account;
-        }
-    }
-
     // SIP accounts
     for (const auto& account : Manager::instance().getAllAccounts<SIPAccount>()) {
-        if (!account)
-            continue;
         const MatchRank match(account->matches(userName, server));
 
         // return right away if this is a full match