The problem with your approach is replay attacks. Let's say you can generate a code from the email address and a password. The cryptographic tool for this is a message authentication code, you could use hmac in php too, though it would not be 6 digits.
But such a code would not be a one time token, it would not even be timebound, it would be valid forever, for all future correspondence with the same email address, which is not right for this application. The correct way to use hmac for this would be to include a nonce (random value) or a timestamp together with the email address, but that would also have to be stored - and with that, you could simply just store a fully random value as well.
One thing you could actually do is apply hmac to the email address AND the datetime that email was added to your site (I guess you store that already), and only accept a code if the datetime is not too old. This would still not be a one-time token, but would at least be time limited, which mitigates some of the risk.
Also a hmac is not 6 characters, but especially if it is not a one-time token, 6 characters is not enough anyway, and/or you should have other protections in place against brute force - which again will be stateful in some way, ie. something will have to be stored.
In short, while you can get partial solutions to some of the related problems, and you might be able to mitigate many of the risks in a fully stateless solution where you don't store anything additional, it would likely be a lot simpler and more secure to just store a random code. Simplicity is really good for security.