Merely as an aside -- the other items mentioned are the root of your problem -- but this just strikes me as curious:
Since strlen returns a size_t, why would you explicitly cast the return value from a size_t to a size_t, and then assign it to an int?
int identlen = (size_t) strlen(ident);
It seems as though you're afraid of using a size_t value due to unfamiliarity, perhaps, but then using a cast with something you are unfamiliar with seems a dangerous proposition.
And are you using C99 or C++ for the declarations that follow statements?
By the way, I might go with something like this to start.
const char source = "email@example.com";
char host, nick, ident;
if ( sscanf(source, "%127[^!]!%127[^@]@%127[^\n]", nick, ident, host) == 3 )
printf(" nick: %s\n", nick);
printf("ident: %s\n", ident);
printf(" host: %s\n", host);
/* my output