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

Rails中配置邮件定时发送:注册时及注册3个月后发件

How to Add a Scheduled 3-Month Post-Signup Email in Rails (While Keeping Existing Signup Emails)

Hey Mike, great question! Let's break this down into manageable steps to get that scheduled email up and running without disrupting your existing signup flow. I'll cover two common approaches for Rails scheduled tasks — pick the one that fits your setup best.

First: Prep the Email Template & Mailer Method

Since you already have signup emails working with the exchange gem, we just need to add a new email for the 3-month follow-up:

  1. Open your user mailer (probably app/mailers/user_mailer.rb) and add a new method:

    class UserMailer < ApplicationMailer
      # Your existing signup email method here
      def welcome_email(user)
        # ... your existing code
      end
    
      # New 3-month follow-up email
      def three_months_after_signup_email(user)
        @user = user
        mail(to: @user.email, subject: "We Missed You! Three Months Since You Joined")
      end
    end
    
  2. Create the email templates in app/views/user_mailer/:

    • three_months_after_signup_email.html.erb (HTML version)
    • three_months_after_signup_email.text.erb (plain text fallback)
      Fill these with your desired follow-up content — keep it personal!

Option 1: Use the whenever Gem (Simple Cron Jobs)

If you don't have a background queue set up, whenever is a straightforward way to manage cron tasks through Ruby.

Steps:

  1. Add the gem to your Gemfile:

    gem 'whenever', require: false
    

    Run bundle install to install it.

  2. Generate the schedule config file:

    wheneverize .
    

    This creates config/schedule.rb.

  3. Configure the daily cron job in config/schedule.rb:

    every :day, at: '2:00 am' do # Run daily at 2 AM (low traffic time)
      runner "User.send_three_month_followup_emails"
    end
    
  4. Add the method to your User model to handle finding users and sending emails:

    class User < ApplicationRecord
      # Add a column to track if we've sent this email (prevents duplicates!)
      # Run this migration first: rails generate migration AddThreeMonthsEmailSentAtToUsers three_months_email_sent_at:datetime
      # Then run rails db:migrate
    
      def self.send_three_month_followup_emails
        # Find users who signed up exactly 3 months ago and haven't gotten the email yet
        three_months_ago_window = 3.months.ago.beginning_of_day..3.months.ago.end_of_day
        eligible_users = where(created_at: three_months_ago_window, three_months_email_sent_at: nil)
    
        eligible_users.each do |user|
          UserMailer.three_months_after_signup_email(user).deliver_now
          user.update!(three_months_email_sent_at: Time.current)
        end
      end
    
  5. Deploy the cron job:

    # For production
    whenever --update-crontab
    # For development (if you want to test locally)
    whenever --update-crontab --set environment=development
    

If you're already using Sidekiq for background jobs, this is the better approach — it keeps email sending off your main server and is more scalable.

Steps:

  1. Add the gems to your Gemfile:

    gem 'sidekiq'
    gem 'sidekiq-cron'
    

    Run bundle install.

  2. Configure Sidekiq to load cron jobs on startup. Create/modify config/initializers/sidekiq.rb:

    Sidekiq.configure_server do |config|
      config.on(:startup) do
        # Load cron jobs from the schedule.yml file
        Sidekiq::Cron::Job.load_from_hash YAML.load_file(Rails.root.join('config', 'schedule.yml'))
      end
    end
    
    Sidekiq.configure_client do |config|
      # Standard Sidekiq client config (if you already have this, leave it)
    end
    
  3. Create the cron schedule file config/schedule.yml:

    send_three_month_followup_emails:
      cron: "0 2 * * *" # Daily at 2 AM (cron syntax: minute hour day month weekday)
      class: "ThreeMonthsAfterSignupWorker"
      queue: default
    
  4. Create the Sidekiq worker in app/workers/three_months_after_signup_worker.rb:

    class ThreeMonthsAfterSignupWorker
      include Sidekiq::Worker
      sidekiq_options retry: 3 # Retry failed emails 3 times
    
      def perform
        three_months_ago_window = 3.months.ago.beginning_of_day..3.months.ago.end_of_day
        # Use find_each to handle large user lists efficiently
        User.where(created_at: three_months_ago_window, three_months_email_sent_at: nil).find_each do |user|
          UserMailer.three_months_after_signup_email(user).deliver_later
          user.update!(three_months_email_sent_at: Time.current)
        end
      end
    end
    
  5. Start Sidekiq (and make sure it runs in production):

    bundle exec sidekiq
    

    For deployment, use a process manager like systemd or supervisord to keep Sidekiq running.

Key Notes to Avoid Headaches

  • Prevent duplicate emails: The three_months_email_sent_at column is critical — don't skip adding that migration. It ensures you never send the same email twice to a user.
  • Test locally: For development, you can tweak the cron schedule to run every minute (* * * * *) to test quickly, or manually trigger the worker/method in the Rails console:
    # For whenever approach
    User.send_three_month_followup_emails
    # For Sidekiq approach
    ThreeMonthsAfterSignupWorker.perform_async
    
  • Use deliver_later: If using Sidekiq, always use deliver_later instead of deliver_now to offload email sending to the background.

Let me know if you hit any snags — whether it's setting up the migration, tweaking the cron schedule, or troubleshooting email delivery!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:05:29