Applescript Replace sub-procedure doesn't work with '@'
I tried running the first example:

set theBody to "Dear %%FirstName%%-
... 
This message was sent to %%EmailAddress%%."

set theBody to my replace(theBody, "%%FirstName%%", "First")
set theBody to my replace(theBody, "%%EmailAddress%%", "first.last@company.com")

on replace(this_text, search_string, replacement_string)
    set AppleScript's text item delimiters to the search_string
    set the item_list to every text item of this_text
    set AppleScript's text item delimiters to the replacement_string
    set this_text to the item_list as string
    set AppleScript's text item delimiters to ""
    return this_text
end replace


The result was:

Dear First-
... 
This message was sent to first.last@company.com.


So it seemed to work just fine. The replace handler shouldn't have any problems with strings that contain special characters, so there might be something else you're missing.

Also restoring text item delimiters is not necessary as far as I know, and you don't need AppleScript's outside tell blocks, so the replace handler can be simplified to something like this:

on replace(input, x, y)
    set text item delimiters to x
    set ti to text items of input
    set text item delimiters to y
    ti as text
end replace