func (m *Message) writeMultipartStart(b *bytes.Buffer, writer *multipart.Writer) error { multipart := ` Content-Type: multipart/alternative; charset="UTF-8"; boundary="%s" ` _, err := b.WriteString(fmt.Sprintf(multipart, writer.Boundary())) return err }
func SendMediaRequest(client *twittergo.Client, reqUrl string, params map[string]string, media []byte) (mediaResp twittergo.MediaResponse, err error) { var ( req *http.Request resp *twittergo.APIResponse body io.ReadWriter = bytes.NewBufferString("") mp *multipart.Writer writer io.Writer contentType string ) mp = multipart.NewWriter(body) for key, value := range params { mp.WriteField(key, value) } if media != nil { if writer, err = mp.CreateFormField("media"); err != nil { return } writer.Write(media) } contentType = fmt.Sprintf("multipart/form-data;boundary=%v", mp.Boundary()) mp.Close() if req, err = http.NewRequest("POST", reqUrl, body); err != nil { return } req.Header.Set("Content-Type", contentType) if resp, err = client.SendRequest(req); err != nil { return } err = resp.Parse(&mediaResp) return }
func (m *Message) writeMultipartEnd(b *bytes.Buffer, writer *multipart.Writer) error { multipart := ` --%s-- ` _, err := b.WriteString(fmt.Sprintf(multipart, writer.Boundary())) return err }
func (m *Message) writeContentTypeWithBoundary(b *bytes.Buffer, writer *multipart.Writer, contentType string) error { contentTypeFormat := ` --%s Content-Type: %s; charset=UTF-8; Content-Transfer-Encoding: 8bit ` _, err := b.WriteString(fmt.Sprintf(contentTypeFormat, writer.Boundary(), contentType)) return err }
func GetBody() (body io.ReadWriter, header string, err error) { var ( mp *multipart.Writer media []byte writer io.Writer ) body = bytes.NewBufferString("") mp = multipart.NewWriter(body) media, err = ioutil.ReadFile("tweet_media/media.png") if err != nil { return } mp.WriteField("status", fmt.Sprintf("Hello %v!", time.Now())) writer, err = mp.CreateFormFile("media[]", "media.png") if err != nil { return } writer.Write(media) header = fmt.Sprintf("multipart/form-data;boundary=%v", mp.Boundary()) mp.Close() return }
// Bytes gets the encoded MIME message. func (m *Message) Bytes() ([]byte, error) { var buffer = &bytes.Buffer{} header := textproto.MIMEHeader{} var err error // Require To, Cc, or Bcc // We'll parse the slices into a list of addresses // and then make sure that list isn't empty. toAddrs := getAddressListString(m.To) ccAddrs := getAddressListString(m.Cc) bccAddrs := getAddressListString(m.Bcc) var hasTo = toAddrs != "" var hasCc = ccAddrs != "" var hasBcc = bccAddrs != "" if !hasTo && !hasCc && !hasBcc { return nil, ErrMissingRecipient } if hasTo { header.Add("To", toAddrs) } if hasCc { header.Add("Cc", ccAddrs) } // BCC header is excluded on purpose. // BCC recipients aren't included in the message // headers and are only used at the SMTP level. var emptyAddress mail.Address // Require From address if m.From == emptyAddress { return nil, ErrMissingFromAddress } header.Add("From", m.From.String()) // Optional ReplyTo if m.ReplyTo != emptyAddress { header.Add("Reply-To", m.ReplyTo.String()) } // Optional Subject if m.Subject != "" { quotedSubject := qEncodeAndWrap(m.Subject, 9 /* len("Subject: ") */) if quotedSubject[0] == '"' { // qEncode used simple quoting, which adds quote // characters to email subjects. quotedSubject = quotedSubject[1 : len(quotedSubject)-1] } header.Add("Subject", quotedSubject) } // Date if _, ok := m.Headers["Date"]; !ok { header.Add("Date", time.Now().UTC().Format(time.RFC822)) } for k, v := range m.Headers { header[k] = v } header.Add("MIME-Version", "1.0") var mixedw *multipart.Writer var hasAttachments = m.Attachments != nil && len(m.Attachments) > 0 if hasAttachments { // Top level multipart writer for our `multipart/mixed` body. // only needed if we have attachments mixedw = multipart.NewWriter(buffer) header.Add("Content-Type", fmt.Sprintf("multipart/mixed;%s boundary=%s", crlf, mixedw.Boundary())) err = writeHeader(buffer, header) if err != nil { return nil, err } header = textproto.MIMEHeader{} // Write the start of our `multipart/mixed` body. _, err = fmt.Fprintf(buffer, "--%s%s", mixedw.Boundary(), crlf) if err != nil { return nil, err } } var altw *multipart.Writer if m.Body != "" && m.HTMLBody != "" { // Nested multipart writer for our `multipart/alternative` body. altw = multipart.NewWriter(buffer) header.Add("Content-Type", fmt.Sprintf("multipart/alternative;%s boundary=%s", crlf, altw.Boundary())) err := writeHeader(buffer, header) if err != nil { return nil, err } } // Only include an empty plain text body if the html body is also empty. if m.Body != "" || m.Body == "" && m.HTMLBody == "" { if altw != nil { header = textproto.MIMEHeader{} } header.Add("Content-Type", "text/plain; charset=utf-8") header.Add("Content-Transfer-Encoding", "quoted-printable") //header.Add("Content-Transfer-Encoding", "base64") var writer io.Writer if altw != nil { partw, err := altw.CreatePart(header) if err != nil { return nil, err } writer = partw } else { writer = buffer err = writeHeader(buffer, header) if err != nil { return nil, err } } bodyBytes := []byte(m.Body) //encoder := NewBase64MimeEncoder(writer) encoder := qprintable.NewEncoder(qprintable.DetectEncoding(m.Body), writer) _, err = encoder.Write(bodyBytes) if err != nil { return nil, err } err = encoder.Close() if err != nil { return nil, err } } if m.HTMLBody != "" { if altw != nil { header = textproto.MIMEHeader{} } header.Add("Content-Type", "text/html; charset=utf-8") //header.Add("Content-Transfer-Encoding", "quoted-printable") header.Add("Content-Transfer-Encoding", "base64") var writer io.Writer if altw != nil { partw, err := altw.CreatePart(header) if err != nil { return nil, err } writer = partw } else { writer = buffer err = writeHeader(buffer, header) if err != nil { return nil, err } } htmlBodyBytes := []byte(m.HTMLBody) encoder := NewBase64MimeEncoder(writer) //encoder := qprintable.NewEncoder(qprintable.DetectEncoding(m.HTMLBody), writer) _, err = encoder.Write(htmlBodyBytes) if err != nil { return nil, err } err = encoder.Close() if err != nil { return nil, err } } if altw != nil { altw.Close() } else { _, err = fmt.Fprintf(buffer, "%s", crlf) if err != nil { return nil, err } } if hasAttachments { for _, attachment := range m.Attachments { contentType := attachment.ContentType if contentType == "" { contentType = mime.TypeByExtension(filepath.Ext(attachment.Name)) if contentType == "" { contentType = "application/octet-stream" } } header := textproto.MIMEHeader{} header.Add("Content-Type", contentType) header.Add("Content-Disposition", fmt.Sprintf(`attachment;%s filename="%s"`, crlf, attachment.Name)) header.Add("Content-Transfer-Encoding", "base64") attachmentPart, err := mixedw.CreatePart(header) if err != nil { return nil, err } if attachment.Data != nil { encoder := NewBase64MimeEncoder(attachmentPart) _, err = io.Copy(encoder, attachment.Data) if err != nil { return nil, err } err = encoder.Close() if err != nil { return nil, err } } } mixedw.Close() } return buffer.Bytes(), nil }