mailersend-ruby 3.1.0 → 3.4.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/.envrc +2 -0
- data/.github/workflows/main.yml +1 -1
- data/.github/workflows/publish_gem.yml +1 -1
- data/.gitignore +2 -1
- data/CHANGELOG.md +9 -0
- data/README.md +423 -0
- data/fixtures/email/email_send_template_language.yml +56 -0
- data/fixtures/emails/emails_list_emails.yml +35 -0
- data/fixtures/emails/emails_list_emails_empty_page.yml +35 -0
- data/fixtures/emails/emails_single_email.yml +35 -0
- data/fixtures/whatsapp/whatsapp_send.yml +47 -0
- data/fixtures/whatsapp/whatsapp_send_multiple_recipients.yml +47 -0
- data/fixtures/whatsapp/whatsapp_send_personalization.yml +47 -0
- data/fixtures/whatsapp_activities/whatsapp_activities_list.yml +43 -0
- data/fixtures/whatsapp_inbound_messages/whatsapp_inbound_messages_get.yml +43 -0
- data/fixtures/whatsapp_inbound_messages/whatsapp_inbound_messages_list.yml +43 -0
- data/fixtures/whatsapp_items/whatsapp_items_get.yml +43 -0
- data/fixtures/whatsapp_items/whatsapp_items_list.yml +43 -0
- data/fixtures/whatsapp_messages/whatsapp_messages_get.yml +43 -0
- data/fixtures/whatsapp_messages/whatsapp_messages_list.yml +43 -0
- data/fixtures/whatsapp_recipient/whatsapp_recipient_get.yml +43 -0
- data/fixtures/whatsapp_recipient/whatsapp_recipient_list.yml +43 -0
- data/fixtures/whatsapp_templates/whatsapp_templates_get.yml +43 -0
- data/fixtures/whatsapp_templates/whatsapp_templates_list.yml +43 -0
- data/flake.lock +27 -0
- data/flake.nix +25 -0
- data/lefthook.yml +14 -0
- data/lib/mailersend/email/email.rb +10 -0
- data/lib/mailersend/emails/emails.rb +44 -0
- data/lib/mailersend/version.rb +1 -1
- data/lib/mailersend/whatsapp/whatsapp.rb +47 -0
- data/lib/mailersend/whatsapp_activities/whatsapp_activities.rb +45 -0
- data/lib/mailersend/whatsapp_inbound_messages/whatsapp_inbound_messages.rb +47 -0
- data/lib/mailersend/whatsapp_items/whatsapp_items.rb +57 -0
- data/lib/mailersend/whatsapp_messages/whatsapp_messages.rb +47 -0
- data/lib/mailersend/whatsapp_recipient/whatsapp_recipient.rb +38 -0
- data/lib/mailersend/whatsapp_templates/whatsapp_templates.rb +44 -0
- data/lib/mailersend.rb +8 -0
- data/spec/email_rspec.rb +15 -0
- data/spec/emails_rspec.rb +175 -0
- data/spec/whatsapp_activities_rspec.rb +38 -0
- data/spec/whatsapp_inbound_messages_rspec.rb +49 -0
- data/spec/whatsapp_items_rspec.rb +52 -0
- data/spec/whatsapp_messages_rspec.rb +50 -0
- data/spec/whatsapp_recipient_rspec.rb +40 -0
- data/spec/whatsapp_rspec.rb +65 -0
- data/spec/whatsapp_templates_rspec.rb +48 -0
- metadata +39 -1
data/flake.nix
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
description = "MailerSend Ruby SDK environment";
|
|
3
|
+
|
|
4
|
+
inputs = {
|
|
5
|
+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
outputs = { self, nixpkgs }:
|
|
9
|
+
let
|
|
10
|
+
systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ];
|
|
11
|
+
forEachSystem = f:
|
|
12
|
+
nixpkgs.lib.genAttrs systems (system: f system nixpkgs.legacyPackages.${system});
|
|
13
|
+
in
|
|
14
|
+
{
|
|
15
|
+
devShells = forEachSystem (system: pkgs: {
|
|
16
|
+
default = pkgs.mkShell {
|
|
17
|
+
packages = with pkgs; [
|
|
18
|
+
lefthook
|
|
19
|
+
gitleaks
|
|
20
|
+
git-secrets
|
|
21
|
+
];
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
data/lefthook.yml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
pre-commit:
|
|
3
|
+
commands:
|
|
4
|
+
gitleaks:
|
|
5
|
+
run: gitleaks git --pre-commit --redact --staged --verbose --no-banner
|
|
6
|
+
fail_text: Staged changes contain a secret. Remove it; never commit and revert.
|
|
7
|
+
secrets:
|
|
8
|
+
run: |
|
|
9
|
+
git secrets --list | grep -q 'mssp' || {
|
|
10
|
+
git secrets --register-aws
|
|
11
|
+
git secrets --add 'mlsn\.[A-Za-z0-9._-]+'
|
|
12
|
+
git secrets --add 'mssp\.[A-Za-z0-9._-]+'
|
|
13
|
+
}
|
|
14
|
+
git secrets --scan {staged_files}
|
|
@@ -16,6 +16,7 @@ module Mailersend
|
|
|
16
16
|
:reply_to,
|
|
17
17
|
:attachments,
|
|
18
18
|
:template_id,
|
|
19
|
+
:language,
|
|
19
20
|
:tags,
|
|
20
21
|
:variables,
|
|
21
22
|
:personalization,
|
|
@@ -40,6 +41,7 @@ module Mailersend
|
|
|
40
41
|
@headers = {}
|
|
41
42
|
@list_unsubscribe = nil
|
|
42
43
|
@send_at = send_at
|
|
44
|
+
@language = nil
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def add_recipients(recipients)
|
|
@@ -86,6 +88,13 @@ module Mailersend
|
|
|
86
88
|
@template_id = template_id
|
|
87
89
|
end
|
|
88
90
|
|
|
91
|
+
# Language code (e.g. 'de', 'fr', 'pt-BR'). Only meaningful when a
|
|
92
|
+
# template_id is set; ignored for raw html/text sends. Max length 10.
|
|
93
|
+
# Supported: de, en, es, fr, it, lt, nl, pl, pt-BR
|
|
94
|
+
def add_language(language)
|
|
95
|
+
@language = language
|
|
96
|
+
end
|
|
97
|
+
|
|
89
98
|
def add_tags(tags)
|
|
90
99
|
@tags << tags
|
|
91
100
|
end
|
|
@@ -131,6 +140,7 @@ module Mailersend
|
|
|
131
140
|
'variables' => @variables,
|
|
132
141
|
'personalization' => @personalization,
|
|
133
142
|
'template_id' => @template_id,
|
|
143
|
+
'language' => @language,
|
|
134
144
|
'attachments' => @attachments,
|
|
135
145
|
'headers' => @headers,
|
|
136
146
|
'list_unsubscribe' => @list_unsubscribe,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# Emails endpoint from MailerSend API.
|
|
5
|
+
class Emails
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:domain_id,
|
|
8
|
+
:date_from,
|
|
9
|
+
:date_to,
|
|
10
|
+
:limit,
|
|
11
|
+
:page,
|
|
12
|
+
:email_id
|
|
13
|
+
|
|
14
|
+
def initialize(client = Mailersend::Client.new)
|
|
15
|
+
@client = client
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def list(domain_id:, date_from:, date_to:, limit: nil, page: nil, status: nil, interaction: nil,
|
|
19
|
+
recipient_email: nil, message_id: nil, template_id: nil, subject: nil, tag: nil)
|
|
20
|
+
hash = {
|
|
21
|
+
'domain_id' => domain_id,
|
|
22
|
+
'date_from' => date_from,
|
|
23
|
+
'date_to' => date_to,
|
|
24
|
+
'limit' => limit,
|
|
25
|
+
'page' => page,
|
|
26
|
+
# The API rejects a scalar status/interaction with 422, so they are always sent in array form.
|
|
27
|
+
'status[]' => status,
|
|
28
|
+
'interaction[]' => interaction,
|
|
29
|
+
'recipient_email' => recipient_email,
|
|
30
|
+
'message_id' => message_id,
|
|
31
|
+
'template_id' => template_id,
|
|
32
|
+
'subject' => subject,
|
|
33
|
+
'tag' => tag
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/emails',
|
|
37
|
+
query: URI.encode_www_form(hash.compact)))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def single(email_id:)
|
|
41
|
+
client.http.get("#{MAILERSEND_API_URL}/email/#{email_id}")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/mailersend/version.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# Send a WhatsApp message through MailerSend API
|
|
5
|
+
class WhatsApp
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:from,
|
|
8
|
+
:to,
|
|
9
|
+
:template_id,
|
|
10
|
+
:personalization
|
|
11
|
+
|
|
12
|
+
def initialize(client = Mailersend::Client.new)
|
|
13
|
+
@client = client
|
|
14
|
+
@from = ''
|
|
15
|
+
@to = []
|
|
16
|
+
@template_id = ''
|
|
17
|
+
@personalization = []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def add_from(from)
|
|
21
|
+
@from = from
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def add_to(to)
|
|
25
|
+
@to << to
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add_template_id(template_id)
|
|
29
|
+
@template_id = template_id
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def add_personalization(personalization)
|
|
33
|
+
@personalization << personalization
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def send
|
|
37
|
+
message = {
|
|
38
|
+
'from' => @from,
|
|
39
|
+
'to' => @to,
|
|
40
|
+
'template_id' => @template_id,
|
|
41
|
+
'personalization' => @personalization
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
client.http.post("#{MAILERSEND_API_URL}/whatsapp/send", json: message.delete_if { |_, value| value.to_s.strip == '' || value == [] || value == {} })
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# WhatsApp Activities endpoint from MailerSend API.
|
|
5
|
+
class WhatsAppActivities
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:whatsapp_item_id,
|
|
8
|
+
:whatsapp_message_id,
|
|
9
|
+
:recipient,
|
|
10
|
+
:type,
|
|
11
|
+
:date_from,
|
|
12
|
+
:date_to,
|
|
13
|
+
:page,
|
|
14
|
+
:limit
|
|
15
|
+
|
|
16
|
+
def initialize(client = Mailersend::Client.new)
|
|
17
|
+
@client = client
|
|
18
|
+
@whatsapp_item_id = whatsapp_item_id
|
|
19
|
+
@whatsapp_message_id = whatsapp_message_id
|
|
20
|
+
@recipient = recipient
|
|
21
|
+
@type = type
|
|
22
|
+
@date_from = date_from
|
|
23
|
+
@date_to = date_to
|
|
24
|
+
@page = page
|
|
25
|
+
@limit = limit
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def list(whatsapp_item_id: nil, whatsapp_message_id: nil, recipient: nil, type: nil, date_from: nil, date_to: nil,
|
|
29
|
+
page: nil, limit: nil)
|
|
30
|
+
hash = {
|
|
31
|
+
'whatsapp_item_id' => whatsapp_item_id,
|
|
32
|
+
'whatsapp_message_id' => whatsapp_message_id,
|
|
33
|
+
'recipient' => recipient,
|
|
34
|
+
'type[]' => type,
|
|
35
|
+
'date_from' => date_from,
|
|
36
|
+
'date_to' => date_to,
|
|
37
|
+
'page' => page,
|
|
38
|
+
'limit' => limit
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/whatsapp/activities',
|
|
42
|
+
query: URI.encode_www_form(hash.compact)))
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# WhatsApp Inbound Messages endpoint from MailerSend API.
|
|
5
|
+
class WhatsAppInboundMessages
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:whatsapp_account_id,
|
|
8
|
+
:from,
|
|
9
|
+
:type,
|
|
10
|
+
:date_from,
|
|
11
|
+
:date_to,
|
|
12
|
+
:page,
|
|
13
|
+
:limit,
|
|
14
|
+
:whatsapp_inbound_message_id
|
|
15
|
+
|
|
16
|
+
def initialize(client = Mailersend::Client.new)
|
|
17
|
+
@client = client
|
|
18
|
+
@whatsapp_account_id = whatsapp_account_id
|
|
19
|
+
@from = from
|
|
20
|
+
@type = type
|
|
21
|
+
@date_from = date_from
|
|
22
|
+
@date_to = date_to
|
|
23
|
+
@page = page
|
|
24
|
+
@limit = limit
|
|
25
|
+
@whatsapp_inbound_message_id = whatsapp_inbound_message_id
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def list(whatsapp_account_id: nil, from: nil, type: nil, date_from: nil, date_to: nil, page: nil, limit: nil)
|
|
29
|
+
hash = {
|
|
30
|
+
'whatsapp_account_id' => whatsapp_account_id,
|
|
31
|
+
'from' => from,
|
|
32
|
+
'type[]' => type,
|
|
33
|
+
'date_from' => date_from,
|
|
34
|
+
'date_to' => date_to,
|
|
35
|
+
'page' => page,
|
|
36
|
+
'limit' => limit
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/whatsapp/inbound-messages',
|
|
40
|
+
query: URI.encode_www_form(hash.compact)))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def get(whatsapp_inbound_message_id:)
|
|
44
|
+
client.http.get("#{MAILERSEND_API_URL}/whatsapp/inbound-messages/#{whatsapp_inbound_message_id}")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# WhatsApp Items endpoint from MailerSend API.
|
|
5
|
+
class WhatsAppItems
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:recipient,
|
|
8
|
+
:whatsapp_message_id,
|
|
9
|
+
:status,
|
|
10
|
+
:whatsapp_account_id,
|
|
11
|
+
:from,
|
|
12
|
+
:template_id,
|
|
13
|
+
:date_from,
|
|
14
|
+
:date_to,
|
|
15
|
+
:page,
|
|
16
|
+
:limit,
|
|
17
|
+
:whatsapp_item_id
|
|
18
|
+
|
|
19
|
+
def initialize(client = Mailersend::Client.new)
|
|
20
|
+
@client = client
|
|
21
|
+
@recipient = recipient
|
|
22
|
+
@whatsapp_message_id = whatsapp_message_id
|
|
23
|
+
@status = status
|
|
24
|
+
@whatsapp_account_id = whatsapp_account_id
|
|
25
|
+
@from = from
|
|
26
|
+
@template_id = template_id
|
|
27
|
+
@date_from = date_from
|
|
28
|
+
@date_to = date_to
|
|
29
|
+
@page = page
|
|
30
|
+
@limit = limit
|
|
31
|
+
@whatsapp_item_id = whatsapp_item_id
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def list(recipient: nil, whatsapp_message_id: nil, status: nil, whatsapp_account_id: nil, from: nil,
|
|
35
|
+
template_id: nil, date_from: nil, date_to: nil, page: nil, limit: nil)
|
|
36
|
+
hash = {
|
|
37
|
+
'recipient' => recipient,
|
|
38
|
+
'whatsapp_message_id' => whatsapp_message_id,
|
|
39
|
+
'status[]' => status,
|
|
40
|
+
'whatsapp_account_id' => whatsapp_account_id,
|
|
41
|
+
'from' => from,
|
|
42
|
+
'template_id' => template_id,
|
|
43
|
+
'date_from' => date_from,
|
|
44
|
+
'date_to' => date_to,
|
|
45
|
+
'page' => page,
|
|
46
|
+
'limit' => limit
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/whatsapp/items',
|
|
50
|
+
query: URI.encode_www_form(hash.compact)))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def get(whatsapp_item_id:)
|
|
54
|
+
client.http.get("#{MAILERSEND_API_URL}/whatsapp/items/#{whatsapp_item_id}")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# WhatsApp Messages endpoint from MailerSend API.
|
|
5
|
+
class WhatsAppMessages
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:whatsapp_account_id,
|
|
8
|
+
:from,
|
|
9
|
+
:template_id,
|
|
10
|
+
:date_from,
|
|
11
|
+
:date_to,
|
|
12
|
+
:page,
|
|
13
|
+
:limit,
|
|
14
|
+
:whatsapp_message_id
|
|
15
|
+
|
|
16
|
+
def initialize(client = Mailersend::Client.new)
|
|
17
|
+
@client = client
|
|
18
|
+
@whatsapp_account_id = whatsapp_account_id
|
|
19
|
+
@from = from
|
|
20
|
+
@template_id = template_id
|
|
21
|
+
@date_from = date_from
|
|
22
|
+
@date_to = date_to
|
|
23
|
+
@page = page
|
|
24
|
+
@limit = limit
|
|
25
|
+
@whatsapp_message_id = whatsapp_message_id
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def list(whatsapp_account_id: nil, from: nil, template_id: nil, date_from: nil, date_to: nil, page: nil, limit: nil)
|
|
29
|
+
hash = {
|
|
30
|
+
'whatsapp_account_id' => whatsapp_account_id,
|
|
31
|
+
'from' => from,
|
|
32
|
+
'template_id' => template_id,
|
|
33
|
+
'date_from' => date_from,
|
|
34
|
+
'date_to' => date_to,
|
|
35
|
+
'page' => page,
|
|
36
|
+
'limit' => limit
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/whatsapp/messages',
|
|
40
|
+
query: URI.encode_www_form(hash.compact)))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def get(whatsapp_message_id:)
|
|
44
|
+
client.http.get("#{MAILERSEND_API_URL}/whatsapp/messages/#{whatsapp_message_id}")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# WhatsApp Recipient endpoint from MailerSend API.
|
|
5
|
+
class WhatsAppRecipient
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:status,
|
|
8
|
+
:phone_number,
|
|
9
|
+
:page,
|
|
10
|
+
:limit,
|
|
11
|
+
:whatsapp_recipient_id
|
|
12
|
+
|
|
13
|
+
def initialize(client = Mailersend::Client.new)
|
|
14
|
+
@client = client
|
|
15
|
+
@status = status
|
|
16
|
+
@phone_number = phone_number
|
|
17
|
+
@page = page
|
|
18
|
+
@limit = limit
|
|
19
|
+
@whatsapp_recipient_id = whatsapp_recipient_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def list(status: nil, phone_number: nil, page: nil, limit: nil)
|
|
23
|
+
hash = {
|
|
24
|
+
'status' => status,
|
|
25
|
+
'phone_number' => phone_number,
|
|
26
|
+
'page' => page,
|
|
27
|
+
'limit' => limit
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/whatsapp/recipients',
|
|
31
|
+
query: URI.encode_www_form(hash.compact)))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get(whatsapp_recipient_id:)
|
|
35
|
+
client.http.get("#{MAILERSEND_API_URL}/whatsapp/recipients/#{whatsapp_recipient_id}")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailersend
|
|
4
|
+
# WhatsApp Templates endpoint from MailerSend API.
|
|
5
|
+
class WhatsAppTemplates
|
|
6
|
+
attr_accessor :client,
|
|
7
|
+
:whatsapp_account_id,
|
|
8
|
+
:status,
|
|
9
|
+
:category,
|
|
10
|
+
:language,
|
|
11
|
+
:page,
|
|
12
|
+
:limit,
|
|
13
|
+
:whatsapp_template_id
|
|
14
|
+
|
|
15
|
+
def initialize(client = Mailersend::Client.new)
|
|
16
|
+
@client = client
|
|
17
|
+
@whatsapp_account_id = whatsapp_account_id
|
|
18
|
+
@status = status
|
|
19
|
+
@category = category
|
|
20
|
+
@language = language
|
|
21
|
+
@page = page
|
|
22
|
+
@limit = limit
|
|
23
|
+
@whatsapp_template_id = whatsapp_template_id
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def list(whatsapp_account_id: nil, status: nil, category: nil, language: nil, page: nil, limit: nil)
|
|
27
|
+
hash = {
|
|
28
|
+
'whatsapp_account_id' => whatsapp_account_id,
|
|
29
|
+
'status' => status,
|
|
30
|
+
'category' => category,
|
|
31
|
+
'language' => language,
|
|
32
|
+
'page' => page,
|
|
33
|
+
'limit' => limit
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
client.http.get(URI::HTTPS.build(host: MAILERSEND_API_BASE_HOST, path: '/v1/whatsapp/templates',
|
|
37
|
+
query: URI.encode_www_form(hash.compact)))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get(whatsapp_template_id:)
|
|
41
|
+
client.http.get("#{MAILERSEND_API_URL}/whatsapp/templates/#{whatsapp_template_id}")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/mailersend.rb
CHANGED
|
@@ -10,12 +10,20 @@ require_relative 'mailersend/dmarc_monitoring/dmarc_monitoring'
|
|
|
10
10
|
require_relative 'mailersend/domains/domains'
|
|
11
11
|
require_relative 'mailersend/email/email'
|
|
12
12
|
require_relative 'mailersend/email_verification/email_verification'
|
|
13
|
+
require_relative 'mailersend/emails/emails'
|
|
13
14
|
require_relative 'mailersend/inbound_routing/inbound_routing'
|
|
14
15
|
require_relative 'mailersend/messages/messages'
|
|
15
16
|
require_relative 'mailersend/recipients/recipients'
|
|
16
17
|
require_relative 'mailersend/scheduled_messages/scheduled_messages'
|
|
17
18
|
require_relative 'mailersend/sender_identity/sender_identity'
|
|
18
19
|
require_relative 'mailersend/sms/sms'
|
|
20
|
+
require_relative 'mailersend/whatsapp/whatsapp'
|
|
21
|
+
require_relative 'mailersend/whatsapp_messages/whatsapp_messages'
|
|
22
|
+
require_relative 'mailersend/whatsapp_items/whatsapp_items'
|
|
23
|
+
require_relative 'mailersend/whatsapp_activities/whatsapp_activities'
|
|
24
|
+
require_relative 'mailersend/whatsapp_inbound_messages/whatsapp_inbound_messages'
|
|
25
|
+
require_relative 'mailersend/whatsapp_recipient/whatsapp_recipient'
|
|
26
|
+
require_relative 'mailersend/whatsapp_templates/whatsapp_templates'
|
|
19
27
|
require_relative 'mailersend/sms_activity/sms_activity'
|
|
20
28
|
require_relative 'mailersend/sms_messages/sms_messages'
|
|
21
29
|
require_relative 'mailersend/sms_number/sms_number'
|
data/spec/email_rspec.rb
CHANGED
|
@@ -26,4 +26,19 @@ RSpec.describe Mailersend::Email do
|
|
|
26
26
|
expect(response.status).to eq(202)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
|
+
|
|
30
|
+
it 'includes the language in the request body when set' do
|
|
31
|
+
# Cassette is matched on the request body, so this passes only when
|
|
32
|
+
# the serialized payload contains the language field.
|
|
33
|
+
VCR.use_cassette('email/email_send_template_language', match_requests_on: %i[method uri body]) do
|
|
34
|
+
email.from = { 'email' => 'sender@test-sdk.com', 'name' => 'Sender' }
|
|
35
|
+
email.recipients = [{ 'email' => 'test@mailerlite.com', 'name' => 'Test' }]
|
|
36
|
+
email.subject = 'Test Email'
|
|
37
|
+
email.add_template_id('123abc')
|
|
38
|
+
email.add_language('de')
|
|
39
|
+
|
|
40
|
+
response = email.send
|
|
41
|
+
expect(response.status).to eq(202)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
29
44
|
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
require 'vcr'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
VCR.configure do |config|
|
|
6
|
+
config.cassette_library_dir = './fixtures'
|
|
7
|
+
config.hook_into :webmock
|
|
8
|
+
config.filter_sensitive_data('<AUTH>') do |interaction|
|
|
9
|
+
interaction.request.headers['Authorization'][0]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
RSpec.describe Mailersend::Emails do
|
|
14
|
+
let(:client) { Mailersend::Client.new(API_TOKEN) }
|
|
15
|
+
let(:emails) { Mailersend::Emails.new(client) }
|
|
16
|
+
|
|
17
|
+
# The three required arguments, reused by every example.
|
|
18
|
+
let(:domain_id) { 'jpzkmgq7e5vl059v' }
|
|
19
|
+
let(:date_from) { 1_756_252_800 }
|
|
20
|
+
let(:date_to) { 1_756_339_200 }
|
|
21
|
+
|
|
22
|
+
describe '#list' do
|
|
23
|
+
# VCR matches on method + URI, so the `uri:` recorded in the cassette is itself the
|
|
24
|
+
# assertion that `list` hits `v1/emails` with domain_id, date_from, date_to, limit and page.
|
|
25
|
+
it 'returns a list of emails' do
|
|
26
|
+
VCR.use_cassette('emails/emails_list_emails', match_requests_on: %i[method uri]) do
|
|
27
|
+
response = emails.list(domain_id: domain_id, date_from: date_from, date_to: date_to, page: 1, limit: 10)
|
|
28
|
+
parsed_response = JSON.parse(response.body)
|
|
29
|
+
|
|
30
|
+
expect(response.status).to eq(200)
|
|
31
|
+
expect(parsed_response['data']).to be_an(Array)
|
|
32
|
+
|
|
33
|
+
email = parsed_response['data'].first
|
|
34
|
+
|
|
35
|
+
expect(email['id']).to eq('6a8fa9b1902fab56e0ce50dd')
|
|
36
|
+
expect(email['from']).to eq('sender@example.com')
|
|
37
|
+
expect(email['to']).to eq('rcpt@example.org')
|
|
38
|
+
expect(email['status']).to eq('sent')
|
|
39
|
+
expect(email['tags']).to eq(['newsletter'])
|
|
40
|
+
expect(email['interaction']).to eq(['opened'])
|
|
41
|
+
expect(email['suppression_reason']).to be_nil
|
|
42
|
+
expect(email['headers']).to eq([{ 'name' => 'X-Custom', 'value' => 'foo' }])
|
|
43
|
+
|
|
44
|
+
# List rows never carry content — it is only returned by `single`.
|
|
45
|
+
expect(email['text']).to be_nil
|
|
46
|
+
expect(email['html']).to be_nil
|
|
47
|
+
|
|
48
|
+
expect(parsed_response['links']['first']).to eq('https://api.mailersend.com/v1/emails?page=1')
|
|
49
|
+
expect(parsed_response['links']['last']).to be_nil
|
|
50
|
+
expect(parsed_response['meta']['current_page']).to eq(1)
|
|
51
|
+
expect(parsed_response['meta']['per_page']).to eq(10)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'returns an empty page past the end of the result set' do
|
|
56
|
+
VCR.use_cassette('emails/emails_list_emails_empty_page', match_requests_on: %i[method uri]) do
|
|
57
|
+
response = emails.list(domain_id: domain_id, date_from: date_from, date_to: date_to, page: 2, limit: 10)
|
|
58
|
+
parsed_response = JSON.parse(response.body)
|
|
59
|
+
|
|
60
|
+
expect(response.status).to eq(200)
|
|
61
|
+
expect(parsed_response['data']).to eq([])
|
|
62
|
+
expect(parsed_response['links']['prev']).to eq('https://api.mailersend.com/v1/emails?page=1')
|
|
63
|
+
expect(parsed_response['links']['next']).to be_nil
|
|
64
|
+
expect(parsed_response['meta']['current_page']).to eq(2)
|
|
65
|
+
expect(parsed_response['meta']['from']).to be_nil
|
|
66
|
+
expect(parsed_response['meta']['to']).to be_nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#single' do
|
|
72
|
+
# The path is singular (`v1/email/{id}`) while `list` is plural (`v1/emails`); the cassette
|
|
73
|
+
# URI pins that difference.
|
|
74
|
+
it 'returns a single email with its recipient and activity' do
|
|
75
|
+
VCR.use_cassette('emails/emails_single_email', match_requests_on: %i[method uri]) do
|
|
76
|
+
response = emails.single(email_id: '6a8fa9b1902fab56e0ce50dd')
|
|
77
|
+
parsed_response = JSON.parse(response.body)
|
|
78
|
+
|
|
79
|
+
expect(response.status).to eq(200)
|
|
80
|
+
expect(parsed_response['data']).to be_a(Hash)
|
|
81
|
+
expect(parsed_response['data']['id']).to eq('6a8fa9b1902fab56e0ce50dd')
|
|
82
|
+
|
|
83
|
+
# `single` adds content, the recipient object and the activity array on top of a list row.
|
|
84
|
+
expect(parsed_response['data']['text']).to eq('Welcome aboard.')
|
|
85
|
+
expect(parsed_response['data']['html']).to eq('<p>Welcome aboard.</p>')
|
|
86
|
+
expect(parsed_response['data']['recipient']).to be_a(Hash)
|
|
87
|
+
expect(parsed_response['data']['recipient']['email']).to eq('rcpt@example.org')
|
|
88
|
+
|
|
89
|
+
activity = parsed_response['data']['activity']
|
|
90
|
+
|
|
91
|
+
expect(activity).to be_an(Array)
|
|
92
|
+
expect(activity.length).to eq(3)
|
|
93
|
+
expect(activity.first).to include('id', 'type', 'created_at')
|
|
94
|
+
expect(activity.first['type']).to eq('opened')
|
|
95
|
+
expect(activity.map { |event| event['type'] }).to eq(%w[opened delivered sent])
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# These examples assert the URI the SDK builds rather than replaying a cassette, because query
|
|
101
|
+
# serialization is the contract that matters most here: the API rejects a scalar `status` or
|
|
102
|
+
# `interaction` with 422, so both must go out as repeated `status[]` / `interaction[]` params and
|
|
103
|
+
# never as a single comma-joined value.
|
|
104
|
+
describe 'query serialization' do
|
|
105
|
+
let(:http) { double('http') }
|
|
106
|
+
let(:requested_urls) { [] }
|
|
107
|
+
|
|
108
|
+
before do
|
|
109
|
+
allow(client).to receive(:http).and_return(http)
|
|
110
|
+
allow(http).to receive(:get) { |url| requested_urls << url.to_s }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'sends status and interaction as repeated array params' do
|
|
114
|
+
emails.list(domain_id: domain_id, date_from: date_from, date_to: date_to, limit: 10, page: 1,
|
|
115
|
+
status: %w[sent delivered], interaction: %w[opened clicked])
|
|
116
|
+
|
|
117
|
+
expect(requested_urls.last).to eq(
|
|
118
|
+
'https://api.mailersend.com/v1/emails' \
|
|
119
|
+
'?domain_id=jpzkmgq7e5vl059v&date_from=1756252800&date_to=1756339200&limit=10&page=1' \
|
|
120
|
+
'&status%5B%5D=sent&status%5B%5D=delivered' \
|
|
121
|
+
'&interaction%5B%5D=opened&interaction%5B%5D=clicked'
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# One key per value, and no comma-joined value anywhere (%2C is an encoded comma).
|
|
125
|
+
expect(requested_urls.last.scan('status%5B%5D=').length).to eq(2)
|
|
126
|
+
expect(requested_urls.last.scan('interaction%5B%5D=').length).to eq(2)
|
|
127
|
+
expect(requested_urls.last).not_to include('%2C')
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'sends a scalar status and interaction in array form too' do
|
|
131
|
+
emails.list(domain_id: domain_id, date_from: date_from, date_to: date_to,
|
|
132
|
+
status: 'sent', interaction: 'opened')
|
|
133
|
+
|
|
134
|
+
expect(requested_urls.last).to eq(
|
|
135
|
+
'https://api.mailersend.com/v1/emails' \
|
|
136
|
+
'?domain_id=jpzkmgq7e5vl059v&date_from=1756252800&date_to=1756339200' \
|
|
137
|
+
'&status%5B%5D=sent&interaction%5B%5D=opened'
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'includes every optional filter when set' do
|
|
142
|
+
emails.list(domain_id: domain_id, date_from: date_from, date_to: date_to, limit: 25, page: 2,
|
|
143
|
+
status: %w[sent], interaction: %w[opened], recipient_email: 'rcpt@example.org',
|
|
144
|
+
message_id: '6a8fa9b1902fab56e0ce50aa', template_id: '7nxe3yjmeq28vp0k',
|
|
145
|
+
subject: 'Welcome', tag: 'newsletter')
|
|
146
|
+
|
|
147
|
+
expect(requested_urls.last).to eq(
|
|
148
|
+
'https://api.mailersend.com/v1/emails' \
|
|
149
|
+
'?domain_id=jpzkmgq7e5vl059v&date_from=1756252800&date_to=1756339200&limit=25&page=2' \
|
|
150
|
+
'&status%5B%5D=sent&interaction%5B%5D=opened' \
|
|
151
|
+
'&recipient_email=rcpt%40example.org&message_id=6a8fa9b1902fab56e0ce50aa' \
|
|
152
|
+
'&template_id=7nxe3yjmeq28vp0k&subject=Welcome&tag=newsletter'
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'omits every optional filter that is nil' do
|
|
157
|
+
emails.list(domain_id: domain_id, date_from: date_from, date_to: date_to)
|
|
158
|
+
|
|
159
|
+
expect(requested_urls.last).to eq(
|
|
160
|
+
'https://api.mailersend.com/v1/emails?domain_id=jpzkmgq7e5vl059v&date_from=1756252800&date_to=1756339200'
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
%w[limit page status interaction recipient_email message_id template_id subject tag].each do |param|
|
|
164
|
+
expect(requested_urls.last).not_to include(param)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'requests the singular v1/email/{id} path for a single email' do
|
|
169
|
+
emails.single(email_id: '6a8fa9b1902fab56e0ce50dd')
|
|
170
|
+
|
|
171
|
+
expect(requested_urls.last).to eq('https://api.mailersend.com/v1/email/6a8fa9b1902fab56e0ce50dd')
|
|
172
|
+
expect(requested_urls.last).not_to include('/v1/emails/')
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|