mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 22:00:49 +01:00
Merge pull request #38 from wneessen/37-attachment-length
Fixes bug with attachment encoding
This commit is contained in:
commit
c6fe75f2d3
2 changed files with 68 additions and 1 deletions
60
base64_writer.go
Normal file
60
base64_writer.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Winni Neessen <winni@neessen.dev>
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -22,6 +22,10 @@ import (
|
||||||
// RFC 2047 suggests 76 characters
|
// RFC 2047 suggests 76 characters
|
||||||
const MaxHeaderLength = 76
|
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
|
// SingleNewLine represents a new line that can be used by the msgWriter to issue a carriage return
|
||||||
const SingleNewLine = "\r\n"
|
const SingleNewLine = "\r\n"
|
||||||
|
|
||||||
|
@ -277,12 +281,14 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {
|
||||||
w = mw.pw
|
w = mw.pw
|
||||||
}
|
}
|
||||||
wbuf := bytes.Buffer{}
|
wbuf := bytes.Buffer{}
|
||||||
|
lb := Base64LineBreaker{}
|
||||||
|
lb.out = &wbuf
|
||||||
|
|
||||||
switch e {
|
switch e {
|
||||||
case EncodingQP:
|
case EncodingQP:
|
||||||
ew = quotedprintable.NewWriter(&wbuf)
|
ew = quotedprintable.NewWriter(&wbuf)
|
||||||
case EncodingB64:
|
case EncodingB64:
|
||||||
ew = base64.NewEncoder(base64.StdEncoding, &wbuf)
|
ew = base64.NewEncoder(base64.StdEncoding, &lb)
|
||||||
case NoEncoding:
|
case NoEncoding:
|
||||||
_, mw.err = f(&wbuf)
|
_, mw.err = f(&wbuf)
|
||||||
n, mw.err = io.Copy(w, &wbuf)
|
n, mw.err = io.Copy(w, &wbuf)
|
||||||
|
@ -296,6 +302,7 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {
|
||||||
|
|
||||||
_, mw.err = f(ew)
|
_, mw.err = f(ew)
|
||||||
mw.err = ew.Close()
|
mw.err = ew.Close()
|
||||||
|
mw.err = lb.Close()
|
||||||
n, mw.err = io.Copy(w, &wbuf)
|
n, mw.err = io.Copy(w, &wbuf)
|
||||||
|
|
||||||
// Since the part writer uses the WriteTo() method, we don't need to add the
|
// Since the part writer uses the WriteTo() method, we don't need to add the
|
||||||
|
|
Loading…
Reference in a new issue