Rails not sending (ical) attachments in emails - ruby-on-rails

I'm trying to send an email with an ical attachment, I'm running rails v.3.2.13 and using the icalendar gem (to generate the ical string) see. (In development mode in case that might be a problem).
The relevant mailer code looks like this:
def mailme
ical = Icalendar::Calendar.new
...
attachments["meetings.ics"] = { mime_type: "text/calendar", content: ical.to_ical }
mail(from: email, to: recipient, ...)
end
there is also template file with the same name (mailme.html.erb)
The problem is the mail (html) is send without the attachment.
As usual any help would be much appreciated.
Thank you.

I've gotten them working with something like below:
mail.attachments['meeting.ics'] = { mime_type: 'application/ics',
content: ical.to_ical }
mail(from: email, to: recipient, ...)
So it's possible you need to call it on #attachments on the mail object instead of calling it on the current context. I'm not sure if your mime type needs to be application/ics, but that's worked fine for me in my systems.

In case someone else stumbles upon this.
If you are using delayed_job check out https://github.com/collectiveidea/delayed_job/wiki/Common-problems#wiki-Sending_emails_with_attachments
To fix this, remember to add this line to your mailer:
content_type "multipart/mixed"

Related

Rails 5.0.1 - ActionMailer with MailGun, setting 'noname' for filename when directly attaching base64 string

I have read the entire official guide here and about 5 questions on SO that describe this problem for Rails 3 and Rails 4.
This question is for Rails 5, but he is using an actual file, not an encoded string.
This is my mailer code (and yes I have both views setup). The email comes through perfectly fine, with the attached PDF.
def pdf_quote(proposal)
#proposal = proposal
email_with_name = %("#{#proposal.first_name} #{#proposal.last_name}" <#{#proposal.email}>)
filename = "QD-#{#proposal.qd_number}_#{#proposal.last_name}.pdf"
attachments[filename] = {
mime_type: 'application/pdf',
encoding: 'Base64',
content: #proposal.pdf_base64
}
mail(
to: email_with_name,
from: 'Floorbook UK <email address>',
subject: 'Your Personal Flooring Quote is attached',
sent_on: Time.now
)
end
In gmail the attachment is called 'noname' and in Postbox it is called 'pb_mime_attachment.pdf'
How can I get ActionMailer to use the filename I provide?
Note that I am using MailGun (mailgun-ruby gem 1.1.4) to send the email, so it could be the gem at fault here.
It turned out to be a bug with 3rd party mailgun-ruby gem.
I raised a bug with them, here are the details:
https://github.com/mailgun/mailgun-ruby/issues/82
It is fixed (I tested it) in version 1.1.5.

Rails mailer and sendgrid with heroku

I am working on adding email functionality to an app I am hosting on heroku.
Here are the relavant files:
app/mailers/user_actions_mailer.rb
def add_user_action(action_params)
#action_params = action_params
from = Email.new(email: 'marklocklear#blah.org')
subject = 'You have been notified'
to = Email.new(email: 'my_user#gmail.com')
content = Content.new(type: 'text/html', value: "test")
mail = Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = sg.client.mail._('send').post(request_body: mail.to_json)
end
This is working fine and I am able to send emails with it. However, my issue is with the 'content' variable above. I want the content to use rails standard mailer template in app/views/user_actions_mailer/add_user_action.html.erb.
I have this file/folder created, but I'm not sure how to point content to this location. I'm tryed not passing content to Mail.new fuction hoping this might trigger rails default mailer wiring, that doesn't seem to work.
I was not able to come up with a solution for this, using the sendgrid-ruby gem which my example above uses.
I ended up refactoring using THIS PAGE from sendgrids ruby-on-rails specific documentation.

PDF corrupted on Outlook with AVG anti-virus software installed

we are having the problem of sending PDF attachment using ActionMailer.
The PDF file was combined from 2 PDF files using combine_pdf gem.
A normal PDF file with our logo.
A docx converted PDF using http://convertapi.com
The combined PDF file is stored on AWS S3. What we did is just attach it using open-uri
require 'open-uri'
class ApplicationMailer < ActionMailer::Base
def employer_notification application_id
#application = JobApplication.find_by_id application_id
return unless #application
attachments[#application.cv_name] = {
mime_type: 'application/pdf',
content: open(#application.cv_url(900)).read
}
mail(
from: "#{#application.fullname}<test#myapp.com>",
to: #application.job.employer_emails(", "),
reply_to: #application.email,
subject: "Application for #{#application.job.title}"
)
end
end
We used Mandrill to send out the emails over the internet and something strangely happened. Some PDF could be viewed properly, some contained font errors and the converted PDF part went blank.
But if we turned off AVG anti-virus, it worked perfectly.
Does anyone have the same problem before? May I know how a PDF file is considered malicious?
Thanks in advance.

How to get RSVP buttons through Icalendar gem

So I've got the Icalendar gem in my ruby project. I'm attempting to get the RSVP buttons of Yes/No/Maybe on the invite but whenever it gets sent I only get a "Add to Calendar".
Was wondering what else I need:
def make_ical_appointment(start_time, end_time, uid, email_one, email_two)
ical = Icalendar::Calendar.new
ical.timezone.tzid = "UTC"
e = Icalendar::Event.new
e.dtstart = start_time
e.dtend = end_time
e.organizer = %W(mailto:#{email_one} mailto#{email_two})
e.uid = uid
ical.add_event(e)
ical.publish
mail.attachments['appointment.ics'] = { mime_type: 'application/ics', content: ical.to_ical }
end
I've read that people need to set it to METHOD:REQUEST, but I'm not sure where to do there. I've also read that you need to set attendees, but it seems you can only set attendees if you have an alarm?
Just looking to get it to look like a regular invite.
There's two things you need to do to solve your problem:
Read RFC-2445, which defines the iCal format. It looks like section 4.8.4.1, which discusses the ATTENDEE property, and 4.2.17, which discusses the RSVP parameter, will be of particular interest.
Look at emails and .ics files you've received that display correctly in various email clients.
The page I linked to in my comment above has three hints.
The first hint
I tried adding this property:calendar.custom_property("METHOD", "REQUEST").[1]
From the docs I think that's supposed to be append_custom_property.
Opening up an invite someone sent me from Google calendar, I found this line:
METHOD:REQUEST
So that seems legit.
The second hint
I would guess that you need to add an ATTENDEE property with RSVP=TRUE and the email set to the same email that Outlook or Yahoo link to their users.[2]
In the same invite I found this:
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=
TRUE;CN=Firstname Lastname;X-NUM-GUESTS=0:mailto:jordan#example.com
I didn't read the whole RFC, but I think it breaks down like this:
ATTENDEE is the property name.
Everything between the first ; and the first : are parameters. Each of them are documented in the RFC, and I don't know if all of them are required, but we can see the RSVP=TRUE parameter there.
Everything after the first :, i.e. mailto:jordan#example.com is the value
Looking at the source of append_custom_property we see that it checks if value is an Icalendar::Value object, and if not it creates one with Icalendar::Values::Text.new(value). Since we have parameters in addition to a value, let's check out that constructor here. We see that it can take a second argument, which is a params Hash.
Now, I haven't tested it, but that suggests to me that you can build a line like the above with code something like the following†:
attendee_params = { "CUTYPE" => "INDIVIDUAL",
"ROLE" => "REQ-PARTICIPANT",
"PARTSTAT" => "NEEDS-ACTION",
"RSVP" => "TRUE",
"CN" => "Firstname Lastname",
"X-NUM-GUESTS" => "0" }
attendee_value = Icalendar::Values::Text.new("MAILTO:jordan#example.com", attendee_params)
ical.append_custom_property("ATTENDEE", attendee_value)
Edit: In Icalendar 2.x it looks like you can also do:
attendee_value = Icalendar::Values::CalAddress.new("MAILTO:jordan#example.com", attendee_params)
ical.append_attendee(attendee_value)
The CalAddress class is a subclass of Uri, which just runs the given value through URI.parse, and append_attendee appears to be a shortcut for append_custom_property("ATTENDEE", ...).
I'm not sure if all of those parameters are actually required, but you can learn what each of them is by reading the RFC.
The third hint
What I had to do to make it work in all mail clients was to send it as a multipart/alternative message with the ical as an alternative view instead of as an attachment.[3]
Sure enough, doing "Show Original" in Gmail I saw that the invite email I got is a multipart email, with a text/calendar part:
--047d7b0721581f7baa050a6c3dc0
Content-Type: text/calendar; charset=UTF-8; method=REQUEST
Content-Transfer-Encoding: 7bit
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
...
...and an application/ics attachment part:
--047d7b0721581f7bae050a6c3dc2
Content-Type: application/ics; name="invite.ics"
Content-Disposition: attachment; filename="invite.ics"
Content-Transfer-Encoding: base64
QkVHSU46VkNBTEVOREFSDQpQUk9ESUQ6LS8vR29vZ2xlIEluYy8vR29vZ2xlIENhbGVuZGFyIDcw
...
The second part you've already got, thanks to mail.attachments. For the first part, you just have to create a new Mail::Part with the correct content_type and add it to mail.parts, which will look something like this:
ical_part = Mail::Part.new do
content_type "text/calendar; charset=UTF-8; method=REQUEST"
body ical.to_ical
end
mail.add_part(ical_part)
That's all I've got. Again, I've tested none of this, and I'm not certain it'll fix your problem, but hopefully it gives you a few ideas.
The most important thing, I think, is to look at the source of emails (if you use Gmail, "Show Original" is under the drop-down menu next to the Reply button) with invites and look at how they're constructed, and likewise look at the .ics attachments and see whether or not they match what you're generating.
Good luck!
†Judging by the way Icalendar transforms the params hash into iCal parameters, I think you can use symbol keys, too, like so:
attendee_params = { cutype: "INDIVIDUAL",
role: "REQ-PARTICIPANT",
partstat: "NEEDS-ACTION",
rsvp: "TRUE",
cn: "Firstname Lastname",
x_num_guests: "0" }

How to identify mandrill webhook

I have a Rails 4 application which sends emails using Mandrill. I am trying to detect weather a mail was opened or bounced, so I am using webhooks for this. I successfully receive the webhooks, but I can't tell which of them identify a particular email from my database.
I've tried using this
def send_message(email)
mail( from: ...,
to: ...,
subject: ...)
headers["X-MC-AutoHtml"] = "true"
headers["X-MC-Track"] = "opens"
headers['X-MC-MergeVars'] = { "id" => some_id }.to_json
end
but I'm not sure if I'm supposed to receive the X-MC-MergeVars back ( this is what I've understand from the docs)
Unfortunately, it's not working.
Do you have any ideas or an alternative solution? Thanks
I've figured it out by myself.
This is the line that needs to be there
headers['X-MC-Metadata'] = { "user_id" => user.id}.to_json
Here are the further details: http://help.mandrill.com/entries/21786413-Using-Custom-Message-Metadata
Hope it helps someone since it cost me several hours.

Resources