// with_env 展示如何通过环境变量管理通道凭据(避免把密钥写死在代码里)。 // // 适用场景:已有多个通道的凭据(SMTP / 阿里云 / AWS SES / Mailgun), // 希望在程序启动时从环境变量读取配置,注册到 Manager 统一管理。 // // 怎么运行: // 1. 复制 .env.example 为 .env(或直接设置下方环境变量) // 2. 安装 dotenv 依赖:go get github.com/joho/godotenv // 3. 设置好至少一个通道的凭据后执行:go run main.go package main import ( "context" "fmt" "log" "os" "code.yun.ink/pkg/mailx" "code.yun.ink/pkg/mailx/aliyun" "code.yun.ink/pkg/mailx/aws" "code.yun.ink/pkg/mailx/mailgun" "code.yun.ink/pkg/mailx/smtp" "github.com/joho/godotenv" // 读取 .env 文件(可选) ) // buildSenders 从环境变量读取凭据,返回已配置好的通道列表。 // 只返回凭据齐全的通道,未配置的通道直接跳过,方便按需启用。 func buildSenders() []mailx.Sender { var senders []mailx.Sender // --- SMTP --- if os.Getenv("SMTP_HOST") != "" { senders = append(senders, smtp.New(smtp.Config{ Host: os.Getenv("SMTP_HOST"), Port: atoi(os.Getenv("SMTP_PORT"), 465), User: os.Getenv("SMTP_USER"), Password: os.Getenv("SMTP_PASSWORD"), From: os.Getenv("SMTP_FROM"), })) } // --- 阿里云邮件推送 --- if os.Getenv("ALIYUN_ACCESS_KEY_ID") != "" { senders = append(senders, aliyun.New(aliyun.Config{ AccessKeyID: os.Getenv("ALIYUN_ACCESS_KEY_ID"), AccessKeySecret: os.Getenv("ALIYUN_ACCESS_KEY_SECRET"), AccountName: os.Getenv("ALIYUN_ACCOUNT_NAME"), Endpoint: os.Getenv("ALIYUN_ENDPOINT"), // 可选,默认 dm.aliyuncs.com })) } // --- AWS SES --- if os.Getenv("AWS_ACCESS_KEY_ID") != "" { senders = append(senders, aws.New(aws.Config{ AccessKeyID: os.Getenv("AWS_ACCESS_KEY_ID"), AccessKeySecret: os.Getenv("AWS_ACCESS_KEY_SECRET"), Region: os.Getenv("AWS_REGION"), Sender: os.Getenv("AWS_SENDER"), })) } // --- Mailgun --- if os.Getenv("MAILGUN_API_KEY") != "" { senders = append(senders, mailgun.New(mailgun.Config{ APIKey: os.Getenv("MAILGUN_API_KEY"), Domain: os.Getenv("MAILGUN_DOMAIN"), Sender: os.Getenv("MAILGUN_SENDER"), })) } return senders } func main() { ctx := context.Background() // 可选:加载 .env 文件(没有 .env 时静默忽略,改用系统环境变量) _ = godotenv.Load() senders := buildSenders() if len(senders) == 0 { log.Fatal("no channel configured, please set env vars (see .env.example)") } // 注册到 Manager,第一个注册的成为默认通道 mgr := mailx.NewManager() for _, s := range senders { if err := mgr.Register(s); err != nil { log.Fatalf("register %s: %v", s.Name(), err) } } log.Printf("registered channels: %v (default: %s)", mgr.Names(), mgr.Default()) msg := mailx.NewMessage(). From(firstNonEmpty(os.Getenv("FROM_ADDR"), os.Getenv("SMTP_FROM"), os.Getenv("AWS_SENDER"), os.Getenv("MAILGUN_SENDER"))). To(os.Getenv("TO_ADDR")). Subject("hello from mailx (env config)"). Text("This email is sent using env-var configured channel."). Build() // 用默认通道发送 if err := mgr.Send(ctx, msg); err != nil { fmt.Println("send failed:", err) return } fmt.Println("send success") } // atoi 解析端口,失败时返回默认值 func atoi(s string, def int) int { n := 0 if _, err := fmt.Sscanf(s, "%d", &n); err != nil || n <= 0 { return def } return n } // firstNonEmpty 返回第一个非空字符串 func firstNonEmpty(vals ...string) string { for _, v := range vals { if v != "" { return v } } return "" }