1. 程式人生 > 其它 >使用 GOLANG 傳送郵件

使用 GOLANG 傳送郵件

目錄

使用 GOLANG 傳送郵件

我們一起來回顧一下上一次咱們說到的GO 的驗證碼案例

  • 驗證碼種類梳理
  • 驗證碼庫的安裝
  • 驗證碼庫的原始碼介紹
  • 實操,編碼
  • 驗證碼效果展示

想看看GO 咋做驗證碼的,歡迎檢視文章 GO 的驗證碼案例

生活和工作中,咱們都離不開郵件的收發,要麼在手機上查收和傳送,要麼在自己的電腦前面進行郵件編輯和處理

可是,我們會發現,很多時候,某類郵件,咱們每天都必須要在同一個時刻發出去

,並且內容也是大同小異的,

而且,有時候因為各種各種各樣的原因,不能準時的傳送郵件,這個時候,咱們如果可以寫一個定製化的傳送郵件的程式那可以說還是很香的

那麼,咱們還是先來看看一些基本的常識吧

郵件是什麼?

郵件是指經傳遞方式處理的檔案

郵件進行傳遞的過程稱為郵遞,而從事郵遞服務的機構或系統,則稱為郵政

郵件有國內郵件和國際郵件兩類

那麼電子郵件又是個啥?

電子郵件是—種用電子手段提供資訊交換的通訊方式是網際網路應用最廣的服務

電子郵件的優勢是啥?

電子郵件依託於網路的電子郵件系統,有如下優勢:

  • 價格非常低廉

不管傳送到哪裡,都只需負擔網費

  • 傳輸快速

幾秒鐘之內可以傳送到世界上任何指定的目的地,與世界上任何一個角落的網路使用者聯絡

電子郵件的形式是啥樣的?

  • 文字
  • 影象
  • 聲音等

想一想每次發郵件都需要經歷如下的步驟

  • 開啟電腦
  • 進入瀏覽器
  • 開啟電子郵件
  • 新建 - 編輯 - 傳送

大部分內容還是複製貼上的,

妥妥的一個工具人,好滴,現在就來看看 使用 GOLang 咋發郵件

郵件協議

咱們使用程式語言需要遵守程式語言的規範,我們在瀏覽器裡面瀏覽網頁也是一樣,需要遵循各種網路協議

那麼,我們傳送郵件的必須也要先知道有哪些郵件協議可以使用,咱們都來列舉一下

  • SMTP

SMTP是 簡單郵件傳輸協議,是一組用於從源地址到目的地址傳輸郵件的規範,通過它來控制郵件的中轉方式

另外 SMTP 協議屬於TCP/IP協議簇

  • POP3

郵局協議的第3個版本,是因特網電子郵件的第一個離線協議標準

  • IMAP

是一種優於POP的新協議

POP一樣,IMAP也能下載郵件、從伺服器中刪除郵件或詢問是否有新郵件

IMAP可讓使用者在伺服器上建立並管理郵件資料夾或郵箱、刪除郵件、查詢某封信的一部分或全部內容

最終完成所有這些工作都不需要把郵件從伺服器下載到使用者的個人計算機上

OK,讓我們開始進入到編碼環節

開始編碼發郵件

咱們今天就使用 SMTP 協議來發送郵件,有如下幾個步驟

  • 在 QQ 郵箱上面,拿到授權碼
  • 編碼,並安裝email 郵件庫
  • 開始傳送郵件

QQ 郵箱上面,拿到授權碼

  • 進入 QQ郵箱,點選 設定 -> 賬戶
  • 下滑頁面,看到 POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務
  • 開啟 POP3/SMTP服務
  • 開啟 IMAP/SMTP服務
  • 生成授權碼,這個授權碼自己找地方儲存起來

編碼,並安裝email 郵件庫

咱們本次寫的郵件小案例,用到的GO 的包是 "github.com/jordan-wright/email" , 我們可以這樣來手動安裝

 go get github.com/jordan-wright/email

不進行手動安裝也沒有問題,咱們可以現在看看 寫一個初版的傳送郵件小案例

package main

import (
   "github.com/jordan-wright/email"
   "log"
   "net/smtp"
)

func main() {
   // 簡單設定 log 引數
   log.SetFlags(log.Lshortfile | log.LstdFlags)

   em := email.NewEmail()
   // 設定 sender 傳送方 的郵箱 , 此處可以填寫自己的郵箱
   em.From = "xx <[email protected]>"
    
   // 設定 receiver 接收方 的郵箱  此處也可以填寫自己的郵箱, 就是自己發郵件給自己
   em.To = []string{"[email protected]"}
    
   // 設定主題
   em.Subject = "小魔童給你發郵件了"
    
   // 簡單設定檔案傳送的內容,暫時設定成純文字
   em.Text = []byte("hello world, 咱們用 golang 發個郵件!!")
    
   //設定伺服器相關的配置
   err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "自己的郵箱賬號", "自己郵箱的授權碼", "smtp.qq.com"))
   if err != nil {
      log.Fatal(err)
   }
   log.Println("send successfully ... ")
}

執行上述程式碼的效果如下:

2021/06/xx xx:36:28 main.go:28: send successfully ...

說明發送郵件成功了,咱們來看看我們的郵箱

果然是傳送成功了 , 竊喜

那麼今天的文章分享就到這裡了吧 ,這時你會問,我想發表格,想發html內容,還想發附件,甚至我想祕密抄送給某些人

好的安排

傳送HTML內容 + 附件

咱們可以先來看看 這個庫支援的哪些欄位,上述NewEmail 方法時候返回一個指標

// NewEmail creates an Email, and returns the pointer to it.
func NewEmail() *Email {
   return &Email{Headers: textproto.MIMEHeader{}}
}

這個指標是指向了一個郵件的資料結構,咱們一起來瞅瞅

// Email is the type used for email messages
type Email struct {
   ReplyTo     []string    
   From        string		// 傳送者
   To          []string		// 接收者
   Bcc         []string		// 密送
   Cc          []string		// 抄送
   Subject     string		// 主題
   Text        []byte // Plaintext message (optional)  
   HTML        []byte // Html message (optional)
   Sender      string // override From as SMTP envelope sender (optional)
   Headers     textproto.MIMEHeader  // 協議頭
   Attachments []*Attachment    // 附件
   ReadReceipt []string
}

看了上述結構,咱們是不是傳送郵件的時候,就可以抄送,密送,新增附件,或者發 HTML 的內容了呢 ,咱們改造一下上述的程式碼

func main() {
   // 簡單設定l og 引數
   log.SetFlags(log.Lshortfile | log.LstdFlags)

   em := email.NewEmail()
   //設定傳送方的郵箱
   em.From = "xx <[email protected]>"
   // 設定接收方的郵箱
   em.To = []string{"[email protected]"}

   // 抄送
   em.Cc = []string{"[email protected]"}

   // 密送
   em.Bcc = []string{"[email protected]"}

   //設定主題
   em.Subject = "小魔童給你發郵件了"
   //設定檔案傳送的內容
   em.HTML = []byte(`
   <h3><a href="https://juejin.cn/user/3465271329953806">歡迎來到小魔童哪吒的主頁</a></h3>
<br/>
<table border="0" style="font-family: '微軟雅黑 Light';" cellpadding="3px">
    <tr>
        <td> 1 </td>
        <td><a href="https://juejin.cn/post/6975686540601245709">GO 中 defer的實現原理</a></td>
    </tr>
    <tr>
        <td> 2 </td>
        <td><a href="https://juejin.cn/post/6975280009082568740">GO 中 Chan 實現原理分享</a></td>
    </tr>
    <tr>
        <td> 3 </td>
        <td><a href="https://juejin.cn/post/6974908615232585764">GO 中 map 的實現原理</a></td>
    </tr>
    <tr>
        <td> 4 </td>
        <td><a href="https://juejin.cn/post/6974539862800072718">GO 中 slice 的實現原理</a></td>
    </tr>
    <tr>
        <td> 5 </td>
        <td> <a href="https://juejin.cn/post/6974169270624190495">GO 中 string 的實現原理</a></td>
    </tr>
    <tr>
        <td> 6 </td>
        <td><a href="https://juejin.cn/post/6973793593987170317">GO 中 ETCD 的編碼案例分享</a></td>
    </tr>
    <tr>
        <td> 7 </td>
        <td><a href="https://juejin.cn/post/6973455825905909797">服務註冊與發現之ETCD</a></td>
    </tr>
    <tr>
        <td> 8 </td>
        <td> <a href="https://juejin.cn/post/6973108979777929230">GO通道和 sync 包的分享</a></td>
    </tr>
    <tr>
        <td> 9 </td>
        <td> <a href="https://juejin.cn/post/6972846349968474142">GO的鎖和原子操作分享</a></td>
    </tr>
</table>
`)
   // 新增附件
   em.AttachFile("./test.html")
   // 設定伺服器相關的配置
   err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "自己的郵箱賬號", "自己郵箱的授權碼", "smtp.qq.com"))
   if err != nil {
      log.Fatal(err)
   }
   log.Println("send successfully ... ")
}

執行之後,咱們去查收一下郵件

抄送,密送,新增附件,傳送 HTML 內容,全部滿上

如何提高發送郵件的效能

get github.com/jordan-wright/email 包裡面為我們提供了連線池,你就說香不香,咱們可以複用上一次的網路連線來發送郵件,而不是每傳送一次郵件,就建立一次連線

我們都知道,建立連線是會耗費時間和資源的,咱們得儘可能的優化

再來一個DEMO,連線池的,咱們運用連線池,建立 一個 有 5 個緩衝的通道,讓 3 個協程去通道里面獲取資料,然後傳送郵件

func main() {

   // 簡單設定l og 引數
   log.SetFlags(log.Lshortfile | log.LstdFlags)

   // 建立有5 個緩衝的通道,資料型別是  *email.Email
   ch := make(chan *email.Email, 5)
   // 連線池
   p, err := email.NewPool(
      "smtp.qq.com:25",
      3,	// 數量設定成 3 個
      smtp.PlainAuth("", "自己的郵箱", "自己郵箱的授權碼", "smtp.qq.com"),
   )

   if err != nil {
      log.Fatal("email.NewPool error : ", err)
   }
	
   // sync 包,控制同步
   var wg sync.WaitGroup
   wg.Add(3)
   for i := 0; i < 3; i++ {
      go func() {
         defer wg.Done()
          // 若 ch 無資料,則阻塞, 若 ch 關閉,則退出迴圈
         for e := range ch {
            // 超時時間 10 秒
            err := p.Send(e, 10*time.Second)
            if err != nil {
               log.Printf( "p.Send error : %v , e = %v , i = %d\n", err , e, i)
            }
         }
      }()
   }

   for i := 0; i < 5; i++ {
      e := email.NewEmail()
      // 設定傳送郵件的基本資訊
      e.From = "xx <[email protected]>"
      e.To = []string{"[email protected]"}
      e.Subject = "test email.NewPool " + fmt.Sprintf("  the %d email",i)
      e.Text = []byte(fmt.Sprintf("test email.NewPool , the %d email !", i))
      ch <- e
   }

   // 關閉通道
   close(ch)
   // 等待子協程退出
   wg.Wait()
   log.Println("send successfully ... ")
}

執行上述程式碼後,咱們檢視郵箱

咱們可以看到,郵件並不是按照順序傳送出來的,這就對了

要是對於上述的sync 使用有疑問的話, 歡迎檢視文章GO通道和 sync 包的分享

總結

  • 分享了郵件,電子郵件是什麼
  • 郵件協議有哪些
  • 如何使用GOLANG 傳送電子郵件
  • 傳送電子郵件如何攜帶純文字,HTML內容,附件等
  • 傳送郵件,如何抄送,如何密送
  • 如何提高發送郵件的效能

之前我們也簡單分享了GOLANG如何傳送郵件,大家可以對比一下,哪一種更加方便golang如何傳送郵件(qq郵箱) |Go主題月

歡迎點贊,關注,收藏

朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力

好了,本次就到這裡,下一次 分享一波GO的爬蟲

技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~