Passed
Push — master ( 715886...74726c )
by eval
06:41 queued 04:58
created

ses/client_xapi_send_raw_email.go   A

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 116
dl 0
loc 173
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
F ses.XSendRawEmailRequest.ToRequest 0 117 24
A ses.*SES.XSendRawEmail 0 8 2
1
package ses
2
3
import (
4
	"bytes"
5
	"context"
6
	"fmt"
7
	"mime/multipart"
8
	"net/textproto"
9
	"strings"
10
)
11
12
// XSendRawEmail sends raw email.
13
func (svc *SES) XSendRawEmail(ctx context.Context, r XSendRawEmailRequest) error {
14
	req, err := r.ToRequest()
15
	if err != nil {
16
		return err
17
	}
18
19
	_, err = svc.SendRawEmail(ctx, req)
20
	return err
21
}
22
23
// XSendRawEmailRequest has parameters for `XSendRawEmail` function.
24
type XSendRawEmailRequest struct {
25
	From            string
26
	To              []string
27
	ReturnPath      string
28
	Subject         string
29
	TextBody        string
30
	TextCharset     string
31
	HTMLBody        string
32
	HTMLCharset     string
33
	ContentLanguage string
34
	MIMEVersion     string
35
	Attachments     []XAttachment
36
37
	// optional
38
	ConfigurationSetName string
39
	FromARN              string
40
	ReturnPathARN        string
41
	SourceARN            string
42
	Tags                 []MessageTag
43
}
44
45
// ToRequest converts to SendRawEmailRequest.
46
// most header codes are based on,
47
//   - https://gist.github.com/carelvwyk/60100f2421c6284391d08374bc887dca
48
//   - https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-raw.html
49
func (r XSendRawEmailRequest) ToRequest() (SendRawEmailRequest, error) {
50
	req := SendRawEmailRequest{
51
		ConfigurationSetName: r.ConfigurationSetName,
52
		Destinations:         r.To,
53
		FromARN:              r.FromARN,
54
		ReturnPathARN:        r.ReturnPathARN,
55
		Source:               r.From,
56
		SourceARN:            r.SourceARN,
57
		Tags:                 r.Tags,
58
	}
59
60
	buf := new(bytes.Buffer)
61
	writer := multipart.NewWriter(buf)
62
63
	// email header part
64
	h := make(textproto.MIMEHeader)
65
	if r.From != "" {
66
		h.Set("From", r.From)
67
	}
68
	if len(r.To) != 0 {
69
		h.Set("To", strings.Join(r.To, ", "))
70
	}
71
	switch {
72
	case r.ReturnPath != "":
73
		h.Set("Return-Path", r.ReturnPath)
74
	case r.From != "":
75
		h.Set("Return-Path", r.From)
76
	}
77
78
	if r.Subject != "" {
79
		h.Set("Subject", r.Subject)
80
	}
81
82
	if r.ContentLanguage != "" {
83
		h.Set("Content-Language", r.ContentLanguage)
84
	}
85
86
	if r.MIMEVersion != "" {
87
		h.Set("MIME-Version", r.MIMEVersion)
88
	}
89
90
	h.Set("Content-Type", "multipart/mixed; boundary=\""+writer.Boundary()+"\"")
91
	_, err := writer.CreatePart(h)
92
	if err != nil {
93
		return req, err
94
	}
95
96
	// text body part
97
	if r.TextBody != "" {
98
		h := make(textproto.MIMEHeader)
99
		charset := r.TextCharset
100
		if charset == "" {
101
			charset = "utf-8"
102
		}
103
		h.Set("Content-Type", fmt.Sprintf("text/plain; charset=%s", charset))
104
		part, err := writer.CreatePart(h)
105
		if err != nil {
106
			return req, err
107
		}
108
		_, err = part.Write([]byte(r.TextBody))
109
		if err != nil {
110
			return req, err
111
		}
112
	}
113
114
	// html body part
115
	if r.HTMLBody != "" {
116
		h := make(textproto.MIMEHeader)
117
		charset := r.HTMLCharset
118
		if charset == "" {
119
			charset = "utf-8"
120
		}
121
		h.Set("Content-Type", fmt.Sprintf("text/html; charset=%s", charset))
122
		part, err := writer.CreatePart(h)
123
		if err != nil {
124
			return req, err
125
		}
126
		_, err = part.Write([]byte(r.HTMLBody))
127
		if err != nil {
128
			return req, err
129
		}
130
	}
131
132
	// attachment part
133
	for _, v := range r.Attachments {
134
		h := make(textproto.MIMEHeader)
135
		h.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, v.Filename))
136
		mimeType := v.MIMEType
137
		if mimeType == "" {
138
			mimeType = "text/plain"
139
		}
140
		h.Set("Content-Type", fmt.Sprintf(`%s; name="%s"`, mimeType, v.Filename))
141
		h.Set("Content-Description", v.Filename)
142
		if v.ContentTransferEncoding != "" {
143
			h.Set("Content-Transfer-Encoding", v.ContentTransferEncoding)
144
		}
145
		part, err := writer.CreatePart(h)
146
		if err != nil {
147
			return req, err
148
		}
149
		_, err = part.Write(v.Data)
150
		if err != nil {
151
			return req, err
152
		}
153
		err = writer.Close()
154
		if err != nil {
155
			return req, err
156
		}
157
	}
158
159
	s := buf.String()
160
	ss := strings.SplitN(s, "\n", 2)
161
	if len(ss) < 2 {
162
		return req, fmt.Errorf("invalid e-mail content: [%+v]", ss)
163
	}
164
	req.RawMessageData = []byte(ss[1])
165
	return req, nil
166
}
167
168
type XAttachment struct {
0 ignored issues
show
introduced by
exported type XAttachment should have comment or be unexported
Loading history...
169
	Data     []byte
170
	Filename string
171
	MIMEType string
172
	// if 'ContentTransferEncoding' is "base64", then 'Data' must be base64 encoded.
173
	ContentTransferEncoding string
174
}
175