diff --git a/README.md b/README.md index 510e0b3..0e438a7 100644 --- a/README.md +++ b/README.md @@ -54,13 +54,16 @@ notifier.UseServices(telegramService) // Send a test message. _ = notifier.Send( + context.Background(), "Subject/Title", - "The actual message. Hello, you awesome gophers! :)", + "The actual message - Hello, you awesome gophers! :)", ) ``` ## Supported services +> Please create feature requests for missing services (see #3 for example) + - *Amazon SES* - *Discord* - *Email* @@ -74,11 +77,6 @@ _ = notifier.Send( - *Twitter* - *WhatsApp* -## Roadmap - -- [ ] Add tests (see [#1](https://github.com/nikoksr/notify/issues/1)) -- [ ] Add more notification services (Issues and PRs are welcome!) - ## Credits - Amazon SES support: [aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) diff --git a/notifier.go b/notifier.go index 09dcf51..26b562f 100644 --- a/notifier.go +++ b/notifier.go @@ -1,9 +1,11 @@ package notify +import "context" + // Notifier defines the behavior for notification services. // // The Send function simply sends a subject and a message string to the internal destination Notifier. // E.g for telegram.Telegram it sends the message to the specified group chat. type Notifier interface { - Send(string, string) error + Send(context.Context, string, string) error } diff --git a/send.go b/send.go index 0a3ac26..982208a 100644 --- a/send.go +++ b/send.go @@ -1,12 +1,14 @@ package notify import ( + "context" + "github.com/pkg/errors" "golang.org/x/sync/errgroup" ) // Send calls the underlying notification services to send the given subject and message to their respective endpoints. -func (n Notify) Send(subject, message string) error { +func (n Notify) Send(ctx context.Context, subject, message string) error { if n.Disabled { return nil } @@ -17,7 +19,7 @@ func (n Notify) Send(subject, message string) error { if service != nil { s := service eg.Go(func() error { - return s.Send(subject, message) + return s.Send(ctx, subject, message) }) } } diff --git a/service/amazonses/amazon_ses.go b/service/amazonses/amazon_ses.go index 7abf377..03c2ca0 100644 --- a/service/amazonses/amazon_ses.go +++ b/service/amazonses/amazon_ses.go @@ -48,7 +48,7 @@ func (a *AmazonSES) AddReceivers(addresses ...string) { // Send takes a message subject and a message body and sends them to all previously set chats. Message body supports // html as markup language. -func (a AmazonSES) Send(subject, message string) error { +func (a AmazonSES) Send(ctx context.Context, subject, message string) error { input := &ses.SendEmailInput{ Source: a.senderAddress, Destination: &types.Destination{ @@ -69,7 +69,7 @@ func (a AmazonSES) Send(subject, message string) error { }, } - _, err := a.client.SendEmail(context.Background(), input) + _, err := a.client.SendEmail(ctx, input) if err != nil { return errors.Wrap(err, "failed to send mail using Amazon SES service") } diff --git a/service/discord/discord.go b/service/discord/discord.go index 0c2d96c..fadaa10 100644 --- a/service/discord/discord.go +++ b/service/discord/discord.go @@ -1,6 +1,8 @@ package discord import ( + "context" + "github.com/bwmarrin/discordgo" "github.com/pkg/errors" ) @@ -88,13 +90,18 @@ func (d *Discord) AddReceivers(channelIDs ...string) { } // Send takes a message subject and a message body and sends them to all previously set chats. -func (d Discord) Send(subject, message string) error { +func (d Discord) Send(ctx context.Context, subject, message string) error { fullMessage := subject + "\n" + message // Treating subject as message title for _, channelID := range d.channelIDs { - _, err := d.client.ChannelMessageSend(channelID, fullMessage) - if err != nil { - return errors.Wrapf(err, "failed to send message to Discord channel '%s'", channelID) + select { + case <-ctx.Done(): + return nil + default: + _, err := d.client.ChannelMessageSend(channelID, fullMessage) + if err != nil { + return errors.Wrapf(err, "failed to send message to Discord channel '%s'", channelID) + } } } diff --git a/service/mail/mail.go b/service/mail/mail.go index 55901bb..9494d8c 100644 --- a/service/mail/mail.go +++ b/service/mail/mail.go @@ -1,6 +1,7 @@ package mail import ( + "context" "net/smtp" "net/textproto" @@ -41,7 +42,14 @@ func (m *Mail) AddReceivers(addresses ...string) { // Send takes a message subject and a message body and sends them to all previously set chats. Message body supports // html as markup language. -func (m Mail) Send(subject, message string) error { +func (m Mail) Send(ctx context.Context, subject, message string) error { + // TODO: Is this necessary? Or do we just do nothing with ctx? + select { + case <-ctx.Done(): + return nil + default: + } + msg := &email.Email{ To: m.receiverAddresses, From: m.senderAddress, diff --git a/service/mailgun/mailgun.go b/service/mailgun/mailgun.go index b021f0d..8788249 100644 --- a/service/mailgun/mailgun.go +++ b/service/mailgun/mailgun.go @@ -39,10 +39,10 @@ func (m *Mailgun) AddReceivers(addresses ...string) { // Send takes a message subject and a message body and sends them to all previously set chats. Message body supports // html as markup language. -func (m Mailgun) Send(subject, message string) error { +func (m Mailgun) Send(ctx context.Context, subject, message string) error { mailMessage := m.client.NewMessage(m.senderAddress, subject, message, m.receiverAddresses...) - _, _, err := m.client.Send(context.Background(), mailMessage) + _, _, err := m.client.Send(ctx, mailMessage) if err != nil { return errors.Wrap(err, "failed to send mail using Mailgun service") } diff --git a/service/msteams/ms_teams.go b/service/msteams/ms_teams.go index 7e48476..c0df637 100644 --- a/service/msteams/ms_teams.go +++ b/service/msteams/ms_teams.go @@ -1,6 +1,8 @@ package msteams import ( + "context" + goteamsnotify "github.com/atc0005/go-teams-notify/v2" "github.com/pkg/errors" ) @@ -43,15 +45,20 @@ func (m *MSTeams) AddReceivers(webHooks ...string) { // html as markup language. // For more information about telegram api token: // -> https://github.com/atc0005/go-teams-notify#example-basic -func (m MSTeams) Send(subject, message string) error { +func (m MSTeams) Send(ctx context.Context, subject, message string) error { msgCard := goteamsnotify.NewMessageCard() msgCard.Title = subject msgCard.Text = message for _, webHook := range m.webHooks { - err := m.client.Send(webHook, msgCard) - if err != nil { - return errors.Wrapf(err, "failed to send message to Microsoft Teams via webhook '%s'", webHook) + select { + case <-ctx.Done(): + return nil + default: + err := m.client.SendWithContext(ctx, webHook, msgCard) + if err != nil { + return errors.Wrapf(err, "failed to send message to Microsoft Teams via webhook '%s'", webHook) + } } } diff --git a/service/plivo/README.md b/service/plivo/README.md index 9b00244..c002086 100644 --- a/service/plivo/README.md +++ b/service/plivo/README.md @@ -16,34 +16,35 @@ following things: package main import ( - "log" + "context" + "log" - "github.com/nikoksr/notify" - "github.com/nikoksr/notify/service/plivo" + "github.com/nikoksr/notify" + "github.com/nikoksr/notify/service/plivo" ) func main() { - plivoSvc, err := plivo.New( - &plivo.ClientOptions{ - AuthID: "", - AuthToken: "", - }, &plivo.MessageOptions{ - Source: "", - }) - if err != nil { - log.Fatalf("plivo.New() failed: %s", err.Error()) - } + plivoSvc, err := plivo.New( + &plivo.ClientOptions{ + AuthID: "", + AuthToken: "", + }, &plivo.MessageOptions{ + Source: "", + }) + if err != nil { + log.Fatalf("plivo.New() failed: %s", err.Error()) + } - plivoSvc.AddReceivers("Destination1") + plivoSvc.AddReceivers("Destination1") - notifier := notify.New() - notifier.UseServices(plivoSvc) + notifier := notify.New() + notifier.UseServices(plivoSvc) - err = notifier.Send("subject", "message") - if err != nil { - log.Fatalf("notifier.Send() failed: %s", err.Error()) - } + err = notifier.Send(context.Background(), "subject", "message") + if err != nil { + log.Fatalf("notifier.Send() failed: %s", err.Error()) + } - log.Printf("notification sent") + log.Printf("notification sent") } ``` diff --git a/service/plivo/doc.go b/service/plivo/doc.go index 7009d40..3729436 100644 --- a/service/plivo/doc.go +++ b/service/plivo/doc.go @@ -29,7 +29,7 @@ Usage: notifier := notify.New() notifier.UseServices(plivoSvc) - err = notifier.Send("subject", "message") + err = notifier.Send(context.Background(), "subject", "message") if err != nil { log.Fatalf("notifier.Send() failed: %s", err.Error()) } diff --git a/service/plivo/mock_plivoMsgClient.go b/service/plivo/mock_plivoMsgClient.go index c0ec80b..796607b 100644 --- a/service/plivo/mock_plivoMsgClient.go +++ b/service/plivo/mock_plivoMsgClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v0.0.0-dev. DO NOT EDIT. +// Code generated by mockery v2.5.1. DO NOT EDIT. package plivo @@ -7,7 +7,7 @@ import ( mock "github.com/stretchr/testify/mock" ) -// mockPlivoMsgClient is an autogenerated mock type for the plivoMsgClient type +// mockPlivoMsgClient is an autogenerated mock type for the mockPlivoMsgClient type type mockPlivoMsgClient struct { mock.Mock } diff --git a/service/plivo/plivo.go b/service/plivo/plivo.go index 2eccf10..8748365 100644 --- a/service/plivo/plivo.go +++ b/service/plivo/plivo.go @@ -1,6 +1,7 @@ package plivo import ( + "context" "fmt" "net/http" "strings" @@ -26,7 +27,7 @@ type MessageOptions struct { CallbackMethod string // The HTTP method to be used when calling CallbackURL - GET or POST(default) } -// plivoMsgClient abstracts Plivo SDK for writing unit tests +// mockPlivoMsgClient abstracts Plivo SDK for writing unit tests type plivoMsgClient interface { Create(plivo.MessageCreateParams) (*plivo.MessageCreateResponseBody, error) } @@ -75,7 +76,14 @@ func (s *Service) AddReceivers(phoneNumbers ...string) { } // Send sends a SMS via Plivo to all previously added receivers. -func (s *Service) Send(subject, message string) error { +func (s *Service) Send(ctx context.Context, subject, message string) error { + // TODO: Same question here. + select { + case <-ctx.Done(): + return nil + default: + } + text := subject + "\n" + message var dst string diff --git a/service/plivo/plivo_test.go b/service/plivo/plivo_test.go index 6f7893a..5dad6e8 100644 --- a/service/plivo/plivo_test.go +++ b/service/plivo/plivo_test.go @@ -1,6 +1,7 @@ package plivo import ( + "context" "errors" "testing" @@ -53,7 +54,8 @@ func TestSend(t *testing.T) { assert.NotNil(svc) // no receivers added - err = svc.Send("message", "test") + ctx := context.Background() + err = svc.Send(ctx, "message", "test") assert.NotNil(err) // test plivo client returning error @@ -62,7 +64,7 @@ func TestSend(t *testing.T) { Return(nil, errors.New("some error")) svc.client = mockClient svc.AddReceivers("67890") - err = svc.Send("message", "test") + err = svc.Send(ctx, "message", "test") assert.NotNil(err) mockClient.AssertExpectations(t) @@ -72,7 +74,7 @@ func TestSend(t *testing.T) { Return(nil, nil) svc.client = mockClient svc.AddReceivers("09876") - err = svc.Send("message", "test") + err = svc.Send(ctx, "message", "test") assert.Nil(err) mockClient.AssertExpectations(t) } diff --git a/service/pushbullet/pushbullet.go b/service/pushbullet/pushbullet.go index e4c3a18..93a1a46 100644 --- a/service/pushbullet/pushbullet.go +++ b/service/pushbullet/pushbullet.go @@ -1,6 +1,8 @@ package pushbullet import ( + "context" + "github.com/cschomburg/go-pushbullet" "github.com/pkg/errors" ) @@ -35,16 +37,21 @@ func (pb *Pushbullet) AddReceivers(deviceNicknames ...string) { // you will need Pushbullet installed on the relevant devices // (android, chrome, firefox, windows) // see https://www.pushbullet.com/apps -func (pb Pushbullet) Send(subject, message string) error { +func (pb Pushbullet) Send(ctx context.Context, subject, message string) error { for _, deviceNickname := range pb.deviceNicknames { - dev, err := pb.client.Device(deviceNickname) - if err != nil { - return errors.Wrapf(err, "failed to find Pushbullet device with nickname '%s'", deviceNickname) - } + select { + case <-ctx.Done(): + return nil + default: + dev, err := pb.client.Device(deviceNickname) + if err != nil { + return errors.Wrapf(err, "failed to find Pushbullet device with nickname '%s'", deviceNickname) + } - err = dev.PushNote(subject, message) - if err != nil { - return errors.Wrapf(err, "failed to send message to Pushbullet device with nickname '%s'", deviceNickname) + err = dev.PushNote(subject, message) + if err != nil { + return errors.Wrapf(err, "failed to send message to Pushbullet device with nickname '%s'", deviceNickname) + } } } diff --git a/service/pushbullet/sms.go b/service/pushbullet/sms.go index 7508760..d7bc376 100644 --- a/service/pushbullet/sms.go +++ b/service/pushbullet/sms.go @@ -1,6 +1,8 @@ package pushbullet import ( + "context" + "github.com/cschomburg/go-pushbullet" "github.com/pkg/errors" ) @@ -43,7 +45,7 @@ func (sms *SMS) AddReceivers(phoneNumbers ...string) { // Send takes a message subject and a message body and sends them to all phone numbers. // see https://help.pushbullet.com/articles/how-do-i-send-text-messages-from-my-computer/ -func (sms SMS) Send(subject, message string) error { +func (sms SMS) Send(ctx context.Context, subject, message string) error { fullMessage := subject + "\n" + message // Treating subject as message title user, err := sms.client.Me() if err != nil { @@ -51,9 +53,14 @@ func (sms SMS) Send(subject, message string) error { } for _, phoneNumber := range sms.phoneNumbers { - err = sms.client.PushSMS(user.Iden, sms.deviceIdentifier, phoneNumber, fullMessage) - if err != nil { - return errors.Wrapf(err, "failed to send SMS message to %s via Pushbullet", phoneNumber) + select { + case <-ctx.Done(): + return nil + default: + err = sms.client.PushSMS(user.Iden, sms.deviceIdentifier, phoneNumber, fullMessage) + if err != nil { + return errors.Wrapf(err, "failed to send SMS message to %s via Pushbullet", phoneNumber) + } } } diff --git a/service/sendgrid/sendgrid.go b/service/sendgrid/sendgrid.go index 6b361ed..a5aff06 100644 --- a/service/sendgrid/sendgrid.go +++ b/service/sendgrid/sendgrid.go @@ -1,6 +1,7 @@ package sendgrid import ( + "context" "net/http" "github.com/pkg/errors" @@ -36,7 +37,7 @@ func (s *SendGrid) AddReceivers(addresses ...string) { // Send takes a message subject and a message body and sends them to all previously set chats. Message body supports // html as markup language. -func (s SendGrid) Send(subject, message string) error { +func (s SendGrid) Send(ctx context.Context, subject, message string) error { from := mail.NewEmail(s.senderName, s.senderAddress) content := mail.NewContent("text/html", message) @@ -53,6 +54,13 @@ func (s SendGrid) Send(subject, message string) error { mailMessage.AddContent(content) mailMessage.SetFrom(from) + // TODO: Should we check here or at the beginning of the func? + select { + case <-ctx.Done(): + return nil + default: + } + resp, err := s.client.Send(mailMessage) if err != nil { return errors.Wrap(err, "failed to send mail using SendGrid service") diff --git a/service/slack/slack.go b/service/slack/slack.go index 875de91..94139d0 100644 --- a/service/slack/slack.go +++ b/service/slack/slack.go @@ -1,6 +1,8 @@ package slack import ( + "context" + "github.com/pkg/errors" "github.com/slack-go/slack" ) @@ -34,16 +36,22 @@ func (s *Slack) AddReceivers(channelIDs ...string) { // Send takes a message subject and a message body and sends them to all previously set channels. // you will need a slack app with the chat:write.public and chat:write permissions. // see https://api.slack.com/ -func (s Slack) Send(subject, message string) error { +func (s Slack) Send(ctx context.Context, subject, message string) error { fullMessage := subject + "\n" + message // Treating subject as message title for _, channelID := range s.channelIDs { - id, timestamp, err := s.client.PostMessage( - channelID, - slack.MsgOptionText(fullMessage, false), - ) - if err != nil { - return errors.Wrapf(err, "failed to send message to Slack channel '%s' at time '%s'", id, timestamp) + select { + case <-ctx.Done(): + return nil + default: + id, timestamp, err := s.client.PostMessageContext( + ctx, + channelID, + slack.MsgOptionText(fullMessage, false), + ) + if err != nil { + return errors.Wrapf(err, "failed to send message to Slack channel '%s' at time '%s'", id, timestamp) + } } } diff --git a/service/telegram/telegram.go b/service/telegram/telegram.go index 0fa4484..49ba1bd 100644 --- a/service/telegram/telegram.go +++ b/service/telegram/telegram.go @@ -1,6 +1,8 @@ package telegram import ( + "context" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" "github.com/pkg/errors" ) @@ -38,17 +40,22 @@ func (t *Telegram) AddReceivers(chatIDs ...int64) { // Send takes a message subject and a message body and sends them to all previously set chats. Message body supports // html as markup language. -func (t Telegram) Send(subject, message string) error { +func (t Telegram) Send(ctx context.Context, subject, message string) error { fullMessage := subject + "\n" + message // Treating subject as message title msg := tgbotapi.NewMessage(0, fullMessage) msg.ParseMode = defaultParseMode for _, chatID := range t.chatIDs { - msg.ChatID = chatID - _, err := t.client.Send(msg) - if err != nil { - return errors.Wrapf(err, "failed to send message to Telegram chat '%d'", chatID) + select { + case <-ctx.Done(): + return nil + default: + msg.ChatID = chatID + _, err := t.client.Send(msg) + if err != nil { + return errors.Wrapf(err, "failed to send message to Telegram chat '%d'", chatID) + } } } diff --git a/service/twitter/twitter.go b/service/twitter/twitter.go index a4ea145..97d6bab 100644 --- a/service/twitter/twitter.go +++ b/service/twitter/twitter.go @@ -1,6 +1,8 @@ package twitter import ( + "context" + "github.com/dghubble/go-twitter/twitter" "github.com/dghubble/oauth1" "github.com/pkg/errors" @@ -68,30 +70,35 @@ func (t *Twitter) AddReceivers(twitterIDs ...string) { // Send takes a message subject and a message body and sends them to all previously set twitterIDs as a DM. // See https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/new-event -func (t Twitter) Send(subject, message string) error { +func (t Twitter) Send(ctx context.Context, subject, message string) error { directMessageData := &twitter.DirectMessageData{ Text: subject + "\n" + message, } for _, twitterID := range t.twitterIDs { - directMessageTarget := &twitter.DirectMessageTarget{ - RecipientID: twitterID, - } - directMessageEvent := &twitter.DirectMessageEvent{ - Type: "message_create", - Message: &twitter.DirectMessageEventMessage{ - Target: directMessageTarget, - Data: directMessageData, - }, - } + select { + case <-ctx.Done(): + return nil + default: + directMessageTarget := &twitter.DirectMessageTarget{ + RecipientID: twitterID, + } + directMessageEvent := &twitter.DirectMessageEvent{ + Type: "message_create", + Message: &twitter.DirectMessageEventMessage{ + Target: directMessageTarget, + Data: directMessageData, + }, + } - directMessageParams := &twitter.DirectMessageEventsNewParams{ - Event: directMessageEvent, - } + directMessageParams := &twitter.DirectMessageEventsNewParams{ + Event: directMessageEvent, + } - _, _, err := t.client.DirectMessages.EventsNew(directMessageParams) - if err != nil { - return errors.Wrapf(err, "failed to send direct message to twitter ID '%s'", twitterID) + _, _, err := t.client.DirectMessages.EventsNew(directMessageParams) + if err != nil { + return errors.Wrapf(err, "failed to send direct message to twitter ID '%s'", twitterID) + } } } diff --git a/service/whatsapp/README.md b/service/whatsapp/README.md index 2a05d38..5d3322d 100644 --- a/service/whatsapp/README.md +++ b/service/whatsapp/README.md @@ -46,7 +46,7 @@ func main() { notifier := notify.New() notifier.UseServices(whatsappSvc) - err = notifier.Send("subject", "message") + err = notifier.Send(context.Background(), "subject", "message") if err != nil { log.Fatalf("notifier.Send() failed: %s", err.Error()) } diff --git a/service/whatsapp/doc.go b/service/whatsapp/doc.go index 6ea71e7..26b069e 100644 --- a/service/whatsapp/doc.go +++ b/service/whatsapp/doc.go @@ -28,7 +28,7 @@ Usage: notifier := notify.New() notifier.UseServices(whatsappSvc) - err = notifier.Send("subject", "message") + err = notifier.Send(context.Background(), "subject", "message") if err != nil { log.Fatalf("notifier.Send() failed: %s", err.Error()) } diff --git a/service/whatsapp/mock_whatsappClient.go b/service/whatsapp/mock_whatsappClient.go index 2eaec39..434367f 100644 --- a/service/whatsapp/mock_whatsappClient.go +++ b/service/whatsapp/mock_whatsappClient.go @@ -1,13 +1,13 @@ -// Code generated by mockery v2.0.4. DO NOT EDIT. +// Code generated by mockery v2.5.1. DO NOT EDIT. package whatsapp import ( - "github.com/Rhymen/go-whatsapp" - "github.com/stretchr/testify/mock" + whatsapp "github.com/Rhymen/go-whatsapp" + mock "github.com/stretchr/testify/mock" ) -// mockWhatsappClient is an autogenerated mock type for the whatsappClient type +// mockWhatsappClient is an autogenerated mock type for the mockWhatsappClient type type mockWhatsappClient struct { mock.Mock } diff --git a/service/whatsapp/whatsapp.go b/service/whatsapp/whatsapp.go index 56c52b8..654872f 100644 --- a/service/whatsapp/whatsapp.go +++ b/service/whatsapp/whatsapp.go @@ -1,6 +1,7 @@ package whatsapp import ( + "context" "encoding/gob" "fmt" "os" @@ -19,7 +20,7 @@ const ( var sessionFilePath = filepath.Join(os.TempDir(), "whatsappSession.gob") -// whatsappClient abstracts go-whatsapp for writing unit tests +// mockWhatsappClient abstracts go-whatsapp for writing unit tests type whatsappClient interface { Login(qrChan chan<- string) (whatsapp.Session, error) RestoreWithSession(session whatsapp.Session) (whatsapp.Session, error) @@ -164,19 +165,24 @@ func (s *Service) AddReceivers(contacts ...string) { } // Send takes a message subject and a message body and sends them to all previously set contacts. -func (s *Service) Send(subject, message string) error { +func (s *Service) Send(ctx context.Context, subject, message string) error { msg := whatsapp.TextMessage{ Text: subject + "\n" + message, } for _, contact := range s.contacts { - msg.Info = whatsapp.MessageInfo{ - RemoteJid: contact + "@s.whatsapp.net", - } + select { + case <-ctx.Done(): + return nil + default: + msg.Info = whatsapp.MessageInfo{ + RemoteJid: contact + "@s.whatsapp.net", + } - _, err := s.client.Send(msg) - if err != nil { - return errors.Wrapf(err, "failed to send message to WhatsApp contact '%s'", contact) + _, err := s.client.Send(msg) + if err != nil { + return errors.Wrapf(err, "failed to send message to WhatsApp contact '%s'", contact) + } } } diff --git a/service/whatsapp/whatsapp_test.go b/service/whatsapp/whatsapp_test.go index 514372b..3124057 100644 --- a/service/whatsapp/whatsapp_test.go +++ b/service/whatsapp/whatsapp_test.go @@ -1,6 +1,7 @@ package whatsapp import ( + "context" "testing" "github.com/Rhymen/go-whatsapp" @@ -37,7 +38,8 @@ func TestSend(t *testing.T) { }).Return("", errors.New("some error")) svc.client = mockClient svc.AddReceivers("Contact1") - err := svc.Send("subject", "message") + ctx := context.Background() + err := svc.Send(ctx, "subject", "message") assert.NotNil(err) mockClient.AssertExpectations(t) @@ -57,7 +59,7 @@ func TestSend(t *testing.T) { }).Return("", nil) svc.client = mockClient svc.AddReceivers("Contact1", "Contact2") - err = svc.Send("subject", "message") + err = svc.Send(ctx, "subject", "message") assert.Nil(err) mockClient.AssertExpectations(t) }