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
	)
	// 发送者邮箱配置
	sender := "[email protected]"
	password := "password"

	// 收件人邮箱
	recipient := "[email protected]"

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

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

	// 邮件主题和内容
	subject := "Test Subject"
	body := "This is the body of the email."

	// 附件路径
	attachmentPath := "aa/test.txt"

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

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

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

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

// CreateMessage 创建邮件消息
func CreateMessage(sender, recipient, subject, body string) string {
	// 创建邮件消息(收件人为多个时,用英文的逗号和空格分割)
	message := fmt.Sprintf("From: %s\r\n", sender)
	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(sender, recipient, subject, body, attachmentPath string) (string, error) {
	// 创建邮件消息
	var msg bytes.Buffer

	// 设置主体
	io.WriteString(&msg, "From: "+sender+"\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
}

你可能感兴趣的:(golang,开发语言,后端)