Skip to content

Commit 5904384

Browse files
authored
feat: Support SMTP as an alternative email provider to Sparkpost (#172)
1 parent eb96049 commit 5904384

File tree

7 files changed

+72
-13
lines changed

7 files changed

+72
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ HackathonManager makes use of a few different third-party services & Ruby gems:
3131

3232
- [Devise](https://github.com/plataformatec/devise) + [MyMLH](https://my.mlh.io/) (authentication & attendee identity)
3333
- [Sidekiq](https://github.com/mperham/sidekiq) (background jobs)
34-
- [Sparkpost](https://www.sparkpost.com/) (email)
34+
- [SparkPost](https://www.sparkpost.com/) (email)
3535
- [Amazon S3](https://aws.amazon.com/s3/) (resume storage)
3636
- [Chartkick](http://chartkick.com/) (management UI charts)
3737
- [Blazer](https://github.com/ankane/blazer) (custom SQL queries, analytics, and charts)

app.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@
5959
"required": false
6060
},
6161
"SPARKPOST_API_KEY": {
62-
"description": "Sparkpost API key for sending email",
62+
"description": "SparkPost API key for sending email",
6363
"required": false
6464
},
6565
"SPARKPOST_CAMPAIGN_ID": {
66-
"description": "Sparkpost campaign ID for sending email (e.g. the name of your hackathon)",
66+
"description": "SparkPost campaign ID for sending email (e.g. the name of your hackathon)",
6767
"required": false
6868
},
6969
"HM_DOMAIN_NAME": {

app/mailers/user_mailer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def incomplete_reminder_email(user_id)
2323

2424
rescue_from SparkPostRails::DeliveryException do |e|
2525
error_codes_to_not_retry = [
26-
"1902", # Generation rejection
26+
"1902", # Generation rejection, specific to the Sparkpost API
2727
]
2828
raise e unless e.blank? || error_codes_to_not_retry.include?(e.service_code)
2929
end

app/views/manage/configs/index.html.haml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,30 @@
6363
= render 'config_row', name: 'Domain Name', key: 'HM_DOMAIN_NAME'
6464
= render 'config_row', name: 'Domain Protocol', key: 'HM_DOMAIN_PROTOCOL', default: 'https'
6565
%hr
66-
= render 'config_row', name: 'Sparkpost API Key', key: 'SPARKPOST_API_KEY', secret: true
67-
= render 'config_row', name: 'Sparkpost Campaign ID', key: 'SPARKPOST_CAMPAIGN_ID'
68-
%hr
6966
= render 'config_row', name: 'My MLH Application ID', key: 'MLH_KEY'
7067
= render 'config_row', name: 'My MLH Secret', key: 'MLH_SECRET', secret: true
7168
%hr
7269
= render 'config_row', name: 'Rollbar Access Token', key: 'ROLLBAR_ACCESS_TOKEN', secret: true, required: false
70+
%hr
71+
%p.mb-0
72+
%b Email Provider
73+
- if Rails.application.config.action_mailer.delivery_method == :smtp
74+
%p
75+
%span.badge.badge-secondary SparkPost
76+
%span.badge.badge-success SMTP
77+
%br
78+
%small
79+
%i To switch to SparkPost, unset the <code>SMTP_ADDRESS</code> environment variable
80+
= render 'config_row', name: 'SMTP Address', key: 'SMTP_ADDRESS'
81+
= render 'config_row', name: 'SMTP Port', key: 'SMTP_PORT', default: 587
82+
= render 'config_row', name: 'SMTP Username', key: 'SMTP_USER_NAME'
83+
= render 'config_row', name: 'SMTP Password', key: 'SMTP_PASSWORD'
84+
- else
85+
%p
86+
%span.badge.badge-success SparkPost
87+
%span.badge.badge-secondary SMTP
88+
%br
89+
%small
90+
%i To switch to SMTP, set the <code>SMTP_ADDRESS</code> environment variable
91+
= render 'config_row', name: 'SparkPost Campaign ID', key: 'SPARKPOST_CAMPAIGN_ID'
92+
= render 'config_row', name: 'SparkPost API Key', key: 'SPARKPOST_API_KEY', secret: true

app/views/manage/questionnaires/_history.html.haml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,10 @@
99
.card.mb-3
1010
.card-header Recent Email Events
1111
.card-body
12-
.email-events{ data: { url: message_events_manage_questionnaire_path(@questionnaire) } }
13-
%em Email events not available at this time.
12+
- email_provider = Rails.application.config.action_mailer.delivery_method
13+
- if email_provider == :sparkpost
14+
.email-events{ data: { url: message_events_manage_questionnaire_path(@questionnaire) } }
15+
%em Email events not available at this time.
16+
- else
17+
%p.alert.alert-info
18+
Not supported with current email provider (#{email_provider})

config/environments/production.rb

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,21 @@
9494

9595
### Custom config below this line ###
9696

97-
# Send email through Sparkpost API
98-
config.action_mailer.delivery_method = :sparkpost
97+
if ENV["SMTP_ADDRESS"].present?
98+
# Send email through SMTP
99+
config.action_mailer.delivery_method = :smtp
100+
config.action_mailer.smtp_settings = {
101+
address: ENV["SMTP_ADDRESS"].presence,
102+
port: ENV["SMTP_PORT"].presence&.to_i || 587,
103+
username: ENV["SMTP_USER_NAME"].presence,
104+
password: ENV["SMTP_PASSWORD"].presence,
105+
authentication: ENV["SMTP_AUTHENTICATION"].presence || "plain",
106+
enable_starttls_auto: ENV["SMTP_STARTTLS_AUTO"] != "false", # defaults to true
107+
}
108+
else
109+
# Send email through SparkPost API
110+
config.action_mailer.delivery_method = :sparkpost
111+
end
99112

100113
# Required for email messages
101114
mailer_url_host = ENV["HM_DOMAIN_NAME"]

docs/deployment-environment-variables.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,36 @@ S3_FORCE_PATH_STYLE=true
6060

6161
### E-mail
6262

63-
Currently, emails are queued via Sidekiq and then sent by Sparkpost's servers.
63+
Emails can be sent using [SparkPost](https://www.sparkpost.com) or traditional SMTP.
6464

65-
Create a Sparkpost API key with **Transmissions: Read/Write** and **Message Events: Read-only** permissions, limited to the production server's IP address. SMTP is _not_ required, as email is sent over the Sparkpost API rather than SMTP.
65+
#### SparkPost
66+
67+
[SparkPost](https://www.sparkpost.com) is the recommended email provider, and provides a free plan suitable for most hackathons.
68+
69+
Create a SparkPost API key with **Transmissions: Read/Write** and **Message Events: Read-only** permissions. The SMTP permission is _not_ required, as email is sent over the SparkPost API instead of SMTP.
70+
71+
For added security, whitelist the API key to your server's IP address.
6672

6773
```bash
6874
SPARKPOST_API_KEY=""
6975
SPARKPOST_CAMPAIGN_ID=""
7076
```
7177

78+
#### SMTP
79+
80+
>Sending email with SMTP over a personal or school email address (such as Gmail) is **NOT** recommended. Your hackathon may easily send several hundred to a few thousand emails during months leading up to the event, which regular email accounts block and may get reported for spam.
81+
>
82+
>Be sure your SMTP provider is configured appropriately for mass email, and check periodically that emails are being delivered successfully.
83+
84+
```bash
85+
SMTP_ADDRESS="mail.example.com"
86+
SMTP_USER_NAME=""
87+
SMTP_PASSWORD=""
88+
SMTP_PORT="" # optional, 587 by default
89+
SMTP_AUTHENTICATION="" # optional, "plain" by default
90+
SMTP_STARTTLS_AUTO="" # optional, "true" by default
91+
```
92+
7293
### Rollbar
7394

7495
Rollbar captures and notifies of errors in production, and requires a server-side access token.

0 commit comments

Comments
 (0)