gmail.go 6.4 KB

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