Skip to content

Commit

Permalink
Add testing api support (#20)
Browse files Browse the repository at this point in the history
* Add Sending::Client enhancements for bulk and sandbox API support (w/o tests)

* Remove Sending module

* Add tests for bulk and sandbox

* Updated CHANGELOG.md

* Create examples folder

* Fixes

* Exclude examples folder from gem build

* Add a test case

* Fixes

* Change version

---------

Co-authored-by: Victor Zagorodny <[email protected]>
  • Loading branch information
Artheanos and vittorius authored Mar 27, 2024
1 parent 1fd0e2a commit 705b4a2
Show file tree
Hide file tree
Showing 32 changed files with 565 additions and 280 deletions.
8 changes: 8 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@ Style/StringLiterals:
Style/StringLiteralsInInterpolation:
Enabled: true
EnforcedStyle: double_quotes

Style/FrozenStringLiteralComment:
Exclude:
- 'examples/**/*'

Style/TrailingCommaInHashLiteral:
Exclude:
- 'examples/**/*'
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## [2.0.0] - 2024-03-20

- Added arguments for `Mailtrap::Client`
- `bulk` to use Mailtrap bulk sending API
- `sandbox` to use Mailtrap sandbox API
- `inbox_id` required when using Mailtrap sandbox API

- Removed Sending namespace, affected classes:
- `Mailtrap::Sending::Client` -> `Mailtrap::Client`
- `Mailtrap::Sending::Error` -> `Mailtrap::Error`
- `Mailtrap::Sending::AttachmentContentError` -> `Mailtrap::AttachmentContentError`
- `Mailtrap::Sending::AuthorizationError` -> `Mailtrap::AuthorizationError`
- `Mailtrap::Sending::MailSizeError` -> `Mailtrap::MailSizeError`
- `Mailtrap::Sending::RateLimitError` -> `Mailtrap::RateLimitError`
- `Mailtrap::Sending::RejectionError` -> `Mailtrap::RejectionError`

## [1.2.2] - 2023-11-01

- Improved error handling
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
mailtrap (1.2.2)
mailtrap (2.0.0)

GEM
remote: https://rubygems.org/
Expand Down
100 changes: 14 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This Ruby gem offers integration with the [official API](https://api-docs.mailtr

Quickly add email sending functionality to your Ruby application with Mailtrap.

(This client uses API v2, for v1 refer to [this documentation](https://mailtrap.docs.apiary.io/))

## Installation

Add this line to your application's Gemfile:
Expand Down Expand Up @@ -40,97 +42,17 @@ mail = Mailtrap::Mail::Base.new(
)

# create client and send
client = Mailtrap::Sending::Client.new(api_key: 'your-api-key')
client = Mailtrap::Client.new(api_key: 'your-api-key')
client.send(mail)
```

### Full
Refer to the [`examples`](examples) folder for other examples.

```ruby
require 'mailtrap'
require 'base64'
- [Full](examples/full.rb)
- [Email template](examples/email_template.rb)
- [ActionMailer](examples/action_mailer.rb)

mail = Mailtrap::Mail::Base.new(
from: { email: '[email protected]', name: 'Mailtrap Test' },
to: [
{ email: '[email protected]', name: 'Your name' }
],
cc: [
{ email: '[email protected]', name: 'Copy To' }
],
bcc: [
{ email: '[email protected]', name: 'Hidden Recipient' }
],
subject: 'You are awesome!',
text: "Congrats for sending test email with Mailtrap!",
category: "Integration Test",
attachments: [
{
content: Base64.encode64('Attachment content'), # base64 encoded content or IO string
filename: 'attachment.txt'
}
],
headers: {
'X-MT-Header': 'Custom header'
},
custom_variables: {
year: 2022
}
)

data = File.open('/path/to/image.jpg').read
encoded = Base64.encode64(data).gsub(/\n/,"")

mail.add_attachment(content: encoded, filename: 'image.png')

client = Mailtrap::Sending::Client.new(api_key: 'your-api-key')
client.send(mail)
```

### Using email template

```ruby
require 'mailtrap'

# create mail object
mail = Mailtrap::Mail::FromTemplate.new(
from: { email: '[email protected]', name: 'Mailtrap Test' },
to: [
{ email: '[email protected]' }
],
template_uuid: '2f45b0aa-bbed-432f-95e4-e145e1965ba2',
template_variables: {
'user_name' => 'John Doe'
}
)

# create client and send
client = Mailtrap::Sending::Client.new(api_key: 'your-api-key')
client.send(mail)
```

### ActionMailer

This gem also adds ActionMailer delivery method. To configure it, add following to your ActionMailer configuration (in Rails projects located in `config/$ENVIRONMENT.rb`):
```ruby
config.action_mailer.delivery_method = :mailtrap
config.action_mailer.mailtrap_settings = {
api_key: ENV.fetch('MAILTRAP_API_KEY')
}
```
And continue to use ActionMailer as usual.

To add `category` and `custom_variables`, add them to the mail generation:
```ruby
mail(
to: '[email protected]',
subject: 'You are awesome!',
category: 'Test category',
custom_variables: { test_variable: 'abc' }
)
```

#### Content-Transfer-Encoding
### Content-Transfer-Encoding

`mailtrap` gem uses Mailtrap API to send emails. Mailtrap API does not try to
replicate SMTP. That is why you should expect some limitations when it comes to
Expand All @@ -144,6 +66,12 @@ better flexibility in that regard. Go to your _Mailtrap account_ → _Email Send
_Sending Domains__Your domain__SMTP/API Settings_ to find the SMTP
configuration example.

## Migration guide v1 → v2

Change `Mailtrap::Sending::Client` to `Mailtrap::Client`.

If you use classes which have `Sending` namespace, remove the namespace like in the example above.

## Development

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.
Expand Down
18 changes: 18 additions & 0 deletions examples/action_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This gem adds ActionMailer delivery method.
# To configure it, add following to your ActionMailer configuration
# (in Rails projects located in `config/$ENVIRONMENT.rb`)
config.action_mailer.delivery_method = :mailtrap
config.action_mailer.mailtrap_settings = {
api_key: ENV.fetch('MAILTRAP_API_KEY'),
# bulk: true, # Bulk sending (@see https://help.mailtrap.io/article/113-sending-streams)
# sandbox: true, inbox_id: 12, # Sandbox sending (@see https://help.mailtrap.io/article/109-getting-started-with-mailtrap-email-testing)
}
# And continue to use ActionMailer as usual.

# To add `category` and `custom_variables`, add them to the mail generation:
mail(
to: '[email protected]',
subject: 'You are awesome!',
category: 'Test category',
custom_variables: { test_variable: 'abc' }
)
17 changes: 17 additions & 0 deletions examples/email_template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'mailtrap'

# create mail object
mail = Mailtrap::Mail::FromTemplate.new(
from: { email: '[email protected]', name: 'Mailtrap Test' },
to: [
{ email: '[email protected]' }
],
template_uuid: '2f45b0aa-bbed-432f-95e4-e145e1965ba2',
template_variables: {
'user_name' => 'John Doe'
}
)

# create client and send
client = Mailtrap::Client.new(api_key: 'your-api-key')
client.send(mail)
48 changes: 48 additions & 0 deletions examples/full.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'mailtrap'
require 'base64'

mail = Mailtrap::Mail::Base.new(
from: { email: '[email protected]', name: 'Mailtrap Test' },
to: [
{ email: '[email protected]', name: 'Your name' }
],
cc: [
{ email: '[email protected]', name: 'Copy To' }
],
bcc: [
{ email: '[email protected]', name: 'Hidden Recipient' }
],
subject: 'You are awesome!',
text: 'Congrats for sending test email with Mailtrap!',
category: 'Integration Test',
attachments: [
{
content: Base64.encode64('Attachment content'), # base64 encoded content or IO string
filename: 'attachment.txt'
}
],
headers: {
'X-MT-Header': 'Custom header'
},
custom_variables: {
year: 2022
}
)

data = File.read('/path/to/image.jpg')
encoded = Base64.encode64(data).gsub(/\n/, '')

mail.add_attachment(content: encoded, filename: 'image.png')

client = Mailtrap::Client.new(api_key: 'your-api-key')

# Custom host / port
# client = Mailtrap::Client.new(api_key: 'your-api-key', api_host: 'alternative.host.mailtrap.io', api_port: 8080)

# Bulk sending (@see https://help.mailtrap.io/article/113-sending-streams)
# client = Mailtrap::Client.new(api_key: 'your-api-key', bulk: true)

# Sandbox sending (@see https://help.mailtrap.io/article/109-getting-started-with-mailtrap-email-testing)
# client = Mailtrap::Client.new(api_key: 'your-api-key', sandbox: true, inbox_id: 12)

client.send(mail)
2 changes: 1 addition & 1 deletion lib/mailtrap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require_relative 'mailtrap/action_mailer' if defined? ActionMailer
require_relative 'mailtrap/mail'
require_relative 'mailtrap/sending'
require_relative 'mailtrap/errors'
require_relative 'mailtrap/version'

module Mailtrap; end
4 changes: 3 additions & 1 deletion lib/mailtrap/action_mailer/delivery_method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module ActionMailer
class DeliveryMethod
attr_accessor :settings

ALLOWED_PARAMS = %i[api_key api_host api_port bulk sandbox inbox_id].freeze

def initialize(settings)
self.settings = settings
end
Expand All @@ -18,7 +20,7 @@ def deliver!(message)
private

def client
@client ||= Mailtrap::Sending::Client.new(**settings.slice(:api_key, :api_host, :api_port))
@client ||= Mailtrap::Client.new(**settings.slice(*ALLOWED_PARAMS))
end
end
end
Expand Down
50 changes: 50 additions & 0 deletions lib/mailtrap/attachment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

require 'base64'
require 'json'

module Mailtrap
class Attachment
attr_accessor :type, :filename, :disposition, :content_id
attr_reader :content

def initialize(content:, filename:, type: nil, disposition: nil, content_id: nil)
self.content = content
@type = type
@filename = filename
@disposition = disposition
@content_id = content_id
end

def as_json
{
'content' => content,
'type' => type,
'filename' => filename,
'disposition' => disposition,
'content_id' => content_id
}.compact
end

def content=(content)
if content.respond_to?(:read)
@content = encode(content)
else
raise AttachmentContentError unless base64?(content)

@content = content
end
end

private

def encode(io)
string = io.read.encode('UTF-8') unless io.respond_to?(:binmode?) && io.binmode?
Base64.encode64(string).gsub(/\n/, '')
end

def base64?(string)
string.is_a?(String) && Base64.strict_encode64(Base64.decode64(string)) == string
end
end
end
Loading

0 comments on commit 705b4a2

Please sign in to comment.