您的位置 首页 golang

「GoLang」用GoLang语言,给自己写读写邮件的工具

大家知道,项目上线了,需要监控项目是否健康运行。正常运行时再检查项目运行结果是否正常。

原先用Python做了一个工具,在后台一直运行。

其工作原理如下:

每5分钟检查生产数据和备份数据是否正常同步,如果正常同步,则每半小时发送一个报告正常的邮件。如果没有正常同步,则每半小时发送一个报告异常的邮件。

刚好现在学GoLang,就去写个读写邮件的工具先练下手。

今天终于调通了读写邮件。

需要导入的包如下,(IDE会自动导入,一般不需要自己写)

   "github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
_ "github.com/emersion/go-message/charset"
"github.com/emersion/go-message/mail"
"gopkg.in/gomail.v2"  

发送邮件,可以各个参数分开写,当然也可以整体放到一个struct里面,如:

 type EmailInfo struct {
ServerHost string // 邮箱服务器地址,如腾讯邮箱为smtp.qq.com
ServerPort int    // 邮箱服务器端口,如腾讯邮箱为587
FromEmail  string // 发件人邮箱地址
FromPasswd string //发件人邮箱密码(注意,这里是明文形式)
Recipient []string //收件人邮箱
CC        []string //抄送
Subject []string //
Body string
Attachfilename string
AttackPath string
}  

发送邮件函数(

其中,最需要注意的就是编码问题,程序中发送邮件还是转成了base64编码。

from参数需要使用FormatAddress再次编码。

附件也需要注意编码问题

):

 func sendmail(emailInfo *EmailInfo)  {
// 发送邮件
var m *gomail.Message
m = gomail.NewMessage( gomail.SetEncoding(gomail.Base64), )  //将邮件内容更改为Base64编码
m.SetHeader("From", m.FormatAddress("www@qq.com","昵称"))//特殊说明,构造From(发件人信息)时需要使用m.FormatAddress方法,因为发件人指定中文名或特殊字符时,需要进行编码
m.SetHeader("To", emailInfo.Recipient...) // 切片可以传递给不定参数
if len(emailInfo.CC) != 0 {
m.SetHeader("Cc", emailInfo.CC...)
}
//m.SetAddressHeader("Cc", "dan@example.com", "昵称")
m.SetHeader("Subject", emailInfo.Subject...) //"测试邮件"
m.SetBody("text/html", emailInfo.Body)//"测试邮件"
if len(emailInfo.Attachfilename)>=1  { //name:="附件.png"  "C:\\Users\\www\\Downloads\\26.png"
m.Attach(emailInfo.AttackPath,
gomail.Rename(emailInfo.Attachfilename),
gomail.SetHeader(map[string][]string{
"Content-Disposition": []string{
fmt.Sprintf(`attachment; filename="%s"`, mime.QEncoding.Encode("UTF-8", emailInfo.Attachfilename)),
},
}),
)
}
d := gomail.NewDialer("smtp.qq.com", 587, "www@qq.com", "fabcdefghthikjh")
// d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil {
panic(err)
}
}  

m.SetHeader(“To”, emailInfo.Recipient…) // 切片可以传递给不定参数

这句代码学到了函数参数还可以这样传递。

main函数中,接收邮件的流程如下:

 //接收邮件log.Println("连接服务器")
c, err := client.DialTLS("imap.qq.com:993", nil)
check_error(err)

defer c.Logout()  // 结束后退出登录  
 if err = c.Login(emailInfo.FromEmail, emailInfo.FromPasswd); err != nil {
   log.Fatal(err)
}
log.Println("已登录")  

如果直接读收件箱,可以这样写(通过下标来指定读取哪几封邮件):

 // Select INBOXvar mbox *imap.MailboxStatusmbox, err = c.Select("INBOX", false)
check_error(err)
log.Println("Flags for INBOX:", mbox.Flags) // [\Answered \Flagged \Deleted \Draft \Seen]// Get the last 4 messagesifrom := uint32(1)
ito := mbox.Messages
if mbox.Messages > 3 {
   //  
seqset := new(imap.SeqSet)
seqset.AddRange(ifrom, ito)  

下面用一个for循环从指定位置读邮件,其中go func() {}部分都是启动一个goroutine子进程(工作线程)去读取内容。

代码中From和To可能还存在编码问题,需要解决–从最后的运行结果也可以看到。

 for i:=uint32(ifrom);i<ito; i++{
   var section imap.BodySectionName   
   items := []imap.FetchItem{section.FetchItem()}

   bodyMsg := make(chan *imap.Message, 1)
   go func() {
      if err := c.Fetch(seqset, items, bodyMsg); err != nil {
         log.Fatal(err)
      }
   }()
   msg := <-bodyMsg
   if msg == nil {
      log.Fatal("服务器没有返回信息")
   }

   r := msg.GetBody(§ion)
   if r == nil {
      log.Fatal("服务器没有返回 message body")
   }
   mr, err := mail.CreateReader(r)
   check_error(err)
   //打印信息   
   header := mr.Header
   if date, err := header.Date(); err == nil {
      log.Println("Date:", date)
   }
   if from, err := header.AddressList("From"); err == nil {
      log.Println("From:", from)
   }
   if to, err := header.AddressList("To"); err == nil {
      log.Println("To:", to)
   }
   if subject, err := header.Subject(); err == nil {
      log.Println("Subject:", subject)
   }
   // 
  for {
      p, err := mr.NextPart()
      if err == io.EOF {break} else {check_error(err)}

      switch h := p.Header.(type) {
      case *mail.InlineHeader:      // This is the message's text (can be plain-text or HTML)         b, _ := ioutil.ReadAll(p.Body)
         log.Printf("Got text: %s\n", string(b))
      case *mail.AttachmentHeader:   // This is an attachment         filename, _ := h.Filename()
         log.Printf("Got attachment: %s\n", filename)
      }
   }
   log.Printf("读取第 %d 封信, 结束!\n", i)
}  

上面是读取信内容。

如果需要读取邮件列表,则可以这样写:

  // 列出邮件
mailboxes := make(chan *imap.MailboxInfo, 15)
done := make(chan error, 1)
go func () {       //创建一个子goroutine(工作进程)去读邮件列表,子进程读完即返回。
done <- c.List("", "*", mailboxes)
}()

log.Println("邮箱:")
for m := range mailboxes {    //邮件列表是一个channel
mbox, err := c.Select(m.Name, false)
check_error(err)
to := mbox.Messages
log.Printf("%s : %d", m.Name, to)//各邮箱的名字,如:收件箱,发件箱,草稿箱 和 邮箱内有多少邮件
}

if err = <-done; err != nil {
log.Fatal(err)
}  

读写邮件,其实还是需要去了解邮件协议。

一封传统的电子邮件:

From: “Tim” <tim@example.com>To: “joe Zhang” <zhang@example.com>Subject: TestDate: Wed, 17 May 2020 12:02:29 -0400Message-ID: <NDBBIAKOPKHFGPLCODIGIEKBCHAA.tim@example.com>

Hello World.

在结构上,这封信分为三个部分:首先是信件头,然后是一个空行,最后是信件内容。

符合规范RFC 822。但是协议规定导致

1)非英语字符都不能在电子邮件中使用;

2)电子邮件中不能插入二进制文件(如图片);

3)电子邮件不能有附件

这导致补充协议 MIME系列诞生。

MIME对传统电子邮件的扩展,表现在它在信件头部分添加了几条语句,主要有三条

第一条是:指明这封信使用了MIME规范

第二条语句是:它表明传递的信息类型和采用的编码

Content-Type: text/plain; charset=”ISO-8859-1″

Content-Type表明信息类型,缺省值为” text/plain”。它包含了主要类型(primary type)和次要类型(subtype)两个部分,两者之间用”/”分割。主要类型有9种,分别是application、audio、example、image、message、model、multipart、text、video。

经常使用的有:

text/plain:纯文本,文件扩展名.txt
text/html:HTML文本,文件扩展名.htm和.html
image/jpeg:jpeg格式的图片,文件扩展名.jpg
image/gif:GIF格式的图片,文件扩展名.gif
audio/x-wave:WAVE格式的音频,文件扩展名.wav
audio/mpeg:MP3格式的音频,文件扩展名.mp3
video/mpeg:MPEG格式的视频,文件扩展名.mpg
application/zip:PK-ZIP格式的压缩文件,文件扩展名.zip

如果信息的主要类型是”text”,那还须指明编码类型”charset”,缺省值是ASCII,也可能”ISO-8859-1″、”UTF-8″、”GB2312″等

MIME规定了第三条语句:

Content-transfer-encoding: base64

举个例子:

邮件的源码:

Date: Wed, 18 Jun 2008 18:07:51 +0800 (CST)

From: xxx <xxx@163.com>

To: yifeng.ruan@gmail.com

Message-ID: <14410503.1073611213783671983.JavaMail.coremail@bj163app54.163.com>

Subject: =?gbk?B?xOO6ww==?=

MIME-Version: 1.0

Content-Type: multipart/alternative;

boundary=”—-=_Part_287491_22998031.1213783671982″

——=_Part_287491_22998031.1213783671982

Content-Type: text/plain; charset=gbk

Content-Transfer-Encoding: base64

IAq4+b7dsr+209PQudi55raoo6yyu7XD1Nq12Le9yM66zs341b7Jz7nSz+DTprXEtqvO96Osx+vE49TaxOO1xLKpv83W0AogIArW0Ln6yr2x6tPvIC0gyO7Su7fltcTN+MLnyNXWvgoKtcS12jEy1cXNvMasyb6z/aOst/HU8s7Sw8fXt76/xOO1xM/gudjU8MjOoaPQu9C7us/X96OhtMvNvMas1Nq4vbz+wO/D5g==

——=_Part_287491_22998031.1213783671982

Content-Type: text/html; charset=gbk

Content-Transfer-Encoding: quoted-printable

<DIV> </DIV><DIV>=B8=F9=BE=DD=B2=BF=B6=D3=D3=D0=B9=D8=B9=E6=B6=A8=A3=AC=B2=BB=B5=C3=D4==DA=B5=D8=B7=BD=C8=CE=BA=CE=CD=F8=D5=BE=C9=CF=B9=D2=CF=E0=D3=A6=B5=C4=B6=AB==CE=F7=A3=AC=C7=EB=C4=E3=D4=DA=C4=E3=B5=C4=B2=A9=BF=CD=D6=D0</DIV><DIV> ……

可以看到这封信的MIME语句是:

MIME-Version: 1.0Content-Type: multipart/alternative;boundary=”—-=_Part_287491_22998031.1213783671982″

“Content-Type: multipart/alternative;”表明这封信的内容,是纯文本和HTML文本的混合。另两个可能的值是multipart/mixed和multipart/related,分别表示”信件内容中有二进制内容”和”信件带有附件”。

“boundary=”—-=_Part_287491_22998031.1213783671982″”表明不同信件内容的分割线是”—-=_Part_287491_22998031.1213783671982″,它通常是一个很长的随机字符串。

信件内容部分又有两个子信件头:

Content-Type: text/plain; charset=gbkContent-Transfer-Encoding: base64

Content-Type: text/html; charset=gbkContent-Transfer-Encoding: quoted-printable

它们表明,第一个部分是gbk编码的纯文本,编码转换格式是base64。第二个部分是gbk编码的HTML文本,编码转化格式是quoted-printable。

文章来源:智云一二三科技

文章标题:「GoLang」用GoLang语言,给自己写读写邮件的工具

文章地址:https://www.zhihuclub.com/97572.shtml

关于作者: 智云科技

热门文章

评论已关闭

1条评论

  1. soft core pordn actreeses upskirt galleryy foor frdee viruus free
    strip videos foor free britney spears free sex tape video gsisha girel historical picrures mmilf
    cunts spreead bikini busters dvvd amazon.
    dc baltimore escots serviice demonstratikn of using a vibdator pon hoot leg penis
    hsatlh miri make a porno tits fllashing in public swinger clubb stateville nc.

    penis tipp vibrating free primtable gay christmas cards
    avol tvs suck dichk mmy spacce ggay kates playground
    cums free breast cancer sign andd symptoms diit shved door handles.

    tommy annders fuck vikdeo no see bikini nufe teens
    on bedd imaqge boards ggay cgeney dick enjergy force taxk
    ddr gives patient orall sexx free pornn uswing toys.
    strip cllubs harrisbgurg ppa area girs licxking pussy juicee wermon fucked doggystylle by dogs erotic
    aalbum stippedr dancing nude sexx horone binxing glo krean adult porno.

    horny tenie pussy chyler leigh nude photos adult entsrtainment in punta gorda
    fl florida abnormall hairy tin men mexico ertic story inn arabic companies sspecializing iin mature domestic oill field.

    black wome flashing titfs miley cyrus busty tits virgin mobile intercept faaq
    paaint a teens rolm tewen nymph archivbes teen chouce ebonhy offce slut.

    32aa gfee escort acult comic erottic boopk ggarys hoot slit
    breast cancer awarenedss pinwheels north pen sex scandzl pplatinum trip adut
    literacy rawte in brazil.
    smoking with breast cancer jessica collihs nude pictures matuhre sotthern esxort bournmouth erotic
    bdstiality cartooons brast pai symtooms heaviness swlling lump hoot milf
    lingerie money talks foxy bbig boob teen.
    sex lindsay lohan pictures freee piics teens xxxx cast of
    nci nud dekalb county sexx offender 100-year-old seex abuser vijtage fireeside
    gifts futanasri porn tub search.
    adhd traits adult silvfer slippers erotgica websits hue xxx moivie fast facce fuckk
    heather chadwell nuide phoros herntai inuyasha fanaft shavfe brown pussy.

网站地图