golang发送邮件

golang发送邮件

package main

import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/smtp"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

func main() {
	var (
		err     error
		message string
	)
	// 设置发送者的显示名称
	senderDisplayName := "xxx平台"

	// 发送者邮箱配置
	username := "user@163.com"
	password := "password"

	// 收件人邮箱
	recipient := "recipient@163.com"

	// 邮箱服务器
	smtpHost := "smtp.163.com"
	smtpPort := 465

	// 设置连接超时时间
	tcpTimeout := 5 * time.Second

	// 邮件主题和内容
	subject := "Test Subject"
	body := "hi,all!\r\n详情请查看附件."

	// 附件路径
	attachmentPath := ""

	// 设置邮件消息
	if attachmentPath == "" {
		message = CreateMessage(senderDisplayName, username, recipient, subject, body)
	} else {
		message, err = CreateMessageWithAttachment(senderDisplayName, username, recipient, subject, body, attachmentPath)
		if err != nil {
			fmt.Println("设置邮件消息失败: ", err)
			return
		}
	}

	// 发送邮件(加密端口: 465/587,不加密端口: 25)
	if smtpPort == 25 {
		err = SendEmailNormal(username, password, smtpHost, message, recipient, smtpPort, tcpTimeout)
	} else {
		err = SendEmailWithTls(username, password, smtpHost, message, recipient, smtpPort, tcpTimeout)
	}

	if err != nil {
		fmt.Println("邮件发送失败:", err)
		return
	}

	fmt.Println("邮件发送成功")
}

// CreateMessage 创建邮件消息
func CreateMessage(senderDisplayName, senderEmail, recipient, subject, body string) string {
	// 创建邮件消息(收件人为多个时,用英文的逗号和空格分割)
	message := fmt.Sprintf("From: "+senderDisplayName+" <%s>\r\n", senderEmail)
	message += fmt.Sprintf("To: %s\r\n", recipient)
	message += fmt.Sprintf("Subject: %s\r\n", subject)
	message += "\r\n" + body

	return message
}

// CreateMessageWithAttachment 创建带附件的邮件消息
func CreateMessageWithAttachment(senderDisplayName, senderEmail, recipient, subject, body, attachmentPath string) (string, error) {
	// 创建邮件消息
	var msg bytes.Buffer

	// 设置主体
	io.WriteString(&msg, "From: "+senderDisplayName+" <"+senderEmail+">\r\n")
	io.WriteString(&msg, "To: "+recipient+"\r\n")
	io.WriteString(&msg, "Subject: "+subject+"\r\n")
	io.WriteString(&msg, "MIME-version: 1.0;\r\n")
	io.WriteString(&msg, "Content-Type: multipart/mixed; boundary=foobar\r\n\r\n")

	// 写入正文
	io.WriteString(&msg, "--foobar\r\n")
	io.WriteString(&msg, "Content-Type: text/plain; charset=\"utf-8\"\r\n\r\n")
	io.WriteString(&msg, body+"\r\n")

	// 写入附件
	attachmentFile, err := os.Open(attachmentPath)
	if err != nil {
		return "", err
	}
	defer attachmentFile.Close()

	io.WriteString(&msg, "--foobar\r\n")
	io.WriteString(&msg, "Content-Type: application/octet-stream\r\n")
	io.WriteString(&msg, "Content-Disposition: attachment; filename=\""+filepath.Base(attachmentPath)+"\"\r\n\r\n")
	io.Copy(&msg, attachmentFile)
	io.WriteString(&msg, "\r\n")

	// 写入结束标志
	io.WriteString(&msg, "--foobar--\r\n")

	return msg.String(), nil
}

// SendEmailWithTls 安全策略的邮件发送
func SendEmailWithTls(username, password, smtpHost, message, recipient string, smtpPort int, tcpTimeout time.Duration) error {
	// 设置SMTP客户端配置
	auth := smtp.PlainAuth("", username, password, smtpHost)

	// 设置Dialer,包含超时设置
	dialer := &net.Dialer{
		Timeout: tcpTimeout,
	}

	// 使用DialWithDialer设置连接超时时间
	conn, err := tls.DialWithDialer(dialer, "tcp", smtpHost+":"+strconv.Itoa(smtpPort), &tls.Config{
		InsecureSkipVerify: true,
	})
	if err != nil {
		return errors.New("DialWithDialer err: " + err.Error())
	}
	defer conn.Close()

	// 连接到smtp服务器
	client, err := smtp.NewClient(conn, smtpHost)
	if err != nil {
		return errors.New("NewClient err: " + err.Error())
	}
	defer client.Quit()

	// 认证
	err = client.Auth(auth)
	if err != nil {
		return errors.New("Auth err: " + err.Error())
	}

	// 设置发件人
	err = client.Mail(username)
	if err != nil {
		return err
	}

	// 设置收件人
	err = client.Rcpt(recipient)
	if err != nil {
		return err
	}

	// 获取数据写入器
	data, err := client.Data()
	if err != nil {
		return err
	}
	defer data.Close()

	// 写入邮件消息
	_, err = data.Write([]byte(message))
	if err != nil {
		return err
	}

	return nil
}

// SendEmailNormal 不带安全策略的邮件发送
func SendEmailNormal(username, password, smtpHost, message, recipient string, smtpPort int, tcpTimeout time.Duration) error {
	// 设置SMTP客户端配置
	auth := smtp.PlainAuth("", username, password, smtpHost)

	// 使用DialTimeout设置连接超时时间
	conn, err := net.DialTimeout("tcp", smtpHost+":"+strconv.Itoa(smtpPort), tcpTimeout)
	if err != nil {
		return errors.New("DialTimeout err: " + err.Error())
	}
	defer conn.Close()

	// 连接到smtp服务器
	client, err := smtp.NewClient(conn, smtpHost)
	if err != nil {
		return errors.New("NewClient err: " + err.Error())
	}
	defer client.Quit()

	// 开始TLS握手
	err = client.StartTLS(&tls.Config{
		InsecureSkipVerify: true,
	})
	if err != nil {
		return errors.New("StartTLS err: " + err.Error())
	}

	// 认证
	err = client.Auth(auth)
	if err != nil {
		return errors.New("Auth err: " + err.Error())
	}

	// 设置发件人
	err = client.Mail(username)
	if err != nil {
		return err
	}

	// 设置收件人
	err = client.Rcpt(recipient)
	if err != nil {
		return err
	}

	// 获取数据写入器
	data, err := client.Data()
	if err != nil {
		return err
	}
	defer data.Close()

	// 写入邮件消息
	_, err = data.Write([]byte(message))
	if err != nil {
		return err
	}

	return nil
}
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值