-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
263 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
indent_size = 2 | ||
charset = utf-8 | ||
max_line_length = 100 | ||
trim_trailing_whitespace = true | ||
insert_final_newline = true | ||
|
||
[{Dockerfile,*.yml,*.yaml,*.json}] | ||
indent_style = tab | ||
indent_size = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"semi": false, | ||
"singleQuote": true, | ||
"trailingComma": "all", | ||
"printWidth": 100 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
# go-email-sender | ||
Simple (but useful) email sender for Go. Support HTML templates and attachments. | ||
# 📮 Go Email Sender | ||
|
||
Simple (but useful) email sender written with pure Go `v1.17`. Support HTML templates and attachments. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/koddr/go-email-sender | ||
|
||
go 1.17 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package sender | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestParseTemplate(t *testing.T) { | ||
// Create folder and file for running tests. | ||
_ = os.Mkdir("tmp", 0700) | ||
file, err := os.OpenFile("tmp/test.html", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0700) | ||
if err != nil { | ||
t.Errorf("Sender.parseTemplate() error = %v", err) | ||
return | ||
} | ||
_, err = file.Write([]byte("<h1>Hello, World!</h1>")) | ||
if err != nil { | ||
t.Errorf("Sender.parseTemplate() error = %v", err) | ||
return | ||
} | ||
defer file.Close() | ||
|
||
// Test cases. | ||
type args struct { | ||
file string | ||
data interface{} | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want string | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "successfully parsing the template file", | ||
args: args{ | ||
file: "tmp/test.html", | ||
data: nil, | ||
}, | ||
want: "<h1>Hello, World!</h1>", | ||
wantErr: false, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := ParseTemplate(tt.args.file, tt.args.data) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("Sender.parseTemplate() error = %v, wantErr %v", err, tt.wantErr) | ||
return | ||
} | ||
if got != tt.want { | ||
t.Errorf("Sender.parseTemplate() = %v, want %v", got, tt.want) | ||
} | ||
os.RemoveAll("tmp") // remove temp folder | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package sender | ||
|
||
import ( | ||
"bytes" | ||
"html/template" | ||
) | ||
|
||
// ParseTemplate ... | ||
func ParseTemplate(file string, data interface{}) (string, error) { | ||
tmpl, errParseFiles := template.ParseFiles(file) | ||
if errParseFiles != nil { | ||
return "", errParseFiles | ||
} | ||
buffer := new(bytes.Buffer) | ||
if errExecute := tmpl.Execute(buffer, data); errExecute != nil { | ||
return "", errExecute | ||
} | ||
return buffer.String(), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package sender | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"mime/quotedprintable" | ||
"net/smtp" | ||
"strings" | ||
) | ||
|
||
// Sender struct for describe auth data for sending emails. | ||
type Sender struct { | ||
Login string | ||
Password string | ||
SMTPServer string | ||
SMTPServerPort int | ||
} | ||
|
||
// NewEmailSender func for create new email sender. | ||
// Includes login, password, SMTP server and port. | ||
func NewEmailSender(login, password, server string, port int) *Sender { | ||
return &Sender{login, password, server, port} | ||
} | ||
|
||
// SendHTMLEmail func for send email with given HTML template and data. | ||
// If template is empty string, it will send with default template. | ||
func (s *Sender) SendHTMLEmail(template string, dest []string, subject string, data interface{}) error { | ||
if template == "" { | ||
template = "templates/default.html" | ||
} | ||
tmpl, errParseTemplate := ParseTemplate(template, data) | ||
if errParseTemplate != nil { | ||
return errParseTemplate | ||
} | ||
body := s.writeEmail(dest, "text/html", subject, tmpl) | ||
s.sendEmail(dest, subject, body) | ||
return nil | ||
} | ||
|
||
// SendPlainEmail func for send plain text email with data. | ||
func (s *Sender) SendPlainEmail(dest []string, subject, data string) error { | ||
body := s.writeEmail(dest, "text/plain", subject, data) | ||
s.sendEmail(dest, subject, body) | ||
return nil | ||
} | ||
|
||
// writeEmail method for prepare email header and body to send. | ||
func (s *Sender) writeEmail(dest []string, contentType, subject, body string) string { | ||
// Define variables. | ||
var message string | ||
var header map[string]string | ||
var encodedMessage bytes.Buffer | ||
|
||
// Create header. | ||
header["From"] = s.Login | ||
header["To"] = strings.Join(dest, ",") | ||
header["Subject"] = subject | ||
header["MIME-Version"] = "1.0" | ||
header["Content-Type"] = fmt.Sprintf("%s; charset=\"utf-8\"", contentType) | ||
header["Content-Transfer-Encoding"] = "quoted-printable" | ||
header["Content-Disposition"] = "inline" | ||
|
||
// Add header values to the message. | ||
for key, value := range header { | ||
message += fmt.Sprintf("%s:%s\r\n", key, value) | ||
} | ||
|
||
// Create writer for make encoding the message. | ||
result := quotedprintable.NewWriter(&encodedMessage) | ||
result.Write([]byte(body)) | ||
result.Close() | ||
|
||
// Return the encoded message string. | ||
message += "\r\n" + encodedMessage.String() | ||
return message | ||
} | ||
|
||
// sendEmail method for send email to destination addresses with subject and body. | ||
func (s *Sender) sendEmail(dest []string, subject, body string) error { | ||
if err := smtp.SendMail( | ||
fmt.Sprintf("%s:%d", s.SMTPServer, s.SMTPServerPort), | ||
smtp.PlainAuth("", s.Login, s.Password, s.SMTPServer), | ||
s.Login, dest, []byte(body), | ||
); err != nil { | ||
return err | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html xmlns="http://www.w3.org/1999/xhtml"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||
<title>✨ The default email from example.com</title> | ||
<style type="text/css"> | ||
body { | ||
margin: 0 auto; | ||
padding: 0; | ||
min-width: 100%; | ||
color: #333333; | ||
font-family: sans-serif; | ||
} | ||
table { | ||
margin: 50px 0 50px 0; | ||
} | ||
code { | ||
color: #003253; | ||
font-family: monospace; | ||
} | ||
.header { | ||
height: 40px; | ||
text-align: center; | ||
text-transform: uppercase; | ||
font-size: 24px; | ||
font-weight: bold; | ||
} | ||
.content { | ||
height: 100px; | ||
font-size: 18px; | ||
line-height: 30px; | ||
} | ||
.footer { | ||
text-align: center; | ||
height: 40px; | ||
font-size: 14px; | ||
} | ||
.footer a { | ||
color: #777777; | ||
text-decoration: none; | ||
font-style: normal; | ||
} | ||
</style> | ||
</head> | ||
<body bgcolor="#FAFAFA"> | ||
<table bgcolor="#FFFFFF" width="100%" border="0" cellspacing="0" cellpadding="0"> | ||
<tr class="header"> | ||
<td style="padding: 40px">✨ The default email</td> | ||
</tr> | ||
<tr class="content"> | ||
<td style="padding: 10px"> | ||
<p> | ||
<strong>Hi,</strong><br /> | ||
This is the default email from | ||
<a href="https://github.com/koddr/go-email-sender" target="_blank" rel="noreferrer" | ||
>koddr/go-email-sender</a | ||
> | ||
</p> | ||
<p>Please specify your HTML template in the <code>SendHTMLEmail</code> method.</p> | ||
</td> | ||
</tr> | ||
<tr class="footer"> | ||
<td style="padding: 40px"> | ||
👨💻 <a href="https://github.com/koddr" target="_blank" rel="noreferrer">@koddr</a> | ||
</td> | ||
</tr> | ||
</table> | ||
</body> | ||
</html> |