Skip to content

Instantly share code, notes, and snippets.

@sowenjub
Last active January 4, 2023 13:38
Show Gist options
  • Save sowenjub/9917305b2b551a31df9f9ed0ec34d242 to your computer and use it in GitHub Desktop.
Save sowenjub/9917305b2b551a31df9f9ed0ec34d242 to your computer and use it in GitHub Desktop.
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
@jumichot
Copy link

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

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