If there's more than one dot, but only one dot after the @ sign (which would be usual), you can just change all dots and change the last one back:
sed 'y/./^/;s/\(@.*\)\^/\1./'
If there's potentially more than one dot both before and after the @ sign, you can do it recursively with a short loop:
sed ':top;s/\.\(.*@\)/^\1/;ttop'
This works in GNU sed; BSD sed requires a newline after a label:
sed ':top
s/\.\(.*@\)/^\1/;ttop'
EDIT: To handle all cases in either GNU sed or BSD sed in a single line command:
sed 'h;s/@.*//;y/./^/;G;s/\n.*@/@/'
h
copies current line (called the "pattern space") to the hold space; the s
command deletes the @
and everything after it; y
works like the shell command tr
and in this case translates all dots to carets; G
appends a newline and the hold space contents to the pattern space; then the last s
command deletes from the newline up to the @
and puts back the @
.