Repository: gogs/gogs
File: internal/email/message.go (Go)

Code before:
func (m *message) WriteTo(w io.Writer) (int64, error) {
	cw := &countingWriter{w: w}

	for _, field := range []string{"From", "To", "Subject", "Date"} {
		vals := m.header[field]
		if len(vals) == 0 {
			continue
		}

		var encoded string
		if field == "Subject" {
			encoded = mime.QEncoding.Encode("utf-8", vals[0])
		} else {
			encoded = sanitizeHeaderValue(strings.Join(vals, ", "))
		}
		if _, err := fmt.Fprintf(cw, "%s: %s\r\n", field, foldHeaderValue(len(field)+2, encoded)); err != nil {
			return cw.n, errors.Wrap(err, "write header")
		}
	}

	if len(m.altParts) > 0 {
		mw := multipart.NewWriter(cw)
		if _, err := fmt.Fprintf(cw, "MIME-Version: 1.0\r\n"); err != nil {
			return cw.n, errors.Wrap(err, "write MIME version")
		}
		if _, err := fmt.Fprintf(cw, "Content-Type: multipart/alternative; boundary=%s\r\n\r\n", mw.Boundary()); err != nil {
			return cw.n, errors.Wrap(err, "write content type")
		}

		mainHeader := textproto.MIMEHeader{}
		mainHeader.Set("Content-Type", m.contentType+"; charset=UTF-8")
		mainHeader.Set("Content-Transfer-Encoding", "quoted-printable")
		part, err := mw.CreatePart(mainHeader)
		if err != nil {
			return cw.n, errors.Wrap(err, "create main part")
		}
		if err := qpWrite(part, m.body); err != nil {
			return cw.n, errors.Wrap(err, "write main body")
		}

		for _, alt := range m.altParts {
			altHeader := textproto.MIMEHeader{}
			altHeader.Set("Content-Type", alt.contentType+"; charset=UTF-8")
			altHeader.Set("Content-Transfer-Encoding", "quoted-printable")
			part, err := mw.CreatePart(altHeader)
			if err != nil {
				return cw.n, errors.Wrap(err, "create alternative part")
			}
			if err := qpWrite(part, alt.body); err != nil {
				return cw.n, errors.Wrap(err, "write alternative body")
			}

Review comment (suggestion):
The multipart boundary parameter is emitted unquoted (`boundary=%s`). Per RFC 2046, boundary values often need to be quoted; some mail clients/servers are stricter and may misparse unquoted boundaries. Prefer `boundary="..."` (and ensure any quotes/backslashes are handled) when writing the `Content-Type` header.
```suggestion
		if _, err := fmt.Fprintf(cw, "Content-Type: multipart/alternative; boundary=\"%s\"\r\n\r\n", mw.Boundary()); err != nil {
```

Code after:
	}

	tlsconfig := &tls.Config{
		InsecureSkipVerify: opts.SkipVerify,
		ServerName:         host,
	}
	if opts.UseCertificate {
		cert, err := tls.LoadX509KeyPair(opts.CertFile, opts.KeyFile)
		if err != nil {
			return nil, err
		}
		tlsconfig.Certificates = []tls.Certificate{cert}
	}
	clientOpts = append(clientOpts, gomail.WithTLSConfig(tlsconfig))

	if len(opts.User) > 0 {
		clientOpts = append(clientOpts,
			gomail.WithSMTPAuth(gomail.SMTPAuthAutoDiscover),
			gomail.WithUsername(opts.User),
			gomail.WithPassword(opts.Password),
		)
	}

	return gomail.NewClient(host, clientOpts...)
}

func sendMessage(msg *message) error {
	client, err := newSMTPClient()
	if err != nil {
		return err
	}
	return client.DialAndSend(msg.msg)
}

func processMailQueue() {
	for msg := range mailQueue {
		to := strings.Join(msg.msg.GetToString(), ", ")
		log.Trace("New e-mail sending request %s: %s", to, msg.info)
		if err := sendMessage(msg); err != nil {
			log.Error("Failed to send emails %s: %s - %v", to, msg.info, err)
		} else {
			log.Trace("E-mails sent %s: %s", to, msg.info)
		}
		msg.confirmChan <- struct{}{}
	}
}

var mailQueue chan *message

// NewContext initializes settings for mailer.
func NewContext() {