gmail.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package mail
  2. import (
  3. "crypto/tls"
  4. "log"
  5. "qfw/util"
  6. "strings"
  7. "sync"
  8. "time"
  9. "github.com/go-gomail/gomail"
  10. )
  11. type GmailAuth struct {
  12. SmtpHost string //邮箱服务器
  13. SmtpPort int //邮箱端口
  14. User string //用户
  15. Pwd string //密码
  16. PoolChan chan *gomail.Dialer
  17. PoolSize int
  18. ReTry int
  19. }
  20. var locker = &sync.Mutex{}
  21. func getDialer(flag bool, auth *GmailAuth, to string) *gomail.Dialer {
  22. if auth.PoolChan == nil {
  23. locker.Lock()
  24. defer locker.Unlock()
  25. if auth.PoolChan == nil {
  26. if auth.PoolSize == 0 {
  27. auth.PoolSize = 1
  28. }
  29. auth.PoolChan = make(chan *gomail.Dialer, auth.PoolSize)
  30. for i := 0; i < auth.PoolSize; i++ {
  31. dialer := gomail.NewPlainDialer(auth.SmtpHost, auth.SmtpPort, auth.User, auth.Pwd) // 发送邮件服务器、端口、发件人账号、发件人密码
  32. dialer.TLSConfig = &tls.Config{ServerName: auth.SmtpHost, InsecureSkipVerify: true}
  33. auth.PoolChan <- dialer
  34. }
  35. }
  36. }
  37. if flag {
  38. log.Println(auth.User, to, "发送邮件getDialer:get new gomail Dialer")
  39. dialer := gomail.NewPlainDialer(auth.SmtpHost, auth.SmtpPort, auth.User, auth.Pwd) // 发送邮件服务器、端口、发件人账号、发件人密码
  40. dialer.TLSConfig = &tls.Config{ServerName: auth.SmtpHost, InsecureSkipVerify: true}
  41. auth.PoolChan <- dialer
  42. }
  43. return <-auth.PoolChan
  44. }
  45. //发送普通
  46. func GSendMail(from, to, cc, bcc, subject, body, fname, rename string, auth *GmailAuth) bool {
  47. m := gomail.NewMessage()
  48. m.SetAddressHeader("From", auth.User, from) // 发件人
  49. m.SetHeader("To",
  50. m.FormatAddress(to, "收件人")) // 收件人
  51. if cc != "" {
  52. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  53. }
  54. if bcc != "" {
  55. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  56. }
  57. m.SetHeader("Subject", subject) // 主题
  58. m.SetBody("text/html", body) // 正文
  59. if fname != "" {
  60. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  61. m.Attach(fname, gomail.Rename(rename), gomail.SetHeader(h)) //添加附件
  62. //m.Attach(fname) //添加附件
  63. }
  64. reTry := auth.ReTry
  65. if reTry == 0 {
  66. reTry = 3
  67. }
  68. return gSend(reTry, auth, m, to)
  69. }
  70. //如果附件是byte,用这个
  71. func GSendMail_B(from, to, cc, bcc, subject, body, fname string, fb []byte, auth *GmailAuth) bool {
  72. m := gomail.NewMessage()
  73. m.SetAddressHeader("From", auth.User, from) // 发件人
  74. m.SetHeader("To",
  75. m.FormatAddress(to, "收件人")) // 收件人
  76. if cc != "" {
  77. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  78. }
  79. if bcc != "" {
  80. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  81. }
  82. m.SetHeader("Subject", subject) // 主题
  83. m.SetBody("text/html", body) // 正文
  84. if fname != "" {
  85. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  86. m.Attach_new(fb, gomail.Rename(fname), gomail.SetHeader(h)) //添加附件
  87. //m.Attach(fname) //添加附件
  88. }
  89. reTry := auth.ReTry
  90. if reTry == 0 {
  91. reTry = 1
  92. }
  93. return gSend(reTry, auth, m, to)
  94. }
  95. //如果附件是byte,用这个,这个是为企业级服务修改的
  96. //20191206 @ren to用|分隔的是抄送用,分隔的是并列
  97. func GSendMail_Bq(from, to, cc, bcc, subject, body, fname string, fb []byte, auth *GmailAuth) bool {
  98. m := gomail.NewMessage()
  99. m.SetAddressHeader("From", auth.User, from) // 发件人
  100. tos := strings.Split(to, "|")
  101. if len(tos) > 0 {
  102. tos1 := strings.Split(tos[0], ",")
  103. m.SetHeader("To", tos1...) // 收件人
  104. }
  105. if len(tos) > 1 {
  106. tos2 := strings.Split(tos[1], ",")
  107. if cc != "" {
  108. tos2 = append(tos2, cc)
  109. }
  110. m.SetHeader("Cc", tos2...) // 收件人
  111. } else {
  112. if cc != "" {
  113. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  114. }
  115. }
  116. if len(tos) > 2 {
  117. tos3 := strings.Split(tos[2], ",")
  118. if bcc != "" {
  119. tos3 = append(tos3, cc)
  120. }
  121. m.SetHeader("Bcc", tos3...) // 收件人
  122. } else {
  123. if bcc != "" {
  124. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  125. }
  126. }
  127. m.SetHeader("Subject", subject) // 主题
  128. m.SetBody("text/html", body) // 正文
  129. if fname != "" {
  130. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  131. m.Attach_new(fb, gomail.Rename(fname), gomail.SetHeader(h)) //添加附件
  132. //m.Attach(fname) //添加附件
  133. }
  134. reTry := auth.ReTry
  135. if reTry == 0 {
  136. reTry = 1
  137. }
  138. return gSend(reTry, auth, m, to)
  139. }
  140. //发送普通这个是为企业级服务修改的
  141. //20191206 @ren to用|分隔的是抄送,分隔的是并列
  142. func GSendMail_q(from, to, cc, bcc, subject, body, fname, rename string, auth *GmailAuth) bool {
  143. m := gomail.NewMessage()
  144. m.SetAddressHeader("From", auth.User, from) // 发件人
  145. tos := strings.Split(to, "|")
  146. if len(tos) > 0 {
  147. tos1 := strings.Split(tos[0], ",")
  148. m.SetHeader("To", tos1...) // 收件人
  149. }
  150. if len(tos) > 1 {
  151. tos2 := strings.Split(tos[1], ",")
  152. if cc != "" {
  153. tos2 = append(tos2, cc)
  154. }
  155. m.SetHeader("Cc", tos2...) // 收件人
  156. } else {
  157. if cc != "" {
  158. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  159. }
  160. }
  161. if len(tos) > 2 {
  162. tos3 := strings.Split(tos[2], ",")
  163. if bcc != "" {
  164. tos3 = append(tos3, cc)
  165. }
  166. m.SetHeader("Bcc", tos3...) // 收件人
  167. } else {
  168. if bcc != "" {
  169. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  170. }
  171. }
  172. m.SetHeader("Subject", subject) // 主题
  173. m.SetBody("text/html", body) // 正文
  174. if fname != "" {
  175. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  176. m.Attach(fname, gomail.Rename(rename), gomail.SetHeader(h)) //添加附件
  177. //m.Attach(fname) //添加附件
  178. }
  179. reTry := auth.ReTry
  180. if reTry == 0 {
  181. reTry = 3
  182. }
  183. return gSend(reTry, auth, m, to)
  184. }
  185. //
  186. func gSend(retry int, auth *GmailAuth, m *gomail.Message, to string) bool {
  187. defer util.Catch()
  188. dialer := getDialer(false, auth, to)
  189. defer func() {
  190. auth.PoolChan <- dialer
  191. }()
  192. status := false
  193. for i := 0; i < retry; i++ {
  194. if err := dialer.DialAndSend(m); err != nil {
  195. dialer = getDialer(true, auth, to)
  196. if retry > 0 {
  197. log.Println(auth.User, to, "第", i+1, "次发送邮件gSend error:", err)
  198. time.Sleep(200 * time.Millisecond)
  199. }
  200. } else {
  201. status = true
  202. break
  203. }
  204. }
  205. return status
  206. }
  207. //先取模后轮询获取一个mail实例
  208. func PollingMail(email string, array []*GmailAuth, f func(g *GmailAuth) bool) bool {
  209. if len(array) == 0 {
  210. return false
  211. }
  212. index := len(email) % len(array)
  213. if f(array[index]) {
  214. return true
  215. }
  216. for i := 0; i < len(array); i++ {
  217. if i == index {
  218. continue
  219. } else if f(array[i]) {
  220. return true
  221. }
  222. }
  223. return false
  224. }