使用自定义Mailer与authentication_keys的Devise无法发送重置密码邮件
Hey there, let's break down this password reset issue you're facing—since your confirmation emails work perfectly, we can narrow the problem to specific parts of the reset flow. Here's step-by-step troubleshooting:
1. Fix the UserMailer Method Name (Critical Bug!)
Devise's recoverable module expects a method named reset_password_instructions to trigger password reset emails, but your code defines reset_user_password_instructions (extra user in the name). This means Devise can't find the method to send the email, so it silently renders the form again without feedback.
Update your UserMailer code:
def reset_password_instructions(record, token, opts={}) # Remove the extra "user" prefix browser = Browser.new @user = record @token = token self.template_model = { username: @user.username.try(:downcase), action_url: edit_user_password_url(@user, reset_password_token: @token), operating_system: browser.platform.name.try(:titleize), browser_name: browser.name.try(:titleize), support_url: 'xxx@xxx.com', } mail to: @user.email, postmark_template_alias: 'community_password_reset' end
2. Configure Devise to Use Username for Password Resets
Your User model uses username as the authentication key, but Devise's recoverable module defaults to looking up users by email. This mismatch means Devise can't find the user when you submit the username, leading to the silent 200 response.
Add this line to config/initializers/devise.rb:
config.reset_password_keys = [:username]
This tells Devise to use the username field from your form to locate the user.
3. Verify Flash Message Rendering
Even if the flow works, you won't see feedback if your flash template isn't rendering correctly. Double-check layouts/_flash.html.erb includes code like this:
<% if notice %> <div class="alert alert-info"><%= notice %></div> <% end %> <% if alert %> <div class="alert alert-danger"><%= alert %></div> <% end %>
Devise automatically sets a notice like "If your username exists in our database, you will receive a password reset link shortly."—this template ensures you see it.
4. Test Email Sending Manually
To confirm the mailer works outside the form flow, run this in your Rails console:
user = User.first # Trigger Devise's full reset flow user.send_reset_password_instructions # Or test the mailer directly UserMailer.reset_password_instructions(user, 'test_token').deliver_now
Check your Postmark dashboard to confirm the email was sent, and look for any errors in the Rails logs.
5. Ensure Proper Parameter Permissions
If you've customized the Users::PasswordsController, make sure it permits the username parameter:
class Users::PasswordsController < Devise::PasswordsController private def user_params params.require(:user).permit(:username, :email, :password, :password_confirmation) end end
Why Confirmation Emails Worked
Your confirmation flow uses the correct method name (confirmation_instructions) that matches what Devise's confirmable module expects, so that part of your setup was already correct.
内容的提问来源于stack exchange,提问作者Shawn Wilson

