Rails5.1.4使用mail_form发送联系表单邮件无响应问题排查
故障定位与解决步骤
核心现象分析
从你提供的控制台日志可以看到,代码执行到--->>> 4 create contact后就没有后续输出了,既没有进入@contact.deliver的成功分支也没有进入失败分支,说明问题出在@contact.deliver方法执行阶段,根本没有走到邮件发送环节,因此Mailgun后台查不到投递日志是符合现象的。
分步排查&修复
先修复表单重复提交问题
你在form_for已经设置remote: true(Rails UJS会自动劫持表单提交为AJAX)的前提下,又给submit按钮加了多余的remote: true,从日志里也能看到两次重复的请求处理流程,先把submit标签上的remote: true删掉:<%= f.submit 'Send Message', class: 'btn btn-send-message-primary' %>补全控制器调试日志,定位deliver阶段的状态
修改homepage_controller.rb的create动作中respond_to块的代码,把验证错误和deliver返回值打印出来:respond_to do |format| puts "--->>> 4 create contact" # 打印模型验证错误,避免静默验证失败 puts "验证错误列表: #{@contact.errors.full_messages.inspect}" deliver_result = @contact.deliver puts "deliver方法返回值: #{deliver_result.inspect}" if deliver_result puts "--->>> Pass create contact" # 原有成功逻辑 @contact = Homepage.new format.html { render 'index'} format.js { flash.now[:success] = @message = "Thank you for your message. I'll get back to you soon!" } else puts "--->>> Fails create contact" # 原有失败逻辑 format.html { render 'index' } format.js { flash.now[:error] = @message = "Message did not send." } end end重新提交表单后,根据输出内容判断问题:
- 如果验证错误列表里有内容,说明是表单参数不符合模型的验证规则,修正对应验证配置即可
- 如果deliver返回nil而非布尔值,说明你的mail_form模型配置有问题
检查mail_form模型配置(
app/models/homepage.rb)
如果你未贴出模型代码,大概率是配置不符合要求,重点检查这几点:- 模型必须继承
MailForm::Base,不能继承ActiveRecord::Base - 所有用到的属性必须显式声明
attribute,比如attribute :name, validate: true - 蜜罐字段
nickname必须加captcha: true标记,否则不会触发防垃圾逻辑 - 必须定义
headers方法,且from地址必须是你在Mailgun后台验证过的域名下的邮箱地址,不能直接用用户输入的发件邮箱——这是最常见的静默失效原因:Mailgun会把未验证的发件人地址当成伪造邮件,直接在SMTP握手阶段丢弃请求,不会进入投递日志。
正确的headers写法参考:
def headers { subject: "网站联系表单新留言", to: "你的收件邮箱@xxx.com", from: "no-reply@你的Mailgun验证过的域名.com", reply_to: @email # 把用户输入的邮箱设为回复地址,方便后续直接回复 } end- 模型必须继承
手动在控制台复现问题
打开rails console,手动创建contact对象测试deliver流程:# 手动实例化表单对象,填入测试参数 test_contact = Homepage.new( name: "测试用户", email: "test@example.com", message: "测试留言内容", nickname: "" ) # 赋值request(mail_form的防垃圾逻辑依赖request对象) test_contact.request = ActionDispatch::TestRequest.create({}) # 先检查验证是否通过 puts test_contact.valid? puts test_contact.errors.full_messages # 手动调用deliver,直接查看抛出的错误 test_contact.deliver这一步会直接暴露所有底层错误,比如SMTP认证失败、发件人不合法、headers缺失等问题。
其他注意事项
- 确认你的
mail_formgem版本适配当前的Ruby 2.4.1 + Rails 5.1.4环境,推荐使用2.5.1版本,避免高版本gem的兼容性问题 - 如果后续需要用异步发送邮件,注意不要把deliver方法放到延迟任务里,mail_form的request对象不能跨序列化传递,需要提前把需要的参数提取出来再处理
内容的提问来源于stack exchange,提问作者Amer Bearat
相关产品推荐
相关产品推荐

