diff --git a/DOCS.md b/DOCS.md index cedf995..4795dde 100644 --- a/DOCS.md +++ b/DOCS.md @@ -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`
`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`
`EMAIL_FILENAME` | diff --git a/cmd/vela-email/main.go b/cmd/vela-email/main.go index 2251f17..933409e 100644 --- a/cmd/vela-email/main.go +++ b/cmd/vela-email/main.go @@ -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"}, @@ -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{ @@ -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"), @@ -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"), diff --git a/cmd/vela-email/plugin.go b/cmd/vela-email/plugin.go index d4640e6..c00f77c 100644 --- a/cmd/vela-email/plugin.go +++ b/cmd/vela-email/plugin.go @@ -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)") @@ -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 @@ -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 } @@ -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 } diff --git a/cmd/vela-email/plugin_test.go b/cmd/vela-email/plugin_test.go index 3d92764..af1ef1d 100644 --- a/cmd/vela-email/plugin_test.go +++ b/cmd/vela-email/plugin_test.go @@ -26,6 +26,7 @@ var ( Username: "username", Password: "password", } + noAttachment = &email.Attachment{ Filename: "", } @@ -38,10 +39,11 @@ var ( } mockPlugin = &Plugin{ - Email: mockEmail, - SMTPHost: mockSMTPHost, - Attachment: noAttachment, - BuildEnv: mockBuildEnv, + Email: mockEmail, + EmailFilename: "", + SMTPHost: mockSMTPHost, + Attachment: noAttachment, + BuildEnv: mockBuildEnv, } ) @@ -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, }, }, { @@ -80,8 +83,9 @@ func TestValidateSuccess(t *testing.T) { To: []string{"fakemail1@example.com", "fakemail2@example.com"}, From: "fakemail3@example.com", }, - SMTPHost: mockSMTPHost, - Attachment: noAttachment, + EmailFilename: "", + SMTPHost: mockSMTPHost, + Attachment: noAttachment, }, }, { @@ -91,6 +95,7 @@ func TestValidateSuccess(t *testing.T) { To: []string{"fakemail1@example.com", "fakemail2@example.com"}, From: "fakemail3@example.com", }, + EmailFilename: "", SMTPHost: &SMTPHost{ Host: "smtphost.com", Port: "587", @@ -113,8 +118,9 @@ func TestValidateSuccess(t *testing.T) { Sender: "sender", ReadReceipt: []string{"idk"}, }, - SMTPHost: mockSMTPHost, - Attachment: noAttachment, + EmailFilename: "", + SMTPHost: mockSMTPHost, + Attachment: noAttachment, }, }, { @@ -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", }, }, }, @@ -153,7 +182,8 @@ func TestValidateErrors(t *testing.T) { Email: &email.Email{ From: "fakemail@example.com", }, - Attachment: noAttachment, + EmailFilename: "", + Attachment: noAttachment, }, wantErr: ErrorMissingEmailToParam, }, @@ -163,27 +193,51 @@ func TestValidateErrors(t *testing.T) { Email: &email.Email{ To: []string{"fakemail@example.com"}, }, - 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", }, @@ -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", }, @@ -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", }, @@ -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, }, }, { @@ -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, }, }, } @@ -319,9 +379,10 @@ func TestInjectEnvBadVar(t *testing.T) { From: "fakemail3@example.com", Subject: "This is a bad subject {{ .SOME_OTHER_VARIABLE }}", }, - SMTPHost: mockSMTPHost, - Attachment: noAttachment, - BuildEnv: mockBuildEnv, + EmailFilename: "", + SMTPHost: mockSMTPHost, + Attachment: noAttachment, + BuildEnv: mockBuildEnv, }, }, } diff --git a/cmd/vela-email/testdata/example1.txt b/cmd/vela-email/testdata/example1.txt index 917b47a..611d575 100644 --- a/cmd/vela-email/testdata/example1.txt +++ b/cmd/vela-email/testdata/example1.txt @@ -1,5 +1,7 @@ From: vela-noreply@fakemail.com To: fakemail1@example.com, fakemail2@example.com +Bcc: fakemail@example.com +Cc: fakemail@example.com Subject: Vela Pipeline for {{ .VELA_REPO_FULL_NAME }} {{ .VELA_BUILD_BRANCH }} Content-Type: text/plain diff --git a/cmd/vela-email/testdata/vela.png b/cmd/vela-email/testdata/vela.png new file mode 100644 index 0000000..179db41 Binary files /dev/null and b/cmd/vela-email/testdata/vela.png differ