Skip to content

Commit

Permalink
Merge pull request #38 from wneessen/37-attachment-length
Browse files Browse the repository at this point in the history
Fixes bug with attachment encoding
  • Loading branch information
wneessen committed Aug 14, 2022
2 parents a3a143d + ffa1b47 commit c6fe75f
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
60 changes: 60 additions & 0 deletions base64_writer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: 2022 Winni Neessen <[email protected]>
//
// SPDX-License-Identifier: MIT

package mail

import "io"

// Base64LineBreaker is a io.WriteCloser that writes Base64 encoded data streams
// with line breaks at a given line length
type Base64LineBreaker struct {
line [MaxBodyLength]byte
used int
out io.Writer
}

var nl = []byte(SingleNewLine)

// Write writes the data stream and inserts a SingleNewLine when the maximum
// line length is reached
func (l *Base64LineBreaker) Write(b []byte) (n int, err error) {
if l.used+len(b) < MaxBodyLength {
copy(l.line[l.used:], b)
l.used += len(b)
return len(b), nil
}

n, err = l.out.Write(l.line[0:l.used])
if err != nil {
return
}
excess := MaxBodyLength - l.used
l.used = 0

n, err = l.out.Write(b[0:excess])
if err != nil {
return
}

n, err = l.out.Write(nl)
if err != nil {
return
}

return l.Write(b[excess:])
}

// Close closes the Base64LineBreaker and writes any access data that is still
// unwritten in memory
func (l *Base64LineBreaker) Close() (err error) {
if l.used > 0 {
_, err = l.out.Write(l.line[0:l.used])
if err != nil {
return
}
_, err = l.out.Write(nl)
}

return
}
9 changes: 8 additions & 1 deletion msgwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import (
// RFC 2047 suggests 76 characters
const MaxHeaderLength = 76

// MaxBodyLength defines the maximum line length for the mail body
// RFC 2047 suggests 76 characters
const MaxBodyLength = 76

// SingleNewLine represents a new line that can be used by the msgWriter to issue a carriage return
const SingleNewLine = "\r\n"

Expand Down Expand Up @@ -277,12 +281,14 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {
w = mw.pw
}
wbuf := bytes.Buffer{}
lb := Base64LineBreaker{}
lb.out = &wbuf

switch e {
case EncodingQP:
ew = quotedprintable.NewWriter(&wbuf)
case EncodingB64:
ew = base64.NewEncoder(base64.StdEncoding, &wbuf)
ew = base64.NewEncoder(base64.StdEncoding, &lb)
case NoEncoding:
_, mw.err = f(&wbuf)
n, mw.err = io.Copy(w, &wbuf)
Expand All @@ -296,6 +302,7 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {

_, mw.err = f(ew)
mw.err = ew.Close()
mw.err = lb.Close()
n, mw.err = io.Copy(w, &wbuf)

// Since the part writer uses the WriteTo() method, we don't need to add the
Expand Down

0 comments on commit c6fe75f

Please sign in to comment.