azure_communication_email 0.1.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6425a9b60979a7f4d2388fd367a092ee2f63ffa90c087ab71e923bb8944419f
4
- data.tar.gz: a455a2ec63a22d96849d102a0af4860633c76720ce85d6b35d20b9fa68461c96
3
+ metadata.gz: 7dc5641d67751daefdc4edd8e5f749235c3432fab68daa16dc5050b6d0f574d4
4
+ data.tar.gz: 9994f7260ac36ce4a284d0113b344f3b8a71b4cb41185b7da60f479a302d18f1
5
5
  SHA512:
6
- metadata.gz: df8bb2c7678d15227d6b50d3ecc950cf8984a05ef71f870e82dd0fc8f6bce24439fd59d291a684d280e3a61e8f987579675a9d939bf6a49deda8971e4774880b
7
- data.tar.gz: 7ca782265ac31312825f7fbc78cac03225266e9edfb55cd8e9ca6d62012f780a2462d2c254e91c3748fb4dd10bebe1fc74935a5c88a1d271f97c1e6e1f93ca65
6
+ metadata.gz: 5da5ad3a1cf4b559c320e3405c4d691a357e3db8fbb918aae7b6524f3b04f7b0ab97d90fa9741888d063964490293d0ebdb92f788bcc5090266f9de87394a674
7
+ data.tar.gz: 1de7203d9fe1bec1eb197f7bf47bc2ee31911be9f1edd7de57f51729290bb4a4327134bf9ca94fe377672e4a61d28059970c16f546a25a39da5447d42f00bcfa
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Azure Communication Email
2
2
 
3
- Azure Communication Email is an Action Mailer delivery method for Ruby on Rails using the Azure Communication Email API.
3
+ Azure Communication Email is an Action Mailer delivery method for Ruby on Rails using the [Azure Email Communications Service](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/email/create-email-communication-resource?pivots=platform-azp).
4
4
 
5
5
  ## Installation
6
6
 
@@ -16,9 +16,9 @@ Or add it manually to your Gemfile:
16
16
  gem "azure_communication_email"
17
17
  ```
18
18
 
19
- ## Usage
19
+ ## Configuration
20
20
 
21
- To send emails using Azure Communication Services, configure Action Mailer with the `:azure_communication_email` delivery method and provide the necessary credentials.
21
+ Create an Azure Communication Services resource, connect a verified email domain, and configure the delivery method in the environment where email should be sent:
22
22
 
23
23
  ```ruby
24
24
  # config/environments/production.rb
@@ -26,12 +26,61 @@ To send emails using Azure Communication Services, configure Action Mailer with
26
26
  Rails.application.configure do
27
27
  config.action_mailer.delivery_method = :azure_communication_email
28
28
  config.action_mailer.azure_communication_email_settings = {
29
- endpoint: ENV.fetch("ACS_EMAIL_ENDPOINT"),
30
- access_key: ENV.fetch("ACS_EMAIL_ACCESS_KEY"),
29
+ endpoint: ENV.fetch("ACS_EMAIL_ENDPOINT"),
30
+ access_key: ENV.fetch("ACS_EMAIL_ACCESS_KEY")
31
31
  }
32
32
  end
33
33
  ```
34
34
 
35
+ `endpoint` is the complete Communication Services endpoint, for example `https://my-resource.communication.azure.com`. `access_key` is one of that resource's access keys.
36
+
37
+ The optional `api_version` setting defaults to `2025-01-15-preview`. This version is used because it supports sender display names for custom domains.
38
+
39
+ Keep `config.action_mailer.delivery_method = :test` in the test environment so tests do not send real email.
40
+
41
+ ## Usage
42
+
43
+ Use Action Mailer normally; no Azure-specific mailer class is needed:
44
+
45
+ ```ruby
46
+ class UserMailer < ApplicationMailer
47
+ def welcome_email(user)
48
+ @user = user
49
+ mail(to: @user.email, from: "donotreply@<yourdomain>.com", subject: "Hello World!")
50
+ end
51
+ end
52
+ ```
53
+
54
+ Send through Active Job in most application code:
55
+
56
+ ```ruby
57
+ UserMailer.with(user: user).welcome_email.deliver_later
58
+ ```
59
+
60
+ The delivery method maps Action Mailer messages to Azure, including:
61
+
62
+ - plain-text and HTML bodies, including multipart messages
63
+ - `to`, `cc`, `bcc`, and `reply_to` recipients with display names
64
+ - regular and inline attachments
65
+ - `X-` custom headers
66
+ - a sender display name when using a custom domain
67
+
68
+ Azure limits the total request size, including attachments, to 10 MB.
69
+
70
+ ## Delivery status and errors
71
+
72
+ Azure accepts email asynchronously. A successful `deliver_now` or delivery job means Azure returned `202 Accepted`; it does not guarantee final delivery to the recipient. Use Azure Monitor or Event Grid email events for final delivery and bounce tracking.
73
+
74
+ Configuration errors, connection failures, timeouts, authentication failures, and non-successful HTTP responses raise `AzureCommunicationEmail::Error`. The HTTP connection timeout is 5 seconds and the response timeout is 15 seconds.
75
+
76
+ For a quick production check, send a message from the Rails console with `deliver_now`. Use a verified sender address and inspect Azure's email logs if the recipient does not receive it.
77
+
78
+ ## Links
79
+
80
+ - [Service limits for Azure Communication Services](https://learn.microsoft.com/en-us/azure/communication-services/concepts/service-limits#email)
81
+ - [Monitor Azure Communication Services email events](https://learn.microsoft.com/en-us/azure/communication-services/concepts/email/email-event-data)
82
+ - [How to add and remove Multiple Sender Addresses to Email Communication Service](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/email/add-multiple-senders?pivots=platform-azp)
83
+
35
84
  ## Contributing
36
85
 
37
86
  Bug reports and pull requests are welcome.
@@ -10,7 +10,7 @@ require "uri"
10
10
 
11
11
  module AzureCommunicationEmail
12
12
  class DeliveryMethod
13
- DEFAULTS = { api_version: "2023-03-31" }
13
+ DEFAULTS = { api_version: "2025-01-15-preview" }
14
14
 
15
15
  attr_accessor :endpoint, :api_version, :access_key
16
16
 
@@ -53,6 +53,8 @@ module AzureCommunicationEmail
53
53
  end
54
54
 
55
55
  response
56
+ rescue Error
57
+ raise
56
58
  rescue StandardError => e
57
59
  raise Error, "Error sending email: #{e.message}"
58
60
  end
@@ -12,32 +12,44 @@ module AzureCommunicationEmail
12
12
 
13
13
  def as_json
14
14
  hash = {
15
- "senderAddress" => first_address(@mail.from),
15
+ "senderAddress" => first_sender_address,
16
16
  "content" => {
17
17
  "subject" => @mail.subject.to_s,
18
18
  "plainText" => plain_text_body
19
19
  },
20
20
  "recipients" => {
21
- "to" => recipient_objects(@mail.to)
21
+ "to" => recipient_objects(:to)
22
22
  }
23
23
  }
24
24
 
25
- html = html_body
26
- hash["content"]["html"] = html if html.present?
25
+ # Does only work with custom domains
26
+ if (name = first_sender_display_name).present?
27
+ hash["senderDisplayName"] = name
28
+ end
29
+
30
+ if (html = html_body).present?
31
+ hash["content"]["html"] = html
32
+ end
27
33
 
28
- cc = recipient_objects(@mail.cc)
29
- bcc = recipient_objects(@mail.bcc)
30
- hash["recipients"]["cc"] = cc if cc.present?
31
- hash["recipients"]["bcc"] = bcc if bcc.present?
34
+ if (cc = recipient_objects(:cc)).present?
35
+ hash["recipients"]["cc"] = cc
36
+ end
32
37
 
33
- reply_to = recipient_objects(@mail.reply_to)
34
- hash["replyTo"] = reply_to if reply_to.present?
38
+ if (bcc = recipient_objects(:bcc)).present?
39
+ hash["recipients"]["bcc"] = bcc
40
+ end
41
+
42
+ if (reply_to = recipient_objects(:reply_to)).present?
43
+ hash["replyTo"] = reply_to
44
+ end
35
45
 
36
- headers = custom_headers
37
- hash["headers"] = headers if headers.present?
46
+ if (headers = custom_headers).present?
47
+ hash["headers"] = headers
48
+ end
38
49
 
39
- attachments = attachment_objects
40
- hash["attachments"] = attachments if attachments.present?
50
+ if (attachments = attachment_objects).present?
51
+ hash["attachments"] = attachments
52
+ end
41
53
 
42
54
  hash
43
55
  end
@@ -49,34 +61,74 @@ module AzureCommunicationEmail
49
61
  private
50
62
 
51
63
  def plain_text_body
52
- if @mail.text_part
53
- @mail.text_part.decoded
54
- else
55
- @mail.body.decoded.to_s
56
- end
64
+ return extract_text_part if @mail.text_part
65
+ return extract_plain_body if @mail.mime_type.to_s.start_with?("text/plain")
66
+ return extract_bare_body if @mail.mime_type.to_s.blank?
67
+
68
+ "" # HTML-only message
57
69
  end
58
70
 
59
71
  def html_body
60
- @mail.html_part&.decoded
72
+ return extract_html_part if @mail.html_part
73
+ return extract_html_body if @mail.mime_type.to_s.start_with?("text/html")
74
+
75
+ nil
76
+ end
77
+
78
+ def extract_text_part
79
+ @mail.text_part.body.decoded.to_s
61
80
  end
62
81
 
63
- def first_address(list)
64
- Array(list).compact_blank.first
82
+ def extract_plain_body
83
+ @mail.body.decoded.to_s
65
84
  end
66
85
 
67
- def recipient_objects(addresses)
68
- Array(addresses).compact_blank.map { |address| { "address" => address } }
86
+ def extract_bare_body
87
+ @mail.body&.decoded.to_s
88
+ end
89
+
90
+ def extract_html_part
91
+ @mail.html_part.body.decoded.to_s
92
+ end
93
+
94
+ def extract_html_body
95
+ @mail.body.decoded.to_s
96
+ end
97
+
98
+ def address_list(field_sym)
99
+ field = @mail[field_sym]
100
+ return [] unless field.respond_to?(:addrs)
101
+ field.addrs
102
+ end
103
+
104
+ def first_sender_address
105
+ address_list(:from).first&.address.to_s
106
+ end
107
+
108
+ def first_sender_display_name
109
+ address_list(:from).first&.display_name.to_s.strip
110
+ end
111
+
112
+ def recipient_objects(field_sym)
113
+ address_list(field_sym).map do |addr|
114
+ obj = { "address" => addr.address.to_s }
115
+ name = addr.display_name.to_s.strip
116
+ obj["displayName"] = name if name.present?
117
+ obj
118
+ end
69
119
  end
70
120
 
71
121
  def attachment_objects
72
122
  return [] unless @mail.attachments&.any?
73
123
 
74
124
  @mail.attachments.map do |attachment|
75
- {
125
+ object = {
76
126
  "name" => attachment.filename.to_s,
77
127
  "contentType" => attachment.mime_type.to_s,
78
128
  "contentInBase64" => Base64.strict_encode64(attachment.body.decoded)
79
129
  }
130
+ object["contentId"] = attachment.cid if attachment.inline?
131
+ object
80
132
  end
81
133
  end
82
134
 
@@ -84,8 +136,8 @@ module AzureCommunicationEmail
84
136
  return {} unless @mail.header
85
137
 
86
138
  @mail.header.fields
87
- .select { |field| field.name =~ /\AX-/i }
88
- .to_h { |field| [ field.name, field.value.to_s ] }
139
+ .select { |field| field.name =~ /\AX-/i }
140
+ .to_h { |field| [ field.name, field.value.to_s ] }
89
141
  end
90
142
  end
91
143
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AzureCommunicationEmail
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -3,7 +3,6 @@
3
3
  require_relative "azure_communication_email/version"
4
4
  require_relative "azure_communication_email/delivery_method"
5
5
 
6
- # Auto-register with Rails when loaded
7
- if defined?(Rails) && defined?(ActionMailer)
8
- ActionMailer::Base.add_delivery_method :azure_communication_email, AzureCommunicationEmail::DeliveryMethod
6
+ ActiveSupport.on_load(:action_mailer) do
7
+ add_delivery_method :azure_communication_email, AzureCommunicationEmail::DeliveryMethod
9
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: azure_communication_email
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devran Cosmo Uenal
@@ -65,8 +65,7 @@ dependencies:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '2.8'
68
- description: Action Mailer delivery method using the Azure Communication Services
69
- Email API.
68
+ description: Action Mailer delivery method using the Azure Email Communications Service.
70
69
  email:
71
70
  - maccosmo@gmail.com
72
71
  executables: []
@@ -96,14 +95,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
95
  requirements:
97
96
  - - ">="
98
97
  - !ruby/object:Gem::Version
99
- version: 3.2.0
98
+ version: 3.3.0
100
99
  required_rubygems_version: !ruby/object:Gem::Requirement
101
100
  requirements:
102
101
  - - ">="
103
102
  - !ruby/object:Gem::Version
104
103
  version: '0'
105
104
  requirements: []
106
- rubygems_version: 3.7.1
105
+ rubygems_version: 4.0.10
107
106
  specification_version: 4
108
- summary: Azure Communication Services Email Delivery Method for Action Mailer
107
+ summary: Azure Email Communications Service Delivery Method for Action Mailer
109
108
  test_files: []