What are we protecting against?
First of all one should ask what they are protecting against exactly. In this case there are two different threats:
- Threat 1 An attacker brute forces random emails to find valid registered emails. This could be theoretically used to create spam lists, but as far as I know has never been done as it's simpler to just sent the emails than go through the extra trouble (The number of time that I have receive spam mail claiming my [some US bank] account needed action despite not living in the US is countless).
- Threat 2 An attacker is targeting a specific user or a list of specific users. This is especially important when the bare fact someone is registered somewhere can have consequences. Example: The very act of having an account on Grindr or Ashley Madison can be dangerous in certain communities.
The bigger picture
The next question to think about is what other places might expose the same information and considering those as a whole. Typically the registration form will inform the user if the entered email is already registered, but this of course doesn't apply to most B2B software. Beyond that 'share with user' features (an input box where an email can be entered to share some object with this user) will often also expose this information, but as those are rare I won't include those in this answer.
Solutions for a system with public registration
First of all it's good to acknowledge to not informing the user that an account already exists during the registration process is from an UX perspective very unpleasant. The same applies to password reset forms that silently fail1 when the user makes a typo or has multiple emails. This doesn't mean it's something one shouldn't do, but one should weigh it against the security risks and benefits.
Given a system with public registration the important thing to consider is how big Threat 2 is to the users of your product. Given even a modest risk it can be prudent to change the registration form to start with only entering a name and email, giving a message "check your email to continue sign up", and if the email is already registered sending the user an email informing them of this. Similarly in that case the password reset form will not inform the user in any way whether the email is valid.
On the other hand if Threat 2 is minimal we have to model exclusively against Threat 1. Of course the previous approach will also function perfectly against Threat 1 exclusively, but considering the UX cost it's worth considering other solutions. The most obvious solution is rate limiting2 on both the 'email exists check' and 'password forgotten' checks (technically those calls can even go to the same API endpoint). These will often be designed to be fairly lenient for the first 10 calls or so, but get very limited very quickly after that point.
Important: Never remove error messages from the password registration without also implementing similar restrictions on the registration form.
Solutions for a system without public registration
It all boils down to the same issues as above (and I should have written this first), but without the 'extra' cost of the hit to the registration UX it's relatively 'cheaper' to have a secure password forgotten form, although of course it's still unpleasant for users and you still can consider whether rate limiting isn't enough for your specific threat model.
1: Instead of silently failing it's wise to at least sent an email to the entered email informing them that their email wasn't found. This 1) demotivates attackers from mass abusing the system (as it will be noticed) and 2) prevents users from wondering why they aren't getting an email.
2: Do note that rate limiting can negatively affect users of large networks or VPNs. Always consider how important that audience is to you and based on that spend an adequate amount of time to ensure the application stays functional even when rate limiting is harshest (e.g. by lowering the rate limit by solving a captcha or setting the maximum rate limit to around once per minute and ensuring the application will wait the full minute (note: still will be unpleasant given a team of users signing up for the same service at the start of the same meeting)).