Skip to content

Instantly share code, notes, and snippets.

@sowenjub
Last active Sep 29, 2021
Embed
What would you like to do?
A concern adapted from the GoRails ActionMailbox episode https://gorails.com/episodes/save-action-mailbox-html-emails-with-action-text?autoplay=1
# mailboxes/concerns/mail_params.rb
module MailParams
extend ActiveSupport::Concern
def mail_params
attachments = build_attachments
body = build_rich_body(attachments)
{ subject: mail.subject, body: body, attachments: attachments.map { |a| a[:blob] } }
end
def build_attachments
mail.attachments.map do |attachment|
blob = ActiveStorage::Blob.create_after_upload!(
io: StringIO.new(attachment.decoded),
filename: attachment.filename,
content_type: attachment.content_type,
)
{ original: attachment, blob: blob }
end
end
def build_rich_body(attachments)
if mail.multipart? && mail.html_part
document = Nokogiri::HTML(mail.html_part.body.decoded)
attachments.map do |attachment_hash|
attachment = attachment_hash[:original]
blob = attachment_hash[:blob]
if attachment.content_id.present?
# Remove the beginning and end < >
content_id = attachment.content_id[1...-1]
element = document.at_css "img[src='cid:#{content_id}']"
element.replace "<action-text-attachment sgid=\"#{blob.attachable_sgid}\" content-type=\"#{attachment.content_type}\" filename=\"#{attachment.filename}\"></action-text-attachment>"
end
end
document.at_css("body").inner_html.encode("utf-8")
elsif mail.multipart? && mail.text_part
mail.text_part.body.decoded
else
mail.decoded
end
end
end
# models/post.rb
class Post < ApplicationRecord
has_rich_text :body
has_many_attached :attachments
end
# mailboxes/posts_mailbox.rb
class PostsMailbox < ApplicationMailbox
include MailParams
def process
Post.create mail_params
end
end
@sowenjub
Copy link
Author

sowenjub commented Mar 24, 2021

@jumichot
Copy link

jumichot commented Apr 11, 2021

Thank you for the gist !
FYI, I tested with a gmail inbound email, I got an error line 33 : element can be nil and element.replace fails.
You can add a next unless element line 34 to fix it.

@sowenjub
Copy link
Author

sowenjub commented Apr 12, 2021

@jumichot Interesting, but then your text content won't feature the attachment. We could simply append the action-text-attachment. But maybe that content_id appears inside another HTML tag?
What does the mail.html_part.body.decoded look like?

@jumichot
Copy link

jumichot commented Apr 12, 2021

My test case : 2 attachments

  • one embedded direclty in the email body (via drag and dropping an image in gmail interface), the attachment is present in the html via an image tag
  • and one another regular attachment that doesn't appear in the html body (that cause the problem)

Both attachments have content_ids

The body looks like that :

<div dir=3D"ltr"><div><div dir=3D"ltr" class=3D"gmail_signature" data-smart=
mail=3D"gmail_signature"><div dir=3D"ltr"><div><div dir=3D"ltr"><div dir=3D=
"ltr"><div><br></div></div></div></div></div></div></div><div class=3D"gmai=
l_quote"><br><div dir=3D"ltr">Bonjour Julien,<div><br></div><div>Ceci est u=
n test, pouvez-vous intervenir au plus vite =C3=A0 l&#39;adresse indiqu=C3=
=A9e ci dessous ?</div><div><br></div><div>Merci d&#39;avance<img src=3D"ci=
d:ii_kncy5jja0" alt=3D"Screenshot 2021-04-10 at 10.33.18.png" width=3D"543"=
 height=3D"126" style=3D"margin-right:0px"><br><div><div dir=3D"ltr" data-s=
martmail=3D"gmail_signature"><div dir=3D"ltr"><div><div dir=3D"ltr"><div di=
r=3D"ltr"><div>Cordialement,=C2=A0</div><div><br></div><div>--</div><div><b=
>Julien</b></div><div><br></div><div><br></div><br></div></div></div=
></div></div></div></div></div>
</div></div>

and my .mail.attachments.map(&:content_id) looks like that ["<ii_kncy5jja0>", "<f_kncy6vaw1>"]

The attachment with the content id f_kncy6vaw1 is not present in the HTML and raise an error.

@sowenjub
Copy link
Author

sowenjub commented Apr 12, 2021

Alright, then I guess we need to append the attachment.
Also, we may want to delete the signature.
I'll revisit that sometime later, this feature is on pause for a couple of days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment