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

来源:互联网 发布:ubuntu 创建新文件夹 编辑:程序博客网 时间:2024/06/06 12:28

        简单邮件传输协议(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 mailimport ("encoding/base64""fmt""net""time")const (tb string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")type Sender struct {UserName stringPassword stringFrom     stringTo       stringSubject  stringText     stringHost     string}func NewSender(host, userName, password string, to string, subject, text string) (r_sender Sender) {r_sender.UserName = userNamer_sender.Password = passwordr_sender.From = userNamer_sender.To = tor_sender.Subject = subjectr_sender.Text = textr_sender.Host = hostreturn}func (this *Sender) SendMail() (e error) {var (deadline time.Duration = 5 * time.Secondencoding *base64.Encodingbuf      []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 mainimport ("./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-mail250-PIPELINING250-AUTH LOGIN PLAIN250-AUTH=LOGIN PLAIN250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urz5c00UCa0xDrUUUUj250-STARTTLS250 8BITMIME334 dXNlcm5hbWU6334 UGFzc3dvcmQ6235 Authentication successful250 Mail OK250 Mail OK354 End data with <CR><LF>.<CR><LF>250 Mail OK queued as smtp10,DsCowEBJW2Q4BQJTGF3hBA--.94S2 1392641336421 closing transmission channel

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

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

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

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

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

0 0
原创粉丝点击