diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index c3bb144..28afba9 100755 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -39,8 +39,7 @@ class MessagesController < ApplicationController (uids_remote-uids_local).each_slice($defaults["imap_fetch_slice"].to_i) do |slice| messages = @mailbox.uid_fetch(slice, ImapMessageModule::IMAPMessage.fetch_attr) messages.each do |m| - mess = ImapMessageModule::IMAPMessage.fromImap(m) - Message.createForUser(@current_user,@current_folder,mess) + Message.createForUser(@current_user,@current_folder,m) end end @@ -141,41 +140,50 @@ class MessagesController < ApplicationController @attachments = [] @render_as_text = [] - @message = @current_user.messages.find(params[:id]) + @message = @current_user.messages.find_by_uid(params[:id]) @message.update_attributes(:unseen => false) imap_message = @mailbox.fetch_body(@message.uid) parts = imap_message.split(/\r\n\r\n/) @message_header = parts[0] - mail = Mail.new(imap_message) - @title = mail.subject - if mail.multipart? - idx = 0 - mail.parts.each do |part| - case part.content_type - when /^text\/plain/ then - @render_as_text << part.body.raw_source - else - a = Attachment.new( :message_id => @message.id, - :description => part.content_description, - :type => part.content_type, - :content => part.body.raw_source, - :idx => idx - ) - @attachments << a - end - idx += 1 + @mail = Mail.new(imap_message) + if @mail.multipart? +# idx = 0 +# @mail.parts.each do |part| +# a = Attachment.new( :message_id => @message.id, +# :description => part.content_description, +# :type => part.content_type, +# :content => part.body.raw_source, +# :encoding => part.content_transfer_encoding, +# :idx => idx, +# :multipart => part.multipart? +# ) +# logger.custom('a',a.to_s) +# if a.isText? +# @render_as_text << a.content_normalized +# else +# @attachments << a +# end +# +# idx += 1 +# end + Attachment.fromPart(@attachments,@message.id,@mail.parts,0) + @attachments.each do |a| + a.isText? ? @render_as_text << a.content_normalized : @render_as_text end + else - if mail.content_type.nil? - @render_as_text << mail.body.raw_source - else - a = Attachment.new( :message_id => @message.id, - :type => mail.content_type, - :encoding => mail.body.encoding, - :charset => mail.body.charset, - :content => mail.body.raw_source, + a = Attachment.new( :message_id => @message.id, + :description => @mail.content_description, + :type => @mail.content_type, + :encoding => @mail.body.encoding, + :charset => @mail.body.charset, + :content => @mail.body.raw_source, :idx => 0 ) + logger.custom('a',a.to_s) + if a.isText? + @render_as_text << a.content_normalized + else @attachments << a end end @@ -203,6 +211,7 @@ class MessagesController < ApplicationController :description => part.content_description, :type => part.content_type, :content => part.body.raw_source, + :encoding => part.content_transfer_encoding, :idx => params[:idx] ) else @@ -216,7 +225,7 @@ class MessagesController < ApplicationController end headers['Content-type'] = a.type headers['Content-Disposition'] = %(attachment; filename="#{a.name}") - render :text => a.content_decoded + render :text => a.decode end end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 5304635..42b2497 100755 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -13,10 +13,14 @@ class UserController < ApplicationController end def authenticate - if !$defaults["only_can_logins"].include?(params[:user][:email]) - redirect_to :controller => 'internal', :action => 'onlycanlogins' - return false + + if not $defaults["only_can_logins"].nil? + if not $defaults["only_can_logins"].include?(params[:user][:email]) + redirect_to :controller => 'internal', :action => 'onlycanlogins' + return false + end end + user = User.find_by_email(params[:user][:email]) if user.nil? redirect_to :action => 'unknown' ,:email=> params[:user][:email] diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb index bfcdbc3..11eaf5a 100755 --- a/app/helpers/messages_helper.rb +++ b/app/helpers/messages_helper.rb @@ -14,15 +14,24 @@ module MessagesHelper date.nil? ? t(:no_data) : date.strftime("%Y-%m-%d %H:%M") end - def address_formatter(addr) - ImapMessageModule::IMAPAddress.parse(addr).friendly - end +# def address_formatter(addr) +# ImapMessageModule::IMAPAddress.parse(addr).friendly +# end + + def address_formatter(addr,mode) + s = "" + length = $defaults["msg_address_length"].to_i + fs = addr.split(/= length ? s = s[0,length]+"..." : s + else + fs[0].size.zero? ? s = "<" + fs[1] + ">" : s << fs[0] + " <" + fs[1] + ">" + end + + return h(s) - def show_address_formatter(addr) - html = "" - fs = addr.split(/#/) - fs[0].size.zero? ? html << h("<")+fs[1]+h("@")+fs[2]+h(">") : html << fs[0]+h(" <")+fs[1]+h("@")+fs[2]+h(">") - html end def subject_formatter(message) @@ -32,7 +41,7 @@ module MessagesHelper length = $defaults["msg_subject_length"].to_i message.subject.length >= length ? s = message.subject[0,length]+"..." : s = message.subject end - link_to s,{:controller => 'messages', :action => 'show', :id => message.id} , :title => message.subject + link_to s,{:controller => 'messages', :action => 'show', :id => message.uid} , :title => message.subject end def attachment_formatter(message) @@ -61,8 +70,9 @@ module MessagesHelper end def content_text_plain_for_render(text) - html = h(text) - html.gsub!(/\r\n/,"
") + html = "
"
+        html << h(text)
+        html << "
" html end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 60cb816..affcefb 100755 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -3,20 +3,51 @@ class Attachment include ActiveModel::Conversion extend ActiveModel::Naming - attr_accessor :type, :charset, :encoding, :name, :description, :content, :message_id, :idx + attr_accessor :type, :charset, :encoding, :name, :description, :content, :message_id, :idx, :boundary, :format, :multipart attr_reader :link def initialize(attributes = {}) + attributes.each do |name, value| send("#{name}=", value) end - if @type =~ /name=(\S+)/ - @name = $1 - @type =~ /^(\S+);/ - @type = $1 - else - @name = "no_name.dat" + if not @type.nil? + params = @type.split(/;\s*/) + @type = params[0] + params.each do |p| + if p =~ /=/ + fields = p.split(/=/) + key = fields[0] + value = fields[1] + if Attachment.attribute_method?(key) == true + send("#{key}=", value) + end + end + end + end + end + + def multipart? + multipart + end + + def self.fromPart(attachments,id,parts,idx) + parts.each do |part| + a = Attachment.new( :message_id => id, + :description => part.content_description, + :type => part.content_type, + :content => part.body.raw_source, + :encoding => part.content_transfer_encoding, + :idx => idx, + :multipart => part.multipart? + ) + if a.multipart? + fromPart(attachments,id,part.parts,idx) + else + attachments << a + end + idx += 1 end end @@ -24,6 +55,25 @@ class Attachment false end + + + def name + if @name.nil? + case type + when /^text\/html/ + "index#{idx}.html" + when /^multipart/ + "multipart#{idx}.part" + when /^text\/plain/ + "file#{idx}.txt" + else + "filaname.dat" + end + else + @name + end + end + def to_s s = "Attachment:\n" instance_variables.sort.each do |name| @@ -36,8 +86,12 @@ class Attachment s end + def isText? + @type.nil? or @type =~ /^text\/plain/ + end + def title - @description.nil? ? @name : @description + @description.nil? ? name : @description end def type @@ -52,6 +106,51 @@ class Attachment @encoding.nil? ? '' : @encoding end + def format + @format.nil? ? '' : @format + end + + def boundary + @boundary.nil? ? '' : @boundary + end + + def decode + case @encoding + when /quoted-printable/ + decoded = @content.gsub(/_/," ").unpack("M").first + when /base64/ + decoded = @content.unpack("m").first + when /uuencode/ + array = @content.split(/\n/) + if array[0] =~ /^begin/ + size = array.size + array.delete_at(size-1) + array.delete_at(size-2) + array.delete_at(0) + end + string = array.join + decoded = string.unpack("u").first + else + decoded = @content + end + end + + def content_normalized + + decoded = decode + + if not @charset == 'UTF-8' + @charset.nil? ? charset = $defaults["msg_unknown_encoding"] : charset = @charset + charseted = Iconv.iconv("UTF-8",charset,decoded) + else + charseted = decoded + end + + charseted + + end + +end # def to_html # html = "" # html << "" @@ -81,9 +180,4 @@ class Attachment # html # end - def content_decoded - # TODO attachments decoding - @content - end -end diff --git a/app/models/message.rb b/app/models/message.rb index 4001327..e676b4e 100755 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -1,8 +1,47 @@ +require 'iconv' + class Message < ActiveRecord::Base + belongs_to :user belongs_to :folder - attr_accessor :body + set_primary_key :uid + attr_accessible :unseen, :to_addr, :size, :content_type, :folder_id, :subject, :date, :uid, :from_addr, :user_id, :msg_id + + def self.decode(text,unknown_encoding = $defaults["msg_unknown_encoding"]) + begin + if text.=~(/^=\?/).nil? + after = Iconv.conv('UTF-8',unknown_encoding,text) + else + f = text.split(/\?/) + case f[2].downcase + when 'q': + after = f[3].gsub(/_/," ").unpack("M").first + when 'b': + after = f[3].gsub(/_/," ").unpack("m").first + else + return text + end + + if f[1].downcase != 'utf-8' + after = Iconv.conv('UTF-8',f[1],after) + end + + end + return after + rescue + logger.error("Class Message: String decode error: #{text}") + return text + end + end + + def self.addr_to_db(addr) + ret = "" + name = addr.name + name.nil? ? ret : ret << decode(name) + ret << "<" + addr.mailbox + "@" + addr.host + ret + end def self.getPageForUser(user,folder,page,sort_field,sort_dir) @@ -17,23 +56,33 @@ class Message < ActiveRecord::Base Message.paginate :page => page , :per_page => user.prefs.msgs_per_page.to_i, :conditions=> ['user_id = ? and folder_id = ?', user.id,folder.id],:order => order end - def self.createForUser(user,folder,mess) + def self.createForUser(user,folder,imap_message) + + envelope = imap_message.attr['ENVELOPE'] + + from = addr_to_db(envelope.from[0]) + to = addr_to_db(envelope.to[0]) + + envelope.subject.nil? ? subject = "" : subject = decode(envelope.subject) + create( :user_id => user.id, :folder_id => folder.id, - :msg_id => mess.message_id, - :uid => mess.uid, - :from_addr => mess.from_to_db, - :to_addr => mess.to_to_db, - :subject => mess.subject, - :content_type => mess.content_type, - :date => mess.date, - :unseen => mess.unseen, - :size => mess.size) - end + :msg_id => envelope.message_id, + :uid => imap_message.attr['UID'].to_i, + :from_addr => from, + :to_addr => to, + :subject => subject, + :content_type => imap_message.attr['BODYSTRUCTURE'].media_type.downcase, + :date => envelope.date, + :unseen => !(imap_message.attr['FLAGS'].member? :Seen), + :size => imap_message.attr['RFC822.SIZE'] + ) + end def change_folder(folder) update_attributes(:folder_id => folder.id) end + end diff --git a/config/defaults.yml b/config/defaults.yml index fab7635..902b34f 100755 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -17,8 +17,12 @@ msgs_inbox_view_fields: [from_addr, subject, date, size] msgs_sent_view_fields: [to_addr, subject, date, size] msg_subject_length: 45 +msg_address_length: 35 msg_search_fields: [subject, from, to] +# if encoding can not be get from data +msg_unknown_encoding: ISO-8859-2 + imap_debug: false imap_use_ssl: 'false' imap_port: 143 @@ -35,4 +39,5 @@ mailbox_trash: INBOX.Trash mailbox_sent: INBOX.sent mailbox_drafts: INBOX.drafts +# array of logins which only can login to application, comment it to allow everyone to login only_can_logins: [wtodryk] diff --git a/db/migrate/20110727134352_create_messages.rb b/db/migrate/20110727134352_create_messages.rb index 4a9f3ba..6d106a3 100755 --- a/db/migrate/20110727134352_create_messages.rb +++ b/db/migrate/20110727134352_create_messages.rb @@ -1,6 +1,6 @@ class CreateMessages < ActiveRecord::Migration def self.up - create_table :messages do |t| + create_table :messages ,:id => false do |t| t.integer :folder_id t.integer :user_id t.string :msg_id diff --git a/db/schema.rb b/db/schema.rb index 046f187..19415c8 100755 --- a/db/schema.rb +++ b/db/schema.rb @@ -37,7 +37,7 @@ ActiveRecord::Schema.define(:version => 20110816120258) do t.string "alter_name" end - create_table "messages", :force => true do |t| + create_table "messages", :id => false, :force => true do |t| t.integer "folder_id" t.integer "user_id" t.string "msg_id" diff --git a/lib/imap_message.rb b/lib/imap_message.rb index 9774b91..fc71b47 100755 --- a/lib/imap_message.rb +++ b/lib/imap_message.rb @@ -46,40 +46,41 @@ end class IMAPMessage @@fetch_attr = ['ENVELOPE','BODYSTRUCTURE', 'FLAGS', 'UID', 'RFC822.SIZE'] + #@@fetch_attr = ['RFC822','FLAGS', 'UID', 'RFC822.SIZE'] - attr_accessor :envelope,:uid,:content_type,:size,:unseen,:from,:message_id,:to,:from,:subject,:date - - def initialize - end - - def self.fromImap(message) - m = IMAPMessage.new - envelope = message.attr['ENVELOPE'] - m.envelope = envelope - m.message_id = envelope.message_id - m.date = envelope.date - m.subject = envelope.subject - m.uid = message.attr['UID'] - #content_type = m.attr['BODYSTRUCTURE'].multipart? ? 'multipart' : 'text' - m.content_type = message.attr['BODYSTRUCTURE'].media_type.downcase - m.size = message.attr['RFC822.SIZE'] - m.unseen = !(message.attr['FLAGS'].member? :Seen) - m.from = IMAPAddress.from_address(envelope.from[0]) - m.to = IMAPAddress.from_address(envelope.to[0]) - m - end - +# attr_accessor :envelope,:uid,:content_type,:size,:unseen,:from,:message_id,:to,:from,:subject,:date +# +# def initialize +# end +# +# def self.fromImap(message) +# m = IMAPMessage.new +# envelope = message.attr['ENVELOPE'] +# m.envelope = envelope +# m.message_id = envelope.message_id +# m.date = envelope.date +# m.subject = envelope.subject +# m.uid = message.attr['UID'] +# #content_type = m.attr['BODYSTRUCTURE'].multipart? ? 'multipart' : 'text' +# m.content_type = message.attr['BODYSTRUCTURE'].media_type.downcase +# m.size = message.attr['RFC822.SIZE'] +# m.unseen = !(message.attr['FLAGS'].member? :Seen) +# m.from = IMAPAddress.from_address(envelope.from[0]) +# m.to = IMAPAddress.from_address(envelope.to[0]) +# m +# end +# def self.fetch_attr @@fetch_attr end - - def from_to_db - from.to_db - end - - def to_to_db - to.to_db - end +# +# def from_to_db +# from.to_db +# end +# +# def to_to_db +# to.to_db +# end end diff --git a/themes/olive/stylesheets/style.css b/themes/olive/stylesheets/style.css index b0b3b80..c3df1e6 100755 --- a/themes/olive/stylesheets/style.css +++ b/themes/olive/stylesheets/style.css @@ -499,6 +499,11 @@ div.render_text pre { padding: 5px; border: 1px solid #5E634E; margin: 10px 0 0 0; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ } span.attachment { @@ -512,4 +517,3 @@ span.attachment pre { span.attachment span.title { font-weight: bold; } - diff --git a/themes/olive/views/messages/_header.html.erb b/themes/olive/views/messages/_header.html.erb index cfa8264..564c2e2 100755 --- a/themes/olive/views/messages/_header.html.erb +++ b/themes/olive/views/messages/_header.html.erb @@ -1,6 +1,6 @@
- <%= raw mail_param_view(@message,"from_addr",show_address_formatter(@message.from_addr)) %> - <%= raw mail_param_view(@message,"to_addr",show_address_formatter(@message.to_addr)) %> + <%= raw mail_param_view(@message,"from_addr",address_formatter(@message.from_addr,:message)) %> + <%= raw mail_param_view(@message,"to_addr",address_formatter(@message.to_addr,:message)) %> <%= raw mail_param_view(@message,"subject",@message.subject) %> <%= raw mail_param_view(@message,"date",date_formatter(@message.date)) %> <%= hidden_field_tag 'uids[]', @message.uid %> diff --git a/themes/olive/views/messages/_row.html.erb b/themes/olive/views/messages/_row.html.erb index 55bcbea..86e27eb 100755 --- a/themes/olive/views/messages/_row.html.erb +++ b/themes/olive/views/messages/_row.html.erb @@ -1,6 +1,12 @@ <%= check_box_tag "uids[]", row.uid %> <%= attachment_formatter(row) %> -<%= address_formatter(row.from_addr) %> + +<% if @current_folder.hasFullName?($defaults["mailbox_sent"]) %> + <%= address_formatter(row.to_addr,:index) %> +<% else %> + <%= address_formatter(row.from_addr,:index) %> +<% end %> + <%= subject_formatter(row) %> <%= date_formatter(row.date) %> <%= size_formatter(row.size) %><%= raw(' ') %> diff --git a/themes/olive/views/messages/show.html.erb b/themes/olive/views/messages/show.html.erb index 1071b98..21956c1 100755 --- a/themes/olive/views/messages/show.html.erb +++ b/themes/olive/views/messages/show.html.erb @@ -30,9 +30,7 @@

<% else %> <% @render_as_text.each do |r| %> -
                  <%= raw content_text_plain_for_render(r) %>
-                 
<% end %> <% end %>