Send inline images with cid (load images via http/https in src).

This commit is contained in:
Martin Edenhofer 2016-05-10 15:06:51 +02:00
parent 530c844f68
commit 549978d731
9 changed files with 94 additions and 18 deletions

View file

@ -537,6 +537,28 @@ class TicketsController < ApplicationController
article = Ticket::Article.new(Ticket::Article.param_validation( params ))
article.ticket_id = ticket.id
# store dataurl images to store
if form_id && article.body && article.content_type =~ %r{text/html}i
article.body.gsub!( %r{(<img\s.+?src=")(data:image/(jpeg|png);base64,.+?)">}i ) { |_item|
file_attributes = StaticAssets.data_url_attributes($2)
cid = "#{ticket.id}.#{form_id}.#{rand(999_999)}@#{Setting.get('fqdn')}"
headers_store = {
'Content-Type' => file_attributes[:mime_type],
'Mime-Type' => file_attributes[:mime_type],
'Content-ID' => cid,
'Content-Disposition' => 'inline',
}
store = Store.add(
object: 'UploadCache',
o_id: form_id,
data: file_attributes[:content],
filename: cid,
preferences: headers_store
)
"#{$1}cid:#{cid}\">"
}
end
# find attachments in upload cache
if form_id
article.attachments = Store.list(

View file

@ -82,9 +82,23 @@ module Channel::EmailBuild
if html_alternative
html_container = Mail::Part.new { content_type 'multipart/related' }
html_container.add_part html_alternative
alternative_bodies.add_part html_container
# place to add inline attachments related to html alternative
if attr[:attachments]
attr[:attachments].each do |attachment|
next if attachment.class == Hash
next if attachment.preferences['Content-ID'].empty?
attachment = Mail::Part.new do
content_type attachment.preferences['Content-Type']
content_id attachment.preferences['Content-ID']
content_disposition attachment.preferences['Content-Disposition'] || 'inline'
content_transfer_encoding 'binary'
body attachment.content.force_encoding('BINARY')
end
html_container.add_part attachment
end
end
alternative_bodies.add_part html_container
end
mail.add_part alternative_bodies
@ -96,11 +110,12 @@ module Channel::EmailBuild
attachment['content-id'] = nil
mail.attachments[ attachment[:filename] ] = attachment
else
next if !attachment.preferences['Content-ID'].empty?
mail.attachments[attachment.filename] = {
:content_type => attachment.preferences['Content-Type'],
:mime_type => attachment.preferences['Mime-Type'],
:content => attachment.content,
'content-id' => nil,
content_disposition: attachment.preferences['Content-Disposition'] || 'attachment',
content_type: attachment.preferences['Content-Type'],
mime_type: attachment.preferences['Mime-Type'],
content: attachment.content,
}
end
end

View file

@ -18,8 +18,8 @@ add an attachment to storage
o_id: 4711,
data: binary_string,
preferences: {
:content_type => 'image/png',
:content_id => 234,
content_type: 'image/png',
content_id: 234,
}
)
@ -69,8 +69,8 @@ returns
size: 94123,
filename: 'image.png',
preferences: {
:content_type => 'image/png',
:content_id => 234,
content_type: 'image/png',
content_id: 234,
}
}
store1.content # binary_string

View file

@ -37,6 +37,30 @@ class Ticket::Article < ApplicationModel
self.message_id_md5 = Digest::MD5.hexdigest(message_id.to_s)
end
# insert inline image urls
def self.insert_urls(article, attachments)
inline_attachments = {}
article['body'].gsub!( /(<img\s(style.+?|)src=")cid:(.+?)(">)/i ) { |item|
replace = item
# look for attachment
attachments.each {|file|
next if !file.preferences['Content-ID'] || file.preferences['Content-ID'] != $3
replace = "#{$1}/api/v1/ticket_attachment/#{article['ticket_id']}/#{article['id']}/#{file.id}#{$4}"
inline_attachments[file.id] = true
break
}
replace
}
new_attachments = []
attachments.each {|file|
next if inline_attachments[file.id]
new_attachments.push file
}
article['attachments'] = new_attachments
article
end
private
# strip not wanted chars

View file

@ -39,6 +39,20 @@ returns
# add attachment list to article
data[ Ticket::Article.to_app_model ][ id ]['attachments'] = attachments
if !data[ Ticket::Article.to_app_model ][ id ]['attachments'].empty?
if data[ Ticket::Article.to_app_model ][ id ]['content_type'] =~ %r{text/html}i
if data[ Ticket::Article.to_app_model ][ id ]['body'] =~ /<img/i
# insert inline images with urls
attributes = Ticket::Article.insert_urls(
data[ Ticket::Article.to_app_model ][ id ],
data[ Ticket::Article.to_app_model ][ id ]['attachments']
)
data[ Ticket::Article.to_app_model ][ id ] = attributes
end
end
end
end
%w(created_by_id updated_by_id).each {|local_user_id|

View file

@ -7,5 +7,6 @@ class ContenteditableIamges < ActiveRecord::Migration
change_column :text_modules, :content, :text, limit: 10.megabytes + 1, null: false
change_column :signatures, :body, :text, limit: 10.megabytes + 1, null: true
change_column :ticket_articles, :body, :text, limit: 20.megabytes + 1, null: false
change_column :taskbars, :state, :text, limit: 20.megabytes + 1, null: true
end
end