gophish-ruby 0.4.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,8 @@ This document provides detailed API reference for the Gophish Ruby SDK.
9
9
  - [Group Class](#group-class)
10
10
  - [Template Class](#template-class)
11
11
  - [Page Class](#page-class)
12
+ - [SMTP Class](#smtp-class)
13
+ - [Campaign Class](#campaign-class)
12
14
  - [Error Handling](#error-handling)
13
15
  - [Examples](#examples)
14
16
 
@@ -407,6 +409,7 @@ The `Gophish::Template` class represents an email template in Gophish.
407
409
  |-----------|------|----------|-------------|
408
410
  | `id` | Integer | No | Unique template identifier (set by server) |
409
411
  | `name` | String | Yes | Template name |
412
+ | `envelope_sender` | String | No | Envelope sender email address for advanced delivery control |
410
413
  | `subject` | String | No | Email subject line |
411
414
  | `text` | String | No | Plain text email content |
412
415
  | `html` | String | No | HTML email content |
@@ -531,6 +534,22 @@ Get the number of attachments.
531
534
  puts "Attachments: #{template.attachment_count}"
532
535
  ```
533
536
 
537
+ ##### `#has_envelope_sender?`
538
+
539
+ Check if template has an envelope sender configured.
540
+
541
+ **Returns:** Boolean
542
+
543
+ **Example:**
544
+
545
+ ```ruby
546
+ template = Gophish::Template.new(envelope_sender: "noreply@company.com")
547
+ puts template.has_envelope_sender? # => true
548
+
549
+ template = Gophish::Template.new
550
+ puts template.has_envelope_sender? # => false
551
+ ```
552
+
534
553
  #### Usage Examples
535
554
 
536
555
  ##### Create a Template
@@ -568,6 +587,33 @@ template.add_attachment(image_content, "image/png", "logo.png")
568
587
  template.save
569
588
  ```
570
589
 
590
+ ##### Template with Envelope Sender
591
+
592
+ ```ruby
593
+ # Create template with envelope sender for better deliverability
594
+ template = Gophish::Template.new(
595
+ name: "Corporate IT Update",
596
+ envelope_sender: "noreply@company.com", # Separate envelope sender
597
+ subject: "Important IT Security Update",
598
+ html: <<~HTML
599
+ <html>
600
+ <body>
601
+ <h1>IT Security Department</h1>
602
+ <p>We've detected suspicious activity on your account.</p>
603
+ <p><a href="{{.URL}}">Click here to verify your account</a></p>
604
+ <p>Thank you,<br>IT Security Team</p>
605
+ </body>
606
+ </html>
607
+ HTML
608
+ )
609
+
610
+ if template.save
611
+ puts "Template created with envelope sender"
612
+ puts "Envelope sender: #{template.envelope_sender}"
613
+ puts "Has envelope sender: #{template.has_envelope_sender?}"
614
+ end
615
+ ```
616
+
571
617
  ##### Import from Email
572
618
 
573
619
  ```ruby
@@ -944,6 +990,885 @@ if page.destroy
944
990
  end
945
991
  ```
946
992
 
993
+ ## SMTP Class
994
+
995
+ The `Gophish::Smtp` class represents an SMTP sending profile in Gophish campaigns.
996
+
997
+ ### Class: `Gophish::Smtp < Gophish::Base`
998
+
999
+ #### Attributes
1000
+
1001
+ | Attribute | Type | Required | Description |
1002
+ |-----------|------|----------|-------------|
1003
+ | `id` | Integer | No | Unique SMTP profile identifier (set by server) |
1004
+ | `name` | String | Yes | SMTP profile name |
1005
+ | `username` | String | No | SMTP authentication username |
1006
+ | `password` | String | No | SMTP authentication password |
1007
+ | `host` | String | Yes | SMTP server hostname |
1008
+ | `interface_type` | String | No | Interface type (default: "SMTP") |
1009
+ | `from_address` | String | Yes | From email address (must be valid email format) |
1010
+ | `ignore_cert_errors` | Boolean | No | Whether to ignore SSL certificate errors (default: false) |
1011
+ | `modified_date` | String | No | Last modification timestamp (set by server) |
1012
+ | `headers` | Array | No | Array of custom header hashes |
1013
+
1014
+ #### Header Structure
1015
+
1016
+ Each header in the `headers` array must have:
1017
+
1018
+ | Field | Type | Required | Description |
1019
+ |-------|------|----------|-------------|
1020
+ | `key` | String | Yes | Header name |
1021
+ | `value` | String | Yes | Header value |
1022
+
1023
+ #### Validations
1024
+
1025
+ - `name` must be present
1026
+ - `host` must be present
1027
+ - `from_address` must be present and have valid email format
1028
+ - Each header must be a Hash with both `key` and `value`
1029
+
1030
+ #### Instance Methods
1031
+
1032
+ ##### `#add_header(key, value)`
1033
+
1034
+ Add a custom header to the SMTP profile.
1035
+
1036
+ **Parameters:**
1037
+
1038
+ - `key` (String) - Header name
1039
+ - `value` (String) - Header value
1040
+
1041
+ **Returns:** Void
1042
+
1043
+ **Side Effects:**
1044
+
1045
+ - Adds header to `headers` array
1046
+ - Marks `headers` attribute as changed
1047
+
1048
+ **Example:**
1049
+
1050
+ ```ruby
1051
+ smtp = Gophish::Smtp.new(name: "Test", host: "smtp.test.com", from_address: "test@example.com")
1052
+ smtp.add_header("X-Mailer", "Company Security Tool")
1053
+ smtp.add_header("Return-Path", "bounces@company.com")
1054
+ ```
1055
+
1056
+ ##### `#remove_header(key)`
1057
+
1058
+ Remove a header by key name.
1059
+
1060
+ **Parameters:**
1061
+
1062
+ - `key` (String) - Header name to remove
1063
+
1064
+ **Returns:** Void
1065
+
1066
+ **Side Effects:**
1067
+
1068
+ - Removes matching header(s) from `headers` array
1069
+ - Marks `headers` attribute as changed if any were removed
1070
+
1071
+ **Example:**
1072
+
1073
+ ```ruby
1074
+ smtp.remove_header("X-Mailer")
1075
+ ```
1076
+
1077
+ ##### `#has_headers?`
1078
+
1079
+ Check if SMTP profile has any custom headers.
1080
+
1081
+ **Returns:** Boolean
1082
+
1083
+ **Example:**
1084
+
1085
+ ```ruby
1086
+ if smtp.has_headers?
1087
+ puts "SMTP profile has #{smtp.header_count} custom headers"
1088
+ end
1089
+ ```
1090
+
1091
+ ##### `#header_count`
1092
+
1093
+ Get the number of custom headers.
1094
+
1095
+ **Returns:** Integer
1096
+
1097
+ **Example:**
1098
+
1099
+ ```ruby
1100
+ puts "Custom headers: #{smtp.header_count}"
1101
+ ```
1102
+
1103
+ ##### `#has_authentication?`
1104
+
1105
+ Check if SMTP profile uses authentication (both username and password are present).
1106
+
1107
+ **Returns:** Boolean
1108
+
1109
+ **Example:**
1110
+
1111
+ ```ruby
1112
+ if smtp.has_authentication?
1113
+ puts "SMTP profile uses authentication"
1114
+ end
1115
+ ```
1116
+
1117
+ ##### `#ignores_cert_errors?`
1118
+
1119
+ Check if SMTP profile ignores SSL certificate errors.
1120
+
1121
+ **Returns:** Boolean
1122
+
1123
+ **Example:**
1124
+
1125
+ ```ruby
1126
+ if smtp.ignores_cert_errors?
1127
+ puts "⚠️ SMTP profile ignores SSL certificate errors"
1128
+ end
1129
+ ```
1130
+
1131
+ #### Usage Examples
1132
+
1133
+ ##### Create a Basic SMTP Profile
1134
+
1135
+ ```ruby
1136
+ smtp = Gophish::Smtp.new(
1137
+ name: "Company Mail Server",
1138
+ host: "smtp.company.com",
1139
+ from_address: "security@company.com"
1140
+ )
1141
+
1142
+ if smtp.save
1143
+ puts "SMTP profile created with ID: #{smtp.id}"
1144
+ else
1145
+ puts "Failed to create SMTP profile: #{smtp.errors.full_messages}"
1146
+ end
1147
+ ```
1148
+
1149
+ ##### Create SMTP Profile with Authentication
1150
+
1151
+ ```ruby
1152
+ smtp = Gophish::Smtp.new(
1153
+ name: "Gmail SMTP",
1154
+ host: "smtp.gmail.com",
1155
+ from_address: "phishing.test@company.com",
1156
+ username: "smtp_user@company.com",
1157
+ password: "app_specific_password",
1158
+ ignore_cert_errors: false
1159
+ )
1160
+
1161
+ puts "Uses authentication: #{smtp.has_authentication?}"
1162
+ puts "Ignores cert errors: #{smtp.ignores_cert_errors?}"
1163
+
1164
+ smtp.save
1165
+ ```
1166
+
1167
+ ##### SMTP Profile with Custom Headers
1168
+
1169
+ ```ruby
1170
+ smtp = Gophish::Smtp.new(
1171
+ name: "Custom Headers SMTP",
1172
+ host: "mail.company.com",
1173
+ from_address: "security@company.com"
1174
+ )
1175
+
1176
+ # Add custom headers for routing and identification
1177
+ smtp.add_header("X-Mailer", "Gophish Security Training")
1178
+ smtp.add_header("X-Campaign-Type", "Phishing Simulation")
1179
+ smtp.add_header("X-Company", "ACME Corp")
1180
+ smtp.add_header("Return-Path", "bounces@company.com")
1181
+
1182
+ puts "Header count: #{smtp.header_count}"
1183
+ puts "Headers: #{smtp.headers.inspect}"
1184
+
1185
+ smtp.save
1186
+ ```
1187
+
1188
+ ##### Update SMTP Profile
1189
+
1190
+ ```ruby
1191
+ smtp = Gophish::Smtp.find(1)
1192
+
1193
+ # Update basic settings
1194
+ smtp.name = "Updated Company SMTP"
1195
+ smtp.ignore_cert_errors = true
1196
+
1197
+ # Add new header
1198
+ smtp.add_header("X-Priority", "High")
1199
+
1200
+ # Remove old header
1201
+ smtp.remove_header("X-Campaign-Type")
1202
+
1203
+ if smtp.save
1204
+ puts "SMTP profile updated successfully"
1205
+ puts "Header count: #{smtp.header_count}"
1206
+ end
1207
+ ```
1208
+
1209
+ ##### SMTP Profile Validation
1210
+
1211
+ ```ruby
1212
+ # Invalid SMTP profile (missing required fields)
1213
+ smtp = Gophish::Smtp.new
1214
+
1215
+ unless smtp.valid?
1216
+ puts "Validation errors:"
1217
+ smtp.errors.full_messages.each { |msg| puts " - #{msg}" }
1218
+ # => ["Name can't be blank", "Host can't be blank", "From address can't be blank"]
1219
+ end
1220
+
1221
+ # Invalid email format
1222
+ smtp = Gophish::Smtp.new(
1223
+ name: "Test SMTP",
1224
+ host: "smtp.test.com",
1225
+ from_address: "invalid-email"
1226
+ )
1227
+
1228
+ unless smtp.valid?
1229
+ puts "Email validation error:"
1230
+ puts smtp.errors[:from_address]
1231
+ # => ["must be a valid email format (email@domain.com)"]
1232
+ end
1233
+
1234
+ # Valid SMTP profile
1235
+ smtp = Gophish::Smtp.new(
1236
+ name: "Valid SMTP",
1237
+ host: "smtp.example.com",
1238
+ from_address: "valid@example.com"
1239
+ )
1240
+
1241
+ puts smtp.valid? # => true
1242
+ ```
1243
+
1244
+ ##### Comprehensive SMTP Configuration
1245
+
1246
+ ```ruby
1247
+ # Production-ready SMTP configuration
1248
+ smtp = Gophish::Smtp.new(
1249
+ name: "Production Mail Server",
1250
+ host: "smtp.company.com",
1251
+ from_address: "security-training@company.com",
1252
+ username: "smtp_service_account",
1253
+ password: ENV['SMTP_PASSWORD'], # Use environment variables for secrets
1254
+ ignore_cert_errors: false, # Always verify certificates in production
1255
+ interface_type: "SMTP"
1256
+ )
1257
+
1258
+ # Add headers for better deliverability and tracking
1259
+ smtp.add_header("X-Mailer", "Gophish Security Training Platform")
1260
+ smtp.add_header("X-Department", "Information Security")
1261
+ smtp.add_header("Return-Path", "bounces+security@company.com")
1262
+ smtp.add_header("Reply-To", "security-team@company.com")
1263
+
1264
+ # Validate before saving
1265
+ if smtp.valid?
1266
+ if smtp.save
1267
+ puts "✓ SMTP profile created successfully!"
1268
+ puts " ID: #{smtp.id}"
1269
+ puts " Name: #{smtp.name}"
1270
+ puts " Host: #{smtp.host}"
1271
+ puts " From: #{smtp.from_address}"
1272
+ puts " Authentication: #{smtp.has_authentication? ? 'Yes' : 'No'}"
1273
+ puts " Custom Headers: #{smtp.header_count}"
1274
+ puts " SSL Verification: #{smtp.ignore_cert_errors? ? 'Disabled' : 'Enabled'}"
1275
+ else
1276
+ puts "✗ Failed to save SMTP profile:"
1277
+ smtp.errors.full_messages.each { |msg| puts " - #{msg}" }
1278
+ end
1279
+ else
1280
+ puts "✗ SMTP validation failed:"
1281
+ smtp.errors.full_messages.each { |msg| puts " - #{msg}" }
1282
+ end
1283
+ ```
1284
+
1285
+ ##### Delete SMTP Profile
1286
+
1287
+ ```ruby
1288
+ smtp = Gophish::Smtp.find(1)
1289
+
1290
+ if smtp.destroy
1291
+ puts "SMTP profile deleted successfully"
1292
+ puts "Profile frozen: #{smtp.frozen?}" # => true
1293
+ end
1294
+ ```
1295
+
1296
+ ##### Security Considerations for SMTP
1297
+
1298
+ ```ruby
1299
+ smtp = Gophish::Smtp.find(1)
1300
+
1301
+ # Security checks
1302
+ puts "🔍 Security Assessment:"
1303
+ puts " Authentication required: #{smtp.has_authentication? ? '✓' : '✗'}"
1304
+ puts " SSL verification: #{smtp.ignore_cert_errors? ? '✗ DISABLED' : '✓ ENABLED'}"
1305
+ puts " From address domain: #{smtp.from_address.split('@').last}"
1306
+
1307
+ if smtp.has_headers?
1308
+ puts " Custom headers (#{smtp.header_count}):"
1309
+ smtp.headers.each do |header|
1310
+ puts " #{header[:key] || header['key']}: #{header[:value] || header['value']}"
1311
+ end
1312
+ end
1313
+
1314
+ # Warn about potential security issues
1315
+ if smtp.ignore_cert_errors?
1316
+ puts "⚠️ WARNING: SSL certificate verification is disabled!"
1317
+ puts " This may allow man-in-the-middle attacks in production."
1318
+ end
1319
+
1320
+ unless smtp.has_authentication?
1321
+ puts "ℹ️ INFO: No authentication configured."
1322
+ puts " Ensure your SMTP server allows unauthenticated sending."
1323
+ end
1324
+ ```
1325
+
1326
+ ## Campaign Class
1327
+
1328
+ The `Gophish::Campaign` class represents a phishing campaign that orchestrates the sending of phishing emails to target groups using templates, landing pages, and SMTP profiles.
1329
+
1330
+ ### Class: `Gophish::Campaign < Gophish::Base`
1331
+
1332
+ #### Attributes
1333
+
1334
+ | Attribute | Type | Required | Description |
1335
+ |-----------|------|----------|-------------|
1336
+ | `id` | Integer | No | Unique campaign identifier (set by server) |
1337
+ | `name` | String | Yes | Campaign name |
1338
+ | `created_date` | String | No | Campaign creation timestamp (set by server) |
1339
+ | `launch_date` | String | No | When the campaign should start sending emails |
1340
+ | `send_by_date` | String | No | Deadline for sending all campaign emails |
1341
+ | `completed_date` | String | No | When the campaign was completed (set by server) |
1342
+ | `template` | Hash/Object | Yes | Reference to email template (can be hash with name or Template instance) |
1343
+ | `page` | Hash/Object | Yes | Reference to landing page (can be hash with name or Page instance) |
1344
+ | `status` | String | No | Current campaign status (e.g., "In progress", "Completed") |
1345
+ | `results` | Array | No | Array of Result instances showing target interactions |
1346
+ | `groups` | Array | Yes | Array of target groups (can be hashes with names or Group instances) |
1347
+ | `timeline` | Array | No | Array of Event instances showing campaign timeline |
1348
+ | `smtp` | Hash/Object | Yes | Reference to SMTP profile (can be hash with name or Smtp instance) |
1349
+ | `url` | String | Yes | Base URL for the campaign |
1350
+
1351
+ #### Validations
1352
+
1353
+ - `name` must be present
1354
+ - `template` must be present (reference to existing template)
1355
+ - `page` must be present (reference to existing landing page)
1356
+ - `groups` must be present and non-empty (references to existing groups)
1357
+ - `smtp` must be present (reference to existing SMTP profile)
1358
+ - `url` must be present
1359
+ - All groups must have names if provided as hashes
1360
+ - All results must have email addresses
1361
+ - All timeline events must have time and message
1362
+
1363
+ #### Class Methods
1364
+
1365
+ ##### `.get_results(id)`
1366
+
1367
+ Get campaign results by campaign ID without loading the full campaign object.
1368
+
1369
+ **Parameters:**
1370
+
1371
+ - `id` (Integer) - Campaign ID
1372
+
1373
+ **Returns:** Array of result hashes
1374
+
1375
+ **Raises:**
1376
+
1377
+ - `StandardError` if campaign not found or API request fails
1378
+
1379
+ **Example:**
1380
+
1381
+ ```ruby
1382
+ results = Gophish::Campaign.get_results(1)
1383
+ puts "Campaign has #{results.length} results"
1384
+ ```
1385
+
1386
+ ##### `.get_summary(id)`
1387
+
1388
+ Get campaign summary statistics by ID without loading the full campaign object.
1389
+
1390
+ **Parameters:**
1391
+
1392
+ - `id` (Integer) - Campaign ID
1393
+
1394
+ **Returns:** Hash of summary statistics
1395
+
1396
+ **Raises:**
1397
+
1398
+ - `StandardError` if campaign not found or API request fails
1399
+
1400
+ **Example:**
1401
+
1402
+ ```ruby
1403
+ summary = Gophish::Campaign.get_summary(1)
1404
+ puts "Campaign stats: #{summary['stats']}"
1405
+ ```
1406
+
1407
+ ##### `.complete(id)`
1408
+
1409
+ Complete a campaign by ID without loading the full campaign object.
1410
+
1411
+ **Parameters:**
1412
+
1413
+ - `id` (Integer) - Campaign ID
1414
+
1415
+ **Returns:** Hash with success status
1416
+
1417
+ **Raises:**
1418
+
1419
+ - `StandardError` if campaign not found or API request fails
1420
+
1421
+ **Example:**
1422
+
1423
+ ```ruby
1424
+ result = Gophish::Campaign.complete(1)
1425
+ puts "Campaign completed: #{result['success']}"
1426
+ ```
1427
+
1428
+ #### Instance Methods
1429
+
1430
+ ##### `#get_results`
1431
+
1432
+ Get detailed campaign results for this campaign instance.
1433
+
1434
+ **Returns:** Array of parsed response data
1435
+
1436
+ **Example:**
1437
+
1438
+ ```ruby
1439
+ campaign = Gophish::Campaign.find(1)
1440
+ results = campaign.get_results
1441
+ puts "Total targets: #{results.length}"
1442
+ ```
1443
+
1444
+ ##### `#get_summary`
1445
+
1446
+ Get campaign summary statistics for this campaign instance.
1447
+
1448
+ **Returns:** Hash of summary data
1449
+
1450
+ **Example:**
1451
+
1452
+ ```ruby
1453
+ campaign = Gophish::Campaign.find(1)
1454
+ summary = campaign.get_summary
1455
+ puts "Campaign summary: #{summary}"
1456
+ ```
1457
+
1458
+ ##### `#complete!`
1459
+
1460
+ Complete the campaign and update the status attribute.
1461
+
1462
+ **Returns:** Hash with success status
1463
+
1464
+ **Side Effects:**
1465
+
1466
+ - Updates `status` attribute to 'Completed' on success
1467
+
1468
+ **Example:**
1469
+
1470
+ ```ruby
1471
+ campaign = Gophish::Campaign.find(1)
1472
+ if campaign.in_progress?
1473
+ result = campaign.complete!
1474
+ puts "Campaign completed: #{result['success']}"
1475
+ puts "New status: #{campaign.status}"
1476
+ end
1477
+ ```
1478
+
1479
+ ##### `#in_progress?`
1480
+
1481
+ Check if campaign is currently running.
1482
+
1483
+ **Returns:** Boolean (true if status is "In progress")
1484
+
1485
+ **Example:**
1486
+
1487
+ ```ruby
1488
+ if campaign.in_progress?
1489
+ puts "Campaign is actively running"
1490
+ end
1491
+ ```
1492
+
1493
+ ##### `#completed?`
1494
+
1495
+ Check if campaign has been completed.
1496
+
1497
+ **Returns:** Boolean (true if status is "Completed")
1498
+
1499
+ **Example:**
1500
+
1501
+ ```ruby
1502
+ if campaign.completed?
1503
+ puts "Campaign has finished"
1504
+ end
1505
+ ```
1506
+
1507
+ ##### `#launched?`
1508
+
1509
+ Check if campaign has a launch date set.
1510
+
1511
+ **Returns:** Boolean (true if launch_date is not blank)
1512
+
1513
+ **Example:**
1514
+
1515
+ ```ruby
1516
+ if campaign.launched?
1517
+ puts "Campaign launched at: #{campaign.launch_date}"
1518
+ end
1519
+ ```
1520
+
1521
+ ##### `#has_send_by_date?`
1522
+
1523
+ Check if campaign has a send-by deadline configured.
1524
+
1525
+ **Returns:** Boolean (true if send_by_date is not blank)
1526
+
1527
+ **Example:**
1528
+
1529
+ ```ruby
1530
+ if campaign.has_send_by_date?
1531
+ puts "Must complete sending by: #{campaign.send_by_date}"
1532
+ end
1533
+ ```
1534
+
1535
+ #### Nested Classes
1536
+
1537
+ ##### `Gophish::Campaign::Result`
1538
+
1539
+ Represents individual target results within a campaign.
1540
+
1541
+ **Attributes:**
1542
+
1543
+ | Attribute | Type | Description |
1544
+ |-----------|------|-------------|
1545
+ | `id` | String | Result identifier |
1546
+ | `first_name` | String | Target's first name |
1547
+ | `last_name` | String | Target's last name |
1548
+ | `position` | String | Target's position |
1549
+ | `email` | String | Target's email address |
1550
+ | `status` | String | Current result status |
1551
+ | `ip` | String | IP address of target interactions |
1552
+ | `latitude` | Float | Geographic latitude |
1553
+ | `longitude` | Float | Geographic longitude |
1554
+ | `send_date` | String | When email was sent |
1555
+ | `reported` | Boolean | Whether target reported the email |
1556
+ | `modified_date` | String | Last modification timestamp |
1557
+
1558
+ **Instance Methods:**
1559
+
1560
+ - `#reported?` - Check if target reported the phishing email
1561
+ - `#clicked?` - Check if target clicked the phishing link (status == "Clicked Link")
1562
+ - `#opened?` - Check if target opened the email (status == "Email Opened")
1563
+ - `#sent?` - Check if email was sent to target (status == "Email Sent")
1564
+ - `#submitted_data?` - Check if target submitted data on landing page (status == "Submitted Data")
1565
+
1566
+ ##### `Gophish::Campaign::Event`
1567
+
1568
+ Represents timeline events within a campaign.
1569
+
1570
+ **Attributes:**
1571
+
1572
+ | Attribute | Type | Description |
1573
+ |-----------|------|-------------|
1574
+ | `email` | String | Target email associated with event |
1575
+ | `time` | String | Event timestamp |
1576
+ | `message` | String | Event description |
1577
+ | `details` | String | Additional event details (JSON string) |
1578
+
1579
+ **Instance Methods:**
1580
+
1581
+ - `#has_details?` - Check if event has additional details
1582
+ - `#parsed_details` - Parse details JSON into hash (returns empty hash on parse error)
1583
+
1584
+ #### Usage Examples
1585
+
1586
+ ##### Create a Basic Campaign
1587
+
1588
+ ```ruby
1589
+ campaign = Gophish::Campaign.new(
1590
+ name: "Q1 Security Awareness Training",
1591
+ template: { name: "Phishing Template" }, # Reference existing template by name
1592
+ page: { name: "Login Page" }, # Reference existing landing page by name
1593
+ groups: [{ name: "Marketing Team" }], # Reference existing groups by name
1594
+ smtp: { name: "Company SMTP" }, # Reference existing SMTP profile by name
1595
+ url: "https://phishing.company.com" # Base URL for campaign
1596
+ )
1597
+
1598
+ if campaign.save
1599
+ puts "Campaign created successfully!"
1600
+ puts " ID: #{campaign.id}"
1601
+ puts " Name: #{campaign.name}"
1602
+ puts " Status: #{campaign.status}"
1603
+ else
1604
+ puts "Failed to create campaign:"
1605
+ campaign.errors.full_messages.each { |msg| puts " - #{msg}" }
1606
+ end
1607
+ ```
1608
+
1609
+ ##### Create a Scheduled Campaign
1610
+
1611
+ ```ruby
1612
+ # Create a campaign with specific launch timing
1613
+ campaign = Gophish::Campaign.new(
1614
+ name: "Scheduled Phishing Test",
1615
+ template: { name: "Email Template" },
1616
+ page: { name: "Landing Page" },
1617
+ groups: [
1618
+ { name: "HR Department" },
1619
+ { name: "Finance Team" }
1620
+ ],
1621
+ smtp: { name: "SMTP Profile" },
1622
+ url: "https://training.company.com",
1623
+ launch_date: "2024-01-15T09:00:00Z", # Start sending at 9 AM
1624
+ send_by_date: "2024-01-15T17:00:00Z" # Finish sending by 5 PM
1625
+ )
1626
+
1627
+ if campaign.save
1628
+ puts "Scheduled campaign created:"
1629
+ puts " Launch Date: #{campaign.launch_date}"
1630
+ puts " Send By Date: #{campaign.send_by_date}"
1631
+ puts " Launched? #{campaign.launched?}"
1632
+ puts " Has send by date? #{campaign.has_send_by_date?}"
1633
+ end
1634
+ ```
1635
+
1636
+ ##### Monitor Campaign Progress
1637
+
1638
+ ```ruby
1639
+ # Load and monitor an existing campaign
1640
+ campaign = Gophish::Campaign.find(1)
1641
+
1642
+ puts "Campaign: #{campaign.name}"
1643
+ puts "Status: #{campaign.status}"
1644
+ puts "In progress? #{campaign.in_progress?}"
1645
+ puts "Completed? #{campaign.completed?}"
1646
+
1647
+ # Get detailed results
1648
+ results = campaign.get_results
1649
+ puts "\nCampaign Results Summary:"
1650
+ puts " Total targets: #{results.length}"
1651
+
1652
+ # Analyze results by status
1653
+ clicked_count = 0
1654
+ opened_count = 0
1655
+ reported_count = 0
1656
+
1657
+ campaign.results.each do |result|
1658
+ clicked_count += 1 if result.clicked?
1659
+ opened_count += 1 if result.opened?
1660
+ reported_count += 1 if result.reported?
1661
+ end
1662
+
1663
+ puts " Clicked links: #{clicked_count}"
1664
+ puts " Opened emails: #{opened_count}"
1665
+ puts " Reported phishing: #{reported_count}"
1666
+ puts " Click rate: #{(clicked_count.to_f / results.length * 100).round(2)}%"
1667
+ ```
1668
+
1669
+ ##### Analyze Campaign Timeline
1670
+
1671
+ ```ruby
1672
+ campaign = Gophish::Campaign.find(1)
1673
+
1674
+ puts "Campaign Timeline:"
1675
+ campaign.timeline.each do |event|
1676
+ puts " #{event.time}: #{event.message}"
1677
+ puts " Email: #{event.email}" if event.email
1678
+
1679
+ # Check for additional event details
1680
+ if event.has_details?
1681
+ details = event.parsed_details
1682
+ puts " Details: #{details.inspect}"
1683
+ end
1684
+ puts ""
1685
+ end
1686
+ ```
1687
+
1688
+ ##### Complete a Running Campaign
1689
+
1690
+ ```ruby
1691
+ campaign = Gophish::Campaign.find(1)
1692
+
1693
+ if campaign.in_progress?
1694
+ puts "Completing campaign '#{campaign.name}'..."
1695
+
1696
+ result = campaign.complete!
1697
+
1698
+ if result['success']
1699
+ puts "✓ Campaign completed successfully"
1700
+ puts " Final status: #{campaign.status}"
1701
+ puts " Completed date: #{campaign.completed_date}"
1702
+ else
1703
+ puts "✗ Failed to complete campaign: #{result['message']}"
1704
+ end
1705
+ else
1706
+ puts "Campaign is not in progress (current status: #{campaign.status})"
1707
+ end
1708
+ ```
1709
+
1710
+ ##### Campaign with Object References
1711
+
1712
+ ```ruby
1713
+ # Create campaign using actual object instances instead of name references
1714
+ template = Gophish::Template.find(1)
1715
+ page = Gophish::Page.find(2)
1716
+ group = Gophish::Group.find(3)
1717
+ smtp = Gophish::Smtp.find(4)
1718
+
1719
+ campaign = Gophish::Campaign.new(
1720
+ name: "Advanced Campaign Setup",
1721
+ template: template, # Full template object
1722
+ page: page, # Full page object
1723
+ groups: [group], # Array of group objects
1724
+ smtp: smtp, # Full SMTP object
1725
+ url: "https://secure.company.com/phishing"
1726
+ )
1727
+
1728
+ # The campaign will automatically serialize these objects appropriately
1729
+ if campaign.save
1730
+ puts "Campaign created using object references"
1731
+ puts "Template: #{campaign.template.name}"
1732
+ puts "Page: #{campaign.page.name}"
1733
+ puts "Groups: #{campaign.groups.map(&:name).join(', ')}"
1734
+ puts "SMTP: #{campaign.smtp.name}"
1735
+ end
1736
+ ```
1737
+
1738
+ ##### Campaign Validation Examples
1739
+
1740
+ ```ruby
1741
+ # Invalid campaign - missing required components
1742
+ incomplete_campaign = Gophish::Campaign.new(name: "Incomplete Campaign")
1743
+
1744
+ unless incomplete_campaign.valid?
1745
+ puts "Validation errors:"
1746
+ incomplete_campaign.errors.full_messages.each { |msg| puts " - #{msg}" }
1747
+ # Output:
1748
+ # - Template can't be blank
1749
+ # - Page can't be blank
1750
+ # - Groups can't be blank
1751
+ # - Smtp can't be blank
1752
+ # - Url can't be blank
1753
+ end
1754
+
1755
+ # Invalid group structure
1756
+ invalid_groups_campaign = Gophish::Campaign.new(
1757
+ name: "Test Campaign",
1758
+ template: { name: "Template" },
1759
+ page: { name: "Page" },
1760
+ groups: [{}], # Invalid: group without name
1761
+ smtp: { name: "SMTP" },
1762
+ url: "https://test.com"
1763
+ )
1764
+
1765
+ unless invalid_groups_campaign.valid?
1766
+ puts "Group validation error:"
1767
+ puts invalid_groups_campaign.errors.full_messages.first
1768
+ # => "Groups item at index 0 must have a name"
1769
+ end
1770
+
1771
+ # Valid campaign
1772
+ valid_campaign = Gophish::Campaign.new(
1773
+ name: "Valid Campaign",
1774
+ template: { name: "Test Template" },
1775
+ page: { name: "Test Page" },
1776
+ groups: [{ name: "Test Group" }],
1777
+ smtp: { name: "Test SMTP" },
1778
+ url: "https://valid.example.com"
1779
+ )
1780
+
1781
+ puts "Campaign valid? #{valid_campaign.valid?}" # => true
1782
+ ```
1783
+
1784
+ ##### Bulk Campaign Operations
1785
+
1786
+ ```ruby
1787
+ # Create multiple campaigns programmatically
1788
+ templates = Gophish::Template.all
1789
+ groups = Gophish::Group.all
1790
+ page = Gophish::Page.find(1)
1791
+ smtp = Gophish::Smtp.find(1)
1792
+
1793
+ campaigns_created = 0
1794
+
1795
+ templates.each do |template|
1796
+ campaign = Gophish::Campaign.new(
1797
+ name: "Auto Campaign - #{template.name}",
1798
+ template: template,
1799
+ page: page,
1800
+ groups: [groups.sample], # Random group for testing
1801
+ smtp: smtp,
1802
+ url: "https://training.company.com",
1803
+ launch_date: (Time.now + 1.hour).iso8601
1804
+ )
1805
+
1806
+ if campaign.save
1807
+ campaigns_created += 1
1808
+ puts "✓ Created campaign: #{campaign.name}"
1809
+ else
1810
+ puts "✗ Failed to create campaign for template #{template.name}:"
1811
+ campaign.errors.full_messages.each { |msg| puts " #{msg}" }
1812
+ end
1813
+ end
1814
+
1815
+ puts "\nCreated #{campaigns_created} campaigns successfully"
1816
+ ```
1817
+
1818
+ ##### Campaign Reporting
1819
+
1820
+ ```ruby
1821
+ # Generate comprehensive campaign report
1822
+ def generate_campaign_report(campaign_id)
1823
+ campaign = Gophish::Campaign.find(campaign_id)
1824
+
1825
+ puts "="*60
1826
+ puts "CAMPAIGN REPORT: #{campaign.name}"
1827
+ puts "="*60
1828
+
1829
+ puts "\nBasic Information:"
1830
+ puts " ID: #{campaign.id}"
1831
+ puts " Status: #{campaign.status}"
1832
+ puts " Created: #{campaign.created_date}"
1833
+ puts " Launched: #{campaign.launch_date || 'Not launched'}"
1834
+ puts " Completed: #{campaign.completed_date || 'Not completed'}"
1835
+
1836
+ puts "\nCampaign Components:"
1837
+ puts " Template: #{campaign.template.name rescue 'Unknown'}"
1838
+ puts " Landing Page: #{campaign.page.name rescue 'Unknown'}"
1839
+ puts " SMTP Profile: #{campaign.smtp.name rescue 'Unknown'}"
1840
+ puts " Target Groups: #{campaign.groups.map(&:name).join(', ') rescue 'Unknown'}"
1841
+
1842
+ puts "\nResults Summary:"
1843
+ total_targets = campaign.results.length
1844
+ puts " Total Targets: #{total_targets}"
1845
+
1846
+ if total_targets > 0
1847
+ sent = campaign.results.count(&:sent?)
1848
+ opened = campaign.results.count(&:opened?)
1849
+ clicked = campaign.results.count(&:clicked?)
1850
+ submitted = campaign.results.count(&:submitted_data?)
1851
+ reported = campaign.results.count(&:reported?)
1852
+
1853
+ puts " Emails Sent: #{sent} (#{(sent.to_f/total_targets*100).round(1)}%)"
1854
+ puts " Emails Opened: #{opened} (#{(opened.to_f/total_targets*100).round(1)}%)"
1855
+ puts " Links Clicked: #{clicked} (#{(clicked.to_f/total_targets*100).round(1)}%)"
1856
+ puts " Data Submitted: #{submitted} (#{(submitted.to_f/total_targets*100).round(1)}%)"
1857
+ puts " Phishing Reported: #{reported} (#{(reported.to_f/total_targets*100).round(1)}%)"
1858
+ end
1859
+
1860
+ puts "\nTimeline Events: #{campaign.timeline.length}"
1861
+ campaign.timeline.last(5).each do |event|
1862
+ puts " #{event.time}: #{event.message}"
1863
+ end
1864
+
1865
+ puts "\n" + "="*60
1866
+ end
1867
+
1868
+ # Usage
1869
+ generate_campaign_report(1)
1870
+ ```
1871
+
947
1872
  ## Error Handling
948
1873
 
949
1874
  ### Validation Errors