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

juxuny · · 4338 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

        简单邮件传输协议(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


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:juxuny

查看原文:Go 语言 SMTP指令发邮件(实例)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4338 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传