Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

### Unreleased
* Documented `tracking_options.domain_name` hash support for custom link and open tracking hostnames. See the [message tracking documentation](https://developer.nylas.com/docs/v3/email/message-tracking/)

### [6.8.1]
* Documented `tentative_as_busy` support in the `Calendars#get_free_busy` request body, consistent with other Nylas SDKs

Expand Down
99 changes: 98 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,103 @@ Before running any example, make sure to:
export NYLAS_TEST_EMAIL="test@example.com" # Email address to send test messages to
```

#### Custom tracking hostnames

Set `tracking_options.domain_name` to an active custom hostname owned by your organization. Enable
link tracking, open tracking, or both in the same hash. If `domain_name` is omitted, tracked messages
use the default Nylas tracking hostname. See the
[message tracking documentation](https://developer.nylas.com/docs/v3/email/message-tracking/) for
registration, validation, and failure behavior.

##### Regular Send

```ruby
nylas.messages.send(
identifier: grant_id,
request_body: {
to: [{ email: "recipient@example.com" }],
subject: "Your update",
body: '<a href="https://example.com">View update</a>',
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
)
```

##### Transactional Send

The sender domain belongs in the Transactional Send route. The distinct `tracking_options.domain_name`
value belongs in the request body and is used for recipient-visible links and open pixels.

```ruby
sender_domain = "sender.example.com"
transactional_path = "/v3/domains/#{sender_domain}/messages/send"
transactional_request_body = {
from: [{ email: "billing@sender.example.com" }],
to: [{ email: "recipient@example.com" }],
subject: "Your receipt",
body: '<a href="https://example.com/receipt">View receipt</a>',
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}

# POST transactional_path with transactional_request_body.
```

##### Drafts

```ruby
draft, = nylas.drafts.create(
identifier: grant_id,
request_body: {
to: [{ email: "recipient@example.com" }],
subject: "Draft update",
body: '<a href="https://example.com">View update</a>',
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
)

nylas.drafts.update(
identifier: grant_id,
draft_id: draft[:id],
request_body: {
subject: "Updated draft subject"
# Omit tracking_options to preserve the draft's existing tracking settings.
}
)
```

##### Scheduled Send

Custom tracking hostnames are validated when the message is scheduled and revalidated before delivery.

```ruby
nylas.messages.send(
identifier: grant_id,
request_body: {
to: [{ email: "recipient@example.com" }],
subject: "Scheduled update",
body: '<a href="https://example.com">View update</a>',
send_at: Time.now.to_i + 3600,
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
)
```

### Notetaker
- `notetaker/notetaker_example.rb`: Shows basic Notetaker functionality, including:
- Inviting a Notetaker to a meeting
Expand Down Expand Up @@ -123,4 +220,4 @@ When adding new examples:
If you encounter any issues or have questions about these examples, please:
1. Check the [Nylas documentation](https://developer.nylas.com)
2. Visit our [GitHub repository](https://github.com/nylas/nylas-ruby)
3. Contact [Nylas support](https://support.nylas.com)
3. Contact [Nylas support](https://support.nylas.com)
6 changes: 6 additions & 0 deletions lib/nylas/resources/drafts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ def find(identifier:, draft_id:)
#
# @param identifier [String] Grant ID or email account in which to create the draft.
# @param request_body [Hash] The values to create the message with.
# Use `:tracking_options` with `:links` or `:opens` enabled to track the draft. To use a custom
# tracking hostname, set `:domain_name` inside `:tracking_options` to an active hostname owned
# by your organization.
# If you're attaching files, you must pass an array of [File] objects, or
# you can pass in base64 encoded strings if the total attachment size is less than 3mb.
# You can also use {FileUtils::attach_file_request_builder} to build each object attach.
Expand All @@ -61,6 +64,9 @@ def create(identifier:, request_body:)
# @param identifier [String] Grant ID or email account in which to update the draft.
# @param draft_id [String] The id of the draft to update.
# @param request_body [Hash] The values to create the message with.
# To replace the draft's custom tracking hostname, set `:tracking_options` with `:links` or
# `:opens` enabled and a `:domain_name`. Omit `:tracking_options` to preserve the draft's
# existing tracking settings.
# If you're attaching files, you must pass an array of [File] objects, or
# you can pass in base64 encoded strings if the total attachment size is less than 3mb.
# You can also use {FileUtils::attach_file_request_builder} to build each object attach.
Expand Down
5 changes: 5 additions & 0 deletions lib/nylas/resources/messages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ def clean_messages(identifier:, request_body:)
#
# @param identifier [String] Grant ID or email account from which to delete an object.
# @param request_body [Hash] The values to create the message with.
# Use `:tracking_options` with `:links` or `:opens` enabled to track a message. To use a custom
# tracking hostname, set `:domain_name` inside `:tracking_options` to an active hostname owned
# by your organization. Omit `:domain_name` to use the default Nylas tracking hostname.
# Set `:send_at` to a Unix timestamp to schedule the message; custom tracking hostnames are
# validated when the send is scheduled and revalidated before delivery.
# If you're attaching files, you must pass an array of [File] objects, or
# you can pass in base64 encoded strings if the total attachment size is less than 3mb.
# You can also use {FileUtils::attach_file_request_builder} to build each object attach.
Expand Down
20 changes: 20 additions & 0 deletions spec/nylas/handler/http_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,26 @@ class TestHttpClient
)
end

it "serializes a custom tracking hostname using the documented JSON shape" do
payload = {
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
request = http_client.send(:build_request, method: :post, path: "https://test.api.nylas.com/foo",
payload: payload, api_key: "fake-key")

expect(JSON.parse(request[:payload])).to eq(
"tracking_options" => {
"links" => true,
"opens" => true,
"domain_name" => "links.example.com"
}
)
end

it "returns the correct request with a multipart flag (string key)" do
payload = { "multipart" => true }
request = http_client.send(:build_request, method: :post, path: "https://test.api.nylas.com/foo",
Expand Down
45 changes: 45 additions & 0 deletions spec/nylas/resources/drafts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,29 @@
expect(draft_response).to eq(response)
end

it "forwards a custom tracking hostname in the request body" do
identifier = "abc-123-grant-id"
request_body = {
subject: "Tracked draft",
to: [{ email: "recipient@example.com" }],
body: '<a href="https://example.com">View update</a>',
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
path = "#{api_uri}/v3/grants/#{identifier}/drafts"

allow(drafts).to receive(:post)
.with(path: path, request_body: request_body)
.and_return(response)

draft_response = drafts.create(identifier: identifier, request_body: request_body)

expect(draft_response).to eq(response)
end

it "calls the post method with the correct parameters for small attachments" do
identifier = "abc-123-grant-id"
mock_file = instance_double("file")
Expand Down Expand Up @@ -181,6 +204,28 @@
expect(draft_response).to eq(response)
end

it "forwards a replacement custom tracking hostname in the request body" do
identifier = "abc-123-grant-id"
draft_id = "5d3qmne77v32r8l4phyuksl2x"
request_body = {
tracking_options: {
links: true,
opens: true,
domain_name: "replacement-links.example.com"
}
}
path = "#{api_uri}/v3/grants/#{identifier}/drafts/#{draft_id}"

allow(drafts).to receive(:put)
.with(path: path, request_body: request_body)
.and_return(response)

draft_response = drafts.update(identifier: identifier, draft_id: draft_id,
request_body: request_body)

expect(draft_response).to eq(response)
end

it "calls the put method with the correct parameters and attachments" do
identifier = "abc-123-grant-id"
draft_id = "5d3qmne77v32r8l4phyuksl2x"
Expand Down
47 changes: 47 additions & 0 deletions spec/nylas/resources/messages_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,53 @@
expect(message_response).to eq(response)
end

it "forwards a custom tracking hostname in the request body" do
identifier = "abc-123-grant-id"
request_body = {
subject: "Tracked message",
to: [{ email: "recipient@example.com" }],
body: '<a href="https://example.com">View update</a>',
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
path = "#{api_uri}/v3/grants/#{identifier}/messages/send"

allow(messages).to receive(:post)
.with(path: path, request_body: request_body)
.and_return(response)

message_response = messages.send(identifier: identifier, request_body: request_body)

expect(message_response).to eq(response)
end

it "forwards a custom tracking hostname for a scheduled send" do
identifier = "abc-123-grant-id"
request_body = {
subject: "Scheduled tracked message",
to: [{ email: "recipient@example.com" }],
body: '<a href="https://example.com">View update</a>',
send_at: 1_893_456_000,
tracking_options: {
links: true,
opens: true,
domain_name: "links.example.com"
}
}
path = "#{api_uri}/v3/grants/#{identifier}/messages/send"

allow(messages).to receive(:post)
.with(path: path, request_body: request_body)
.and_return(response)

message_response = messages.send(identifier: identifier, request_body: request_body)

expect(message_response).to eq(response)
end

it "calls the post method with the correct parameters and attachments" do
identifier = "abc-123-grant-id"
mock_file = instance_double("file")
Expand Down
Loading