Skip to content

Commit

Permalink
enhancement: Add ability to attach files to email (#6)
Browse files Browse the repository at this point in the history
* add attachment to email code & tests

* clean

* switch test image

Co-authored-by: David May <[email protected]>
  • Loading branch information
kaymckay and wass3r authored Mar 21, 2022
1 parent 27291da commit b1a1505
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 43 deletions.
6 changes: 6 additions & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ The following parameters are used to configure the image:

### Attachment

| Parameter | Description | Required | Default | Environment Variables |
| ------------ | ------------------------------ | -------- | ------- | -------------------------------------------- |
| `attachment` | file will be attached to email | false | N/A | `PARAMETER_ATTACHMENT`<br>`EMAIL_ATTACHMENT` |

### Email Filename

| Parameter | Description | Required | Default | Environment Variables |
| ---------- | --------------------------------------------------------- | -------- | ------- | ---------------------------------------- |
| `filename` | data in attached file will be used to populate the email. | false | N/A | `PARAMETER_FILENAME`<br>`EMAIL_FILENAME` |
Expand Down
23 changes: 16 additions & 7 deletions cmd/vela-email/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ func main() {
Name: "readreceipt",
Usage: "request read receipts and delivery notifications",
},
// Attachment flag
&cli.StringFlag{
EnvVars: []string{"PARAMETER_ATTACHMENT", "EMAIL_ATTACHMENT"},
Name: "attachment",
Usage: "file to attach to email",
},
// SmtpHost flags
&cli.StringFlag{
EnvVars: []string{"PARAMETER_HOST", "EMAIL_HOST"},
Expand All @@ -129,11 +135,11 @@ func main() {
Name: "password",
Usage: "smtp host password",
},
// Attachment flag
// EmailFilename flag
&cli.StringFlag{
EnvVars: []string{"PARAMETER_FILENAME", "EMAIL_FILENAME"},
Name: "filename",
Usage: "file to attach to email",
Usage: "file that contains email information (To, From, Subject, etc.)",
},
// TLSConfig flag
&cli.BoolFlag{
Expand Down Expand Up @@ -229,11 +235,6 @@ func run(c *cli.Context) error {
// auth configuration
Auth: c.String("auth"),

// attachment configuration
Attachment: &email.Attachment{
Filename: c.String("filename"),
},

// email configuration
Email: &email.Email{
ReplyTo: c.StringSlice("replyto"),
Expand All @@ -248,6 +249,14 @@ func run(c *cli.Context) error {
ReadReceipt: c.StringSlice("readreceipt"),
},

// email filename configuration
EmailFilename: c.String("filename"),

// attachment configuration
Attachment: &email.Attachment{
Filename: c.String("attachment"),
},

// smtp configuration
SMTPHost: &SMTPHost{
Host: c.String("host"),
Expand Down
30 changes: 24 additions & 6 deletions cmd/vela-email/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ var (
// ErrorMissingEmailFromParam is returned when the plugin is missing the From email parameter.
ErrorMissingEmailFromParam = errors.New("missing email parameter: From")

// ErrorEmptyAttach is returned when the plugin finds the provided attachment to be empty.
ErrorEmptyAttach = errors.New("attachment provided is empty")
// ErrorEmptyFile is returned when the plugin finds the provided attachment to be empty.
ErrorEmptyFile = errors.New("file provided is empty")

// ErrorMissingSMTPParam is returned when the plugin is missing a smtp host or port parameter.
ErrorMissingSMTPParam = errors.New("missing smtp parameter (host/port)")
Expand All @@ -38,6 +38,8 @@ type (
Plugin struct {
// Email arguments loaded for the plugin
Email *email.Email
// EmailFilename arguments loaded for the plugin
EmailFilename string
// Attachment arguments loaded for the plugin
Attachment *email.Attachment
// SmtpHost arguments loaded for the plugin
Expand Down Expand Up @@ -78,17 +80,17 @@ func (p *Plugin) Validate() error {

logrus.Info("Validating Parameters...")

if len(p.Attachment.Filename) != 0 {
fileInfo, err := os.Stat(p.Attachment.Filename)
if len(p.EmailFilename) != 0 {
fileInfo, err := os.Stat(p.EmailFilename)
if errors.Is(err, os.ErrNotExist) {
return os.ErrNotExist
}

if fileInfo.Size() == 0 {
return ErrorEmptyAttach
return ErrorEmptyFile
}

file, err := os.Open(p.Attachment.Filename)
file, err := os.Open(p.EmailFilename)
if err != nil {
return err
}
Expand Down Expand Up @@ -119,6 +121,22 @@ func (p *Plugin) Validate() error {
return ErrorMissingEmailFromParam
}

if len(p.Attachment.Filename) != 0 {
fileInfo, err := os.Stat(p.Attachment.Filename)
if errors.Is(err, os.ErrNotExist) {
return os.ErrNotExist
}

if fileInfo.Size() == 0 {
return ErrorEmptyFile
}

p.Attachment, err = p.Email.AttachFile(p.Attachment.Filename)
if err != nil {
return err
}
}

if len(p.SMTPHost.Host) == 0 || len(p.SMTPHost.Port) == 0 {
return ErrorMissingSMTPParam
}
Expand Down
121 changes: 91 additions & 30 deletions cmd/vela-email/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var (
Username: "username",
Password: "password",
}

noAttachment = &email.Attachment{
Filename: "",
}
Expand All @@ -38,10 +39,11 @@ var (
}

mockPlugin = &Plugin{
Email: mockEmail,
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
Email: mockEmail,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
}
)

Expand All @@ -68,9 +70,10 @@ func TestValidateSuccess(t *testing.T) {
{
name: "return no errors: single To email",
parameters: Plugin{
Email: mockEmail,
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
Email: mockEmail,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
},
},
{
Expand All @@ -80,8 +83,9 @@ func TestValidateSuccess(t *testing.T) {
To: []string{"[email protected]", "[email protected]"},
From: "[email protected]",
},
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
},
},
{
Expand All @@ -91,6 +95,7 @@ func TestValidateSuccess(t *testing.T) {
To: []string{"[email protected]", "[email protected]"},
From: "[email protected]",
},
EmailFilename: "",
SMTPHost: &SMTPHost{
Host: "smtphost.com",
Port: "587",
Expand All @@ -113,8 +118,9 @@ func TestValidateSuccess(t *testing.T) {
Sender: "sender",
ReadReceipt: []string{"idk"},
},
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
},
},
{
Expand All @@ -124,9 +130,32 @@ func TestValidateSuccess(t *testing.T) {
To: []string{""},
From: "",
},
SMTPHost: mockSMTPHost,
EmailFilename: "testdata/example1.txt",
SMTPHost: mockSMTPHost,
Attachment: &email.Attachment{
Filename: "testdata/example1.txt",
Filename: "",
},
},
},
{
name: "return no errors: add txt attachment to email",
parameters: Plugin{
Email: mockEmail,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: &email.Attachment{
Filename: "",
},
},
},
{
name: "return no errors: add png image attachment to email",
parameters: Plugin{
Email: mockEmail,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: &email.Attachment{
Filename: "testdata/vela.png",
},
},
},
Expand All @@ -153,7 +182,8 @@ func TestValidateErrors(t *testing.T) {
Email: &email.Email{
From: "[email protected]",
},
Attachment: noAttachment,
EmailFilename: "",
Attachment: noAttachment,
},
wantErr: ErrorMissingEmailToParam,
},
Expand All @@ -163,27 +193,51 @@ func TestValidateErrors(t *testing.T) {
Email: &email.Email{
To: []string{"[email protected]"},
},
Attachment: noAttachment,
EmailFilename: "",
Attachment: noAttachment,
},
wantErr: ErrorMissingEmailFromParam,
},
{
name: "Email parameters missing from attachment",
name: "Email parameters missing from file",
parameters: Plugin{
Email: &email.Email{
To: []string{""},
From: "",
},
SMTPHost: mockSMTPHost,
EmailFilename: "testdata/badattachment.txt",
SMTPHost: mockSMTPHost,
Attachment: &email.Attachment{
Filename: "testdata/badattachment.txt",
Filename: "",
},
},
wantErr: io.EOF,
},
{
name: "Email file missing",
parameters: Plugin{
EmailFilename: "testdata/doesnotexist.txt",
Attachment: &email.Attachment{
Filename: "",
},
},
wantErr: os.ErrNotExist,
},
{
name: "Email file empty",
parameters: Plugin{
EmailFilename: "testdata/empty.txt",
Attachment: &email.Attachment{
Filename: "",
},
},
wantErr: ErrorEmptyFile,
},
{
name: "Email attachment missing",
parameters: Plugin{
Email: mockEmail,
EmailFilename: "",
Attachment: &email.Attachment{
Filename: "testdata/doesnotexist.txt",
},
Expand All @@ -193,16 +247,19 @@ func TestValidateErrors(t *testing.T) {
{
name: "Email attachment empty",
parameters: Plugin{
Email: mockEmail,
EmailFilename: "",
Attachment: &email.Attachment{
Filename: "testdata/empty.txt",
},
},
wantErr: ErrorEmptyAttach,
wantErr: ErrorEmptyFile,
},
{
name: "SMTP host missing",
parameters: Plugin{
Email: mockEmail,
Email: mockEmail,
EmailFilename: "",
SMTPHost: &SMTPHost{
Port: "1902",
},
Expand All @@ -213,7 +270,8 @@ func TestValidateErrors(t *testing.T) {
{
name: "SMTP port missing",
parameters: Plugin{
Email: mockEmail,
Email: mockEmail,
EmailFilename: "",
SMTPHost: &SMTPHost{
Host: "smtphost.com",
},
Expand Down Expand Up @@ -252,9 +310,10 @@ func TestInjectEnvSuccess(t *testing.T) {
Subject: DefaultSubject,
Text: []byte("This is some text for repo: {{ .VELA_REPO_FULL_NAME }}"),
},
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
},
},
{
Expand All @@ -266,9 +325,10 @@ func TestInjectEnvSuccess(t *testing.T) {
Subject: "Commit failure on vela build: {{ .VELA_BUILD_NUMBER }}",
Text: []byte("This is some text for repo: {{ .VELA_REPO_FULL_NAME }}"),
},
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
},
},
}
Expand Down Expand Up @@ -319,9 +379,10 @@ func TestInjectEnvBadVar(t *testing.T) {
From: "[email protected]",
Subject: "This is a bad subject {{ .SOME_OTHER_VARIABLE }}",
},
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
EmailFilename: "",
SMTPHost: mockSMTPHost,
Attachment: noAttachment,
BuildEnv: mockBuildEnv,
},
},
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/vela-email/testdata/example1.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
From: [email protected]
To: [email protected], [email protected]
Bcc: [email protected]
Cc: [email protected]
Subject: Vela Pipeline for {{ .VELA_REPO_FULL_NAME }} {{ .VELA_BUILD_BRANCH }}
Content-Type: text/plain

Expand Down
Binary file added cmd/vela-email/testdata/vela.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b1a1505

Please sign in to comment.