ActionMailer configuration API

Hello,

TL;DR: I’d like to move ActionMailer configuration to confg/mail.yml (just like config/database.yml). In order to make that possible (in a sane way), I would like to standardize the way ActiveRecord and ActionMailer are configured.

As I was poking around to see how I would implement configuring ActionMailer with config/mail.yml, I was reminded how different the configuration APIs for ActiveRecord and ActionMailer are.

My plan is to make the ActionMailer configuration api mirror the ActiveRecord configuration api. That is, the following should work:

current ActiveRecord configuration

ActiveRecord::Base.configurations = {

development: {

adapter:    "postgresql",

host:       "localhost",

database:   "myapp_development",

username:   "rails",

password:   "sekret",

},

test: {

adapter:    "sqlite3",

database:   "db/test.sqlite3",

pool:       5,

timeout:    5000,

},

production: { } # … etc

}

proposed ActionMailer configuration

ActionMailer::Base.configurations = {

development: {

adapter:    "sendmail",                     # renamed from delivery_method to match ActiveRecord

location:   "/usr/sbin/sendmail",

arguments:  "-i -t",

},

test: { adapter: “test” }, # this would be the default

production: {

adapter:          "smtp",

host:             "[smtp.sendgrid.net](http://smtp.sendgrid.net)",      # renamed from address

port:             "587",

authentication:   :plain,

username:         ENV["SENDGRID_USERNAME"], # renamed from user_name

password:         ENV["SENDGRID_PASSWORD"],

},

}

I chose to make ActionMailer like ActiveRecord because I think that more people know ActiveRecord’s configuration. However, if there is something about the way ActionMailer is configured that is desired, then ActiveRecord’s configuration could also be changed (although it seems like it would be harder to change and deprecate ActiveRecord configuration).

A few thoughts:

  • ActionMailer stores configuration for each delivery method (smtp_settings, sendmail_settings). I’m not sure why this is, but to me it makes more sense to flatten this configuration structure and split it up by environment.

  • This would be a major configuration change. If the change is accepted, I would write graceful deprecation and perhaps a migration helper.

  • I mentioned this idea to Aaron Patterson at Railsconf. He brought up the idea of having a more generic configuration storage mechanizm. While I’m not specifically working on that, I think this is a step in that direction.

A few questions:

  • Any thoughts in general? Is this a good idea? Does anyone have major problems with this?

  • Does it make sense to rename configuration options such as renaming address to host in order to match the ActiveRecord configuration options more closely? Once again, I would make sure to not break existing configurations.

  • Is there anything about the current ActionMailer configuration api that is better than ActiveRecord’s?

I will start chipping away at this, and probably come back with more questions after a first pass.

I would apreciate any initial feedback.

Thank you for your time,

-Amiel

Storing configuration in your git repository is not the greatest thing on earth: http://www.12factor.net/config

At least by pulling it from code it becomes very easy to assign to ENV Variables.

Richard,

I agree that storing configuration in git is not ideal.

My hope is that:

  1. moving mail configuration to mail.yml will encourage mail configuration to be treated more like database configuration is now (by default, database.yml is not included in git; and a database.yml.example is provided).

  2. if the configuration apis are the same, any future efforts that change the way ActiveRecord is configured, will more easily apply to ActionMailer as well.

Thanks for your response,

-Amiel

if anything, I’d rather see database.yml go away and have AR configured through the application config api instead. the current state of affairs makes it more difficult to e.g. use an external configuration repository like ZooKeeper. that will continue to be true as long as AR has no documented public configuration api and simply expects the user to provide database.yml (the half-baked DATABASE_URL environment variable support notwithstanding). please don’t send AM down the same path and make the situation even worse.

Brian, I see your point.

I actually think that this project will actually benefit you. My goal is to standardize the api in which ActiveRecord and ActionMailer are configured.

I don’t think I can decide to make this public, but I think that with the standardization will also come API stability.

Another problem is that database.yml is required, so you can’t configure ActiveRecord programmatically.

I don’t see database.yml going away, but it would be nice if rails didn’t raise an exception on boot when it can’t find database.yml.

Another similar approach to what I had before could be this configuration API:

ActiveRecord::Base.configuration = {

adapter: “postgresql”,

host: “localhost”,

database: “myapp_development”,

username: “rails”,

password: “sekret”,

}

ActionMailer::Base.configuration = {

adapter: “sendmail”,

location: “/usr/sbin/sendmail”,

arguments: “-i -t”,

}

ActiveRecord::Base would still respond to .configurations, which would just throw away configurations for any environments but the current one.

This would make configuring ActiveRecord and ActionMailer programmatically easier.

What do you think?

Anyone else have opinions on this before I get started?

-Amiel

sounds fine to me.

I have a separate issue with having a static single-environment configuration like this because it’s the root cause of some other problems I’ve had with database configuration, but describing that would just confuse this issue and can wait til another day.

thanks for your response!

Ok,

I’ve got a start on this: https://github.com/amiel/rails/compare/actionmailer-configuration.

So far, I’ve just got the ActionMailer::Base.configuration api as well as deprecated support for the previous ActionMailer::Base.xxx_settings api.

Adding mail.yml at this point is trivial. Any thoughts on this before I send in a pull-request?

Thanks,

-Amiel