Skip to content

Commit

Permalink
initial commit. mandrill, mailgun, sendgrid, file and log providers. …
Browse files Browse the repository at this point in the history
…some tests
  • Loading branch information
Maya Sergeeva committed Jun 15, 2022
1 parent 06e0d50 commit 19e4750
Show file tree
Hide file tree
Showing 28 changed files with 2,148 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
.idea
vendor
.golangci*.yml
linter.mk
bin
c.out
tests.mk
29 changes: 29 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ----
## LINTER stuff start

linter_include_check:
@[ -f linter.mk ] && echo "linter.mk include exists" || (echo "getting linter.mk from github.com" && curl -sO https://raw.githubusercontent.com/spacetab-io/makefiles/master/golang/linter.mk)

.PHONY: lint
lint: linter_include_check
@make -f linter.mk go_lint

## LINTER stuff end
# ----

# ----
## TESTS stuff start

tests_include_check:
@[ -f tests.mk ] && echo "tests.mk include exists" || (echo "getting tests.mk from github.com" && curl -sO https://raw.githubusercontent.com/spacetab-io/makefiles/master/golang/tests.mk)

tests: tests_include_check
@make -f tests.mk go_tests
.PHONY: tests

tests_html: tests_include_check
@make -f tests.mk go_tests_html
.PHONY: tests_html

## TESTS stuff end
# ----
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# mails-go

Golang library for email sending.

## Providers

List of available providers:

* [Sendgrid](github.com/sendgrid/sendgrid-go)
* [Mandrill](github.com/mattbaird/gochimp)
* [Mailgun](github.com/mailgun/mailgun-go/v4)
* [SMTP](github.com/xhit/go-simple-mail/v2)
* log
* file

## Usage

```go
package main

import (
"context"
"time"

"github.com/spacetab-io/configuration-structs-go/v2/configuration/mimetype"
"github.com/spacetab-io/configuration-structs-go/v2/mailing"
"github.com/spacetab-io/mails-go/contracts"
"github.com/spacetab-io/mails-go/providers"
)

func main() {
// 1. Get Provider config (with should implement mailing.MailProviderConfigInterface
// For Example, Sendgrid Config
sendgridCfg := mailing.SendgridConfig{
Enabled: true,
Key: "APIKey",
SendTimeout: 5 * time.Second,
}

// 2. Initiate provider
// Sendgrid provider
sendgrid, err := providers.NewSendgrid(sendgridCfg)
if err != nil {
panic(err)
}

// 3. Prepare Message with should implement contracts.MessageInterface
msg := contracts.Message{
To: mailing.MailAddressList{
{Email: "toOne@spacetab.io", Name: "To One"},
{Email: "totwo@spacetab.io", Name: "To Two"},
},
MimeType: mime.TextPlain,
Subject: "Test email",
Content: []byte("test email content"),
}

// 4. Send message
if err := sendgrid.Send(context.Background(), msg); err != nil {
panic(err)
}
}
```
77 changes: 77 additions & 0 deletions contracts/attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package contracts

import (
"os"
"path/filepath"
"strings"

mime "github.com/gabriel-vasile/mimetype"
"github.com/spacetab-io/mails-go/errors"
)

type AttachMethod string

const (
AttachMethodInline AttachMethod = "inline"
AttachMethodFile AttachMethod = "file"
)

type Attachment struct {
MimeType string
AttachMethod AttachMethod
Filename string
Name string
Extension string
Content []byte
}

func NewAttachmentFromFile(filePath string) (a Attachment, err error) {
fi, err := os.Stat(filePath)
if err != nil {
return
}

if fi.IsDir() {
return a, errors.ErrAttachmentIsNotAFile
}

a.Content, err = os.ReadFile(filePath)
if err != nil {
return
}

fileName := fi.Name()
m, _ := mime.DetectFile(filePath)

a.MimeType = m.String()
a.Extension = strings.Trim(filepath.Ext(filePath), ".")
a.Name = fileName[:len(fileName)-len(filepath.Ext(fileName))]
a.Filename = fi.Name()
a.AttachMethod = AttachMethodFile

return a, nil
}

func (a Attachment) IsEmpty() bool {
return len(a.Content) == 0
}

func (a Attachment) GetFileName() string {
return a.Filename
}

func (a Attachment) GetMimeType() string {
return a.MimeType
}

func (a Attachment) GetContent() []byte {
return a.Content
}

func (a Attachment) GetName() string {
return a.Name
}

func (a Attachment) GetAttachMethod() AttachMethod {
return a.AttachMethod
}
16 changes: 16 additions & 0 deletions contracts/attachmentInterface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package contracts

type MessageAttachmentListInterface interface {
GetList() []MessageAttachmentInterface
IsEmpty() bool
GetFileNames() []string
}

type MessageAttachmentInterface interface {
IsEmpty() bool
GetFileName() string
GetName() string
GetMimeType() string
GetContent() []byte
GetAttachMethod() AttachMethod
}
31 changes: 31 additions & 0 deletions contracts/attachmentList.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package contracts

type MessageAttachmentList []Attachment

func (mal MessageAttachmentList) GetFileNames() []string {
if mal.IsEmpty() {
return nil
}

fileNames := make([]string, 0, len(mal.GetList()))

for _, file := range mal.GetList() {
fileNames = append(fileNames, file.GetFileName())
}

return fileNames
}

func (mal MessageAttachmentList) GetList() []MessageAttachmentInterface {
mm := make([]MessageAttachmentInterface, 0, len(mal))

for _, ma := range mal {
mm = append(mm, ma)
}

return mm
}

func (mal MessageAttachmentList) IsEmpty() bool {
return len(mal) == 0
}
146 changes: 146 additions & 0 deletions contracts/attachment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package contracts_test

import (
"os"
"testing"

"github.com/spacetab-io/mails-go/contracts"
"github.com/spacetab-io/mails-go/errors"
"github.com/stretchr/testify/assert"
)

var testAtt = contracts.Attachment{
MimeType: "text/plain; charset=utf-8",
AttachMethod: contracts.AttachMethodFile,
Filename: "test.file",
Name: "test",
Extension: "file",
Content: []byte("some content"),
}

func TestNewAttachmentFromFile(t *testing.T) {
type testCase struct {
name string
in string
exp contracts.Attachment
err error
}

tcs := []testCase{
{
name: "normal attachment",
in: "./test.file",
exp: contracts.Attachment{
MimeType: "text/plain; charset=utf-8",
AttachMethod: contracts.AttachMethodFile,
Name: "test",
Filename: "test.file",
Extension: "file",
Content: []byte("some content"),
},
err: nil,
},
{
name: "not existing file attachment",
in: "./not_existing_test.file",
exp: contracts.Attachment{},
err: os.ErrNotExist,
},
{
name: "attachment is a dir",
in: "../contracts",
exp: contracts.Attachment{},
err: errors.ErrAttachmentIsNotAFile,
},
//{
// name: "not available to read file",
// in: "./test_no_access.file",
// exp: contracts.Attachment{},
// err: os.ErrPermission,
// },
}

t.Parallel()

for _, tc := range tcs {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

att, err := contracts.NewAttachmentFromFile(tc.in)
if tc.err != nil {
if !assert.ErrorIs(t, err, tc.err) {
t.FailNow()
}
} else {
if !assert.NoError(t, err) {
t.FailNow()
}
}

assert.Equal(t, tc.exp, att)
})
}
}

func TestAttachment_IsEmpty(t *testing.T) {
type testCase struct {
name string
in contracts.Attachment
exp bool
}

tcs := []testCase{
{
name: "empty attachment",
in: contracts.Attachment{},
exp: true,
},
{
name: "filled attachment",
in: testAtt,
exp: false,
},
}

t.Parallel()

for _, tc := range tcs {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

assert.Equal(t, tc.exp, tc.in.IsEmpty())
})
}
}

func TestAttachment_GetFileName(t *testing.T) {
t.Parallel()

assert.Equal(t, "test.file", testAtt.GetFileName())
}

func TestAttachment_GetMimeType(t *testing.T) {
t.Parallel()

assert.Equal(t, "text/plain; charset=utf-8", testAtt.GetMimeType())
}

func TestAttachment_GetName(t *testing.T) {
t.Parallel()

assert.Equal(t, "test", testAtt.GetName())
}

func TestAttachment_GetAttachMethod(t *testing.T) {
t.Parallel()

assert.Equal(t, contracts.AttachMethodFile, testAtt.GetAttachMethod())
}

func TestAttachment_GetContent(t *testing.T) {
t.Parallel()

assert.Equal(t, []byte("some content"), testAtt.GetContent())
}
6 changes: 6 additions & 0 deletions contracts/loggerInterface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package contracts

type LoggerInterface interface {
Print(log string)
Printf(format string, args ...interface{})
}
Loading

0 comments on commit 19e4750

Please sign in to comment.