跳转至

Phoenix

适用于 Phoenix 1.7+(Elixir)应用的集成指南。Mailexam 通过 SwooshSwoosh.Adapters.SMTP 适配器(gen_smtp 库)作为 SMTP 接入。

前置条件

  • Mailexam 账户,以及已创建并具备 SMTP 凭据的项目
  • Elixir 1.15+ 及 Erlang/OTP 26+。

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

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

1. 依赖

创建项目(默认模板已包含 Swoosh Mailer):

mix phx.new my_app
cd my_app

若项目使用 --no-mailer 标志创建,在 mix.exs 中添加:

defp deps do
  [
    # ... Phoenix 依赖 ...
    {:swoosh, "~> 1.17"},
    {:gen_smtp, "~> 1.2"}
  ]
end
mix deps.get

并手动创建 MyApp.Mailer 模块(见下文)。

2. 环境变量

mix phx.server 前导出变量(或在 IDE 运行配置中设置):

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

SMTP 主机:YOUR_LOGIN.mailexam.cn

发件人地址

MAIL_FROM 可以是任意测试地址——邮件进入 Mailexam,而非真实收件人。

备选端口

MAILEXAM_PORT=587

配置中:tls: :always

MAILEXAM_PORT=2525

tls: :always,与 587 相同。

MAILEXAM_PORT=25

配置中:tls: :never

3. Mailer 配置

lib/my_app/mailer.ex

defmodule MyApp.Mailer do
  use Swoosh.Mailer, otp_app: :my_app
end

config/runtime.exs(片段 — 应用启动时生效):

import Config

login = System.get_env("MAILEXAM_LOGIN")
password = System.get_env("MAILEXAM_PASSWORD")
port = String.to_integer(System.get_env("MAILEXAM_PORT") || "587")

if login && password do
  config :my_app, MyApp.Mailer,
    adapter: Swoosh.Adapters.SMTP,
    relay: "#{login}.mailexam.cn",
    username: login,
    password: password,
    port: port,
    tls: if(port in [587, 2525], do: :always, else: :never),
    auth: :always
end

4. 发送邮件

lib/my_app/test_email.ex

defmodule MyApp.TestEmail do
  import Swoosh.Email

  def deliver(to \\ "user@example.test", subject \\ "Phoenix + Mailexam", body \\ "来自 Phoenix 的 Mailexam 测试") do
    from = System.get_env("MAIL_FROM") || "noreply@example.test"

    email =
      new()
      |> from(from)
      |> to(to)
      |> subject(subject)
      |> text_body(body)

    MyApp.Mailer.deliver(email)
  end
end

5. Phoenix 路由

lib/my_app_web/controllers/mail_controller.ex

defmodule MyAppWeb.MailController do
  use MyAppWeb, :controller

  def create(conn, params) do
    to = params["to"] || "user@example.test"
    subject = params["subject"] || "Phoenix + Mailexam"
    body = params["body"] || "来自 Phoenix 的 Mailexam 测试"

    case MyApp.TestEmail.deliver(to, subject, body) do
      {:ok, _} ->
        json(conn, %{status: "ok"})

      {:error, reason} ->
        conn
        |> put_status(:internal_server_error)
        |> json(%{error: inspect(reason)})
    end
  end
end

lib/my_app_web/router.ex

scope "/", MyAppWeb do
  post "/mail/test", MailController, :create
end

启动并验证:

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

mix phx.server
curl -X POST http://127.0.0.1:4000/mail/test \
  -H 'Content-Type: application/json' \
  -d '{"to":"user@example.test","subject":"测试","body":"你好"}'

邮件将出现在 Mailexam 控制台 → 您的项目 → 收件箱。

6. 本地开发与 CI

环境 建议
local export 变量或 .env + direnv
CI GitLab CI/CD Variables 中的密钥 MAILEXAM_LOGINMAILEXAM_PASSWORD

.gitlab-ci.yml 示例:

variables:
  MAILEXAM_LOGIN: $MAILEXAM_LOGIN
  MAILEXAM_PASSWORD: $MAILEXAM_PASSWORD
  MAILEXAM_PORT: "587"
  MAIL_FROM: "noreply@example.test"

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

7. 常见问题

TLS 或认证失败

  • relay 须为 {login}.mailexam.cnusername — 邮件中的同一登录名。
  • 登录名和密码为同一项目的邮件成对凭据

587 端口

  • 需要 tls: :always,而非 :never

:smtp_response / 超时

  • 确认 gen_smtp 在依赖中,且在 mix phx.server 前已设置变量。

控制台中看不到邮件

  • 查看同一 Mailexam 项目的收件箱。
  • 开发环境启用日志:config :logger, level: :debug

参见