Turn on transactional emails with loops

This commit is contained in:
Max Wofford 2025-03-12 16:03:54 -04:00
parent 35b31caa1c
commit 60bc0a53ba
6 changed files with 43 additions and 20 deletions

View file

@ -28,4 +28,7 @@ ENCRYPTION_KEY_DERIVATION_SALT=generate_a_salt_and_put_it_here
SMTP_USER_NAME=replace_with_your_smtp_username
SMTP_PASSWORD=replace_with_your_smtp_password
SMTP_ADDRESS=replace_with_your_smtp_address
SMTP_PORT=replace_with_your_smtp_port
SMTP_PORT=replace_with_your_smtp_port
# some emails are sent via loops.so again, not needed for local development
LOOPS_API_KEY=your_loops_api_key_here

View file

@ -35,25 +35,17 @@ class SessionsController < ApplicationController
def email
email = params[:email].downcase
email_address = EmailAddress.find_by(email: email)
if email_address
# Existing user - send sign in link
token = email_address.user.create_email_signin_token
AuthMailer.sign_in_email(email_address, token).deliver_later
redirect_to root_path(sign_in_email: true), notice: "Check your email for a sign-in link!"
else
# New user - create account and send sign in link
user = User.create!(
username: email.split("@").first,
)
email_address = user.email_addresses.create!(email: email)
token = user.create_email_signin_token
AuthMailer.sign_in_email(email_address, token).deliver_later
redirect_to root_path(sign_in_email: true), notice: "Welcome! Check your email for a sign-in link!"
# Use a transaction to ensure both user and email are created atomically
email_address = ActiveRecord::Base.transaction do
EmailAddress.find_by(email: email) || begin
user = User.create!
user.email_addresses.create!(email: email)
end
end
LoopsMailer.sign_in_email(email_address).deliver_later
redirect_to root_path(sign_in_email: true)
end
def token

View file

@ -0,0 +1,22 @@
class LoopsMailer < ApplicationMailer
# Override the default mailer settings to use Loops.so SMTP
self.delivery_method = :smtp
self.smtp_settings = {
address: "smtp.loops.so",
port: 587,
user_name: "loops",
password: ENV["LOOPS_API_KEY"],
authentication: "plain",
enable_starttls: true
}
def sign_in_email(email_address)
@email = email_address.email
@token = email_address.user.create_email_signin_token.token
@sign_in_url = auth_token_url(@token)
mail(
to: @email,
)
end
end

View file

@ -3,7 +3,6 @@ class User < ApplicationRecord
encrypts :slack_access_token
validates :slack_uid, uniqueness: true, allow_nil: true
validates :username, presence: true
has_many :heartbeats
has_many :email_addresses

View file

@ -18,4 +18,4 @@
If you didn't request this email, you can safely ignore it.
</p>
</body>
</html>
</html>

View file

@ -0,0 +1,7 @@
{
"transactionalId": "cm86bg9vd00xuddjuh5u5mfuu",
"email": "<%= @email %>",
"dataVariables": {
"auth_link": "<%= @sign_in_url %>"
}
}