1 package main 2 3 import ( 4 "crypto/tls" 5 "io" 6 "net" 7 "net/http" 8 "net/smtp" 9 "net/url" 10 "strings" 11 "text/template" 12 ) 13 14 var ( 15 compiledEmailTemplate *template.Template 16 emailServer string 17 emailTLS bool 18 emailFrom string 19 emailAuth smtp.Auth 20 ) 21 22 func setEmailVars(server, username, password, templateT string) error { 23 // smtp://host:port or smtps://host:port for TLS 24 u, err := url.Parse(server) 25 if err != nil { 26 return err 27 } 28 t, err := template.New("email").Parse(templateT) 29 if err != nil { 30 return err 31 } 32 compiledEmailTemplate = t 33 emailServer = u.Hostname() 34 emailTLS = u.Scheme == "smtps" 35 if p := u.Port(); p == "" { 36 if emailTLS { 37 emailServer = u.Hostname() + ":465" 38 } else { 39 emailServer = u.Hostname() + ":25" 40 } 41 } else { 42 emailServer = u.Hostname() + ":" + p 43 } 44 emailAuth = smtp.PlainAuth("", username, password, emailServer) 45 emailFrom = username 46 return nil 47 } 48 49 func (c *Calls) PrepareEmail(eventID int64, md *MessageData) error { 50 return c.prepareMessage(compiledEmailTemplate, eventID, md) 51 } 52 53 func (c *Calls) SendEmail(md MessageData, e *string) error { 54 message := md.Message 55 headers := make([]byte, 0, len(message)+3) 56 for { 57 i := strings.Index(message, "\n") 58 if i < 0 { 59 break 60 } 61 line := message[:i] 62 message = message[i+1:] 63 line = strings.TrimRight(line, "\r") 64 if line == "" { 65 headers = append(headers, "\r\n"...) 66 break 67 } 68 i = strings.Index(line, ":") 69 canHeader := http.CanonicalHeaderKey(line[:i]) 70 if i > 0 && len(line) > i+1 && (canHeader == "Subject" || canHeader == "Mime-Version" || canHeader == "Content-Type") { 71 headers = append(headers, canHeader...) 72 headers = append(headers, ": "...) 73 headers = append(headers, strings.TrimSpace(line[i+1:])...) 74 headers = append(headers, "\r\n"...) 75 } else { 76 message = line + "\n" + message 77 break 78 } 79 } 80 81 headers = append(headers, "\r\n"...) 82 83 var ( 84 event Event 85 client Client 86 ) 87 err := c.GetEvent(md.ID, &event) 88 if err != nil { 89 return err 90 } 91 err = c.GetClient(event.ClientID, &client) 92 if err != nil { 93 return err 94 } 95 var conn net.Conn 96 if emailTLS { 97 conn, err = tls.Dial("tcp", emailServer, nil) 98 } else { 99 conn, err = net.Dial("tcp", emailServer) 100 } 101 if err != nil { 102 return err 103 } 104 cl, err := smtp.NewClient(conn, emailServer) 105 if err == nil { 106 err = cl.Auth(emailAuth) 107 if err == nil { 108 err = cl.Mail(emailFrom) 109 if err == nil { 110 err = cl.Rcpt(client.Email) 111 if err == nil { 112 var wr io.WriteCloser 113 wr, err = cl.Data() 114 if err == nil { 115 _, err = wr.Write(append(headers, message...)) 116 if err == nil { 117 err = wr.Close() 118 if err == nil { 119 err = cl.Quit() 120 } 121 } 122 } 123 } 124 } 125 } 126 } 127 if err != nil { 128 *e = err.Error() 129 } else { 130 _, err = c.statements[MessageSent].Exec(md.ID) 131 if err != nil { 132 return err 133 } 134 } 135 return nil 136 } 137