ses/client_xapi_send_raw_email.go   A
last analyzed

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Importance

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