Yes, that sounds good - except that they can’t “Log in again” if they’ve forgotten their password … but I get what you mean I presume it’s possible to detect that the link has already been used, and to say that too, if it was the case?
The reason I suggest a note explaining the expiration rule is for transparency of the system state and behavior. I think you’re right that the system can better help the user recognise and recover from this particular “error state” when it happens. But preventing the error state to begin with would surely be more desirable?
The only way I can think of doing that simply is by exposing the system state and mechanism in the email through relevant documentation.
Imagine a real world equivalent: someone gives you the key code to access a door in a basement.
They say, “Use this key code open the door,” but they don’t tell you that the key code is valid for one time use and only good for today. Now, if you ever try to use that key code a second time or wait until tomorrow, the door could give you a nice error message telling you that they code has expired - but wouldn’t you be left thinking, “Why didn’t that ahole tell me it was a one-time code when he gave it to me?”
The more human thing is to tell the person that they key code is one-time only and only good for today when giving it to them so that they avoid making the mistake in future.