gophish-ruby 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +143 -2
- data/docs/API_REFERENCE.md +252 -4
- data/docs/EXAMPLES.md +342 -0
- data/docs/GETTING_STARTED.md +83 -0
- data/lib/gophish/base.rb +6 -24
- data/lib/gophish/group.rb +2 -0
- data/lib/gophish/template.rb +94 -0
- data/lib/gophish/version.rb +1 -1
- data/lib/gophish-ruby.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba7f348fc87e10ad752fe1b59ce329357ca0948dc180b5e5912210fc55a82a44
|
4
|
+
data.tar.gz: bbfd2bad8612b3814f04820c9bcb3e13cf21352b2712e13c85a2cce37c3e4cf5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 697688a9381c1f53c4174e0d3922b4effc5d582dbd56dd0c71d40370126fb287e143ea7ee18fab7856cff52fc19d16ab6514baa04ca8759a3a8e6997cece2b97
|
7
|
+
data.tar.gz: 48965fe82e77390d55df53cbc9c763edc411e055dadcd51fd7852dba49f17ac519b48a7986a021be2b7eb7ca40153a3effee4d5b999887fa400052f31a437d95
|
data/CHANGELOG.md
CHANGED
@@ -8,16 +8,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
10
|
### Added
|
11
|
+
- **Template Management System**
|
12
|
+
- `Gophish::Template` class for managing email templates
|
13
|
+
- Full CRUD operations for templates (create, read, update, delete)
|
14
|
+
- Support for HTML and plain text email content
|
15
|
+
- Comprehensive validations requiring template name and content
|
16
|
+
- Email import functionality with `Template.import_email` class method
|
17
|
+
- Option to convert links during email import for tracking
|
18
|
+
|
19
|
+
- **Attachment Management**
|
20
|
+
- Add attachments to templates with `#add_attachment` method
|
21
|
+
- Remove attachments by name with `#remove_attachment` method
|
22
|
+
- Query attachment status with `#has_attachments?` and `#attachment_count`
|
23
|
+
- Automatic Base64 encoding of attachment content
|
24
|
+
- Validation of attachment structure (content, type, name required)
|
25
|
+
|
26
|
+
- **Enhanced Change Tracking**
|
27
|
+
- Migrated from custom change tracking to ActiveModel::Dirty
|
28
|
+
- Improved change detection with `#changed?` and `#clear_changes_information`
|
29
|
+
- Better integration with Rails-style attribute tracking
|
30
|
+
|
11
31
|
- Comprehensive documentation with getting started guide, API reference, and examples
|
12
32
|
- Enhanced README with detailed usage instructions and configuration examples
|
13
33
|
|
14
34
|
### Changed
|
35
|
+
- **Breaking Change**: Replaced custom `@changed_attributes` system with ActiveModel::Dirty
|
36
|
+
- Updated Base class to use `define_attribute_methods` for proper dirty tracking
|
37
|
+
- Modified `#update_record` to include `id` in update payload for proper API calls
|
15
38
|
- Improved error messages for validation failures
|
16
39
|
- Enhanced CSV import validation with better error reporting
|
17
40
|
|
18
41
|
### Fixed
|
19
42
|
- Console script requiring wrong file name (`gophish_ruby` → `gophish-ruby`)
|
20
43
|
- Spec helper requiring wrong file name for consistent naming
|
44
|
+
- Corrected require statement in main library file for Template class
|
21
45
|
|
22
46
|
## [0.1.0] - 2025-08-29
|
23
47
|
|
data/README.md
CHANGED
@@ -11,9 +11,11 @@ A Ruby SDK for the [Gophish](https://getgophish.com/) phishing simulation platfo
|
|
11
11
|
- **ActiveModel Integration**: Familiar Rails-like attributes, validations, and callbacks
|
12
12
|
- **Automatic Authentication**: Built-in API key authentication for all requests
|
13
13
|
- **CSV Import Support**: Easy bulk import of targets from CSV files
|
14
|
+
- **Email Template Management**: Create, modify, and manage email templates with attachment support
|
15
|
+
- **Email Import**: Import existing emails and convert them to templates
|
14
16
|
- **SSL Configuration**: Configurable SSL verification for development environments
|
15
17
|
- **Debug Support**: Built-in debugging capabilities for API interactions
|
16
|
-
- **Change Tracking**: Automatic tracking of attribute changes
|
18
|
+
- **Change Tracking**: Automatic tracking of attribute changes with ActiveModel::Dirty
|
17
19
|
- **Comprehensive Validation**: Built-in validations for all data models
|
18
20
|
|
19
21
|
## Installation
|
@@ -184,9 +186,110 @@ unless group.valid?
|
|
184
186
|
end
|
185
187
|
```
|
186
188
|
|
189
|
+
### Templates Management
|
190
|
+
|
191
|
+
Templates define the email content for your phishing campaigns, including HTML/text content and attachments.
|
192
|
+
|
193
|
+
#### Creating a Template
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
# Create a new email template
|
197
|
+
template = Gophish::Template.new(
|
198
|
+
name: "Phishing Awareness Test",
|
199
|
+
subject: "Security Update Required",
|
200
|
+
html: "<h1>Important Security Update</h1><p>Please click <a href='{{.URL}}'>here</a> to update your password.</p>",
|
201
|
+
text: "Important Security Update\n\nPlease visit {{.URL}} to update your password."
|
202
|
+
)
|
203
|
+
|
204
|
+
if template.save
|
205
|
+
puts "Template created successfully with ID: #{template.id}"
|
206
|
+
else
|
207
|
+
puts "Failed to create template: #{template.errors.full_messages}"
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
#### Adding Attachments
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
template = Gophish::Template.new(
|
215
|
+
name: "Invoice Template",
|
216
|
+
subject: "Invoice #12345",
|
217
|
+
html: "<p>Please find your invoice attached.</p>"
|
218
|
+
)
|
219
|
+
|
220
|
+
# Add an attachment
|
221
|
+
file_content = File.read("path/to/invoice.pdf")
|
222
|
+
template.add_attachment(file_content, "application/pdf", "invoice.pdf")
|
223
|
+
|
224
|
+
puts "Template has #{template.attachment_count} attachments"
|
225
|
+
```
|
226
|
+
|
227
|
+
#### Managing Attachments
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
# Check if template has attachments
|
231
|
+
if template.has_attachments?
|
232
|
+
puts "Template has attachments"
|
233
|
+
end
|
234
|
+
|
235
|
+
# Remove an attachment by name
|
236
|
+
template.remove_attachment("invoice.pdf")
|
237
|
+
puts "Attachments remaining: #{template.attachment_count}"
|
238
|
+
```
|
239
|
+
|
240
|
+
#### Importing Email Content
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
# Import an existing email (.eml file content)
|
244
|
+
email_content = File.read("path/to/email.eml")
|
245
|
+
|
246
|
+
imported_data = Gophish::Template.import_email(
|
247
|
+
email_content,
|
248
|
+
convert_links: true # Convert links to Gophish tracking format
|
249
|
+
)
|
250
|
+
|
251
|
+
# Create template from imported data
|
252
|
+
template = Gophish::Template.new(imported_data)
|
253
|
+
template.name = "Imported Email Template"
|
254
|
+
template.save
|
255
|
+
```
|
256
|
+
|
257
|
+
#### Retrieving Templates
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
# Get all templates
|
261
|
+
templates = Gophish::Template.all
|
262
|
+
puts "Found #{templates.length} templates"
|
263
|
+
|
264
|
+
# Find a specific template by ID
|
265
|
+
template = Gophish::Template.find(1)
|
266
|
+
puts "Template: #{template.name}"
|
267
|
+
```
|
268
|
+
|
269
|
+
#### Updating a Template
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
template = Gophish::Template.find(1)
|
273
|
+
template.subject = "Updated Subject Line"
|
274
|
+
template.html = "<h1>Updated Content</h1>"
|
275
|
+
|
276
|
+
if template.save
|
277
|
+
puts "Template updated successfully"
|
278
|
+
end
|
279
|
+
```
|
280
|
+
|
281
|
+
#### Deleting a Template
|
282
|
+
|
283
|
+
```ruby
|
284
|
+
template = Gophish::Template.find(1)
|
285
|
+
if template.destroy
|
286
|
+
puts "Template deleted successfully"
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
187
290
|
### Change Tracking
|
188
291
|
|
189
|
-
The SDK automatically tracks changes to attributes:
|
292
|
+
The SDK automatically tracks changes to attributes using ActiveModel::Dirty:
|
190
293
|
|
191
294
|
```ruby
|
192
295
|
group = Gophish::Group.find(1)
|
@@ -258,6 +361,44 @@ Each target in the `targets` array should have:
|
|
258
361
|
|
259
362
|
- `#import_csv(csv_data)` - Import targets from CSV data
|
260
363
|
|
364
|
+
#### `Gophish::Template`
|
365
|
+
|
366
|
+
Represents a Gophish email template.
|
367
|
+
|
368
|
+
**Attributes:**
|
369
|
+
|
370
|
+
- `id` (Integer) - Unique template identifier
|
371
|
+
- `name` (String) - Template name (required)
|
372
|
+
- `subject` (String) - Email subject line
|
373
|
+
- `text` (String) - Plain text email content
|
374
|
+
- `html` (String) - HTML email content
|
375
|
+
- `modified_date` (String) - Last modification timestamp
|
376
|
+
- `attachments` (Array) - Array of attachment hashes
|
377
|
+
|
378
|
+
**Attachment Structure:**
|
379
|
+
Each attachment in the `attachments` array should have:
|
380
|
+
|
381
|
+
- `content` (String) - Base64 encoded file content (required)
|
382
|
+
- `type` (String) - MIME type of the attachment (required)
|
383
|
+
- `name` (String) - Filename of the attachment (required)
|
384
|
+
|
385
|
+
**Class Methods:**
|
386
|
+
|
387
|
+
- `.import_email(content, convert_links: false)` - Import email content and return template data
|
388
|
+
|
389
|
+
**Instance Methods:**
|
390
|
+
|
391
|
+
- `#add_attachment(content, type, name)` - Add an attachment to the template
|
392
|
+
- `#remove_attachment(name)` - Remove an attachment by filename
|
393
|
+
- `#has_attachments?` - Check if template has any attachments
|
394
|
+
- `#attachment_count` - Get the number of attachments
|
395
|
+
|
396
|
+
**Validations:**
|
397
|
+
|
398
|
+
- Template must have a name
|
399
|
+
- Template must have either text or HTML content (or both)
|
400
|
+
- All attachments must have content, type, and name
|
401
|
+
|
261
402
|
## Development
|
262
403
|
|
263
404
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/docs/API_REFERENCE.md
CHANGED
@@ -7,6 +7,7 @@ This document provides detailed API reference for the Gophish Ruby SDK.
|
|
7
7
|
- [Configuration](#configuration)
|
8
8
|
- [Base Class](#base-class)
|
9
9
|
- [Group Class](#group-class)
|
10
|
+
- [Template Class](#template-class)
|
10
11
|
- [Error Handling](#error-handling)
|
11
12
|
- [Examples](#examples)
|
12
13
|
|
@@ -125,7 +126,7 @@ Create or update the resource on the server.
|
|
125
126
|
**Side Effects:**
|
126
127
|
|
127
128
|
- Sets `@persisted` to true on success
|
128
|
-
- Clears
|
129
|
+
- Clears change tracking information on success
|
129
130
|
- Adds errors to `#errors` on failure
|
130
131
|
|
131
132
|
**Example:**
|
@@ -207,7 +208,7 @@ group = Gophish::Group.new
|
|
207
208
|
puts group.new_record? # => true
|
208
209
|
```
|
209
210
|
|
210
|
-
##### `#
|
211
|
+
##### `#changed`
|
211
212
|
|
212
213
|
Get array of attribute names that have changed.
|
213
214
|
|
@@ -218,7 +219,23 @@ Get array of attribute names that have changed.
|
|
218
219
|
```ruby
|
219
220
|
group = Gophish::Group.find(1)
|
220
221
|
group.name = "New Name"
|
221
|
-
puts group.
|
222
|
+
puts group.changed # => ["name"]
|
223
|
+
```
|
224
|
+
|
225
|
+
##### `#changed?`
|
226
|
+
|
227
|
+
Check if any attributes have changed.
|
228
|
+
|
229
|
+
**Returns:** Boolean
|
230
|
+
|
231
|
+
**Example:**
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
group = Gophish::Group.find(1)
|
235
|
+
puts group.changed? # => false
|
236
|
+
|
237
|
+
group.name = "New Name"
|
238
|
+
puts group.changed? # => true
|
222
239
|
```
|
223
240
|
|
224
241
|
##### `#attribute_changed?(attr)`
|
@@ -236,8 +253,8 @@ Check if a specific attribute has changed.
|
|
236
253
|
```ruby
|
237
254
|
group = Gophish::Group.find(1)
|
238
255
|
group.name = "New Name"
|
256
|
+
puts group.name_changed? # => true (using dynamic method)
|
239
257
|
puts group.attribute_changed?(:name) # => true
|
240
|
-
puts group.attribute_changed?("targets") # => false
|
241
258
|
```
|
242
259
|
|
243
260
|
##### `#attribute_was(attr)`
|
@@ -256,6 +273,7 @@ Get the previous value of a changed attribute.
|
|
256
273
|
group = Gophish::Group.find(1)
|
257
274
|
original_name = group.name
|
258
275
|
group.name = "New Name"
|
276
|
+
puts group.name_was # => original_name (using dynamic method)
|
259
277
|
puts group.attribute_was(:name) # => original_name
|
260
278
|
```
|
261
279
|
|
@@ -376,6 +394,236 @@ group.import_csv(csv_content)
|
|
376
394
|
group.save
|
377
395
|
```
|
378
396
|
|
397
|
+
## Template Class
|
398
|
+
|
399
|
+
The `Gophish::Template` class represents an email template in Gophish.
|
400
|
+
|
401
|
+
### Class: `Gophish::Template < Gophish::Base`
|
402
|
+
|
403
|
+
#### Attributes
|
404
|
+
|
405
|
+
| Attribute | Type | Required | Description |
|
406
|
+
|-----------|------|----------|-------------|
|
407
|
+
| `id` | Integer | No | Unique template identifier (set by server) |
|
408
|
+
| `name` | String | Yes | Template name |
|
409
|
+
| `subject` | String | No | Email subject line |
|
410
|
+
| `text` | String | No | Plain text email content |
|
411
|
+
| `html` | String | No | HTML email content |
|
412
|
+
| `modified_date` | String | No | Last modification timestamp (set by server) |
|
413
|
+
| `attachments` | Array | No | Array of attachment hashes |
|
414
|
+
|
415
|
+
#### Attachment Structure
|
416
|
+
|
417
|
+
Each attachment in the `attachments` array must have:
|
418
|
+
|
419
|
+
| Field | Type | Required | Description |
|
420
|
+
|-------|------|----------|-------------|
|
421
|
+
| `content` | String | Yes | Base64 encoded file content |
|
422
|
+
| `type` | String | Yes | MIME type (e.g., "application/pdf") |
|
423
|
+
| `name` | String | Yes | Filename |
|
424
|
+
|
425
|
+
#### Validations
|
426
|
+
|
427
|
+
- `name` must be present
|
428
|
+
- Must have either `text` or `html` content (or both)
|
429
|
+
- Each attachment must be a Hash with required fields (`content`, `type`, `name`)
|
430
|
+
|
431
|
+
#### Class Methods
|
432
|
+
|
433
|
+
##### `.import_email(content, convert_links: false)`
|
434
|
+
|
435
|
+
Import email content and return template data.
|
436
|
+
|
437
|
+
**Parameters:**
|
438
|
+
|
439
|
+
- `content` (String) - Raw email content (.eml format)
|
440
|
+
- `convert_links` (Boolean) - Whether to convert links for Gophish tracking (default: false)
|
441
|
+
|
442
|
+
**Returns:** Hash of template attributes
|
443
|
+
|
444
|
+
**Raises:**
|
445
|
+
|
446
|
+
- `StandardError` if import fails
|
447
|
+
|
448
|
+
**Example:**
|
449
|
+
|
450
|
+
```ruby
|
451
|
+
email_content = File.read("sample.eml")
|
452
|
+
template_data = Gophish::Template.import_email(email_content, convert_links: true)
|
453
|
+
|
454
|
+
template = Gophish::Template.new(template_data)
|
455
|
+
template.name = "Imported Template"
|
456
|
+
template.save
|
457
|
+
```
|
458
|
+
|
459
|
+
#### Instance Methods
|
460
|
+
|
461
|
+
##### `#add_attachment(content, type, name)`
|
462
|
+
|
463
|
+
Add an attachment to the template.
|
464
|
+
|
465
|
+
**Parameters:**
|
466
|
+
|
467
|
+
- `content` (String) - File content (will be Base64 encoded automatically)
|
468
|
+
- `type` (String) - MIME type
|
469
|
+
- `name` (String) - Filename
|
470
|
+
|
471
|
+
**Returns:** Void
|
472
|
+
|
473
|
+
**Side Effects:**
|
474
|
+
|
475
|
+
- Adds attachment to `attachments` array
|
476
|
+
- Marks `attachments` attribute as changed
|
477
|
+
|
478
|
+
**Example:**
|
479
|
+
|
480
|
+
```ruby
|
481
|
+
template = Gophish::Template.new(name: "Test", html: "<p>Test</p>")
|
482
|
+
file_content = File.read("document.pdf")
|
483
|
+
template.add_attachment(file_content, "application/pdf", "document.pdf")
|
484
|
+
```
|
485
|
+
|
486
|
+
##### `#remove_attachment(name)`
|
487
|
+
|
488
|
+
Remove an attachment by filename.
|
489
|
+
|
490
|
+
**Parameters:**
|
491
|
+
|
492
|
+
- `name` (String) - Filename of attachment to remove
|
493
|
+
|
494
|
+
**Returns:** Void
|
495
|
+
|
496
|
+
**Side Effects:**
|
497
|
+
|
498
|
+
- Removes matching attachment(s) from `attachments` array
|
499
|
+
- Marks `attachments` attribute as changed if any were removed
|
500
|
+
|
501
|
+
**Example:**
|
502
|
+
|
503
|
+
```ruby
|
504
|
+
template.remove_attachment("document.pdf")
|
505
|
+
```
|
506
|
+
|
507
|
+
##### `#has_attachments?`
|
508
|
+
|
509
|
+
Check if template has any attachments.
|
510
|
+
|
511
|
+
**Returns:** Boolean
|
512
|
+
|
513
|
+
**Example:**
|
514
|
+
|
515
|
+
```ruby
|
516
|
+
if template.has_attachments?
|
517
|
+
puts "Template has #{template.attachment_count} attachments"
|
518
|
+
end
|
519
|
+
```
|
520
|
+
|
521
|
+
##### `#attachment_count`
|
522
|
+
|
523
|
+
Get the number of attachments.
|
524
|
+
|
525
|
+
**Returns:** Integer
|
526
|
+
|
527
|
+
**Example:**
|
528
|
+
|
529
|
+
```ruby
|
530
|
+
puts "Attachments: #{template.attachment_count}"
|
531
|
+
```
|
532
|
+
|
533
|
+
#### Usage Examples
|
534
|
+
|
535
|
+
##### Create a Template
|
536
|
+
|
537
|
+
```ruby
|
538
|
+
template = Gophish::Template.new(
|
539
|
+
name: "Phishing Test Template",
|
540
|
+
subject: "Important Security Update",
|
541
|
+
html: "<h1>Security Update Required</h1><p>Please click <a href='{{.URL}}'>here</a> to update.</p>",
|
542
|
+
text: "Security Update Required\n\nPlease visit {{.URL}} to update your credentials."
|
543
|
+
)
|
544
|
+
|
545
|
+
if template.save
|
546
|
+
puts "Template created with ID: #{template.id}"
|
547
|
+
end
|
548
|
+
```
|
549
|
+
|
550
|
+
##### Template with Attachments
|
551
|
+
|
552
|
+
```ruby
|
553
|
+
template = Gophish::Template.new(
|
554
|
+
name: "Invoice Template",
|
555
|
+
subject: "Invoice #{{.RId}}",
|
556
|
+
html: "<p>Please find your invoice attached.</p>"
|
557
|
+
)
|
558
|
+
|
559
|
+
# Add PDF attachment
|
560
|
+
pdf_content = File.read("invoice.pdf")
|
561
|
+
template.add_attachment(pdf_content, "application/pdf", "invoice.pdf")
|
562
|
+
|
563
|
+
# Add image attachment
|
564
|
+
image_content = File.read("logo.png")
|
565
|
+
template.add_attachment(image_content, "image/png", "logo.png")
|
566
|
+
|
567
|
+
template.save
|
568
|
+
```
|
569
|
+
|
570
|
+
##### Import from Email
|
571
|
+
|
572
|
+
```ruby
|
573
|
+
# Import existing email
|
574
|
+
email_content = File.read("phishing_template.eml")
|
575
|
+
imported_data = Gophish::Template.import_email(
|
576
|
+
email_content,
|
577
|
+
convert_links: true # Convert links for tracking
|
578
|
+
)
|
579
|
+
|
580
|
+
template = Gophish::Template.new(imported_data)
|
581
|
+
template.name = "Imported Phishing Template"
|
582
|
+
template.save
|
583
|
+
```
|
584
|
+
|
585
|
+
##### Update Template
|
586
|
+
|
587
|
+
```ruby
|
588
|
+
template = Gophish::Template.find(1)
|
589
|
+
template.subject = "Updated Subject"
|
590
|
+
template.html = "<h1>Updated Content</h1>"
|
591
|
+
|
592
|
+
# Add new attachment
|
593
|
+
template.add_attachment(File.read("new_doc.pdf"), "application/pdf", "new_doc.pdf")
|
594
|
+
|
595
|
+
# Remove old attachment
|
596
|
+
template.remove_attachment("old_doc.pdf")
|
597
|
+
|
598
|
+
template.save
|
599
|
+
```
|
600
|
+
|
601
|
+
##### Template Validation
|
602
|
+
|
603
|
+
```ruby
|
604
|
+
# Invalid template (no content)
|
605
|
+
template = Gophish::Template.new(name: "Test Template")
|
606
|
+
|
607
|
+
unless template.valid?
|
608
|
+
puts "Validation errors:"
|
609
|
+
template.errors.full_messages.each { |msg| puts " - #{msg}" }
|
610
|
+
# => ["Need to specify at least plaintext or HTML content"]
|
611
|
+
end
|
612
|
+
|
613
|
+
# Invalid attachment
|
614
|
+
template = Gophish::Template.new(
|
615
|
+
name: "Test",
|
616
|
+
html: "<p>Test</p>",
|
617
|
+
attachments: [{ name: "file.pdf" }] # Missing content and type
|
618
|
+
)
|
619
|
+
|
620
|
+
unless template.valid?
|
621
|
+
puts template.errors.full_messages
|
622
|
+
# => ["Attachments item at index 0 must have a content",
|
623
|
+
# "Attachments item at index 0 must have a type"]
|
624
|
+
end
|
625
|
+
```
|
626
|
+
|
379
627
|
## Error Handling
|
380
628
|
|
381
629
|
### Validation Errors
|
data/docs/EXAMPLES.md
CHANGED
@@ -6,6 +6,7 @@ This document contains practical examples for common use cases with the Gophish
|
|
6
6
|
|
7
7
|
- [Basic Operations](#basic-operations)
|
8
8
|
- [CSV Operations](#csv-operations)
|
9
|
+
- [Template Operations](#template-operations)
|
9
10
|
- [Error Handling](#error-handling)
|
10
11
|
- [Advanced Scenarios](#advanced-scenarios)
|
11
12
|
- [Production Examples](#production-examples)
|
@@ -252,6 +253,347 @@ end
|
|
252
253
|
group = import_large_csv("large_employee_list.csv", "All Company Employees")
|
253
254
|
```
|
254
255
|
|
256
|
+
## Template Operations
|
257
|
+
|
258
|
+
### Basic Template Creation
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
# Simple text and HTML template
|
262
|
+
template = Gophish::Template.new(
|
263
|
+
name: "Security Awareness Training",
|
264
|
+
subject: "Important Security Update - Action Required",
|
265
|
+
html: <<~HTML,
|
266
|
+
<h1>Security Update Required</h1>
|
267
|
+
<p>Dear {{.FirstName}},</p>
|
268
|
+
<p>We have detected suspicious activity on your account. Please click <a href="{{.URL}}">here</a> to verify your account immediately.</p>
|
269
|
+
<p>This link will expire in 24 hours.</p>
|
270
|
+
<p>Best regards,<br>IT Security Team</p>
|
271
|
+
HTML
|
272
|
+
text: <<~TEXT
|
273
|
+
Security Update Required
|
274
|
+
|
275
|
+
Dear {{.FirstName}},
|
276
|
+
|
277
|
+
We have detected suspicious activity on your account. Please visit {{.URL}} to verify your account immediately.
|
278
|
+
|
279
|
+
This link will expire in 24 hours.
|
280
|
+
|
281
|
+
Best regards,
|
282
|
+
IT Security Team
|
283
|
+
TEXT
|
284
|
+
)
|
285
|
+
|
286
|
+
if template.save
|
287
|
+
puts "✓ Template '#{template.name}' created with ID: #{template.id}"
|
288
|
+
else
|
289
|
+
puts "✗ Failed to create template: #{template.errors.full_messages}"
|
290
|
+
end
|
291
|
+
```
|
292
|
+
|
293
|
+
### Template with Attachments
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
# Create template with multiple attachments
|
297
|
+
template = Gophish::Template.new(
|
298
|
+
name: "Invoice Phishing Template",
|
299
|
+
subject: "Invoice #{{.RId}} - Payment Due",
|
300
|
+
html: "<h1>Invoice Attached</h1><p>Dear {{.FirstName}},</p><p>Please find your invoice attached for immediate payment.</p>"
|
301
|
+
)
|
302
|
+
|
303
|
+
# Add PDF invoice attachment
|
304
|
+
pdf_content = File.read("sample_invoice.pdf")
|
305
|
+
template.add_attachment(pdf_content, "application/pdf", "invoice_#{Time.now.strftime('%Y%m%d')}.pdf")
|
306
|
+
|
307
|
+
# Add company logo
|
308
|
+
logo_content = File.read("company_logo.png")
|
309
|
+
template.add_attachment(logo_content, "image/png", "logo.png")
|
310
|
+
|
311
|
+
# Add fake Excel spreadsheet
|
312
|
+
excel_content = File.read("expense_report.xlsx")
|
313
|
+
template.add_attachment(excel_content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Q4_expenses.xlsx")
|
314
|
+
|
315
|
+
puts "Template has #{template.attachment_count} attachments"
|
316
|
+
|
317
|
+
if template.save
|
318
|
+
puts "✓ Template with attachments created successfully"
|
319
|
+
end
|
320
|
+
```
|
321
|
+
|
322
|
+
### Email Import from .EML Files
|
323
|
+
|
324
|
+
```ruby
|
325
|
+
# Import existing phishing email
|
326
|
+
def import_phishing_template(eml_file_path, template_name)
|
327
|
+
unless File.exist?(eml_file_path)
|
328
|
+
puts "✗ EML file not found: #{eml_file_path}"
|
329
|
+
return nil
|
330
|
+
end
|
331
|
+
|
332
|
+
email_content = File.read(eml_file_path)
|
333
|
+
|
334
|
+
# Import with link conversion for tracking
|
335
|
+
begin
|
336
|
+
imported_data = Gophish::Template.import_email(email_content, convert_links: true)
|
337
|
+
rescue StandardError => e
|
338
|
+
puts "✗ Email import failed: #{e.message}"
|
339
|
+
return nil
|
340
|
+
end
|
341
|
+
|
342
|
+
# Create template from imported data
|
343
|
+
template = Gophish::Template.new(imported_data)
|
344
|
+
template.name = template_name
|
345
|
+
|
346
|
+
if template.valid?
|
347
|
+
if template.save
|
348
|
+
puts "✓ Successfully imported template '#{template.name}'"
|
349
|
+
puts " Subject: #{template.subject}"
|
350
|
+
puts " Has HTML: #{!template.html.nil?}"
|
351
|
+
puts " Has Text: #{!template.text.nil?}"
|
352
|
+
puts " Attachments: #{template.attachment_count}"
|
353
|
+
return template
|
354
|
+
else
|
355
|
+
puts "✗ Save failed: #{template.errors.full_messages}"
|
356
|
+
end
|
357
|
+
else
|
358
|
+
puts "✗ Validation failed: #{template.errors.full_messages}"
|
359
|
+
end
|
360
|
+
|
361
|
+
nil
|
362
|
+
end
|
363
|
+
|
364
|
+
# Usage
|
365
|
+
template = import_phishing_template("phishing_email.eml", "Imported Phishing Template")
|
366
|
+
```
|
367
|
+
|
368
|
+
### Template Management Operations
|
369
|
+
|
370
|
+
```ruby
|
371
|
+
# List all existing templates
|
372
|
+
def list_templates
|
373
|
+
templates = Gophish::Template.all
|
374
|
+
puts "Found #{templates.length} templates:"
|
375
|
+
|
376
|
+
templates.each do |template|
|
377
|
+
attachment_info = template.has_attachments? ? " (#{template.attachment_count} attachments)" : ""
|
378
|
+
puts " #{template.id}: #{template.name}#{attachment_info}"
|
379
|
+
puts " Subject: #{template.subject}" if template.subject
|
380
|
+
puts " Modified: #{template.modified_date}" if template.modified_date
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Update existing template
|
385
|
+
def update_template(template_id, new_subject = nil, new_html = nil)
|
386
|
+
begin
|
387
|
+
template = Gophish::Template.find(template_id)
|
388
|
+
rescue StandardError
|
389
|
+
puts "✗ Template #{template_id} not found"
|
390
|
+
return false
|
391
|
+
end
|
392
|
+
|
393
|
+
puts "Updating template '#{template.name}'"
|
394
|
+
|
395
|
+
template.subject = new_subject if new_subject
|
396
|
+
template.html = new_html if new_html
|
397
|
+
|
398
|
+
if template.save
|
399
|
+
puts "✓ Template updated successfully"
|
400
|
+
true
|
401
|
+
else
|
402
|
+
puts "✗ Update failed: #{template.errors.full_messages}"
|
403
|
+
false
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# Clone template with modifications
|
408
|
+
def clone_template(original_id, new_name, modifications = {})
|
409
|
+
begin
|
410
|
+
original = Gophish::Template.find(original_id)
|
411
|
+
rescue StandardError
|
412
|
+
puts "✗ Original template #{original_id} not found"
|
413
|
+
return nil
|
414
|
+
end
|
415
|
+
|
416
|
+
# Create new template with same content
|
417
|
+
new_template = Gophish::Template.new(
|
418
|
+
name: new_name,
|
419
|
+
subject: original.subject,
|
420
|
+
html: original.html,
|
421
|
+
text: original.text
|
422
|
+
)
|
423
|
+
|
424
|
+
# Apply modifications
|
425
|
+
modifications.each do |field, value|
|
426
|
+
new_template.send("#{field}=", value) if new_template.respond_to?("#{field}=")
|
427
|
+
end
|
428
|
+
|
429
|
+
# Copy attachments
|
430
|
+
if original.has_attachments?
|
431
|
+
original.attachments.each do |attachment|
|
432
|
+
new_template.attachments << attachment.dup
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
if new_template.save
|
437
|
+
puts "✓ Template cloned as '#{new_name}' (ID: #{new_template.id})"
|
438
|
+
new_template
|
439
|
+
else
|
440
|
+
puts "✗ Clone failed: #{new_template.errors.full_messages}"
|
441
|
+
nil
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# Usage examples
|
446
|
+
list_templates
|
447
|
+
update_template(1, "Updated Subject Line", "<h1>Updated HTML content</h1>")
|
448
|
+
clone_template(1, "Modified Version", { subject: "Modified Subject" })
|
449
|
+
```
|
450
|
+
|
451
|
+
### Template Validation and Error Handling
|
452
|
+
|
453
|
+
```ruby
|
454
|
+
# Comprehensive template validation
|
455
|
+
def validate_template_thoroughly(template)
|
456
|
+
puts "Validating template '#{template.name}'"
|
457
|
+
|
458
|
+
# Basic validation
|
459
|
+
unless template.valid?
|
460
|
+
puts "✗ Basic validation failed:"
|
461
|
+
template.errors.full_messages.each { |error| puts " - #{error}" }
|
462
|
+
return false
|
463
|
+
end
|
464
|
+
|
465
|
+
# Content validation
|
466
|
+
has_html = !template.html.nil? && !template.html.strip.empty?
|
467
|
+
has_text = !template.text.nil? && !template.text.strip.empty?
|
468
|
+
|
469
|
+
unless has_html || has_text
|
470
|
+
puts "✗ Template has no content (neither HTML nor text)"
|
471
|
+
return false
|
472
|
+
end
|
473
|
+
|
474
|
+
# Gophish template variable validation
|
475
|
+
content = "#{template.html} #{template.text} #{template.subject}"
|
476
|
+
|
477
|
+
# Check for common Gophish template variables
|
478
|
+
variables_found = content.scan(/\{\{\.(\w+)\}\}/).flatten.uniq
|
479
|
+
puts " Found template variables: #{variables_found.join(', ')}" if variables_found.any?
|
480
|
+
|
481
|
+
# Warn about missing tracking URL
|
482
|
+
unless content.include?('{{.URL}}')
|
483
|
+
puts " ⚠ Warning: No {{.URL}} tracking variable found"
|
484
|
+
end
|
485
|
+
|
486
|
+
# Attachment validation
|
487
|
+
if template.has_attachments?
|
488
|
+
puts " Validating #{template.attachment_count} attachments:"
|
489
|
+
template.attachments.each_with_index do |attachment, index|
|
490
|
+
name = attachment[:name] || attachment['name']
|
491
|
+
type = attachment[:type] || attachment['type']
|
492
|
+
content = attachment[:content] || attachment['content']
|
493
|
+
|
494
|
+
puts " #{index + 1}. #{name} (#{type})"
|
495
|
+
|
496
|
+
if content.nil? || content.empty?
|
497
|
+
puts " ✗ Missing content"
|
498
|
+
return false
|
499
|
+
end
|
500
|
+
|
501
|
+
# Validate Base64 encoding
|
502
|
+
begin
|
503
|
+
Base64.strict_decode64(content)
|
504
|
+
puts " ✓ Valid Base64 encoding"
|
505
|
+
rescue ArgumentError
|
506
|
+
puts " ✗ Invalid Base64 encoding"
|
507
|
+
return false
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
puts "✓ Template validation passed"
|
513
|
+
true
|
514
|
+
end
|
515
|
+
|
516
|
+
# Test various template scenarios
|
517
|
+
def test_template_scenarios
|
518
|
+
# Valid template
|
519
|
+
valid_template = Gophish::Template.new(
|
520
|
+
name: "Valid Template",
|
521
|
+
subject: "Test {{.FirstName}}",
|
522
|
+
html: "<p>Click {{.URL}} to continue</p>",
|
523
|
+
text: "Visit {{.URL}} to continue"
|
524
|
+
)
|
525
|
+
validate_template_thoroughly(valid_template)
|
526
|
+
|
527
|
+
# Invalid template (no content)
|
528
|
+
invalid_template = Gophish::Template.new(
|
529
|
+
name: "Invalid Template",
|
530
|
+
subject: "Test"
|
531
|
+
)
|
532
|
+
validate_template_thoroughly(invalid_template)
|
533
|
+
|
534
|
+
# Template with attachment
|
535
|
+
template_with_attachment = Gophish::Template.new(
|
536
|
+
name: "Attachment Template",
|
537
|
+
html: "<p>See attachment</p>"
|
538
|
+
)
|
539
|
+
template_with_attachment.add_attachment("Hello World", "text/plain", "test.txt")
|
540
|
+
validate_template_thoroughly(template_with_attachment)
|
541
|
+
end
|
542
|
+
|
543
|
+
test_template_scenarios
|
544
|
+
```
|
545
|
+
|
546
|
+
### Bulk Template Operations
|
547
|
+
|
548
|
+
```ruby
|
549
|
+
# Create multiple templates from a configuration
|
550
|
+
def create_template_suite(campaign_name)
|
551
|
+
templates = [
|
552
|
+
{
|
553
|
+
name: "#{campaign_name} - Initial Email",
|
554
|
+
subject: "Important Account Update Required",
|
555
|
+
html: "<h1>Account Update</h1><p>Dear {{.FirstName}}, please update your account by clicking <a href='{{.URL}}'>here</a>.</p>",
|
556
|
+
text: "Dear {{.FirstName}}, please update your account by visiting {{.URL}}"
|
557
|
+
},
|
558
|
+
{
|
559
|
+
name: "#{campaign_name} - Follow-up",
|
560
|
+
subject: "URGENT: Account Suspension Notice",
|
561
|
+
html: "<h1 style='color: red;'>URGENT</h1><p>Your account will be suspended in 24 hours. Verify immediately: {{.URL}}</p>",
|
562
|
+
text: "URGENT: Your account will be suspended in 24 hours. Verify at {{.URL}}"
|
563
|
+
},
|
564
|
+
{
|
565
|
+
name: "#{campaign_name} - Final Warning",
|
566
|
+
subject: "Final Warning - Account Closure",
|
567
|
+
html: "<h1>Final Warning</h1><p>This is your last chance to save your account: {{.URL}}</p>",
|
568
|
+
text: "Final Warning: Last chance to save your account at {{.URL}}"
|
569
|
+
}
|
570
|
+
]
|
571
|
+
|
572
|
+
created_templates = []
|
573
|
+
|
574
|
+
templates.each_with_index do |template_data, index|
|
575
|
+
puts "Creating template #{index + 1}/#{templates.length}: #{template_data[:name]}"
|
576
|
+
|
577
|
+
template = Gophish::Template.new(template_data)
|
578
|
+
|
579
|
+
if template.save
|
580
|
+
puts " ✓ Created with ID: #{template.id}"
|
581
|
+
created_templates << template
|
582
|
+
else
|
583
|
+
puts " ✗ Failed: #{template.errors.full_messages}"
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
puts "\nTemplate suite '#{campaign_name}' creation completed"
|
588
|
+
puts "Successfully created: #{created_templates.length}/#{templates.length} templates"
|
589
|
+
|
590
|
+
created_templates
|
591
|
+
end
|
592
|
+
|
593
|
+
# Usage
|
594
|
+
suite = create_template_suite("Q4 Security Training")
|
595
|
+
```
|
596
|
+
|
255
597
|
## Error Handling
|
256
598
|
|
257
599
|
### Comprehensive Error Handling
|
data/docs/GETTING_STARTED.md
CHANGED
@@ -84,6 +84,27 @@ else
|
|
84
84
|
end
|
85
85
|
```
|
86
86
|
|
87
|
+
### 4. Create Your First Template
|
88
|
+
|
89
|
+
Templates define the email content for your phishing campaigns:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
# Create a basic email template
|
93
|
+
template = Gophish::Template.new(
|
94
|
+
name: "Security Awareness Test",
|
95
|
+
subject: "Important Security Update Required",
|
96
|
+
html: "<h1>Security Update</h1><p>Please click <a href='{{.URL}}'>here</a> to update your password.</p>",
|
97
|
+
text: "Security Update\n\nPlease visit {{.URL}} to update your password."
|
98
|
+
)
|
99
|
+
|
100
|
+
if template.save
|
101
|
+
puts "✓ Template created successfully with ID: #{template.id}"
|
102
|
+
else
|
103
|
+
puts "✗ Failed to create template:"
|
104
|
+
template.errors.full_messages.each { |error| puts " - #{error}" }
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
87
108
|
## Common Workflows
|
88
109
|
|
89
110
|
### Importing Targets from CSV
|
@@ -125,6 +146,68 @@ else
|
|
125
146
|
end
|
126
147
|
```
|
127
148
|
|
149
|
+
### Working with Templates
|
150
|
+
|
151
|
+
#### Creating Templates with Attachments
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
# Create template with file attachments
|
155
|
+
template = Gophish::Template.new(
|
156
|
+
name: "Invoice Template",
|
157
|
+
subject: "Your Invoice #{{.RId}}",
|
158
|
+
html: "<p>Dear {{.FirstName}},</p><p>Please find your invoice attached.</p>"
|
159
|
+
)
|
160
|
+
|
161
|
+
# Add PDF attachment
|
162
|
+
pdf_content = File.read("sample_invoice.pdf")
|
163
|
+
template.add_attachment(pdf_content, "application/pdf", "invoice.pdf")
|
164
|
+
|
165
|
+
# Check attachments
|
166
|
+
puts "Template has #{template.attachment_count} attachments" if template.has_attachments?
|
167
|
+
|
168
|
+
template.save
|
169
|
+
```
|
170
|
+
|
171
|
+
#### Importing Email Templates
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
# Import an existing email (.eml file)
|
175
|
+
email_content = File.read("phishing_template.eml")
|
176
|
+
|
177
|
+
imported_data = Gophish::Template.import_email(
|
178
|
+
email_content,
|
179
|
+
convert_links: true # Convert links for Gophish tracking
|
180
|
+
)
|
181
|
+
|
182
|
+
template = Gophish::Template.new(imported_data)
|
183
|
+
template.name = "Imported Email Template"
|
184
|
+
template.save
|
185
|
+
|
186
|
+
puts "Imported template: #{template.name}"
|
187
|
+
```
|
188
|
+
|
189
|
+
#### Managing Existing Templates
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# List all templates
|
193
|
+
puts "Existing templates:"
|
194
|
+
Gophish::Template.all.each do |template|
|
195
|
+
attachment_info = template.has_attachments? ? " (#{template.attachment_count} attachments)" : ""
|
196
|
+
puts " #{template.id}: #{template.name}#{attachment_info}"
|
197
|
+
end
|
198
|
+
|
199
|
+
# Update a template
|
200
|
+
template = Gophish::Template.find(1)
|
201
|
+
template.subject = "Updated Subject Line"
|
202
|
+
template.html = "<h1>Updated Content</h1><p>New message content here.</p>"
|
203
|
+
|
204
|
+
# Add or remove attachments
|
205
|
+
template.add_attachment(File.read("new_file.pdf"), "application/pdf", "new_file.pdf")
|
206
|
+
template.remove_attachment("old_file.pdf")
|
207
|
+
|
208
|
+
template.save
|
209
|
+
```
|
210
|
+
|
128
211
|
### Managing Existing Groups
|
129
212
|
|
130
213
|
```ruby
|
data/lib/gophish/base.rb
CHANGED
@@ -13,12 +13,13 @@ module Gophish
|
|
13
13
|
include ActiveModel::Model
|
14
14
|
include ActiveModel::Attributes
|
15
15
|
include ActiveModel::Validations
|
16
|
+
include ActiveModel::Dirty
|
16
17
|
include ActiveRecord::Callbacks
|
17
18
|
|
18
19
|
def initialize(attributes = {})
|
19
20
|
@persisted = false
|
20
|
-
@changed_attributes = {}
|
21
21
|
super(attributes)
|
22
|
+
clear_changes_information
|
22
23
|
end
|
23
24
|
|
24
25
|
def self.configuration
|
@@ -125,7 +126,7 @@ module Gophish
|
|
125
126
|
send "#{key}=", value if respond_to? "#{key}="
|
126
127
|
end
|
127
128
|
@persisted = true
|
128
|
-
|
129
|
+
clear_changes_information
|
129
130
|
end
|
130
131
|
|
131
132
|
def handle_error_response(response)
|
@@ -145,9 +146,9 @@ module Gophish
|
|
145
146
|
|
146
147
|
def update_record
|
147
148
|
return false if id.nil?
|
148
|
-
return true
|
149
|
+
return true unless changed?
|
149
150
|
|
150
|
-
response = self.class.put "#{self.class.resource_path}/#{id}
|
151
|
+
response = self.class.put "#{self.class.resource_path}/#{id}", request_options(body_for_update)
|
151
152
|
return handle_error_response response unless response.success?
|
152
153
|
|
153
154
|
update_attributes_from_response response.parsed_response
|
@@ -177,29 +178,10 @@ module Gophish
|
|
177
178
|
end
|
178
179
|
|
179
180
|
def body_for_update
|
180
|
-
body_for_create
|
181
|
-
end
|
182
|
-
|
183
|
-
def attribute_changed?(attribute)
|
184
|
-
@changed_attributes.key? attribute.to_s
|
185
|
-
end
|
186
|
-
|
187
|
-
def changed_attributes
|
188
|
-
@changed_attributes.keys
|
189
|
-
end
|
190
|
-
|
191
|
-
def attribute_was(attribute)
|
192
|
-
@changed_attributes[attribute.to_s]
|
181
|
+
body_for_create.merge id:
|
193
182
|
end
|
194
183
|
|
195
184
|
def []=(attribute, value)
|
196
|
-
attribute_str = attribute.to_s
|
197
|
-
current_value = send attribute if respond_to? attribute
|
198
|
-
|
199
|
-
unless current_value == value
|
200
|
-
@changed_attributes[attribute_str] = current_value
|
201
|
-
end
|
202
|
-
|
203
185
|
send "#{attribute}=", value if respond_to? "#{attribute}="
|
204
186
|
end
|
205
187
|
end
|
data/lib/gophish/group.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Gophish
|
6
|
+
class Template < Base
|
7
|
+
attribute :id, :integer
|
8
|
+
attribute :name, :string
|
9
|
+
attribute :subject, :string
|
10
|
+
attribute :text, :string
|
11
|
+
attribute :html, :string
|
12
|
+
attribute :modified_date, :string
|
13
|
+
attribute :attachments, default: -> { [] }
|
14
|
+
|
15
|
+
define_attribute_methods :id, :name, :subject, :text, :html, :modified_date, :attachments
|
16
|
+
|
17
|
+
validates :name, presence: true
|
18
|
+
validate :validate_content_presence
|
19
|
+
validate :validate_attachments_structure
|
20
|
+
|
21
|
+
def body_for_create
|
22
|
+
{ name:, subject:, text:, html:, attachments: }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.import_email(content, convert_links: false)
|
26
|
+
options = build_import_options content, convert_links
|
27
|
+
response = post '/import/email', options
|
28
|
+
raise StandardError, 'Failed to import email' unless response.success?
|
29
|
+
|
30
|
+
response.parsed_response
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.build_import_options(content, convert_links)
|
34
|
+
{
|
35
|
+
body: { content:, convert_links: }.to_json,
|
36
|
+
headers: { 'Content-Type' => 'application/json' }
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_attachment(content, type, name)
|
41
|
+
encoded_content = encode_content content
|
42
|
+
attachments << { content: encoded_content, type:, name: }
|
43
|
+
attachments_will_change!
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove_attachment(name)
|
47
|
+
original_size = attachments.size
|
48
|
+
attachments.reject! { |attachment| attachment[:name] == name || attachment['name'] == name }
|
49
|
+
attachments_will_change! if attachments.size != original_size
|
50
|
+
end
|
51
|
+
|
52
|
+
def has_attachments?
|
53
|
+
!attachments.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def attachment_count
|
57
|
+
attachments.length
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def encode_content(content)
|
63
|
+
content.is_a?(String) ? Base64.strict_encode64(content) : content
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_content_presence
|
67
|
+
return unless text.blank? && html.blank?
|
68
|
+
|
69
|
+
errors.add :base, 'Need to specify at least plaintext or HTML content'
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_attachments_structure
|
73
|
+
return if attachments.blank?
|
74
|
+
return errors.add :attachments, 'must be an array' unless attachments.is_a? Array
|
75
|
+
|
76
|
+
attachments.each_with_index { |attachment, index| validate_attachment attachment, index }
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate_attachment(attachment, index)
|
80
|
+
return errors.add :attachments, "item at index #{index} must be a hash" unless attachment.is_a? Hash
|
81
|
+
|
82
|
+
validate_attachment_field attachment, index, :content
|
83
|
+
validate_attachment_field attachment, index, :type
|
84
|
+
validate_attachment_field attachment, index, :name
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_attachment_field(attachment, index, field)
|
88
|
+
value = attachment[field] || attachment[field.to_s]
|
89
|
+
return unless value.blank?
|
90
|
+
|
91
|
+
errors.add :attachments, "item at index #{index} must have a #{field}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/gophish/version.rb
CHANGED
data/lib/gophish-ruby.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gophish-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eli Sebastian Herrera Aguilar
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- lib/gophish/base.rb
|
106
106
|
- lib/gophish/configuration.rb
|
107
107
|
- lib/gophish/group.rb
|
108
|
+
- lib/gophish/template.rb
|
108
109
|
- lib/gophish/version.rb
|
109
110
|
- sig/gophish/ruby.rbs
|
110
111
|
homepage: https://github.com/EliSebastian/gopish-ruby
|