提供電子郵件服務的協議叫作:SMTP(Simple Mail Transfer Protocol)爲了可以高效安全的進行數據的傳輸,SMTP協議底層使用的TCP實現兩端的鏈接。html
早期的電子郵件收發的工做機制如上圖所示。發送端和接收端之間經過SMTP底層的TCP簡歷鏈接。經過網絡直接將郵件發送到對方的磁盤上。golang
可是問題也隨之而來:安全
若是接收方沒有開機,或者開機了可是沒有鏈接網絡,那麼就不能經過SMTP協議創建鏈接,這時發送端只能是個隔一段時間後重試,直到接收端開機了,聯網了,發送端才能成功的將郵件發送給接收方。問題很明顯,接收方只要不開機,發送方的郵件就不能發送出去,若是是東方國家和西方國家之間的兩我的各自在各自的白天才開機,那豈不是他們之間的郵件根本不可能發送出去了?服務器
爲了解決這個問題,郵件服務器出現了:網絡
這時收發郵件的工做機制就演變成了上圖那樣。發送方 面向 郵件服務器發送郵件,而無論接收方是否開機,是否聯網,接收方經過上線後使用POP3(Post Office Proto-col)從郵件服務器接收郵件。dom
整個過程當中,郵件服務器是不會斷電的。tcp
經過上圖能夠看到,SMTP是發送電子郵件時使用的協議。 它底層使用tcp的25號端口。在這個tcp鏈接上進行控制,應答,以及數據的傳輸。ide
客戶端以文本的方式發送請求,郵件服務器每次回覆3位數字做爲應答。好比客戶端首次會發送 HELO<domain>
表示請求創建鏈接。正常的話郵件服務器會回覆250,表示完成請求命令。3d
SMTP協議中規定,以'.'最爲郵件正文的結束符。當正文前面有一個'.'或者有兩個'.' 都要進行特殊處理。code
SMTP不會校驗發送者,因此咱們常常會收到垃圾郵件,聽說也會有「POP before SMTP」 和「SMTP認證」機制,來防止冒充發送人。從而減小垃圾郵件的數量。
POP服務器也是一臺一直處於充電狀態的服務器。
客戶端經過pop3協議從pop服務器上接收發送方發過來的協議,可是在接收以前是須要進行用戶身份驗證的,也就是說,客戶端得將本身的帳號密碼發送到POP服務器,經過驗證後才能取回屬於本身的郵件
POP與SMTP同樣,都是基於TCP鏈接完成相應的操做的。
IMAP和POP協議同樣都是接收電子郵件時使用的協議。
若是使用IMAP,即便不用將電子郵件下載到本地也能夠閱讀。由於IMAP實現了字啊服務端處理MIME類型的數據,因此他能實現當一封電子郵件有10個附件時,它能直接打開其中的某一個。並且在服務端做出已讀/未讀,等狀體的修改。
郵件地址一般都是由兩部分組成: 名稱@地址
。
常見的像 123@qq.com
這種郵件的地址。
123就是名稱,qq.com就是地址。 電子郵件的地址和域名構造相同,後面的com是頂級域名。
如今的電子郵件地址由DNS統一管理。DNS裏面存儲着各個郵件地址,和這個郵件地址做爲發送地址時所對應的郵件服務器的域名信息。咱們把這種映射關係稱爲MX記錄。由於方纔說了,對如今的郵件發送機制來講,發送者是將郵件發送到郵件服務器上。那經過查詢DNS中的MX記錄,就能知道xxx@qq.com.
和 xxx@163.com
這種不一樣的郵件後綴所對應的郵件服務器的域名,經過域名進一步找到這個機器。
最初的很長一段時間裏,郵件只能發送文本信息。後臺能發送的數據類型已經被拓展到了MIME。能夠發送諸如gif, video,png,jpg,jpeg,text/plain 等等類型的數據。具體發送啥樣的信息,經過Content-Type定義。
實例代碼以下:
package mail import ( "strconv" ) import "gopkg.in/gomail.v2" func SendMail(mailTo []string, subject string, body string) error { mailConn := map[string]string{ "user": "6464xxxx8@qq.com", // 郵件發送者的地址 "pass": "trsxxxxxxxxxxcd", // qq郵箱填受權碼,百度一下獲取方式。 "host": "smtp.qq.com", // 發送將郵件發送給騰訊的smtp郵件服務器 "port": "465", // 發送郵件使用的端口 } port, _ := strconv.Atoi(mailConn["port"]) m := gomail.NewMessage() m.SetHeader("From", m.FormatAddress(mailConn["user"], "自動化成績查詢")) m.SetHeader("To", mailTo...) //發送給多個用戶 m.SetHeader("Subject", subject) //設置郵件主題 m.SetBody("text/html", body) //設置郵件正文 d := gomail.NewDialer(mailConn["host"], port, mailConn["user"], mailConn["pass"]) err := d.DialAndSend(m) return err } /* 發送郵件 stuEmail:學生的郵箱 subject:標題 body:發送的內容 */ func DoSendMail(stuEmail , subject, body string) (e error) { mailTo := []string{stuEmail} err := SendMail(mailTo, subject, body) if err != nil { e = err return e } return nil } //func main() { // //定義收件人 // mailTo := []string{ // "2693xxxx8@qq.com", // "196xxxxx30@qq.com", // } // //郵件主題爲"Hello" // subject := "Hi 出成績了" // // 郵件正文 // body := "請查收您的新成績" // // err := SendMail(mailTo, subject, body) // if err != nil { // log.Println(err) // fmt.Println("send fail") // return // } // fmt.Println("send successfully") //}