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

能否从本地主机发送邮件?自建SMTP服务器投递失败求助

搭建SMTP服务器发送OTP邮件遇到的问题

我的目标是搭建一台SMTP服务器,从noreply@myname.com发送包含OTP的邮件。目前在个人电脑上开发,没有公网地址或域名,尝试发送邮件到myname@gmail.com,但收件箱和垃圾邮件文件夹里都找不到这封邮件。

已执行操作

  • 启动go-smtp服务器:$ go run cmd/server/main.go
  • 运行go-smtp客户端:$ go run cmd/client/main.go

go-smtp服务器输出

(base) jason@Jasons-Mac-mini server % go run main.go
2022/09/23 13:35:38 Starting server at :1025
2022/09/23 13:56:06 Mail from: test@localhost
2022/09/23 13:56:06 Rcpt to: // email redacted for stackoverflow
2022/09/23 13:56:06 Data: This is the email body

go-smtp客户端输出

(base) jason@Jasons-Mac-mini client % go run main.go
2022/09/23 13:56:06 Mail sent! time elapsed: 1.988625ms

相关代码文件

cmd/client/main.go

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/emersion/go-smtp"
)

func main() {
    start := time.Now()

    // Connect to the remote SMTP server.
    c, err := smtp.Dial("localhost:1025")
    if err != nil {
        log.Fatal(err)
    }

    // Set the sender and recipient first
    if err := c.Mail("test@localhost", nil); err != nil {
        log.Fatal(err)
    }
    if err := c.Rcpt("jasonong713@gmail.com"); err != nil {
        log.Fatal(err)
    }

    // Send the email body.
    wc, err := c.Data()
    if err != nil {
        log.Fatal(err)
    }
    _, err = fmt.Fprintf(wc, "This is the email body")
    if err != nil {
        log.Fatal(err)
    }
    err = wc.Close()
    if err != nil {
        log.Fatal(err)
    }

    // Send the QUIT command and close the connection.
    err = c.Quit()
    if err != nil {
        log.Fatal(err)
    }

    log.Println("Mail sent! time elapsed:", time.Since(start))
}

cmd/server/main.go

package main

import (
    "log"
    "time"

    "github.com/emersion/go-smtp"
    "github.com/godataid/sendemail"
)

func main() {
    be := &sendemail.Backend{}

    s := smtp.NewServer(be)

    s.Addr = ":1025"
    s.Domain = "localhost"
    s.ReadTimeout = 10 * time.Second
    s.WriteTimeout = 10 * time.Second
    s.MaxMessageBytes = 1024 * 1024
    s.MaxRecipients = 50
    s.AllowInsecureAuth = true

    log.Println("Starting server at", s.Addr)
    if err := s.ListenAndServe(); err != nil {
        log.Fatalln(err)
    }
}

backend.go

package sendemail

import "github.com/emersion/go-smtp"

type Backend struct{}

// Authenticate a user. Return smtp.ErrAuthUnsupported if you don't want to
// support this.
func (be *Backend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
    return nil, smtp.ErrAuthUnsupported
}

// Called if the client attempts to send mail without logging in first.
// Return smtp.ErrAuthRequired if you don't want to support this.
func (be *Backend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
    return &Session{}, nil
}

session.go

package sendemail

import (
    "io"
    "log"

    "github.com/emersion/go-smtp"
)

type Session struct{}

// Discard currently processed message.
func (s *Session) Reset() {}

// Free all resources associated with session.
func (s *Session) Logout() error {
    return nil
}

// Set return path for currently processed message.
func (s *Session) Mail(from string, opts smtp.MailOptions) error {
    log.Println("Mail from:", from)
    return nil
}

// Add recipient for currently processed message.
func (s *Session) Rcpt(to string) error {
    log.Println("Rcpt to:", to)
    return nil
}

// Set currently processed message contents and send it.
func (s *Session) Data(r io.Reader) error {
    if b, err := io.ReadAll(r); err != nil {
        return err
    } else {
        log.Println("Data:", string(b))
    }
    return nil
}

内容的提问来源于stack exchange,提问作者Jason Rich Darmawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:10:20