Advertisement
Guest User

Untitled

a guest
Oct 18th, 2019
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.75 KB | None | 0 0
  1. package gmail
  2.  
  3. import (
  4. "bytes"
  5. "crypto/tls"
  6. "encoding/base64"
  7. "errors"
  8. "fmt"
  9. "io/ioutil"
  10. "net/smtp"
  11. "path/filepath"
  12. "strings"
  13. )
  14.  
  15. // Email represents a single message, which may contain
  16. // attachments.
  17. type Email struct {
  18. Subject, Body string
  19. From string
  20. Name string
  21. Password string
  22. ContentType string
  23. To []string
  24. Attachments map[string][]byte
  25. }
  26.  
  27. // Compose begins a new email, filling the subject and body,
  28. // and allocating memory for the list of recipients and the
  29. // attachments.
  30. func Compose(Subject, Body string) *Email {
  31. out := new(Email)
  32. out.Subject = Subject
  33. out.Body = Body
  34. out.To = make([]string, 0, 1)
  35. out.Attachments = make(map[string][]byte)
  36. return out
  37. }
  38.  
  39. // Attach takes a filename and adds this to the message.
  40. // Note that since only the filename is stored (and not
  41. // its path, for privacy reasons), multiple files in
  42. // different directories but with the same filename and
  43. // extension cannot be sent.
  44. func (e *Email) Attach(Filename string) error {
  45. b, err := ioutil.ReadFile(Filename)
  46. if err != nil {
  47. return err
  48. }
  49.  
  50. _, fname := filepath.Split(Filename)
  51. e.Attachments[fname] = b
  52. return nil
  53. }
  54.  
  55. // AddRecipient adds a single recipient.
  56. func (e *Email) AddRecipient(Recipient string) {
  57. e.To = append(e.To, Recipient)
  58. }
  59.  
  60. // AddRecipients adds one or more recipients.
  61. func (e *Email) AddRecipients(Recipients ...string) {
  62. e.To = append(e.To, Recipients...)
  63. }
  64.  
  65. // Send sends the email, returning any error encountered.
  66. func (e *Email) Send() error {
  67. if e.From == "" {
  68. return errors.New("Error: No sender specified. Please set the Email.From field.")
  69. }
  70. if e.To == nil || len(e.To) == 0 {
  71. return errors.New("Error: No recipient specified. Please set the Email.To field.")
  72. }
  73. if e.Password == "" {
  74. return errors.New("Error: No password specified. Please set the Email.Password field.")
  75. }
  76.  
  77. auth := smtp.PlainAuth(
  78. "",
  79. e.From,
  80. e.Password,
  81. "smtp.gmail.com",
  82. )
  83.  
  84. conn, err := smtp.Dial("smtp.gmail.com:587")
  85. if err != nil {
  86. return err
  87. }
  88.  
  89. err = conn.StartTLS(&tls.Config{ServerName: "smtp.gmail.com"})
  90. if err != nil {
  91. return err
  92. }
  93.  
  94. err = conn.Auth(auth)
  95. if err != nil {
  96. return err
  97. }
  98.  
  99. err = conn.Mail(e.From)
  100. if err != nil {
  101. if strings.Contains(err.Error(), "530 5.5.1") {
  102. return errors.New("Error: Authentication failure. Your username or password is incorrect.")
  103. }
  104. return err
  105. }
  106.  
  107. for _, recipient := range e.To {
  108. err = conn.Rcpt(recipient)
  109. if err != nil {
  110. return err
  111. }
  112. }
  113.  
  114. wc, err := conn.Data()
  115. if err != nil {
  116. return err
  117. }
  118. defer wc.Close()
  119. _, err = wc.Write(e.Bytes())
  120. if err != nil {
  121. return err
  122. }
  123.  
  124. return nil
  125. }
  126.  
  127. func (e *Email) Bytes() []byte {
  128. buf := bytes.NewBuffer(nil)
  129.  
  130. buf.WriteString("Subject: " + e.Subject + "\n")
  131. buf.WriteString("MIME-Version: 1.0\n")
  132.  
  133. if e.Name != "" {
  134. buf.WriteString(fmt.Sprintf("From: %s <%s>\n", e.Name, e.From))
  135. }
  136.  
  137. // Boundary is used by MIME to separate files.
  138. boundary := "f46d043c813270fc6b04c2d223da"
  139.  
  140. if len(e.Attachments) > 0 {
  141. buf.WriteString("Content-Type: multipart/mixed; boundary=" + boundary + "\n")
  142. buf.WriteString("--" + boundary + "\n")
  143. }
  144.  
  145. if e.ContentType == "" {
  146. e.ContentType = "text/plain; charset=utf-8"
  147. }
  148. buf.WriteString(fmt.Sprintf("Content-Type: %s\n", e.ContentType))
  149. buf.WriteString(e.Body)
  150.  
  151. if len(e.Attachments) > 0 {
  152. for k, v := range e.Attachments {
  153. buf.WriteString("\n\n--" + boundary + "\n")
  154. buf.WriteString("Content-Type: application/octet-stream\n")
  155. buf.WriteString("Content-Transfer-Encoding: base64\n")
  156. buf.WriteString("Content-Disposition: attachment; filename=\"" + k + "\"\n\n")
  157.  
  158. b := make([]byte, base64.StdEncoding.EncodedLen(len(v)))
  159. base64.StdEncoding.Encode(b, v)
  160. buf.Write(b)
  161. buf.WriteString("\n--" + boundary)
  162. }
  163.  
  164. buf.WriteString("--")
  165. }
  166.  
  167. return buf.Bytes()
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement