Hash email address with a non-random salt for moderate security?

Crypto noob here. I have an application that has only moderate security requirements (internal use, limited audience). I want to send a unique url with a token in it to each user. If anyone has the url, they can submit information on the user's behalf.

Can I just hash their email with a secret salt to produce the same token every time? I realize these won't expire, and knowing the token lets anyone spoof the user, but these are acceptable for my application. When they submit information, I'm thinking I can just re-hash their email with the secret, and make sure it matches the submitted token.

Is this a bad idea? Which hashing algorithm should I use? Should I change my approach?

There's absolutely zero need to have the token tied to the user's email address.

Just add a column in the database for the token, generate the token randomly, and send it out to the user. If you want to go one step further, send the user the token, but only store $H(token)$ in the database, where $H$ is a sound cryptographic hash function of your choosing.

From a cryptographic standpoint a MAC would be perfect (e.g. HMAC-SHA256(strong secret key, email)). As long as no-one knows your secret key it is infeasible to find a token for another mail.

One thing you will probably have to handle is: What happens when someone changes their email? What if someone resubmits the same form? Should the token be invalidated if a user changes their password? You could also consider using HMAC(strong secret key, HMAC(user id, current user password hash)) so that the token gets invalidated if the user changes his password but not his email.

Ultimately, the simplest option is likely to just use a database table or column (e.g. userid, token, date issued) with randomly generated tokens that get expired once a user has used them or after a certain amount of time, to save you headaches later on.

Assuming no databases are involved, you could embed a plain expiry timestamp (e.g. current time + one hour) along with the URL. Then, compute the MAC of concatenating the expiry timestamp and the email. For example:

/submit?
m=user@mail.com&                      User email
e=1447271022&                         Expiry timestamp
t=54fffd55bd01a1ef3f69476b669ba853    HMAC-MD5('12345', 'user@mail.com1447271022')


When receiving the URL, compute the MAC. If it's OK, look if the URL has expired, currentTime > e.

Now the URL is valid only for sometime.