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

基于Ruby on Rails适配Office 365 OAuth2的邮件发送代码改造求助

Switching ActionMailer to OAuth2 for Office 365 (Ruby 2.2.1 + Rails 4.2.5)

Let's walk through converting your existing SMTP login setup to OAuth2 authentication for Office 365. Since your stack is older (Ruby 2.2.1, Rails 4.2.5), we'll use compatible gems and configurations.

Step 1: Add Required Gem

First, add the oauth2 gem (compatible with Ruby 2.2.x) to your Gemfile:

gem 'oauth2', '~> 1.4'

Run bundle install to install it.

Step 2: Register an Azure AD Application

You need to create an app in Azure Active Directory to get OAuth2 credentials:

  • Go to the Azure Portal → Azure Active Directory → App Registrations → New Registration.
  • Name your app, select the appropriate account type (e.g., "Accounts in any organizational directory"), and set a redirect URI (can be http://localhost:3000/auth/callback for testing).
  • After registration, copy your Client ID (from Overview) and create a Client Secret (under Certificates & Secrets).
  • Grant the app the SMTP.Send delegated permission (under API Permissions → Add a permission → Microsoft Graph → Delegated Permissions → Search for "SMTP.Send").
  • Get a Refresh Token: Use a tool like Postman to authenticate and retrieve a refresh token. The scope should include offline_access https://outlook.office.com/SMTP.Send.

Step 3: Configure ActionMailer with OAuth2

Replace your old SMTP settings with this OAuth2 configuration. Create a new initializer at config/initializers/mailer_oauth2.rb:

require 'oauth2'

# Load credentials from environment variables (never hardcode these!)
AZURE_OAUTH2 = {
  client_id: ENV['AZURE_CLIENT_ID'],
  client_secret: ENV['AZURE_CLIENT_SECRET'],
  refresh_token: ENV['AZURE_REFRESH_TOKEN'],
  sender_email: ENV['OFFICE365_SENDER_EMAIL'],
  token_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
}

# Initialize OAuth2 client
oauth_client = OAuth2::Client.new(
  AZURE_OAUTH2[:client_id],
  AZURE_OAUTH2[:client_secret],
  site: 'https://login.microsoftonline.com',
  token_url: AZURE_OAUTH2[:token_url]
)

# Helper to fetch a fresh access token
def fetch_oauth2_token
  # Start with expired token to force refresh
  existing_token = OAuth2::AccessToken.from_hash(oauth_client, {
    refresh_token: AZURE_OAUTH2[:refresh_token],
    expires_at: Time.now.to_i - 1
  })
  existing_token.refresh!.token
end

# Configure ActionMailer
ActionMailer::Base.smtp_settings = {
  address: 'smtp.office365.com',
  port: 587,
  domain: 'your-domain.com', # Replace with your actual domain
  authentication: :oauth2,
  user_name: AZURE_OAUTH2[:sender_email],
  enable_starttls_auto: true,
  oauth2_token: fetch_oauth2_token
}

# Auto-refresh token before each email delivery (handles token expiration)
class OAuth2TokenRefresher
  def self.delivering_email(message)
    message.smtp_settings[:oauth2_token] = fetch_oauth2_token
  end
end

ActionMailer::Base.register_interceptor(OAuth2TokenRefresher)

Step 4: Update Environment Variables

Add these to your .env file (use dotenv-rails gem if you don't already have it):

AZURE_CLIENT_ID=your-client-id-here
AZURE_CLIENT_SECRET=your-client-secret-here
AZURE_REFRESH_TOKEN=your-refresh-token-here
OFFICE365_SENDER_EMAIL=your-sender-email@domain.com

Step 5: Verify Your Mailer Method

Your existing general_mail method should work as-is, but double-check attachment handling to ensure binary reading is correct:

def general_mail(to, subject, content, attachmts = [])
  attachmts.each do |attachment|
    attachments[File.basename(attachment)] = File.read(attachment, mode: 'rb')
  end
  
  mail(to: to, subject: subject) do |format|
    format.text { render text: content }
  end
end

Step 6: Test the Setup

Run this in your Rails console to test sending an email:

NotificationMailer.general_mail('test@example.com', 'OAuth2 Test', 'This email uses OAuth2!').deliver_now

Key Notes

  • Refresh Token Expiry: Delegated refresh tokens can expire. If you run into issues, re-authenticate to get a new refresh token. For long-term use, consider using an application permission flow (requires admin consent) which doesn't need a user-specific refresh token.
  • Security: Never commit credentials to version control. Always use environment variables or a secrets manager.
  • Compatibility: The oauth2 ~>1.4 gem is confirmed to work with Ruby 2.2.1 and Rails 4.2.5.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:25:26