Packages
swoosh
1.25.0
1.26.3
1.26.2
1.26.1
1.26.0
1.25.3
1.25.2
1.25.1
1.25.0
1.24.0
1.23.1
1.23.0
1.22.1
1.22.0
1.21.0
1.20.1
1.20.0
1.19.9
1.19.8
1.19.7
1.19.6
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.17.10
1.17.9
1.17.8
retired
1.17.7
retired
1.17.6
1.17.5
1.17.4
retired
1.17.3
1.17.2
1.17.1
1.17.0
1.16.12
1.16.11
1.16.10
1.16.9
1.16.8
1.16.7
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
retired
1.16.1
retired
1.16.0
1.15.3
1.15.2
1.15.1
1.15.0
1.14.4
1.14.3
1.14.2
1.14.1
1.14.0
1.13.0
1.12.0
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
retired
1.11.0
1.10.3
1.10.2
1.10.1
1.10.0
1.9.1
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.2
1.5.1
1.5.0
1.4.0
1.3.11
1.3.10
1.3.9
1.3.8
retired
1.3.7
1.3.6
retired
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.9
1.0.8
retired
1.0.7
retired
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.25.6
0.25.5
0.25.4
0.25.3
retired
0.25.2
0.25.1
0.25.0
0.24.4
0.24.3
0.24.2
0.24.1
0.24.0
0.23.5
0.23.4
0.23.3
0.23.2
0.23.1
0.23.0
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.0
0.14.0
0.13.0
0.12.1
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Compose, deliver and test your emails easily in Elixir. Supports SMTP, Sendgrid, Mandrill, Postmark, Mailgun and many more out of the box. Preview your emails in the browser. Test your email sending code.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/swoosh/adapters/ms_graph.ex
defmodule Swoosh.Adapters.MsGraph do
@moduledoc ~S"""
An adapter that sends email using the Microsoft Graph API.
For reference: [Microsoft Graph API docs](https://learn.microsoft.com/en-us/graph/api/user-sendmail)
**This adapter requires an API Client.** Swoosh comes with Hackney, Finch and Req out of the box.
See the [installation section](https://hexdocs.pm/swoosh/Swoosh.html#module-installation)
for details.
> ### Dependency {: .info}
>
> Microsoft Graph adapter requires `:gen_smtp` to work properly.
> `:gen_smtp` is only used to encode the email body to MIME format.
## Configuration options
* `:auth` - either a function, a {mod, func, args} tuple, or a string that returns/is an OAuth 2.0 access token.
* `:base_url` - the base URL to use as the Microsoft Graph API endpoint. Defaults to the standard Microsoft Graph API endpoint.
* `:url` - the full URL to use as the Microsoft Graph API endpoint. If this is provided, `:base_url` is ignored. Useful for doing delegated sends such that the from of the email is maintained, but auth is done using the full URL (like when using a Distribution List).
## Example
# config/config.exs
config :sample, Sample.Mailer,
adapter: Swoosh.Adapters.MsGraph,
auth: fn -> Sample.OAuthTokenRequester.request_token() end
# lib/sample/mailer.ex
defmodule Sample.Mailer do
use Swoosh.Mailer, otp_app: :sample
end
"""
use Swoosh.Adapter,
required_config: [:auth],
required_deps: [gen_smtp: :gen_smtp_client]
require Logger
alias Swoosh.Email
@base_url "https://graph.microsoft.com/v1.0"
def deliver(%Email{} = email, config \\ []) do
Logger.debug("Delivering email using #{__MODULE__} Swoosh adapter: #{inspect(email)}")
headers = prepare_headers(config)
url = api_endpoint_url(email, config)
body = encode_body(email, config)
case Swoosh.ApiClient.post(url, headers, body, email) do
# Per https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http#response
# if successful, this method returns 202 Accepted response code. It doesn't return anything in the response body.
{:ok, 202, _headers, body} ->
Logger.debug("202 response, body: #{inspect(body)}")
{:ok, %{}}
# If the request body includes malformed MIME content, this method returns 400 Bad request and the following error message: "Invalid base64 string for MIME content."
{:ok, 400, _headers, body} ->
Logger.debug("400 response, body: #{inspect(body)}")
{:error, {400, body}}
# No other return codes are documented, but we'll treat them as an error.
{:ok, code, _headers, body} ->
Logger.debug("Unexpected response, code: #{code}, body: #{inspect(body)}")
{:error, {code, body}}
{:error, reason} ->
{:error, reason}
end
end
@doc false
# Encodes the email to headers and MIME content, encoded in base64,
# per https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http#request-body.
def encode_body(email, config) do
email
|> Swoosh.Adapters.SMTP.Helpers.body(config)
|> Base.encode64()
end
defp base_url(config), do: config[:base_url] || @base_url
defp api_endpoint_url(email, config) do
if config[:url] do
config[:url]
else
{_, from_email} = email.from
"#{base_url(config)}/users/#{from_email}/sendMail"
end
end
defp prepare_headers(config) do
[
{"User-Agent", "swoosh/#{Swoosh.version()}"},
{"Authorization", "Bearer #{auth(config)}"},
# Per https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http#request-headers
# we use a Content-Type of `text/plain` for MIME content.
{"Content-Type", "text/plain"}
]
end
defp auth(config) do
case config[:auth] do
func when is_function(func, 0) ->
func.()
{m, f, a} when is_atom(m) and is_atom(f) and is_list(a) ->
apply(m, f, a)
token when is_binary(token) ->
token
nil ->
raise "Missing required config :auth, it can be a function, a {mod, func, args} tuple, or a string"
end
end
end