...
Source file
src/tawesoft.co.uk/go/email/attachment.go
Documentation:
src/tawesoft.co.uk/go/email/attachment.go
1 package email
2
3 import (
4 "bytes"
5 "encoding/base64"
6 "encoding/json"
7 "fmt"
8 "io"
9 "mime"
10 "os"
11 "path"
12 )
13
14
15 type Attachment struct {
16
17 Filename string
18
19
20
21 Mimetype string
22
23
24 Reader func() (io.ReadCloser, error)
25 }
26
27 type jsonAttachment struct {
28 Filename string
29 Mimetype string
30 Content []byte
31 }
32
33
34
35 func (a *Attachment) MarshalJSON() ([]byte, error) {
36 r, err := a.Reader()
37 if err != nil {
38 return nil, fmt.Errorf("attachment open error: %v", err)
39 }
40 defer r.Close()
41
42 w := &bytes.Buffer{}
43 encoder := base64.NewEncoder(base64.StdEncoding, lineBreaker{writer: w})
44 defer encoder.Close()
45
46 _, err = io.Copy(encoder, r)
47 if err != nil {
48 return nil, fmt.Errorf("attachment read error: %v", err)
49 }
50
51 return json.Marshal(jsonAttachment{
52 Filename: a.Filename,
53 Mimetype: a.Mimetype,
54 Content: w.Bytes(),
55 })
56 }
57
58
59
60 func (a *Attachment) UnmarshalJSON(data []byte) error {
61 var j jsonAttachment
62
63 err := json.Unmarshal(data, &j)
64 if err != nil { return err }
65
66 a.Filename = j.Filename
67 a.Mimetype = j.Mimetype
68 a.Reader = func() (io.ReadCloser, error) {
69 r := bytes.NewReader(j.Content)
70 decoder := base64.NewDecoder(base64.StdEncoding, r)
71 return io.NopCloser(decoder), nil
72 }
73
74 return nil
75 }
76
77
78
79 func FileAttachment(src string) *Attachment {
80
81 var mimetype string
82 var base = path.Base(src)
83
84 var reader = func() (io.ReadCloser, error) {
85 return os.Open(src)
86 }
87
88 mimetype = mime.TypeByExtension(path.Ext(src))
89 if mimetype == "" {
90 mimetype = "application/octet-stream"
91 }
92
93 return &Attachment{
94 Filename: base,
95 Mimetype: mimetype,
96 Reader: reader,
97 }
98 }
99
100
101 func (a *Attachment) write(w io.Writer) error {
102 fmt.Fprintf(w, "Content-Disposition: attachment; filename=\"%[1]s\"; filename*=\"%[1]s\"\r\n",
103 optionalQEncode(a.Filename))
104 fmt.Fprintf(w, "Content-Type: %s\r\n", a.Mimetype)
105 fmt.Fprintf(w, "Content-Transfer-Encoding: base64\r\n")
106 fmt.Fprintf(w, "\r\n")
107
108 var reader, err = a.Reader()
109 if err != nil {
110 return fmt.Errorf("attachment open error: %v", err)
111 }
112 defer reader.Close()
113
114 var encoder = base64.NewEncoder(base64.StdEncoding, lineBreaker{writer: w})
115 defer encoder.Close()
116
117 _, err = io.Copy(encoder, reader)
118 if err != nil { return err }
119
120 fmt.Fprintf(w, "\r\n")
121 return nil
122 }
123
View as plain text