The implementation I feel most comfortable with:
1. Generate a 256+ bit cryptographically secure random number and base64 it to create a token.
2. Record that token in your database, timestamped, along with the user account for which the token was requested.
3. Mail the token to the user's email address.
4. When the user returns to the site after recovering the token, use that token to look up their account from the database.
5. Expire tokens within single-digit hours so users don't end up accidentally banking password-equivalents in their email accounts.
6. When a user changes their password or requests another password reset, expire all tokens already associated with their account.
I would also recommend:
(a) Not having any in-band administration functionality in your application; instead, have a separate admin application, attached to the same databases, available only on a VPN.
(b) Require 2-factor authentication (such as Duo Security) for both admin VPN access and admin login.
A knock-on benefit of (a): your admin functionality is easier to build, because it doesn't have to do the UI/UX chinups your normal exposed app code has to do; crappy looking admin screens nobody but your employees see are generally fine.