Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ gem 'csv' # LOCKED: csv was loaded from the standard library, but is not part of
gem 'delayed_job'
gem 'delayed_job_active_record'
gem 'drb' # LOCKED: Added because of pry-remote
gem 'email_validator'
gem 'font_awesome5_rails'
gem 'bootstrap', '~> 5'
gem 'friendly_id'
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ GEM
dotenv (= 3.2.0)
railties (>= 6.1)
drb (2.2.3)
email_validator (2.2.4)
activemodel
erb (6.0.2)
erubi (1.13.1)
execjs (2.10.1)
Expand Down Expand Up @@ -635,6 +637,7 @@ DEPENDENCIES
delayed_job_active_record
dotenv-rails
drb
email_validator
fabrication
faker
faraday
Expand Down
9 changes: 9 additions & 0 deletions app/helpers/email_header_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@ module EmailHeaderHelper
private

def mail_args(member, subject, from_email = 'meetings@codebar.io', cc = '', bcc = '')
return nil if invalid_email?(member.email, member.id)

{ from: "codebar.io <#{from_email}>",
to: member.email,
cc: cc,
bcc: bcc,
subject: subject }
end

def invalid_email?(email, member_id)
return false if EmailValidator.valid?(email, mode: :strict)

Rails.logger.warn("[EmailHeaderHelper] Invalid email for member_id=#{member_id}: #{email}")
true
end
end
1 change: 1 addition & 0 deletions app/models/member.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Member < ApplicationRecord
validates :auth_services, presence: true
validates :name, :surname, :email, :about_you, presence: true, if: :can_log_in?
validates :email, uniqueness: true
validates :email, email: { mode: :strict }, if: :can_log_in?
validates :about_you, length: { maximum: 255 }

DIETARY_RESTRICTIONS = %w[vegan vegetarian pescetarian halal gluten_free dairy_free other].freeze
Expand Down
65 changes: 65 additions & 0 deletions spec/helpers/email_header_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
RSpec.describe EmailHeaderHelper do
subject do
Class.new do
include EmailHeaderHelper
public :mail_args
end.new
end
Comment thread
mroderick marked this conversation as resolved.
Outdated

describe '#mail_args' do
let(:member) { Struct.new(:id, :email).new(1, 'test@example.com') }

it 'returns mail arguments for valid email' do
result = subject.mail_args(member, 'Test Subject')
expect(result[:to]).to eq('test@example.com')
expect(result[:subject]).to eq('Test Subject')
end

it 'returns nil for nil email' do
member = Struct.new(:id, :email).new(1, nil)
result = subject.mail_args(member, 'Test Subject')
expect(result).to be_nil
end

it 'returns nil for blank email' do
member = Struct.new(:id, :email).new(1, '')
result = subject.mail_args(member, 'Test Subject')
expect(result).to be_nil
end

it 'returns nil for invalid email format' do
member = Struct.new(:id, :email).new(1, 'invalid-email')
result = subject.mail_args(member, 'Test Subject')
expect(result).to be_nil
end

it 'returns nil for email missing @ symbol' do
member = Struct.new(:id, :email).new(1, 'invalidexample.com')
result = subject.mail_args(member, 'Test Subject')
expect(result).to be_nil
end

it 'returns nil for email missing TLD' do
member = Struct.new(:id, :email).new(1, 'invalid@example')
result = subject.mail_args(member, 'Test Subject')
expect(result).to be_nil
end

it 'returns mail arguments for valid email with plus addressing' do
member = Struct.new(:id, :email).new(1, 'user+tag@example.com')
result = subject.mail_args(member, 'Test Subject')
expect(result[:to]).to eq('user+tag@example.com')
end

it 'includes from email when provided' do
result = subject.mail_args(member, 'Test Subject', 'custom@codebar.io')
expect(result[:from]).to eq('codebar.io <custom@codebar.io>')
end

it 'includes cc and bcc when provided' do
result = subject.mail_args(member, 'Test Subject', 'from@codebar.io', 'cc@codebar.io', 'bcc@codebar.io')
expect(result[:cc]).to eq('cc@codebar.io')
expect(result[:bcc]).to eq('bcc@codebar.io')
end
end
end
31 changes: 31 additions & 0 deletions spec/models/member_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,37 @@
it { expect(member).to validate_presence_of(:surname) }
it { expect(member).to validate_presence_of(:email) }
it { expect(member).to validate_presence_of(:about_you) }

it 'accepts valid email format' do
member.email = 'valid@example.com'
expect(member).to be_valid
end

it 'rejects invalid email format' do
member.email = 'invalid-email'
expect(member).not_to be_valid
expect(member.errors[:email]).to include('is invalid')
end

it 'rejects email missing @ symbol' do
member.email = 'invalidexample.com'
expect(member).not_to be_valid
end

it 'rejects email missing TLD' do
member.email = 'invalid@example'
expect(member).not_to be_valid
end

it 'accepts email with valid subdomains' do
member.email = 'user@mail.example.com'
expect(member).to be_valid
end

it 'accepts email with plus addressing' do
member.email = 'user+tag@example.com'
expect(member).to be_valid
end
end
end

Expand Down