func sendHTMLEmail(email, subject, plainBody, htmlBody string) error { if htmlBody == "" { return sendPlainEmail(email, subject, plainBody) } var buf bytes.Buffer w := multipart.NewWriter(&buf) appendPart(w, func(h textproto.MIMEHeader) { h.Set("Content-Type", "text/plain; charset=utf-8") }, plainBody) appendPart(w, func(h textproto.MIMEHeader) { h.Set("Content-Type", "text/html; charset=utf-8") }, htmlBody) sendemail.SendAsync(&sendemail.Email{ To: []string{email}, Headers: map[string][]string{ "Subject": []string{subject}, "MIME-Version": []string{"1.0"}, "Content-Type": []string{"multipart/alternative; boundary=" + w.Boundary()}, }, Body: string(buf.Bytes()), }) return nil }
func sendPlainEmail(email, subject, plainBody string) error { sendemail.SendAsync(&sendemail.Email{ To: []string{email}, Headers: map[string][]string{ "Subject": []string{subject}, }, Body: plainBody, }) return nil }
func renderError(rw http.ResponseWriter, req *http.Request, reqerr interface{}, stack []byte) { _, filePath, line, _ := runtime.Caller(4) cErrorResponsesIssued.Inc() rw.Header().Set("Content-Type", "text/html; charset=utf-8") rw.Header().Del("Content-Security-Policy") rw.Header().Del("Content-Security-Policy-Report-Only") rw.WriteHeader(http.StatusInternalServerError) type info struct { Error interface{} `yaml:"error"` Stack string `yaml:"stack"` URL string `yaml:"url"` Method string `yaml:"method"` Proto string `yaml:"proto"` Header http.Header `yaml:"header"` ContentLength int64 `yaml:"content-length"` RawRemoteAddr string `yaml:"raw-remote-addr"` Host string `yaml:"host"` FilePath string `yaml:"file-path"` FileLine int `yaml:"file-line"` Time string `yaml:"time"` PostForm url.Values `yaml:"post-form"` } errInfo := info{ Error: reqerr, Stack: strings.Replace(string(stack), "\t", " ", -1), URL: req.URL.String(), Method: req.Method, Proto: req.Proto, Header: req.Header, ContentLength: req.ContentLength, RawRemoteAddr: req.RemoteAddr, Host: req.Host, FilePath: filePath, FileLine: line, Time: time.Now().String(), } if req.ContentLength >= 0 && req.ContentLength <= 4*1024 { // 4k size limit errInfo.PostForm = req.PostForm } b, err := yaml.Marshal(&errInfo) log.Infoe(err, "marshalling emergency error information") // ... shouldEncrypt, shouldEmail := errorMode(req) var encryptedError string if shouldEncrypt { encryptedError = encryptErrorBase64(b) } data := map[string]interface{}{ "EncryptedBlob": encryptedError, "Info": string(b), "Encrypted": shouldEncrypt, "WebmasterAddress": webmasterAddressFlag.Value(), "Notified": shouldEmail, } emergencyErrorTemplate.Execute(rw, data) // send e. mail if shouldEmail { emailBuf := new(bytes.Buffer) emergencyErrorEmailTemplate.Execute(emailBuf, data) subjectLine := fmt.Sprintf("%s panic", exepath.ProgramName) sendemail.SendAsync(&sendemail.Email{ To: []string{panicsToFlag.Value()}, Headers: map[string][]string{ "Subject": []string{subjectLine}, }, Body: string(emailBuf.Bytes()), }) } }