Почему не выводит текст из бд?
Какой ужас...
Или даже так я буду под угрозой sql-инъекций?
prepare само по себе не защищает от инъекций. От того что ты заменил слово query на слово prepare твои запросы защищеннее не станут.
чтобы prepare работало, его надо использовать правильно. 

Про остальной код я вообще молчу. С чего ты решил что execute выводит какие-то данные? Зачем делать два запроса чтобы получить одну и ту же запись? 

$stmt = $db->prepare('SELECT name, surname FROM accounts WHERE mail=?');
$stmt->execute([$_SESSION['mail']]);
$user = $stmt->fetch();
<div class="dash-text" id="account-name"><?= $user['name'] . ' ' . $user['surname'] ?></div>
execute возвращает 1 или 0, то есть true или false. Используйте query или лучше fetchAll() после execute и замените в самом sql-запросе данные из сессии на плейсхолдеры во избежание инъекций и  уже в execute их вставляйте. Да и вообще, я бы советовал пересмотреть логику, довольно странно, что вы где-то составляете запрос а во вью обращаетесь к БД с помощью execute().