Go 语言 SMTP指令发邮件(实例)

        简单邮件传输协议(SMTP)是一种基于文本的电子邮件传输协议,是在因特网中用于在邮件服务器之间交换邮件的协议。SMTP是应用层的服务,可以适应于各种网络系统。SMTP的命令和响应都是基于文本,以命令行为单位,换行符为CR/LF(\r\n)。响应信息一般只有一行,由一个3位数的代码开始,后面可附上很简短的文字说明。

        SMTP要经过建立连接、传送邮件和释放连接3个阶段。具体为:

      (1)建立TCP连接。   
     (2)客户端向服务器发送HELLO命令以标识发件人自己的身份,然后客户端发送MAIL命令。(EHLO 是扩展指令,不同服务器有不同指令)   
     (3)服务器端以OK作为响应,表示准备接收。   
     (4)客户端发送RCPT命令。   
     (5)服务器端表示是否愿意为收件人接收邮件。   
     (6)协商结束,发送邮件,用命令DATA发送输入内容。


下面是以smtp.163.com 服务器为例:

package mail

import (
	"encoding/base64"
	"fmt"
	"net"
	"time"
)

const (
	tb string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
)

type Sender struct {
	UserName string
	Password string
	From     string
	To       string
	Subject  string
	Text     string
	Host     string
}

func NewSender(host, userName, password string, to string, subject, text string) (r_sender Sender) {
	r_sender.UserName = userName
	r_sender.Password = password
	r_sender.From = userName
	r_sender.To = to
	r_sender.Subject = subject
	r_sender.Text = text
	r_sender.Host = host
	return
}

func (this *Sender) SendMail() (e error) {
	var (
		deadline time.Duration = 5 * time.Second
		encoding *base64.Encoding
		buf      []byte = make([]byte, 512)
		r        int
	)
	encoding = base64.NewEncoding(tb)
	conn, e := net.Dial("tcp", this.Host)
	if e != nil {
		return
	}
	defer conn.Close()

	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte("EHLO Juxuny\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte("AUTH LOGIN\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte(encoding.EncodeToString([]byte(this.UserName)) + "\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte(encoding.EncodeToString([]byte(this.Password)) + "\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte("MAIL FROM: <" + this.From + ">" + "\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte("RCPT TO <" + this.To + ">\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		return
	}
	fmt.Println(string(buf[:r-1]))

	conn.Write([]byte("DATA\r\n"))
	conn.Write([]byte("\r\n"))
	conn.Write([]byte("Message-ID: <" + this.From + ">\r\n"))
	conn.Write([]byte("X-Mailer: <MMail 1.0>"))
	conn.Write([]byte("MIME-Version: 1.0"))
	conn.Write([]byte("Content-Type: text/plain"))
	conn.Write([]byte("From: <" + this.From + ">\r\n"))
	conn.Write([]byte("To: <" + this.To + ">\r\n"))
	conn.Write([]byte("Subject: " + this.Subject + "\r\n"))
	conn.Write([]byte("\r\n"))
	conn.Write([]byte(this.Text))
	conn.Write([]byte("\r\n.\r\n"))

	time.Sleep(5e9)
	conn.Write([]byte("QUIT\r\n"))
	conn.SetDeadline(time.Now().Add(deadline))
	r, e = conn.Read(buf)
	if e != nil {
		fmt.Println(e)
		return
	}
	fmt.Println(string(buf[:r-1]))

	return
}


package main

import (
	"./mail"
	"fmt"
)

//NewSender(host, userName, password string, to []string, subject, text string)

func main() {

	s := mail.NewSender("smtp.163.com:25",
		"killuaxyz@163.com",
		"**********",
		"976813280@qq.com",
		"hello mail",
		"Test mail")
	e := s.SendMail()
	if e != nil {
		fmt.Println(e)
	}

}

输出结果:
220 163.com Anti-spam GT for Coremail System (163com[20121016])
250-mail
250-PIPELINING
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urz5c00UCa0xDrUUUUj
250-STARTTLS
250 8BITMIME
334 dXNlcm5hbWU6
334 UGFzc3dvcmQ6
235 Authentication successful
250 Mail OK
250 Mail OK
354 End data with <CR><LF>.<CR><LF>
250 Mail OK queued as smtp10,DsCowEBJW2Q4BQJTGF3hBA--.94S2 1392641336
421 closing transmission channel

连接成功就返回:
220 163.com Anti-spam GT for Coremail System (163com[20121016])

conn.Write([]byte("AUTH LOGIN\r\n")) 之后,服务器返回:334 dXNlcm5hbWU6

(使用base64Decode ,去解密 "dXNlcm5hbWU6"  其实就是“username:” )

这里就发送经过base64加密的用户名

对应的,收到 334 UGFzc3dvcmQ6 之后,就要发送经过base64加密的帐号密码过去,如果验证成功,服务器返回:235 Authentication successful

Go语言中,你可以使用`net/smtp`包来发送电子邮件,并配合`text/template`包来创建动态邮件模板。以下是一个简单的步骤来实现这个功能: 1. **导入所需库**: 首先需要导入`net/smtp`和`text/template`库,它们分别用于SMTP邮件发送和模板处理。 ```go import ( "net/smtp" "text/template" ) ``` 2. **设置模板**: 创建一个`template.Template`实例,可以包含收件人、主题和其他内容变量。 ```go tpl := template.Must(template.New("email").Parse(` To: {{ .To }} Subject: {{ .Subject }} {{ .Body }} `) ``` 这里的`.To`, `.Subject`, `.Body`是模板中的占位符,会被实际值替换。 3. **准备数据**: 准备一个结构体,包含发件人地址、收件人列表、邮件主题以及邮件正文。 ```go type Email struct { From string To []string Subject string Body string } ``` 4. **填充模板并生成HTML字符串**: 使用模板将数据渲染到邮件内容中。 ```go data := Email{ From: "your-email@example.com", To: []string{"recipient1@example.com", "recipient2@example.com"}, Subject: "Test Email", Body: "Hello, this is a test email using Go.", } htmlContent, err := tpl.ExecuteTemplate(bytes.NewBufferString(""), "email", data) if err != nil { // Handle error } ``` 5. **发送邮件**: 使用`smtp.SendMail()`函数发送邮件,这里需要SMTP服务器地址、用户名、密码。 ```go msg := []byte(htmlContent.String()) auth := smtp.PlainAuth("", "your-smtp-username", "your-smtp-password", "smtp.example.com") err = smtp.SendMail("smtp.example.com:587", auth, data.From, data.To, msg) if err != nil { // Handle error } ``` 6. **错误处理**: 别忘了检查可能出现的错误,并适当地处理它们。 ```go if err != nil { log.Fatal(err) return } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值