github.com/amar224/phishing-tool@v0.9.0/models/maillog_test.go (about) 1 package models 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "math" 8 "net/textproto" 9 "time" 10 11 "github.com/gophish/gophish/config" 12 13 "github.com/gophish/gomail" 14 "github.com/jordan-wright/email" 15 "gopkg.in/check.v1" 16 ) 17 18 func (s *ModelsSuite) emailFromFirstMailLog(campaign Campaign, ch *check.C) *email.Email { 19 result := campaign.Results[0] 20 m := &MailLog{} 21 err := db.Where("r_id=? AND campaign_id=?", result.RId, campaign.Id). 22 Find(m).Error 23 ch.Assert(err, check.Equals, nil) 24 25 msg := gomail.NewMessage() 26 err = m.Generate(msg) 27 ch.Assert(err, check.Equals, nil) 28 29 msgBuff := &bytes.Buffer{} 30 _, err = msg.WriteTo(msgBuff) 31 ch.Assert(err, check.Equals, nil) 32 33 got, err := email.NewEmailFromReader(msgBuff) 34 ch.Assert(err, check.Equals, nil) 35 return got 36 } 37 38 func (s *ModelsSuite) TestGetQueuedMailLogs(ch *check.C) { 39 campaign := s.createCampaign(ch) 40 // By default, for campaigns with no launch date, the maillogs are set as 41 // being processed. We need to unlock them first. 42 ms, err := GetMailLogsByCampaign(campaign.Id) 43 ch.Assert(err, check.Equals, nil) 44 err = LockMailLogs(ms, false) 45 ch.Assert(err, check.Equals, nil) 46 ms, err = GetQueuedMailLogs(campaign.LaunchDate) 47 ch.Assert(err, check.Equals, nil) 48 got := make(map[string]*MailLog) 49 for _, m := range ms { 50 got[m.RId] = m 51 } 52 for _, r := range campaign.Results { 53 if m, ok := got[r.RId]; ok { 54 ch.Assert(m.RId, check.Equals, r.RId) 55 ch.Assert(m.CampaignId, check.Equals, campaign.Id) 56 ch.Assert(m.SendDate, check.Equals, campaign.LaunchDate) 57 ch.Assert(m.UserId, check.Equals, campaign.UserId) 58 ch.Assert(m.SendAttempt, check.Equals, 0) 59 } else { 60 ch.Fatalf("Result not found in maillogs: %s", r.RId) 61 } 62 } 63 } 64 65 func (s *ModelsSuite) TestMailLogBackoff(ch *check.C) { 66 campaign := s.createCampaign(ch) 67 result := campaign.Results[0] 68 m := &MailLog{} 69 err := db.Where("r_id=? AND campaign_id=?", result.RId, campaign.Id). 70 Find(m).Error 71 ch.Assert(err, check.Equals, nil) 72 ch.Assert(m.SendAttempt, check.Equals, 0) 73 ch.Assert(m.SendDate, check.Equals, campaign.LaunchDate) 74 75 expectedError := &textproto.Error{ 76 Code: 500, 77 Msg: "Recipient not found", 78 } 79 for i := m.SendAttempt; i < MaxSendAttempts; i++ { 80 err = m.Lock() 81 ch.Assert(err, check.Equals, nil) 82 ch.Assert(m.Processing, check.Equals, true) 83 84 expectedDuration := math.Pow(2, float64(m.SendAttempt+1)) 85 expectedSendDate := m.SendDate.Add(time.Minute * time.Duration(expectedDuration)) 86 err = m.Backoff(expectedError) 87 ch.Assert(err, check.Equals, nil) 88 ch.Assert(m.SendDate, check.Equals, expectedSendDate) 89 ch.Assert(m.Processing, check.Equals, false) 90 result, err := GetResult(m.RId) 91 ch.Assert(err, check.Equals, nil) 92 ch.Assert(result.SendDate, check.Equals, expectedSendDate) 93 ch.Assert(result.Status, check.Equals, StatusRetry) 94 } 95 // Get our updated campaign and check for the added event 96 campaign, err = GetCampaign(campaign.Id, int64(1)) 97 ch.Assert(err, check.Equals, nil) 98 99 // We expect MaxSendAttempts + the initial campaign created event 100 ch.Assert(len(campaign.Events), check.Equals, MaxSendAttempts+1) 101 102 // Check that we receive our error after meeting the maximum send attempts 103 err = m.Backoff(expectedError) 104 ch.Assert(err, check.Equals, ErrMaxSendAttempts) 105 } 106 107 func (s *ModelsSuite) TestMailLogError(ch *check.C) { 108 campaign := s.createCampaign(ch) 109 result := campaign.Results[0] 110 m := &MailLog{} 111 err := db.Where("r_id=? AND campaign_id=?", result.RId, campaign.Id). 112 Find(m).Error 113 ch.Assert(err, check.Equals, nil) 114 ch.Assert(m.RId, check.Equals, result.RId) 115 116 expectedError := &textproto.Error{ 117 Code: 500, 118 Msg: "Recipient not found", 119 } 120 err = m.Error(expectedError) 121 ch.Assert(err, check.Equals, nil) 122 123 // Get our result and make sure the status is set correctly 124 result, err = GetResult(result.RId) 125 ch.Assert(err, check.Equals, nil) 126 ch.Assert(result.Status, check.Equals, Error) 127 128 // Get our updated campaign and check for the added event 129 campaign, err = GetCampaign(campaign.Id, int64(1)) 130 ch.Assert(err, check.Equals, nil) 131 132 expectedEventLength := 2 133 ch.Assert(len(campaign.Events), check.Equals, expectedEventLength) 134 135 gotEvent := campaign.Events[1] 136 es := EventError{Error: expectedError.Error()} 137 ej, _ := json.Marshal(es) 138 expectedEvent := Event{ 139 Id: gotEvent.Id, 140 Email: result.Email, 141 Message: EventSendingError, 142 CampaignId: campaign.Id, 143 Details: string(ej), 144 Time: gotEvent.Time, 145 } 146 ch.Assert(gotEvent, check.DeepEquals, expectedEvent) 147 148 ms, err := GetMailLogsByCampaign(campaign.Id) 149 ch.Assert(err, check.Equals, nil) 150 ch.Assert(len(ms), check.Equals, len(campaign.Results)-1) 151 } 152 153 func (s *ModelsSuite) TestMailLogSuccess(ch *check.C) { 154 campaign := s.createCampaign(ch) 155 result := campaign.Results[0] 156 m := &MailLog{} 157 err := db.Where("r_id=? AND campaign_id=?", result.RId, campaign.Id). 158 Find(m).Error 159 ch.Assert(err, check.Equals, nil) 160 ch.Assert(m.RId, check.Equals, result.RId) 161 162 err = m.Success() 163 ch.Assert(err, check.Equals, nil) 164 165 // Get our result and make sure the status is set correctly 166 result, err = GetResult(result.RId) 167 ch.Assert(err, check.Equals, nil) 168 ch.Assert(result.Status, check.Equals, EventSent) 169 170 // Get our updated campaign and check for the added event 171 campaign, err = GetCampaign(campaign.Id, int64(1)) 172 ch.Assert(err, check.Equals, nil) 173 174 expectedEventLength := 2 175 ch.Assert(len(campaign.Events), check.Equals, expectedEventLength) 176 177 gotEvent := campaign.Events[1] 178 expectedEvent := Event{ 179 Id: gotEvent.Id, 180 Email: result.Email, 181 Message: EventSent, 182 CampaignId: campaign.Id, 183 Time: gotEvent.Time, 184 } 185 ch.Assert(gotEvent, check.DeepEquals, expectedEvent) 186 ch.Assert(result.SendDate, check.Equals, gotEvent.Time) 187 188 ms, err := GetMailLogsByCampaign(campaign.Id) 189 ch.Assert(err, check.Equals, nil) 190 ch.Assert(len(ms), check.Equals, len(campaign.Results)-1) 191 } 192 193 func (s *ModelsSuite) TestGenerateMailLog(ch *check.C) { 194 campaign := Campaign{ 195 Id: 1, 196 UserId: 1, 197 } 198 result := Result{ 199 RId: "abc1234", 200 } 201 err := GenerateMailLog(&campaign, &result, campaign.LaunchDate) 202 ch.Assert(err, check.Equals, nil) 203 204 m := MailLog{} 205 err = db.Where("r_id=?", result.RId).Find(&m).Error 206 ch.Assert(err, check.Equals, nil) 207 ch.Assert(m.RId, check.Equals, result.RId) 208 ch.Assert(m.CampaignId, check.Equals, campaign.Id) 209 ch.Assert(m.SendDate, check.Equals, campaign.LaunchDate) 210 ch.Assert(m.UserId, check.Equals, campaign.UserId) 211 ch.Assert(m.SendAttempt, check.Equals, 0) 212 ch.Assert(m.Processing, check.Equals, false) 213 } 214 215 func (s *ModelsSuite) TestMailLogGenerate(ch *check.C) { 216 campaign := s.createCampaign(ch) 217 result := campaign.Results[0] 218 expected := &email.Email{ 219 Subject: fmt.Sprintf("%s - Subject", result.RId), 220 Text: []byte(fmt.Sprintf("%s - Text", result.RId)), 221 HTML: []byte(fmt.Sprintf("%s - HTML", result.RId)), 222 } 223 got := s.emailFromFirstMailLog(campaign, ch) 224 ch.Assert(got.Subject, check.Equals, expected.Subject) 225 ch.Assert(string(got.Text), check.Equals, string(expected.Text)) 226 ch.Assert(string(got.HTML), check.Equals, string(expected.HTML)) 227 } 228 229 func (s *ModelsSuite) TestMailLogGenerateTransparencyHeaders(ch *check.C) { 230 s.config.ContactAddress = "test@test.com" 231 expectedHeaders := map[string]string{ 232 "X-Mailer": config.ServerName, 233 "X-Gophish-Contact": s.config.ContactAddress, 234 } 235 campaign := s.createCampaign(ch) 236 got := s.emailFromFirstMailLog(campaign, ch) 237 for k, v := range expectedHeaders { 238 ch.Assert(got.Headers.Get(k), check.Equals, v) 239 } 240 } 241 242 func (s *ModelsSuite) TestMailLogGenerateOverrideTransparencyHeaders(ch *check.C) { 243 expectedHeaders := map[string]string{ 244 "X-Mailer": "", 245 "X-Gophish-Contact": "", 246 } 247 smtp := SMTP{ 248 Name: "Test SMTP", 249 Host: "1.1.1.1:25", 250 FromAddress: "Foo Bar <foo@example.com>", 251 UserId: 1, 252 Headers: []Header{ 253 Header{Key: "X-Gophish-Contact", Value: ""}, 254 Header{Key: "X-Mailer", Value: ""}, 255 }, 256 } 257 ch.Assert(PostSMTP(&smtp), check.Equals, nil) 258 campaign := s.createCampaignDependencies(ch) 259 campaign.SMTP = smtp 260 261 ch.Assert(PostCampaign(&campaign, campaign.UserId), check.Equals, nil) 262 got := s.emailFromFirstMailLog(campaign, ch) 263 for k, v := range expectedHeaders { 264 ch.Assert(got.Headers.Get(k), check.Equals, v) 265 } 266 } 267 268 func (s *ModelsSuite) TestUnlockAllMailLogs(ch *check.C) { 269 campaign := s.createCampaign(ch) 270 ms, err := GetMailLogsByCampaign(campaign.Id) 271 ch.Assert(err, check.Equals, nil) 272 for _, m := range ms { 273 ch.Assert(m.Processing, check.Equals, true) 274 } 275 err = UnlockAllMailLogs() 276 ch.Assert(err, check.Equals, nil) 277 ms, err = GetMailLogsByCampaign(campaign.Id) 278 ch.Assert(err, check.Equals, nil) 279 for _, m := range ms { 280 ch.Assert(m.Processing, check.Equals, false) 281 } 282 } 283 284 func (s *ModelsSuite) TestURLTemplateRendering(ch *check.C) { 285 template := Template{ 286 Name: "URLTemplate", 287 UserId: 1, 288 Text: "{{.URL}}", 289 HTML: "{{.URL}}", 290 Subject: "{{.URL}}", 291 } 292 ch.Assert(PostTemplate(&template), check.Equals, nil) 293 campaign := s.createCampaignDependencies(ch) 294 campaign.URL = "http://127.0.0.1/{{.Email}}/" 295 campaign.Template = template 296 297 ch.Assert(PostCampaign(&campaign, campaign.UserId), check.Equals, nil) 298 result := campaign.Results[0] 299 expectedURL := fmt.Sprintf("http://127.0.0.1/%s/?%s=%s", result.Email, RecipientParameter, result.RId) 300 301 got := s.emailFromFirstMailLog(campaign, ch) 302 ch.Assert(got.Subject, check.Equals, expectedURL) 303 ch.Assert(string(got.Text), check.Equals, expectedURL) 304 ch.Assert(string(got.HTML), check.Equals, expectedURL) 305 } 306 307 func (s *ModelsSuite) TestMailLogGenerateEmptySubject(ch *check.C) { 308 309 // in place of using createCampaign, we replicate its small code body 310 // here internally as we want to specify an empty subject to createCampaignDependencies 311 // campaign := s.createCampaign(ch) 312 campaign := s.createCampaignDependencies(ch, "") // specify empty subject 313 // Setup and "launch" our campaign 314 ch.Assert(PostCampaign(&campaign, campaign.UserId), check.Equals, nil) 315 result := campaign.Results[0] 316 317 expected := &email.Email{ 318 Subject: "", 319 Text: []byte(fmt.Sprintf("%s - Text", result.RId)), 320 HTML: []byte(fmt.Sprintf("%s - HTML", result.RId)), 321 } 322 got := s.emailFromFirstMailLog(campaign, ch) 323 ch.Assert(got.Subject, check.Equals, expected.Subject) 324 }