跳转至

Sidekiq

适用于 Ruby on RailsSidekiq 后台邮件投递的集成指南(Ruby 3.2+)。消息通过 Action Mailer 在 Worker 中经 Mailexam SMTP 发送——适合通知与 CI,且不阻塞 HTTP 请求。

Web 层入队任务;Sidekiq 异步发送(类似 Python 的 Celery)。

前置条件

  • Mailexam 账户,以及已创建并具备 SMTP 凭据的项目
  • 消息代理 — Redis(Sidekiq 必需)。
  • Ruby 3.2+、Bundler 及 Rails 应用。

从项目的欢迎邮件(或控制台)中复制:

  • YOUR_LOGIN — SMTP 登录名(例如 xxxxx);
  • YOUR_PASSWORD — SMTP 密码(与登录名成对的唯一凭据);
  • 主机 — YOUR_LOGIN.mailexam.cn登录名一致)。

1. 依赖

Gemfile

gem "rails", "~> 8.1"
gem "sidekiq", "~> 7.3"
gem "redis", "~> 5.0"
gem "dotenv-rails", groups: %i[development test]
bundle install

本地运行 Redis(Docker):

docker run -d --name redis -p 6379:6379 redis:7-alpine

2. 环境变量

项目根目录的 .env

REDIS_URL=redis://localhost:6379/0

MAILEXAM_LOGIN=YOUR_LOGIN
MAILEXAM_PASSWORD=YOUR_PASSWORD
MAILEXAM_PORT=587
MAIL_FROM=noreply@example.test

SMTP 主机:YOUR_LOGIN.mailexam.cnGitHub 参考实现 中域名为 mailexam.io,请按欢迎邮件填写)。

3. Action Mailer 配置

Ruby on Rails 相同 — config/initializers/mailexam_mailer.rb 或环境相关 SMTP 设置。

4. Sidekiq 配置

config/initializers/sidekiq.rb

Sidekiq.configure_server do |config|
  config.redis = { url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0") }
end

Sidekiq.configure_client do |config|
  config.redis = { url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0") }
end

config/sidekiq.yml

:concurrency: 5
:queues:
  - default

config/application.rb 中添加 Worker 自动加载路径:

config.autoload_paths << Rails.root.join("app/workers")
config.eager_load_paths << Rails.root.join("app/workers")

5. Mailer、Worker 与路由

Mailer(与 Rails 示例相同):

# app/mailers/test_mailer.rb
class TestMailer < ApplicationMailer
  def test_email
    @body = params[:body]

    mail(
      to: params[:to],
      subject: params[:subject]
    )
  end
end

Worker:

# app/workers/mail_test_worker.rb
class MailTestWorker
  include Sidekiq::Worker

  def perform(to, subject, body)
    TestMailer.with(
      to: to,
      subject: subject,
      body: body
    ).test_email.deliver_now
  end
end

控制器 — 入队而非 deliver_now

# app/controllers/mail_controller.rb
class MailController < ApplicationController
  def test
    payload = JSON.parse(request.body.read.presence || "{}")

    MailTestWorker.perform_async(
      payload["to"].presence || "user@example.test",
      payload["subject"].presence || "Sidekiq + Mailexam",
      payload["body"].presence || payload["text"].presence || "Mailexam test from Sidekiq"
    )

    render json: { status: "ok", queued: true }
  end
end

启动 Redis、Sidekiq 与 Rails:

bundle exec sidekiq -C config/sidekiq.yml
bin/rails server
curl -X POST http://127.0.0.1:3000/mail/test \
  -H 'Content-Type: application/json' \
  -d '{"to":"user@example.test","subject":"Test","body":"Hello"}'

Worker 处理任务后,邮件将出现在 Mailexam 控制台 → 您的项目 → 收件箱。

完整示例见 Sidekiq 实现示例(GitHub)

6. 本地开发与 CI

环境 建议
local Redis + Sidekiq 进程 + Rails 服务器
CI Redis 服务、REDIS_URL 及 Mailexam 凭据放在流水线变量中

.gitlab-ci.yml 示例:

variables:
  REDIS_URL: redis://redis:6379/0
  MAILEXAM_LOGIN: $MAILEXAM_LOGIN
  MAILEXAM_PASSWORD: $MAILEXAM_PASSWORD
  MAILEXAM_PORT: "587"
  MAIL_FROM: "noreply@example.test"

集成测试后,通过 Mailexam API 验证投递。

7. 常见问题

任务已入队但邮件未发送

  • 确认 Sidekiq 正在运行。
  • 检查 REDIS_URL 与 Redis 连接。
  • 查看 Sidekiq 日志中的 SMTP 错误。

TLS 或认证失败

  • SMTP 主机应为 {login}.mailexam.cn,登录名与欢迎邮件一致。

控制台中看不到邮件

  • 查看同一 Mailexam 项目的收件箱。
  • 等待 Worker 处理完成。

参见