View emails sent - ruby-on-rails

I have config.action_mailer.delivery_method = :test and use delayed_job. I run some code that places an email to be sent in a queue, then run rake jobs:work, but nowhere do I see the email that is sent out, and ActionMailer::Base.deliveries is nil. I'm just looking to debug and view the content of htese emails, how can I do so?

When config.action_mailer.delivery_method is set to :test, emails are not actually sent but instead merely added to a list of "sent" messages. That list exists only in memory. That means only the process that "sent" the email can see the list and verify that it was actually "sent".
Since the code that actually sends your mail is being executed in an external process (through a system() or backtick call), your calling script won't be able to see the in-memory queue of that external process and thus won't be able to verify that the emails were actually "sent".
This shouldn't really be a big deal unless something has gone wrong. By default outgoing emails will be written to the log file, so you can verify that they're actually sending by checking there. If you want to view/manipulate the queue in-memory, you'll have to add code to your job to do so, as that is the only code that will have access to it.

Related

Testing Mails queued with Sidekiq

Because we need to have the ability to schedule email delivery, we have migrated to using Sidekiq to send emails with the deliver_later method. Under the old regime that used deliver_now, our testing could use
ActionMailer::Base.deliveries[index]
to inspect the recipient, subject, body, attachments, etc...
For testing purposes, is there an equivalent mechanism to inspect the contents of queued email when using Sidekiq and deliver_later?
For testing contents of the email, you have to render the email template for which the job needs to be executed. I suggest you should separate unit tests:
Job spec to check if email is getting enqueued with correct parameters.
Email spec to check the email contents.
If you want to go the end-to-end style, use Sidekiq::Testing.inline! to execute the job and then use ActionMailer::Base.deliveries[index] like before.
The solution turned out to be to execute perform_enqueued_jobs after all emails were queued. After this, all of the existing testing mechanisms worked.
See https://api.rubyonrails.org/v7.0.4/classes/ActiveJob/TestHelper.html for additional information.

Automatically logging email sent through Rails

We send out many emails through Rails (and then through Amazon SES). I'd like to now log all of those emails in our database so we know exactly which emails were sent where and all the details. I'd also love to know which class/method sent those emails or some way to tag them.
This must be an extremely common need, so I'm curious if there's a mechanism with Rails to automatically handle this?
mail-logger gem captures the info about the emails sent, and log them to a file.
With a little bit of work it could be customized to write to a database instead.
The gem is overriding delivered_email method to log the details:
class Mail::Logger::Callback
def self.delivered_email(email)
Mail::Logger.logger.info email.inspect
end
end

ActionMailer.deliveries is always an empty array

I am using the Postmark gem for rails and writing Rspecs tests to make sure the emails are actually being sent when the form is valid.
I want to check that ActionMailer::Base.deliveries.last.to matches what I put in the contact form I'd like to test.
However, ActionMailer::Base.deliveries is always an empty array. Even in production, after an email is successfully sent (and received on the other end), the array is still empty when observed with rails c production.
What am I missing? How can I verify that the email has been sent in my tests?
ActionMailer::Base.deliveries array is a feature of :test delivery mode provided by ActionMailer (docs). If you’ve enabled Postmark gem in your test environment, that array will always be empty.
Unless you’re aiming for full integration testing, you should avoid using external services in your tests and stick to the :test delivery method. If you do that, you might also want to take a look at the email-spec gem, which provides a DSL for testing emails sent with ActionMailer.
In case you actually want to send emails in your tests, you can use Postmark Messages Retrieval API to retrieve a sent message via recipient or message ID and verify its contents. This allows for complete black-box testing if this is what you’re looking for.

Kinda-mass emailing from Rails, but with own mail server

I've read most of the other answers on this topic, but a lot of them related to either third-party services like MailChimp (which I'm not necessarily opposed to) or how not to upset the host's email server.
I believe this case is unique so that it'll contribute...
I have my own DigitalOcean droplet running a rails app. I need to send out 100-1000 emails every so often, each with a unique message (a link I'm using for tracking clicks originating from the email).
I'm also operating my own iRedMail server.
Can someone recommend how to best-handle this task? I was going to simply cycle through the list of emails and use the template.html.erb to drop in my link, but what types of problems might I run into?
Thank you!
You should decouple your Rails App from the mail sending so that you don't have to wait in your view for the mails to be sent (assuming that you click on something that triggers the start of your mail sending). Use something like delayed_job or another queueing mechanism that Rails offers and only queue up the sending job of the e-mails. Then when the queue comes to execute the particular job you can customize the message with an HTML part and a text part or whatever else you need and pass them on individually to your MTA.

Delayed::Jobs keeps sending emails if it fails

I used Delayed_Jobs to send emails. Except I think that if it fails to send to 'every single email' then it tries and reruns the entire batch again.
How do I make it skip an email address if its not correct?
if an exception occurs delayed_job will treat the job as failed and keep rerunning it.
You should capture exceptions to make sure that at the end a job will always be considered as succesful.

Resources