gmail.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package mail
  2. import (
  3. "crypto/tls"
  4. "log"
  5. "strings"
  6. "sync"
  7. "time"
  8. "app.yhyue.com/moapp/jybase/common"
  9. "app.yhyue.com/moapp/jybase/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", strings.Split(to, ",")...) // 收件人
  50. if cc != "" {
  51. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  52. }
  53. if bcc != "" {
  54. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  55. }
  56. m.SetHeader("Subject", subject) // 主题
  57. m.SetBody("text/html", body) // 正文
  58. if fname != "" {
  59. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  60. m.Attach(fname, gomail.Rename(rename), gomail.SetHeader(h)) //添加附件
  61. //m.Attach(fname) //添加附件
  62. }
  63. reTry := auth.ReTry
  64. if reTry == 0 {
  65. reTry = 3
  66. }
  67. return gSend(reTry, auth, m, to)
  68. }
  69. // 电销 多人
  70. func GSendMail_dx(from, to, cc, bcc, subject, body, fname, rename string, auth *GmailAuth) bool {
  71. m := gomail.NewMessage()
  72. m.SetAddressHeader("From", auth.User, from) // 发件人
  73. m.SetHeader("To", strings.Split(to, ",")...) // 收件人
  74. if cc != "" {
  75. m.SetHeader("Cc", strings.Split(cc, ",")...) //抄送
  76. }
  77. if bcc != "" {
  78. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  79. }
  80. m.SetHeader("Subject", subject) // 主题
  81. m.SetBody("text/html", body) // 正文
  82. if fname != "" {
  83. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  84. m.Attach(fname, gomail.Rename(rename), gomail.SetHeader(h)) //添加附件
  85. //m.Attach(fname) //添加附件
  86. }
  87. reTry := auth.ReTry
  88. if reTry == 0 {
  89. reTry = 3
  90. }
  91. return gSend(reTry, auth, m, to)
  92. }
  93. // 如果附件是byte,用这个
  94. func GSendMail_B(from, to, cc, bcc, subject, body, fname string, fb []byte, auth *GmailAuth) bool {
  95. m := gomail.NewMessage()
  96. m.SetAddressHeader("From", auth.User, from) // 发件人
  97. m.SetHeader("To",
  98. m.FormatAddress(to, "收件人")) // 收件人
  99. if cc != "" {
  100. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  101. }
  102. if bcc != "" {
  103. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  104. }
  105. m.SetHeader("Subject", subject) // 主题
  106. m.SetBody("text/html", body) // 正文
  107. if fname != "" {
  108. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  109. m.Attach_new(fb, gomail.Rename(fname), gomail.SetHeader(h)) //添加附件
  110. //m.Attach(fname) //添加附件
  111. }
  112. reTry := auth.ReTry
  113. if reTry == 0 {
  114. reTry = 1
  115. }
  116. return gSend(reTry, auth, m, to)
  117. }
  118. // 如果附件是byte,用这个,这个是为企业级服务修改的
  119. // 20191206 @ren to用|分隔的是抄送用,分隔的是并列
  120. func GSendMail_Bq(from, to, cc, bcc, subject, body, fname string, fb []byte, auth *GmailAuth) bool {
  121. m := gomail.NewMessage()
  122. m.SetAddressHeader("From", auth.User, from) // 发件人
  123. tos := strings.Split(to, "|")
  124. if len(tos) > 0 {
  125. tos1 := strings.Split(tos[0], ",")
  126. m.SetHeader("To", tos1...) // 收件人
  127. }
  128. if len(tos) > 1 {
  129. tos2 := strings.Split(tos[1], ",")
  130. if cc != "" {
  131. tos2 = append(tos2, cc)
  132. }
  133. m.SetHeader("Cc", tos2...) // 收件人
  134. } else {
  135. if cc != "" {
  136. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  137. }
  138. }
  139. if len(tos) > 2 {
  140. tos3 := strings.Split(tos[2], ",")
  141. if bcc != "" {
  142. tos3 = append(tos3, cc)
  143. }
  144. m.SetHeader("Bcc", tos3...) // 收件人
  145. } else {
  146. if bcc != "" {
  147. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  148. }
  149. }
  150. m.SetHeader("Subject", subject) // 主题
  151. m.SetBody("text/html", body) // 正文
  152. if fname != "" {
  153. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  154. m.Attach_new(fb, gomail.Rename(fname), gomail.SetHeader(h)) //添加附件
  155. //m.Attach(fname) //添加附件
  156. }
  157. reTry := auth.ReTry
  158. if reTry == 0 {
  159. reTry = 1
  160. }
  161. return gSend(reTry, auth, m, to)
  162. }
  163. // 发送普通这个是为企业级服务修改的
  164. // 20191206 @ren to用|分隔的是抄送,分隔的是并列
  165. func GSendMail_q(from, to, cc, bcc, subject, body, fname, rename string, auth *GmailAuth) bool {
  166. m := gomail.NewMessage()
  167. m.SetAddressHeader("From", auth.User, from) // 发件人
  168. tos := strings.Split(to, "|")
  169. if len(tos) > 0 {
  170. tos1 := strings.Split(tos[0], ",")
  171. m.SetHeader("To", tos1...) // 收件人
  172. }
  173. if len(tos) > 1 {
  174. tos2 := strings.Split(tos[1], ",")
  175. if cc != "" {
  176. tos2 = append(tos2, cc)
  177. }
  178. m.SetHeader("Cc", tos2...) // 收件人
  179. } else {
  180. if cc != "" {
  181. m.SetHeader("Cc", m.FormatAddress(cc, "收件人")) //抄送
  182. }
  183. }
  184. if len(tos) > 2 {
  185. tos3 := strings.Split(tos[2], ",")
  186. if bcc != "" {
  187. tos3 = append(tos3, cc)
  188. }
  189. m.SetHeader("Bcc", tos3...) // 收件人
  190. } else {
  191. if bcc != "" {
  192. m.SetHeader("Bcc", m.FormatAddress(bcc, "收件人")) // 暗送
  193. }
  194. }
  195. m.SetHeader("Subject", subject) // 主题
  196. m.SetBody("text/html", body) // 正文
  197. if fname != "" {
  198. h := map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}
  199. m.Attach(fname, gomail.Rename(rename), gomail.SetHeader(h)) //添加附件
  200. //m.Attach(fname) //添加附件
  201. }
  202. reTry := auth.ReTry
  203. if reTry == 0 {
  204. reTry = 3
  205. }
  206. return gSend(reTry, auth, m, to)
  207. }
  208. func gSend(retry int, auth *GmailAuth, m *gomail.Message, to string) bool {
  209. defer common.Catch()
  210. dialer := getDialer(false, auth, to)
  211. defer func() {
  212. auth.PoolChan <- dialer
  213. }()
  214. status := false
  215. for i := 0; i < retry; i++ {
  216. if err := dialer.DialAndSend(m); err != nil {
  217. dialer = getDialer(true, auth, to)
  218. if retry > 0 {
  219. log.Println(auth.User, to, "第", i+1, "次发送邮件gSend error:", err)
  220. time.Sleep(200 * time.Millisecond)
  221. }
  222. } else {
  223. status = true
  224. break
  225. }
  226. }
  227. return status
  228. }
  229. // 先取模后轮询获取一个mail实例
  230. func PollingMail(email string, array []*GmailAuth, f func(g *GmailAuth) bool) bool {
  231. if len(array) == 0 {
  232. return false
  233. }
  234. index := len(email) % len(array)
  235. if f(array[index]) {
  236. return true
  237. }
  238. for i := 0; i < len(array); i++ {
  239. if i == index {
  240. continue
  241. } else if f(array[i]) {
  242. return true
  243. }
  244. }
  245. return false
  246. }