You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails中根据应用用户配置从数据库获取的发件邮箱凭据

Hey there! Let's walk through how to set up per-user email sending credentials in your Rails app—pulling directly from the database instead of relying on global configs. This approach gives each user their own unique email setup, which is exactly what you're looking for. Here's a step-by-step guide that's proven to work:

Step 1: Add Database Fields for Credentials

First, you need a place to store each user's SMTP details. You can either add columns directly to your users table or create a separate email_credentials table (better if you might need multiple credentials per user later).

For a simple start, let's add columns to the users table:

# Generate a migration
rails generate migration AddEmailCredentialsToUsers smtp_address:string smtp_port:integer smtp_username:string smtp_password:string smtp_authentication:string smtp_enable_starttls_auto:boolean

# Run the migration
rails db:migrate

Tweak the columns based on your email provider's requirements (add smtp_domain for SendGrid, for example).

Step 2: Build a Custom Delivery Method

Rails lets you define custom email delivery methods, which is perfect for pulling per-user credentials. Create an initializer like config/initializers/per_user_smtp.rb:

class PerUserSmtpDelivery
  def initialize(options = {})
    # No global settings needed here—we'll pass the user at delivery time
  end

  def deliver!(mail)
    # Fetch the user we attached to the mail object
    user = mail.instance_variable_get(:@user)
    raise "No user specified for per-user email delivery" unless user

    # Map the user's stored credentials to SMTP settings
    smtp_config = {
      address: user.smtp_address,
      port: user.smtp_port,
      user_name: user.smtp_username,
      password: user.smtp_password,
      authentication: user.smtp_authentication&.to_sym || :plain,
      enable_starttls_auto: user.smtp_enable_starttls_auto || true
    }

    # Use Rails' built-in SMTP to send the email
    Net::SMTP.start(
      smtp_config[:address],
      smtp_config[:port],
      'localhost', # Use your server's hostname if required by the provider
      smtp_config[:user_name],
      smtp_config[:password],
      smtp_config[:authentication]
    ) do |smtp|
      smtp.send_message(mail.encoded, mail.from.first, mail.to)
    end
  end
end

# Register the custom method with Rails
ActionMailer::Base.add_delivery_method :per_user_smtp, PerUserSmtpDelivery
Step 3: Update Your Mailer to Use the Custom Method

In your mailer (e.g., app/mailers/user_mailer.rb), attach the user to the mail object and switch to the custom delivery method:

class UserMailer < ApplicationMailer
  def welcome_email(user)
    @user = user
    # Attach the user so our delivery method can access their credentials
    mail.instance_variable_set(:@user, user)
    # Send using the per-user SMTP method
    mail(
      to: user.email,
      from: user.smtp_username, # Or a custom from address tied to the user
      subject: "Welcome aboard!",
      delivery_method: :per_user_smtp
    )
  end
end

If all emails from this mailer should use per-user credentials, set it as the default:

class UserMailer < ApplicationMailer
  default delivery_method: :per_user_smtp

  def welcome_email(user)
    @user = user
    mail.instance_variable_set(:@user, user)
    mail(to: user.email, from: user.smtp_username, subject: "Welcome aboard!")
  end
end
Step 4: Add Security & Error Handling

Don't skip these critical steps:

  • Encrypt passwords: Never store plaintext SMTP passwords! Use Rails' encrypted attributes to protect the smtp_password column:
    # In app/models/user.rb
    encrypts :smtp_password
    
    (Make sure you've set up encryption keys in your Rails app first—check the Rails docs if you haven't done this.)
  • Validate credentials: Add validations to ensure users provide complete, valid SMTP details:
    # In app/models/user.rb
    validates :smtp_address, :smtp_port, :smtp_username, :smtp_password, presence: true
    validates :smtp_port, numericality: { only_integer: true, greater_than: 0 }
    
  • Catch errors: Add rescue blocks to handle SMTP failures (invalid credentials, connection issues) and log/notify appropriately:
    # Inside PerUserSmtpDelivery#deliver!
    begin
      Net::SMTP.start(...) do |smtp|
        smtp.send_message(mail.encoded, mail.from.first, mail.to)
      end
    rescue Net::SMTPAuthenticationError => e
      Rails.logger.error "SMTP auth failed for user #{user.id}: #{e.message}"
      raise EmailDeliveryError, "Invalid email credentials"
    rescue => e
      Rails.logger.error "Email delivery failed for user #{user.id}: #{e.message}"
      raise EmailDeliveryError, "Could not send email"
    end
    
Step 5: Test the Setup

Create a test user with valid SMTP credentials (use a service like Mailtrap for safe testing):

user = User.create(
  email: "test@example.com",
  smtp_address: "smtp.mailtrap.io",
  smtp_port: 2525,
  smtp_username: "your_mailtrap_username",
  smtp_password: "your_mailtrap_password",
  smtp_authentication: "plain",
  smtp_enable_starttls_auto: true
)

UserMailer.welcome_email(user).deliver_now

Check your Mailtrap inbox or provider logs to confirm the email was sent using the user's credentials.

内容的提问来源于stack exchange,提问作者mamatha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:26:44