swoosh / swoosh Goto Github PK
View Code? Open in Web Editor NEWCompose, deliver and test your emails easily in Elixir
Home Page: https://hexdocs.pm/swoosh
License: MIT License
Compose, deliver and test your emails easily in Elixir
Home Page: https://hexdocs.pm/swoosh
License: MIT License
Write an adapter for sending basic emails through AWS SES.
Implement an adapter for sending basic emails through Postmark.
Create a working adapter for sending basic emails through Mandrill.
The one we have currently are pretty shallow, we should especially the prepare_body
Private is reserved for libraries/frameworks extending Swoosh and the user should never have to tamper with it.
I've configured email for use with mailgun. The email is sending correctly through the mailgun api, but the reply_to isn't being added. I switched to this library specifically for this feature, so it is important for me that this work. I'll be happy to help troubleshoot/fix this issue.
defmodule NwreccOrg.SendMinisiteEmail do
import Swoosh.Email
def proxy(property, params) do
unless Map.has_key?(params, :email) do
params = Map.put(params, :email, "[email protected]")
end
new
|> to({ property.name, property.email})
|> reply_to(params.email)
|> from("[email protected]")
|> subject("Email Contact")
|> text_body(contact_us_text(params))
end
defp contact_us_text(params) do
....
end
end
See d92c732#commitcomment-17055719 for background.
I haven't checked if they have a free offering but if they do that would be a nice thing to do.
Curious on the reasoning for not having a potential way to deliver mail asynchronously? I looked for it in the issues but couldn't find anything. Is this an idea to add or would this restrict the logic too much for another user?
We probably want to have integration tests and API keys available for running tests, the easiest way to do this is to set up a shared account somewhere, somehow, and then we can contact providers and ask for free accounts.
The current TestAdapter breaks with integration testing using hound or wallaby.
The best option seem to be implementing some kind of ownership-based mechanism similar to what Ecto 2 does (elixir-ecto/ecto#1237)
@barisbalic @hubertlepicki @lau I would love to get your thoughts on that
We need to had a field to the Attachment
to set the disposition to either inline
or attachment
. We will probably need another content id
field as well.
It is supported by some of the providers via their web API. (see attachments
section of https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html for instance).
Here's my setup:
config.exs
:
config :elixir_lang_moscow, ElixirLangMoscow.Mailer,
adapter: Swoosh.Adapters.Local
router.ex
:
if Mix.env == :dev do
scope "/dev" do
pipe_through [:browser]
forward "/mailbox", Plug.Swoosh.MailboxPreview, [base_path: "/dev/mailbox"]
end
end
lib/mailer.ex
:
defmodule ElixirLangMoscow.Mailer do
use Swoosh.Mailer, otp_app: :elixir_lang_moscow
end
When sending an email via ElixirLangMoscow.Mailer.deliver/2
it returns something like: {:ok, %{id: "3d96e237f56230a27ba9953688646530"}}
and nothing happens.
My env:
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.3.2)
"phoenix": {:hex, :phoenix, "1.1.6", "7bf19002669c8f692f5a9c8d30dab7b49f3dc56228d5bde92a12fb426b4783c2", [:mix], [{:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: false]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}, {:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}]},
"swoosh": {:hex, :swoosh, "0.4.0", "2e1c90ba80146b4ce79923e7467c0ebf10dc6cf8933f98161fa12dd5ce848928", [:mix], [{:plug, "~> 1.1", [hex: :plug, optional: true]}, {:cowboy, "~> 1.0.0", [hex: :cowboy, optional: true]}, {:gen_smtp, "~> 0.11", [hex: :gen_smtp, optional: false]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: false]}, {:httpoison, "~> 0.8", [hex: :httpoison, optional: false]}]},
Hello,
It looks like this library was started after Bamboo was already established. It would be helpful to have a section in the README addressing how this library differs from Bamboo, and why it was necessary to create a separate project. For example, is there a fundamental design objective or approach which differs between the projects? This will make it easier for consuming developers to decide which is right for them.
Thank you!
Look at using gen_smtp
Hello all!
I'm using Swoosh right now with the Mailgun adapter. One of the features in Mailgun is including custom variables in the params of the post request, and the variables will be later included in mailgun event webhooks, and allow us to identify mails using our variables.
More details: https://documentation.mailgun.com/user_manual.html#attaching-data-to-messages
From looking at prepare_body methods, swoosh mailgun adapter doesn't seem to allow including other params like the custom variables (let me know if this is not the case!!). I would like to make pull request to add this functionality in the mailgun adapter. I already read guidelines for contributing but since I have never contributed to open source codes before, I want to check if this is a good/valid feature to add. :) Please let me know if I should go ahead and add codes!
For local development purposes I'm trying to consolidate all email delivery to a locally running Mailhog instance. By default it runs its SMTP server on port 1025. The Swoosh SMTP adapter doesn't seem to be able to customize the port used and always assumes 25.
I looked into how the config is passed to gen_smtp, and it LOOKS like all I need to do is add port: 1025
to my config and it should theoretically work. But I haven't been able to get it to work.
Any ideas?
It seems that at least for the smtp adapter, the env.ex is read once during compilation and those values are compiled in.
Problem being that I'm using System.get_env("SMTP_USERNAME") for example, these values are not available at compile time, but are during runtime (Docker standard behaviour).
This is fine for things like Postgrex and it's database_url setting, or redis configuration, and even mailman - which is what I'm migrating from.
If it's absolutely necessary to keep that behavior for some reason, could there be a deliver method that takes a config (on the mailer and passes that through to the adapter instead of the static configuration)?
https://developers.sparkpost.com/
I'll probably send a PR when I get some time.
Hi
I'm trying to put the Sendgrid API key in an environment variable rather than hardcoded inside config.exs.
This is what my config looks like:
config :my_app, MyApp.Mailer,
adapter: Swoosh.Adapters.Sendgrid,
api_key: System.get_env("SENDGRID_API_KEY")
It looks like the credentials are loaded fine on development with mix run --no-halt
but when I run on production mode MIX_ENV=prod
the environment variable is not being loaded correctly although I see them on Application.get_all_env(:my_app)
When I replace the get_env with the explicit API key everything works well.
What am I missing here?
%Swoosh.Email
reply_to
also accept {name, email}
user, email
as well as tuplesprovider options
in the struct%Swoosh.Email
functions, clever but confusing and make docs trickyemail address
validation? i.e. contains one @
and one .
?For all the modules, even if it's very basic. At least we'll have something to build on.
Do whatever it takes to integrate swoosh with phoenix, such that it can pick up layouts, templates and anything necessary from views.
The Adapter behaviour's function signature allows of a successful return type as :ok | {:ok, term}
with no indication of why one or the other. This makes pattern matching a bit cumbersome without knowing the internals of the adapter.
Is there a reason why both are supported? Can this be documented more clearly?
I really like how swoosh is structured and I'd like to hear your opinion on possibility of extending the use of the library.
I'd like to propose we reuse the main ideas behind swoosh (adapters, local mailbox) and apply them to text messages - many things could be reused. However there are several approaches we could make:
swoosh-text
project initially copying the code that should be reused, and eventually extracting common components into something like swoosh-core
.I don't want to impose anything, but I think it's an interesting idea worth exploring.
Hello, I'm following the docs to set a mailer using SMTP adapter but I'm getting the following error when executing from iex:
Webapp.ReportEmail.welcome() |> Webapp.Mailer.deliver
** (MatchError) no match of right hand side value: []
(gen_smtp) /home/app/mix_deps/gen_smtp/src/mimemail.erl:1027: :mimemail.dkim_sign/2
(gen_smtp) /home/app/mix_deps/gen_smtp/src/mimemail.erl:982: :mimemail.dkim_sign_email/3
(gen_smtp) /home/app/mix_deps/gen_smtp/src/mimemail.erl:115: :mimemail.encode/2
(swoosh) lib/swoosh/adapters/smtp.ex:40: Swoosh.Adapters.SMTP.deliver/2
Settings implemented:
config/config.exs
config :webapp, Webapp.Mailer,
adapter: Swoosh.Adapters.SMTP,
relay: "smtp.service.com",
username: "[email protected]",
password: "mypass",
tls: :always,
auth: :always,
dkim: [
s: "default", d: "domain.com",
private_key: {:pem_plain, "test-key"} #File.read!("priv/keys/domain.private")
]
lib/webapp/mailer.ex
defmodule Webapp.Mailer do
use Swoosh.Mailer, otp_app: :webapp
end
defmodule Webapp.ReportEmail do
import Swoosh.Email
def welcome() do
new
|> to({"Somebody", "[email protected]"})
|> from({"Other", "[email protected]"})
|> subject("Hello, test!")
|> html_body("Hello you")
|> text_body("Hello you\n")
end
end
Using:
:swoosh, "~> 0.4.0"
gen_smtp: 0.11.0
phoenix, 1.1.6
Elixir (1.3.1)
Ideas please?
It would be good to have some level of integration testing for all the adapters.
Example: Mailgun. It requires you to use the domain you are sending from in API calls. Some sites use more than one domain.
If you have an app that uses several domains, it would be nice if you could pass the domain as part of the parameters to the sending function.
maingun's @base_url var is missing / at the end hence constructing a url like this: https://api.mailgun.net/v3domain.com/messages.
I was able to work around this by adding / in front of my domain_name config.
I am using the SparkPost adaptor with Coherence (which has built in support for Swoosh). The emails are successfully sent from my laptop in development, and I receive them as expected. But using the same config code on the server does not work. I checked the online app logs which is proxy behind nginx and there are no error messages on the app side or nginx side.
I use the ubuntu firewall (ufw) and turned it off and still it does not work.
Checking the account in SparkPost also shows that the emails are sent from the localhost, but as if SparkPost receives no post request from the server.
Would someone have a clue what could be the issue.
Currently, in mix.exs
, you have:
{:poison, "~> 2.1"}
Consider loosening the requirement to also allow version 1.5.x series
{:poison, "~> 1.5 or ~> 2.0"}
After a casual search for Poison in the swoosh codebase:
https://github.com/swoosh/swoosh/search?utf8=%E2%9C%93&q=Poison
I noticed that swoosh uses neither the defimpl
feature of the 1.5.x
poison nor the @derive Poison.Encoder
of the 2.x
series to define it's encoding rules, preferring instead to leave the dirty work to Poison itself.
This means swoosh can probably support both versions of poison, which means, for us pleb end-users, if you could loosen your poison requirement, it would make things a lot easier as a lot of our older libraries depend on the 1.x series of poison.
The macro reads the configuration and sets it to the module attribute @config
. Swoosh supports transforming environment variables, but that's only one way of deploying.
bitwalker/conform is another model that overwrites the sys.config based on a configuration file deployed to the server. If the config was read at runtime, instead of compile time then the conform style of deployments could be supported as well.
Currently the test adapter always returns :ok
:
https://github.com/swoosh/swoosh/blob/master/lib/swoosh/adapters/test.ex
It would be nice if there were some way to write mailer tests for the fail case to ensure that errors are handled well.
In all the adapters
Swoosh depends on the gen_smtp
package version 0.10.0
which uses, apparently, now old spec format and thus I can't compile it using elixir 1.3.0. I am wondering if we can bump the gen_smtp
version to 0.11.0
and release a new minor version, 3.0.1?
Mailgun Adapter will throw an error when sending an email telling 'from' parameter is missing
, but I send this params
Here are the params we sent:
"from=no-reply%40mydomain.fr....."
hackney is used within the Mailgun Adapter and seems to duplicate the content-type header as described in this issue benoitc/hackney#388. Mailgun won't understand the body and throw the error 'from' parameter is missing
Lock hackney to 1.6.5, this issue was introduced with the 1.6.6 release
Support DKIM in the SMTP adapter so that user can sign their emails before sending.
I noticed while doing integration testing that our adapters assume a lot about the response from the provider service. Specifically if the mailgun domain is invalid or can't be found, the provider returns a 404 with a standard HTML page, which breaks horribly when we try to Poison.decode!/1
it.
I suspect other providers and errors are better catered for, but we should check, and decide how to handle this in a uniform manner.
Using swoosh: 0.3.0
and phoenix_swoosh: 0.1.1
.
I am pretty sure this error is being raised because there is something wrong with my config. It is hard to figure out exactly what is missing from the error message.
> MyApp.Emails.forgot_password(%{first_name: "Test", last_name: "User", email: "[email protected]"}, "test") |> MyApp.Mailer.deliver
** (ArgumentError) argument error
:erlang.bit_size(nil)
(swoosh) lib/swoosh/adapters/mailgun.ex:33: Swoosh.Adapters.Mailgun.deliver/2
Quick link to the line in question: https://github.com/swoosh/swoosh/blob/v0.3.0/lib/swoosh/adapters/mailgun.ex#L33
Here is the adapter configuration.
> Application.get_env(:myapp, MyApp.Mailer)
[adapter: Swoosh.Adapters.Mailgun,
api_key: "key-a1a2a2s22d2d2d2d2d2d2",
domain: "mailgun.myapp.com"]
And the raw sys.config
entry just in case this is an issue with strings vs binaries.
[
% ... other config stuff here
{myapp, [
{'Elixir.MyApp.Mailer',[
{adapter,'Elixir.Swoosh.Adapters.Mailgun'},
{api_key,<<"key-a1a2a2s22d2d2d2d2d2d2">>},
{domain,<<"mailgun.myapp.com">>}]}
]},
]
.
Any ideas why this error is happening?
The code works in development where the swoosh config is defined in config/dev.exs
instead of the sys.config
file (exrm).
We should probably raise if stuff like an API key is not set.
When compiling:
remote: ==> swoosh
remote: Compiling 21 files (.ex)
remote: warning: crypto:rand_bytes/1 is deprecated and will be removed in a future release; use crypto:strong_rand_bytes/1
remote: lib/swoosh/adapters/local/storage/memory.ex:120
remote:
remote: Generated swoosh app
Replace the README with something meaningful to users, include some basic examples in lieu of documentation.
When doing end-to-end testing with frontend of features like account registration that involve unique tokens and things like that, it would be useful to have a json version of the mailbox that the tests could query.
I did recently something similar in one of our projects. If you find this idea worth considering I could work on it.
i.e. not JSON-parsable
{:ok, code, _headers, body} when code > 399 ->
{:error, {code, Poison.decode!(body)}}
causes an Poison error
Hello
nothing in the docs for attachments, but the field exist in the email record
cannot find a way to specify attachment file
thanks
We should update the docs and README accordingly.
I'm having an odd problem:
iex(1)> {:ok, conf} = Application.fetch_env(:email, Email.Mailer)
{:ok,
[adapter: Swoosh.Adapters.SMTP, relay: {:system, "EMAIL_HOST"},
username: {:system, "EMAIL_USERNAME"}, password: {:system, "EMAIL_PASSWORD"}]}
iex(2)> Swoosh.Adapters.SMTP.validate_config(conf)
** (UndefinedFunctionError) function Swoosh.Adapters.SMTP.validate_config/1 is undefined (module Swoosh.Adapters.SMTP is not available)
Swoosh.Adapters.SMTP.validate_config([adapter: Swoosh.Adapters.SMTP, relay: {:system, "EMAIL_HOST"}, username: {:system, "EMAIL_USERNAME"}, password: {:system, "EMAIL_PASSWORD"}])
But other adapters are present:
iex(3)> conf = [adapter: Swoosh.Adapters.Logger]
[adapter: Swoosh.Adapters.Logger]
iex(4)> Swoosh.Adapters.Logger.validate_config(conf)
:ok
Am I doing something really silly here?
phoenix_swoosh?
# don't do
config :swoosh, :sendgrid
# do
config :swoosh, MyMailer
Hi,
I was playing around with Coherence and it has a dependency on Swoosh. However, the dependencies are not resolved because swoosh has a strict dependence on Cowboy 1.0.0.
Running dependency resolution...
Failed to use "cowboy" (version 1.1.2) because
phoenix (version 1.2.1) requires ~> 1.0
plug (version 1.3.0) requires ~> 1.0.1 or ~> 1.1
swoosh (versions 0.1.0 to 0.5.0) requires ~> 1.0.0
mix.exs specifies ~> 1.1.2
** (Mix) Hex dependency resolution failed, relax the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock). If you are unable to resolve the conflicts you can try overriding with {:dependency, "~> 1.0", override: true}
Perhaps it should be ~> 1.0 ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.