no, assolutamente, non vanno tag html perché tu al browser stai inviando un documento ben preciso

altrimenti non funziona più nulla poi!

questa parte la puoi incenerire

codice:
    $fr = fopen("certificato_".$paz.".rtf", 'w') ;
    fwrite($fr, $new_rtf);
    fclose($fr);
il file rtf lo hai già in una variabile

detto questo più o meno sembra corretto

ho dato una risistemata al codice ... e a me funziona perfettamente
codice:
<?php

function modifier($vars, $rftfile)
{
    $xchange = array
    (
        '' => "\\",
        '{'  => "{",
        '}'  => "}"
    );

    if(($document = file_get_contents($rftfile)) == false)
    {
        return false;
    }

    foreach($vars as $key => $value)
    {
        foreach($xchange as $orig => $replace)
        {
            $value = str_replace($orig, $replace, $value);
        }

        $document = str_replace($key, $value, $document);
    }

    return $document;
}

// FAKE ROW
$nome = ' --- '; $cognome = ' --- ';
$row = array
(
    'sport'             => 'sport',
    'data_rilascio'     => 'data_rilascio',
    'data_scadenza'     => 'data_scadenza'
);

$paz ='codicefiscale';
$vars = array
(
    '%%SPORT%%'             => $row['sport'],
    '%%NOME%%'              => "{$nome} {$cognome}",
    '%%TIPO_ATTIVITA%%'     => 'agonistica',
    '%%DATA_RILASCIO%%'     => $row['data_rilascio'],
    '%%DATA_SCADENZA%%'     => $row['data_scadenza']
);

$rtfContent = modifier($vars, 'mod_certificato.rtf');

header('Content-Type:application/octet-stream');
header('Content-Length: ' . strlen($rtfContent));
header("Content-Disposition:attachment; filename=\"certificato_{$paz}.rtf\"");

echo $rtfContent;

?>
gli ho dato una sistemata a livello di organizzazione visiva e ho rimosso un poco di codice inutile