Send inline images with cid (load images via http/https in src).
This commit is contained in:
parent
530c844f68
commit
549978d731
9 changed files with 94 additions and 18 deletions
|
@ -129,7 +129,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
|||
# validate image
|
||||
if params[:logo] && params[:logo] =~ /^data:image/i
|
||||
|
||||
file = StaticAssets.data_url_attributes( params[:logo] )
|
||||
file = StaticAssets.data_url_attributes(params[:logo])
|
||||
|
||||
if !file[:content] || !file[:mime_type]
|
||||
messages[:logo] = 'Unable to process image upload.'
|
||||
|
@ -163,19 +163,19 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
|
|||
if params[:logo] && params[:logo] =~ /^data:image/i
|
||||
|
||||
# data:image/png;base64
|
||||
file = StaticAssets.data_url_attributes( params[:logo] )
|
||||
file = StaticAssets.data_url_attributes(params[:logo])
|
||||
|
||||
# store image 1:1
|
||||
StaticAssets.store_raw( file[:content], file[:mime_type] )
|
||||
StaticAssets.store_raw(file[:content], file[:mime_type])
|
||||
end
|
||||
|
||||
if params[:logo_resize] && params[:logo_resize] =~ /^data:image/i
|
||||
|
||||
# data:image/png;base64
|
||||
file = StaticAssets.data_url_attributes( params[:logo_resize] )
|
||||
file = StaticAssets.data_url_attributes(params[:logo_resize])
|
||||
|
||||
# store image 1:1
|
||||
settings[:product_logo] = StaticAssets.store( file[:content], file[:mime_type] )
|
||||
settings[:product_logo] = StaticAssets.store(file[:content], file[:mime_type])
|
||||
end
|
||||
|
||||
# set changed settings
|
||||
|
|
|
@ -67,7 +67,7 @@ class SettingsController < ApplicationController
|
|||
if params[:logo_resize] && params[:logo_resize] =~ /^data:image/i
|
||||
|
||||
# data:image/png;base64
|
||||
file = StaticAssets.data_url_attributes( params[:logo_resize] )
|
||||
file = StaticAssets.data_url_attributes(params[:logo_resize])
|
||||
|
||||
# store image 1:1
|
||||
setting.state = StaticAssets.store( file[:content], file[:mime_type] )
|
||||
|
|
|
@ -250,7 +250,7 @@ class TicketsController < ApplicationController
|
|||
links.each { |item|
|
||||
link_list.push item
|
||||
if item['link_object'] == 'Ticket'
|
||||
linked_ticket = Ticket.lookup( id: item['link_object_value'] )
|
||||
linked_ticket = Ticket.lookup(id: item['link_object_value'])
|
||||
assets = linked_ticket.assets(assets)
|
||||
end
|
||||
}
|
||||
|
@ -534,9 +534,31 @@ class TicketsController < ApplicationController
|
|||
# create article if given
|
||||
form_id = params[:form_id]
|
||||
params.delete(:form_id)
|
||||
article = Ticket::Article.new( Ticket::Article.param_validation( params ) )
|
||||
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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -27,7 +27,7 @@ returns
|
|||
|
||||
store image 1:1 in backend and return filename
|
||||
|
||||
filename = StaticAssets.store_raw( content, content_type )
|
||||
filename = StaticAssets.store_raw(content, content_type)
|
||||
|
||||
returns
|
||||
|
||||
|
|
Loading…
Reference in a new issue