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

Elixir Phoenix通过Amazon SES发邮件遇cacerts未定义问题求助

解决Elixir/Phoenix中使用Amazon SES发送邮件时的cacerts: :undefined错误

底层原因

这个错误的核心是Erlang SSL模块在启用verify: :verify_peer时,无法找到有效的CA证书文件。开启对等验证后,SSL模块需要可信CA证书来验证服务器证书合法性,若指定的证书路径不存在、文件损坏,或配置选项冲突,就会返回cacerts: :undefined错误。

另外你的配置中同时设置ssl: true和tls: :always存在冲突:

  • ssl: true对应465端口的直接SSL连接
  • tls: :always对应587端口的STARTTLS升级
    同时开启会导致SSL模块配置混乱,加重证书加载问题。

解决方案

1. 确认CA证书路径有效性

虽然安装了ca-certificates,但不同环境的证书路径可能不同:

  • Ubuntu/Debian: /etc/ssl/certs/ca-certificates.crt
  • Alpine Linux: /etc/ssl/cert.pem
  • RHEL/CentOS: /etc/pki/tls/certs/ca-bundle.crt

用以下命令验证路径是否存在:

ls -l /etc/ssl/certs/ca-certificates.crt

若文件不存在,需确认证书包是否正确安装,或查找系统实际的CA证书路径。

2. 使用Erlang自带CA证书(推荐)

Elixir生态的certifi包提供预打包的可信CA证书,可避免依赖系统证书路径:

  • 添加certifi到mix.exs依赖:
defp deps do
  [
    # 其他依赖
    {:certifi, "~> 2.11"}
  ]
end
  • 运行mix deps.get安装依赖
  • 修改config/prod.exs配置,用:certifi.cacertfile()获取证书路径:
config :my_app, MyApp.Mailer,
  adapter: Bamboo.SMTPAdapter,
  server: System.get_env("SES_SMTP_SERVER") || "email-smtp.us-east-1.amazonaws.com",
  port: String.to_integer(System.get_env("SES_SMTP_PORT") || "465"),
  username: System.get_env("SES_SMTP_USERNAME"),
  password: System.get_env("SES_SMTP_PASSWORD"),
  ssl: true, # 465端口用ssl: true,不要设置tls选项
  retries: 1,
  ssl_options: [
    verify: :verify_peer,
    cacertfile: :certifi.cacertfile()
  ]

3. 修正端口与加密选项的对应关系

  • 若用465端口:设置ssl: true,不要配置tls相关选项
  • 若用587端口:设置tls: :always、ssl: false,并将ssl_options改为tls_options:
config :my_app, MyApp.Mailer,
  adapter: Bamboo.SMTPAdapter,
  server: System.get_env("SES_SMTP_SERVER") || "email-smtp.us-east-1.amazonaws.com",
  port: String.to_integer(System.get_env("SES_SMTP_PORT") || "587"),
  username: System.get_env("SES_SMTP_USERNAME"),
  password: System.get_env("SES_SMTP_PASSWORD"),
  tls: :always,
  retries: 1,
  tls_options: [
    verify: :verify_peer,
    cacertfile: :certifi.cacertfile()
  ]

生产环境成功配置示例(Amazon SES + Bamboo)

以下是经过验证的生产环境配置,使用certifi规避系统证书依赖:

# mix.exs 依赖
defp deps do
  [
    {:bamboo, "~> 2.2"},
    {:bamboo_smtp, "~> 4.2"},
    {:certifi, "~> 2.11"}
  ]
end

# config/prod.exs
config :my_app, MyApp.Mailer,
  adapter: Bamboo.SMTPAdapter,
  server: System.get_env("SES_SMTP_SERVER"),
  port: 465,
  username: System.get_env("SES_SMTP_USERNAME"),
  password: System.get_env("SES_SMTP_PASSWORD"),
  ssl: true,
  retries: 2,
  ssl_options: [
    verify: :verify_peer,
    cacertfile: :certifi.cacertfile(),
    depth: 2
  ]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 02:25:15