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

如何在Go语言中通过Exim发送邮件(不使用SMTP)?

在Go中通过Exim发送邮件(无需SMTP)

你现在用的gomail.v2主要是针对SMTP协议的,但Exim作为本地邮件传输代理(MTA),支持直接通过命令行或管道接收邮件内容,完全不需要走SMTP流程。下面给你两种实用的实现方式:

方法一:直接调用Exim命令行发送

Exim支持通过-t参数从邮件内容的头信息里自动识别收件人,我们可以直接构建符合RFC标准的邮件内容,然后通过标准输入传给Exim:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
)

func main() {
    // 构建完整的邮件内容,头和正文之间要留空行
    var emailContent bytes.Buffer
    emailContent.WriteString("From: me@example.com\n")
    emailContent.WriteString("To: you@example.com\n")
    emailContent.WriteString("Bcc: youbcc@example.com, anotherbcc@example.com\n")
    emailContent.WriteString("Subject: 测试邮件(直接调用Exim)\n")
    emailContent.WriteString("Content-Type: text/plain; charset=utf-8\n\n")
    emailContent.WriteString("这是通过Exim直接发送的邮件正文,不需要SMTP服务器!")

    // 执行Exim命令,-t表示从邮件头读取收件人列表
    cmd := exec.Command("/usr/sbin/exim", "-t")
    cmd.Stdin = &emailContent

    // 捕获错误输出,方便排查问题
    var stderr bytes.Buffer
    cmd.Stderr = &stderr

    if err := cmd.Run(); err != nil {
        fmt.Printf("邮件发送失败: %v,错误详情: %s\n", err, stderr.String())
        return
    }
    fmt.Println("邮件发送成功!")
}

方法二:结合Gomail构建邮件 + Exim发送

如果你习惯用gomail.v2来处理复杂邮件(比如HTML内容、附件),可以先用Gomail构建好邮件结构,再把生成的邮件内容传给Exim,这样兼顾便捷性和本地投递的需求:

package main

import (
    "bytes"
    "fmt"
    "gopkg.in/gomail.v2"
    "os/exec"
)

func main() {
    // 用Gomail构建邮件,和你原来的代码逻辑一致
    m := gomail.NewMessage()
    m.SetHeader("From", "me@example.com")
    m.SetHeader("To", "you@example.com")
    m.SetAddressHeader("Bcc", "youbcc@example.com", "Bcc收件人")
    m.SetHeader("Bcc", "anotherbcc@example.com")
    m.SetHeader("Subject", "测试邮件(Gomail + Exim)")
    m.SetBody("text/html", "<h1>Hello!</h1><p>这是用Gomail构建的HTML邮件,通过Exim发送。</p>")
    // 可以添加附件
    // m.Attach("document.pdf")

    // 将Gomail的邮件内容写入缓冲区
    var emailBuffer bytes.Buffer
    if err := m.WriteTo(&emailBuffer); err != nil {
        fmt.Printf("构建邮件失败: %v\n", err)
        return
    }

    // 调用Exim发送邮件
    cmd := exec.Command("/usr/sbin/exim", "-t")
    cmd.Stdin = &emailBuffer

    var stderr bytes.Buffer
    cmd.Stderr = &stderr

    if err := cmd.Run(); err != nil {
        fmt.Printf("发送失败: %v,错误信息: %s\n", err, stderr.String())
        return
    }
    fmt.Println("邮件发送成功!")
}

注意事项

  • 确保你的Go程序有执行/usr/sbin/exim的权限,部分系统可能需要将程序加入特定用户组(比如mail组),或者配置Exim允许本地用户投递邮件。
  • 邮件内容的格式要符合RFC规范,尤其是头信息和正文之间的空行,否则Exim可能无法正确解析。
  • 如果你的系统中Exim被链接为sendmail(很多Linux发行版默认这么做),可以把命令换成exec.Command("/usr/sbin/sendmail", "-t"),效果完全一样。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:59:37