ActionMailer + Sidekiq/Redis Sending Duplicate Emails Repeatedly - Rails 4 - ruby-on-rails-4

I'm running rails and redis in development environment on a local ubuntu 18 machine.
The ActionMailer is sending emails appropriately, however it seems as if my computer is off and I come the next day to fire up redis, it resends a bunch of emails.
#invoice controller
InvoiceMailer.send_invoice_to_email(email, #invoice).deliver_later
#InvoiceMailer
def send_invoice_to_email(email, invoice)
#invoice = invoice
attachments["test_invoice_#{invoice.id}_#{Date.today}.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string(pdf: 'Invoice', template: '/invoices/show.pdf.erb', layout: 'application')
)
bcc = ["test <test#test.com>", "test2 <test2#test.com>"]
mail(from: "Test <info#test.com>", to: email, bcc: bcc, subject: "Invoice From test")
end
What could my problem be and how would I debug this?

For future reference - I believe that there were NOT duplicate emails being sent out. I had some issues with the logic. If this is happening to you, first ensure that sidekiq is not queuing emails that are then sent out later on at the same time. Also, it gets confusing if you are testing this by sending actual emails - be careful of how you add "to", "cc", "bcc".

Related

How to get "starred mails" from Gmail or other mail services using IMAP_tools in django

I am able to get inbox emails and also able to get emails from specific folder but i am unable to get "starred" emails.
I tried below code. and i am expecting emails with "starred flag" in response.
from imap_tools import MailBox, A
# Create your views here.
def temp(request):
#Get date, subject and body len of all emails from INBOX folder
with MailBox('smtp.gmail.com').login('admin#gmail.com', 'password', 'INBOX') as mailbox:
temp="empty"
for msg in mailbox.fetch():
temp = (msg.date, msg.subject, msg.html)
return HttpResponse(temp)
https://github.com/ikvk/imap_tools/blob/master/examples/search.py
mailbox.fetch(AND(flagged=True))
(A long time ago in a galaxy far far away) star looked like a flag.

Django ignore 500 errors

I have developed an ecommerce store in Django where I am using twilio sms functionality. Using twilio, sms only sends if number is in proper format and valid.
message = client.messages.create(
body="Dear customer, this is sample msg", to= number, from_= contact )
So I want a way through which if twilio raise an error in sending sms, this errors gets ignore [Don't raise Server Error 500 in prod]. And Website functionality remains normal.
Is there any way to cater it?
To cater such situation, this simply worked:
try:
message = client.messages.create(
body="Dear customer, this is sample msg", to= number, from_= contact )
except Exception as e:
pass

ActionMailer not delivering confirmation emails in test environment - Rails 4

I'm using Rails (4.2.6), Ruby (2.2.4), Devise (4.1.1), Capybara (2.7.1), Capybara-email (2.5.0), Email_spec (2.1.0), Rspec (3.4.0), and Postgres (0.18.4)
After I upgraded the application from Rails 4.1.15 to 4.2.6, several authentification & registration tests fail. Before the upgrade all tests were properly passing. The code works as expected in the development environment (for example, confirmation emails are sent & viewable in the Rails server terminal). The problem of non-delivered emails only occurs in the test environment.
Here's the failing rspec ./spec/features/users/authentification_spec.rb:56:
#Sign up User
visit "/"
click_link "Sign up"
find(:css, "#user_email").set("tester9#example.com")
find(:css, "#user_password").set("password900")
find(:css, "#user_password_confirmation").set("password900")
expect {
click_button "Sign up"
}.to change{ ActionMailer::Base.deliveries.size}.by(1)
When a user completes the form and clicks the "Sign up" button, the page redirects to the "About" page and as expected, the following flash message appears: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
Using save_and_open_page, I confirmed the aforementioned behavior. However, the spec fails with the following error:
Failure/Error:
expect {
click_button "Sign up"
}.to change{ ActionMailer::Base.deliveries.size}.by(1)
expected result to have changed by 1, but was changed by 0
# ./spec/features/users/authentification_spec.rb:56:in `block (2 levels) in <top (required)>'
The error indicates that there are no message objects in the ActionMailer::Base.deliveries array. The results of Pry confirm that the ActionMailer::Base.deliveries array is indeed empty:
[1] pry(main)> mail = ActionMailer::Base.deliveries
=> []
Here's the test log when the spec is run:
Started POST "/users" for 127.0.0.1 at 2016-06-09 16:16:25 -0700
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "user"=>{"email"=>"tester9#example.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
[1m[35m (0.8ms)[0m SAVEPOINT active_record_1
[1m[36mUser Exists (3.3ms)[0m [1mSELECT 1 AS one FROM "users" WHERE "users"."email" = 'tester9#example.com' LIMIT 1[0m
[1m[35mUser Exists (1.9ms)[0m SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('tester9#example.com') LIMIT 1
[1m[36mSQL (2.1ms)[0m [1mINSERT INTO "users" ("email", "encrypted_password", "signup_as", "created_at", "updated_at", "confirmation_token", "confirmation_sent_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"[0m [["email", "tester9#example.com"], ["encrypted_password", "$2a $04$Vruf8j0A.DdOZLPe0qjVp.4PxzdR7sCdLF4FfyAr4dQSxcQAjpAwy"], ["created_at", "2016-06-09 23:16:25.095386"], ["updated_at", "2016-06-09 23:16:25.095386"], ["confirmation_token", "EmY8JyaVAxAfiq7oQ98z"], ["confirmation_sent_at", "2016-06-09 23:16:25.097581"]]
[1m[35m (0.4ms)[0m RELEASE SAVEPOINT active_record_1
Redirected to http://www.example.com/about
Completed 302 Found in 113ms (ActiveRecord: 9.6ms)
The log indicates that a confirmation email was sent, but the deliveries array is empty. Why is that happening? Is the record not being committed or persisted in the test database for some reason? I've read related posts about non-delivery of mail, but have not found a solution to my problem.
Relevant code from test.rb:
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
config.action_mailer.perform_deliveries = true
Relevant contents from rails_helper.rb:
require 'rspec/rails'
require 'devise'
require 'capybara/rails'
require 'database_cleaner'
require 'capybara/poltergeist'
require 'capybara/email/rspec'
require 'email_spec'
# Includes Devise test helpers (e.g., lets you use Devise's "sign_in" method in tests)
config.include Devise::TestHelpers, :type => :controller
config.include Warden::Test::Helpers
Relevant commented-out code from devise.rb:
# Configure the class responsible to send e-mails.
#config.mailer = 'Devise::Mailer'
Mail delivery works as expected in development & production. What is going wrong in the test environment? How can I fix it? Thanks!
Looking at devise - https://github.com/plataformatec/devise/blob/4-1-stable/lib/devise/models/confirmable.rb#L48 - it sends the confirmation email in an after_commit callback - If you're running with transactional testing enabled the after_commit callback will never be called (because the DB transaction is rolled back and never committed) so the email is never sent. Disable transaction based testing for that test and it will probably work.
Just to summarize the discussion between Tom Walpole and codeinspired above into a top-level answer for browsers who might not look into comments, their solution (assuming you use DatabaseCleaner) is to make the following modifications:
rails_helper.rb
# lots of boilerplate and
# other things at the top of this file, but you'll
# eventually see....
RSpec.configure do |config|
# ... other config stuff ...
# sometime after this key line, you want to add:
config.before(:each, truncation: true) do
DatabaseCleaner.strategy = :truncation
end
# ... other config stuff ...
end
For the test that is in question here, you want to modify it to look like the following (note the addition of "truncation: true" in the line starting with the word "it")
something_spec.rb
# ... other stuff ...
describe "some function" do
it "performs a function correctly", truncation: true do
# your test
# goes here
end
end

Get the list of mail chimp subscribers in rails

I am working on a simple rails rails app and i have so many subscribers in my mail mailchimp account and i want to get my all subscribers and send the a mail from my rails app. How do i get my subscribers emails in an array.
my code sample is below
def send_now
#news_letter = NewsLetter.find(params[:id])
gb = Gibbon::API.new("xxx")
members = gb.lists.members({:id => 'xxx'})
#for each goes here to send the mail
redirect_to manage_news_letter_path(#news_letter), notice: "Sent news Letter"
end
I can get the list of subscribers but how can i split out their email into a for_each method in rails cos the format is i in a hash. any help thanks.
example output is below
{"email"=>"xx#xx.com", "id"=>"xx", "euid"=>"xx", "email_type"=>"html", "ip_signup"=>nil, "timestamp_signup"=>nil, "ip_opt"=>"208.68.37.172", "timestamp_opt"=>"2014-02-21 10:38:20", "member_rating"=>2, "info_changed"=>"2014-02-21 10:38:20", "web_id"=>xx, "leid"=>xx, "language"=>nil, "list_id"=>"xx", "list_name"=>"Blanckdigital website List", "merges"=>{"EMAIL"=>"xx#xx.com", "FNAME"=>"", "LNAME"=>""}, "status"=>"subscribed", "timestamp"=>"2014-02-21 10:38:20", "is_gmonkey"=>false, "lists"=>[], "geo"=>[], "clients"=>[], "static_segments"=>[], "notes"=>[]}
what i want is is just the email xx#xx.com alone for each of the subscribers

Sending email not working on heroku

I have this function in forms.py. There is currently no email specifications in my settings.py.
def send_email(FROM_NAME,FROM,TO,SUB,MSG,EXISTING_EMAIL,EXISTING_PASSWORD):
FROMADDR = "%s <%s>" % (FROM_NAME, FROM)
LOGIN = EXISTING_EMAIL
PASSWORD = EXISTING_PASSWORD
TOADDRS = [TO]
SUBJECT = SUB
msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (FROMADDR, ", ".join(TOADDRS), SUBJECT) )
msg += MSG+"\r\n"
server = smtplib.SMTP('smtp.gmail.com', 587)
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.login(LOGIN, PASSWORD)
server.sendmail(FROMADDR, TOADDRS, msg)
server.quit()
I call it my views.py like so
send_email('my_name','from_me#gmail.com','to_som1#gmail.com','my subject','mymessage','my_existing_email#gmail.com','password_to_existing_email')
This works locally. I have tested it with yahoomail and gmail. But when I upload to heroku it gives the error "(535, '5.7.1 Please log in with your web browser and then try again. Learn more at\n5.7.1 support.google.com/mail/bin/answer.py?answer=78754 et6sm2577249qab.8')"
Can anyone help?
You want to use this:
FROMADDR = "%s <%s>" % (your_name, your_email)
You shouldn't be building emails with string interpolation, that's a good way to get your site used to send spam via header injections. See my answer here for details on how to construct emails securely.
Generally speaking, when formatting from addresses, you should use the format Display Name <email#example.com>. See RFC 5322 for details.
Have you read the page linked to in the error message?
If you're repeatedly prompted for your username and password, or if
you're getting an 'invalid credentials' or 'web login required' error,
make sure your password is correct. Keep in mind that password are
case-sensitive.
If you’re sure your password is correct, sign in to your account from
the web version of Gmail instead at http://mail.google.com
In most cases signing in from the web should resolve the issue
Here is what worked for me. After getting the error Please log in with your web browser and then try again. Learn more etc. when trying to send email from my web application, I logged in to the email via browser from my local computer.
After I logged in, there was a yellow notification bar on top which asking me if I want to allow external application access my mail. I confirmed this and Google asked me to log in to the account from the application within the next 10 mins. This will white-list the application.