ActionMailer SMTP生产环境正常本地无法发送问题排查
核心问题分析
生产环境(Heroku)可正常发送邮件,但本地环境无论凭证对错都显示「投递成功」,SendGrid后台无任何记录,说明邮件根本没发往SendGrid服务器,大概率是本地Rails的邮件投递逻辑被默认配置覆盖,或是环境变量加载异常导致。
排查与解决步骤
1. 检查本地开发环境的投递模式
Rails默认在development环境下会把邮件存到本地而非实际发送,即便你在application.rb里配置了SMTP,也可能被config/environments/development.rb的设置覆盖。
打开config/environments/development.rb,查看是否存在以下配置:
config.action_mailer.delivery_method = :letter_opener # 或 :test、:file
如果有,直接改为SMTP模式,也可在这里单独配置本地SMTP参数,避免和生产环境混淆:
config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { user_name: 'apikey', password: ENV['SENDGRID_API_KEY'], address: 'smtp.sendgrid.net', domain: ENV['SENDGRID_DOMAIN'], port: 587, authentication: 'plain', enable_starttls_auto: true }
2. 确认本地环境变量是否加载正常
本地环境下,ENV['SENDGRID_API_KEY']和ENV['SENDGRID_DOMAIN']可能未正确加载。打开Rails控制台执行:
rails c puts ENV['SENDGRID_API_KEY'] puts ENV['SENDGRID_DOMAIN']
如果输出为空,说明环境变量未配置,可通过dotenv管理本地变量:
- 在Gemfile添加:
gem 'dotenv-rails', groups: [:development, :test] - 执行
bundle install - 项目根目录创建
.env文件,写入:
SENDGRID_API_KEY=你的真实API密钥 SENDGRID_DOMAIN=你的域名
- 重启Rails服务器和控制台
3. 开启ActionMailer调试日志
开启详细日志可查看邮件发送的真实过程,快速定位连接或认证问题。在config/environments/development.rb添加:
config.action_mailer.raise_delivery_errors = true config.action_mailer.logger = Logger.new(STDOUT) config.action_mailer.log_level = :debug
重启服务器后发送邮件,控制台会输出SMTP连接、认证的完整日志,能直接看到是否成功连接SendGrid,是否存在认证失败等问题。
4. 直接测试SMTP连接
用纯Ruby脚本测试SMTP连接,排除Rails配置的干扰:
require 'net/smtp' smtp = Net::SMTP.new('smtp.sendgrid.net', 587) smtp.enable_starttls_auto smtp.start(ENV['SENDGRID_DOMAIN'], 'apikey', ENV['SENDGRID_API_KEY'], :plain) do |smtp| puts "SMTP连接成功" end
保存为test_smtp.rb后执行ruby test_smtp.rb,如果报错,说明本地网络或凭证有问题;如果成功,再回到Rails配置排查其他因素。
5. 检查本地网络限制
本地防火墙、代理可能阻断了587端口的连接。可尝试关闭防火墙,或切换网络(比如手机热点)测试,看是否能正常发送邮件。
总结
最常见的原因是开发环境下Rails默认使用本地投递模式(如letter_opener),覆盖了全局SMTP配置;其次是本地环境变量未正确加载。开启调试日志是快速定位问题的关键手段。
内容的提问来源于stack exchange,提问作者Chris A

