diff --git a/Gemfile b/Gemfile index ee025a2..3a30246 100755 --- a/Gemfile +++ b/Gemfile @@ -2,37 +2,7 @@ source 'http://rubygems.org' gem 'rails', '3.0.7' -# Bundle edge Rails instead: -# gem 'rails', :git => 'git://github.com/rails/rails.git' - -#gem 'sqlite3-ruby',:require => 'sqlite3' -gem 'arel' gem 'mysql2' , '0.2.7' gem 'will_paginate', '~> 3.0.beta' gem 'themes_for_rails' gem "ezcrypto", "~> 0.7.2" -gem "mail" -#gem 'tmail' - -# Use unicorn as the web server -# gem 'unicorn' - -# Deploy with Capistrano -# gem 'capistrano' - -# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+) -# gem 'ruby-debug' -# gem 'ruby-debug19', :require => 'ruby-debug' - -# Bundle the extra gems: -# gem 'bj' -# gem 'nokogiri' -# gem 'sqlite3-ruby', :require => 'sqlite3' -# gem 'aws-s3', :require => 'aws/s3' - -# Bundle gems for the local environment. Make sure to -# put test-only gems in this group so their generators -# and rake tasks are available in development mode: -# group :development, :test do -# gem 'webrat' -# end diff --git a/Gemfile.lock b/Gemfile.lock index a2a269d..a439536 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,9 +72,7 @@ PLATFORMS ruby DEPENDENCIES - arel ezcrypto (~> 0.7.2) - mail mysql2 (= 0.2.7) rails (= 3.0.7) themes_for_rails diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d3f7679..4bd6e18 100755 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,7 +8,8 @@ class ApplicationController < ActionController::Base #end protect_from_forgery - before_filter :load_defaults,:set_locale,:current_user + before_filter :load_defaults,:current_user,:set_locale + before_filter :plugins_configuration ################################# protected section ########################################### @@ -30,7 +31,7 @@ class ApplicationController < ActionController::Base if @current_user.nil? I18n.locale = $defaults['locale'] || I18n.default_locale else - I18n.locale = @current_user.prefs.locale || I18n.default_locale + I18n.locale = @current_user.prefs.locale.to_sym || I18n.default_locale end end @@ -52,15 +53,21 @@ class ApplicationController < ActionController::Base def get_current_folders @folders_shown = @current_user.folders.shown.order("name asc") - @current_folder = @current_user.folders.current(@selected_folder) + @current_folder = @current_user.folders.find_by_full_name(@selected_folder) end ##################################### private section ########################################## - #private + private + + def plugins_configuration + WillPaginate::ViewHelpers.pagination_options[:previous_label] = t(:previous_page) + WillPaginate::ViewHelpers.pagination_options[:next_label] = t(:next_page) + end #def route_not_found # render :text => 'What the fuck are you looking for ?', :status => :not_found #end end + diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index b7af37b..f165d2f 100755 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -2,12 +2,73 @@ class ContactsController < ApplicationController before_filter :check_current_user,:selected_folder - before_filter :get_current_folders, :only => [:index] + before_filter :get_current_folders + + before_filter :get_contacts, :only => [:index] theme :theme_resolver def index - flash[:notice] = 'Not implemented yet' + + end + + def ops + if !params["cids"] + flash[:warning] = t(:no_selected,:scope=>:contact) + else + if params["delete"] + params["cids"].each do |id| + @current_user.contacts.find_by_id(id).destroy + end + elsif params["compose"] + redirect_to :controller=>'messages',:action=>'compose',:cids=>params["cids"] + return + end + end + redirect_to(contacts_path) + end + + #problem http://binary10ve.blogspot.com/2011/05/migrating-to-rails-3-got-stuck-with.html + #def destroy + # @current_user.contacts.find(params[:id]).destroy + # redirect_to(contacts_path) + #end + + def new + @contact = Contact.new + end + + def edit + @contact = @current_user.contacts.find(params[:id]) + render 'edit' + end + + def create + @contact = @current_user.contacts.build(params[:contact]) + if @contact.valid? + @contact.save + flash[:notice] = t(:was_created,:scope=>:contact) + redirect_to(contacts_path) + else + render 'new' + end + end + + def update + @contact = @current_user.contacts.find(params[:id]) + if @contact.update_attributes(params[:contact]) + redirect_to(contacts_path) + else + render 'edit' + end + end + + ####################################### private section ################################## + + private + + def get_contacts + @contacts = Contact.getPageForUser(@current_user,params[:page],params[:sort_field],params[:sort_dir]) end end diff --git a/app/controllers/folders_controller.rb b/app/controllers/folders_controller.rb index 20a18d1..fe91111 100755 --- a/app/controllers/folders_controller.rb +++ b/app/controllers/folders_controller.rb @@ -18,35 +18,35 @@ class FoldersController < ApplicationController def create if params["folder"].empty? - flash[:warning] = t(:folder_to_create_empty) + flash[:warning] = t(:to_create_empty,:scope=>:folder) render "index" else begin if params["parent_folder"].empty? @mailbox.create_folder(params[:folder]) else - parent_folder = Folder.find(params["parent_folder"]) + parent_folder = @current_user.folders.find(params["parent_folder"]) if parent_folder.depth >= $defaults["mailbox_max_parent_folder_depth"].to_i - raise Exception, t(:folder_max_depth) + raise Exception, t(:max_depth,:scope=>:folder) end @mailbox.create_folder(parent_folder.full_name + parent_folder.delim + params[:folder]) end rescue Exception => e - flash[:error] = t(:can_not_create_folder) + ' (' + e.to_s + ')' + flash[:error] = t(:can_not_create,:scope=>:folder) + ' (' + e.to_s + ')' render 'index' return end - redirect_to :action => 'refresh', :flash => t(:folder_was_created), :type => :notice + redirect_to :action => 'refresh', :flash => t(:was_created,:scope=>:folder), :type => :notice end end # FIXME if you delete folder you should change current folder because if you go to messages/index you got nil def delete if params["folder"].empty? - flash[:warning] = t(:folder_to_delete_empty) + flash[:warning] = t(:to_delete_empty,:scope=>:folder) render "index" else begin - folder = Folder.find(params["folder"]) + folder = @current_user.folders.find(params["folder"]) system_folders = Array.new system_folders << $defaults["mailbox_inbox"] system_folders << $defaults["mailbox_trash"] @@ -55,13 +55,13 @@ class FoldersController < ApplicationController if system_folders.include?(folder.full_name.downcase) raise Exception, t(:system_folder) end - @mailbox.delete_folder(Folder.find(params["folder"]).full_name) + @mailbox.delete_folder(folder.full_name) rescue Exception => e - flash[:error] = t(:can_not_delete_folder) + ' (' + e.to_s + ')' + flash[:error] = t(:can_not_delete,:scope=>:folder) + ' (' + e.to_s + ')' render 'index' return end - redirect_to :action => 'refresh', :flash => t(:folder_was_deleted), :type => :notice + redirect_to :action => 'refresh', :flash => t(:was_deleted,:scope=>:folder), :type => :notice end end @@ -82,9 +82,6 @@ class FoldersController < ApplicationController def refresh Folder.refresh(@mailbox,@current_user) flash.keep - #if params[:flash] - # flash[params[:type]] = params[:flash] - #end redirect_to :action => 'index' end diff --git a/app/controllers/internal_controller.rb b/app/controllers/internal_controller.rb index bb3c559..3794ea1 100755 --- a/app/controllers/internal_controller.rb +++ b/app/controllers/internal_controller.rb @@ -23,7 +23,7 @@ class InternalController < ApplicationController def loginfailure reset_session - flash[:error] = t(:login_failure) + flash[:error] = t(:login_failure,:scope=>:user) @current_user = nil redirect_to :controller=>'user', :action => 'login' end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 9703948..be903ea 100755 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -11,75 +11,38 @@ class MessagesController < ApplicationController before_filter :check_current_user ,:selected_folder - before_filter :get_current_folders, :only => [:index,:compose,:show] + before_filter :get_current_folders - before_filter :open_imap_session, :only => :refresh - after_filter :close_imap_session, :only => :refresh + before_filter :open_imap_session, :select_imap_folder + after_filter :close_imap_session theme :theme_resolver - @@fetch_attr = ['ENVELOPE','BODYSTRUCTURE', 'FLAGS', 'UID', 'RFC822.SIZE'] def index - open_imap_session - #################### @messages = [] - folder_status = @mailbox.status(@current_folder.full_name) - @current_folder.update_attributes(:messages => folder_status['MESSAGES'], :unseen => folder_status['UNSEEN']) + folder_status = @mailbox.status + @current_folder.update_attributes(:total => folder_status['MESSAGES'], :unseen => folder_status['UNSEEN']) - if folder_status['MESSAGES'].zero? - return + folder_status['MESSAGES'].zero? ? uids_remote = [] : uids_remote = @mailbox.fetch_uids + uids_local = @current_user.messages.where(:folder_id => @current_folder).collect(&:uid) + + (uids_local-uids_remote).each do |uid| + @current_folder.messages.find_by_uid(uid).destroy end - messages = @mailbox.fetch(@current_folder.full_name,1..-1, "UID") - logger.custom('mess',messages) - uids_to_be_fetched = [] - - messages.each do |m| - uids_to_be_fetched << m.attr['UID'] - end - - messages = [] - @current_user.messages.destroy_all - uids_to_be_fetched.each_slice($defaults["imap_fetch_slice"].to_i) do |slice| - logger.custom('slice',slice.join(",")) - messages = @mailbox.uid_fetch(@current_folder.full_name,slice, @@fetch_attr) - - - + (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| - - envelope = m.attr['ENVELOPE'] - uid = m.attr['UID'] - #content_type = m.attr['BODYSTRUCTURE'].multipart? ? 'multipart' : 'text' - content_type = m.attr['BODYSTRUCTURE'].media_type.downcase - size = m.attr['RFC822.SIZE'] - unread = !(m.attr['FLAGS'].member? :Seen) - from = ImapMessageModule::IMAPAddress.from_address(envelope.from[0]) - logger.custom('from',from.to_db) - logger.custom('enevelope_from',envelope) - logger.custom('body',m.attr['BODYSTRUCTURE']) - message = @current_user.messages.create(:folder_id => @current_folder.id, - :msg_id => envelope.message_id, - :uid => uid, - :from => from.to_db, - :to => envelope.to, - :subject => envelope.subject, - :content_type => content_type, - :date => envelope.date, - :unread => unread, - :size => size) - + mess = ImapMessageModule::IMAPMessage.fromImap(m) + Message.createForUser(@current_user,@current_folder,mess) end - end - @messages = Message.getPageForUser(@current_user,params['page']) + @messages = Message.getPageForUser(@current_user,@current_folder,params[:page],params[:sort_field],params[:sort_dir]) - ############### - close_imap_session end def folder @@ -92,20 +55,102 @@ class MessagesController < ApplicationController end def refresh + @folders_shown.each do |f| + @mailbox.set_folder(f.full_name) + folder_status = @mailbox.status + f.update_attributes(:total => folder_status['MESSAGES'], :unseen => folder_status['UNSEEN']) + end + redirect_to :action => 'index' + end + + def emptybin + begin + trash_folder = @current_user.folders.find_by_full_name($defaults["mailbox_trash"]) + @mailbox.set_folder(trash_folder.full_name) + trash_folder.messages.each do |m| + logger.custom('id',m.inspect) + @mailbox.delete_message(m.uid) + end + @mailbox.expunge + trash_folder.messages.destroy_all + trash_folder.update_attributes(:unseen => 0, :total => 0) + rescue Exception => e + flash[:error] = "#{t(:imap_error)} (#{e.to_s})" + end redirect_to :action => 'index' end def ops + begin + if !params["uids"] + flash[:warning] = t(:no_selected,:scope=>:message) + elsif params["delete"] + params["uids"].each do |uid| + @mailbox.delete_message(uid) + @current_user.messages.find_by_uid(uid).destroy + end + @current_folder.update_stats + elsif params["set_unread"] + params["uids"].each do |uid| + @mailbox.set_unread(uid) + @current_user.messages.find_by_uid(uid).update_attributes(:unseen => 1) + end + elsif params["set_read"] + params["uids"].each do |uid| + @mailbox.set_read(uid) + @current_user.messages.find_by_uid(uid).update_attributes(:unseen => 0) + end + elsif params["trash"] + dest_folder = @current_user.folders.find_by_full_name($defaults["mailbox_trash"]) + params["uids"].each do |uid| + @mailbox.move_message(uid,dest_folder.full_name) + message = @current_folder.messages.find_by_uid(uid) + message.change_folder(dest_folder) + end + @mailbox.expunge + dest_folder.update_stats + @current_folder.update_stats + elsif params["copy"] + if params["dest_folder"].empty? + flash[:warning] = t(:no_selected,:scope=>:folder) + else + dest_folder = find(params["dest_folder"]) + params["uids"].each do |uid| + @mailbox.copy_message(uid,dest_folder.full_name) + message = @current_folder.messages.find_by_uid(uid) + new_message = message.clone + new_message.folder_id = dest_folder.id + new_message.save + end + dest_folder.update_stats + @current_folder.update_stats + end + elsif params["move"] + if params["dest_folder"].empty? + flash[:warning] = t(:no_selected,:scope=>:folder) + else + dest_folder = @current_user.folders.find(params["dest_folder"]) + params["uids"].each do |uid| + @mailbox.move_message(uid,dest_folder.full_name) + message = @current_folder.messages.find_by_uid(uid) + message.change_folder(dest_folder) + end + @mailbox.expunge + dest_folder.update_stats + @current_folder.update_stats + end + end + rescue Exception => e + flash[:error] = "#{t(:imap_error)} (#{e.to_s})" + end redirect_to :action => 'index' end def show - @message = Message.find(params[:id]) - flash[:notice] = 'Not impelented yet' - open_imap_session - @body = @mailbox.fetch_body(@current_folder.full_name,@message.uid) - logger.custom('body',@body.inspect) - close_imap_session + @message = @current_user.messages.find(params[:id]) + @message.update_attributes(:unseen => false) + flash[:notice] = 'Not implemented yet' + @body = @mailbox.fetch_body(@message.uid) end end diff --git a/app/controllers/prefs_controller.rb b/app/controllers/prefs_controller.rb index 813be02..b1ac2ed 100755 --- a/app/controllers/prefs_controller.rb +++ b/app/controllers/prefs_controller.rb @@ -2,14 +2,25 @@ class PrefsController < ApplicationController before_filter :check_current_user,:selected_folder - before_filter :get_current_folders, :only => [:index,:compose] + before_filter :get_current_folders + + before_filter :get_prefs theme :theme_resolver def index - flash[:notice] = 'Not implemented yet' - - @prefs = @current_user.prefs end + def update + if params[:prefs] + @prefs.update_attributes(params[:prefs]) + end + redirect_to :action => 'index' + end + + ############################################ private section ######################################### + + def get_prefs + @prefs = @current_user.prefs + end end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 5844412..78b1ed8 100755 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -8,7 +8,7 @@ class UserController < ApplicationController def logout reset_session - flash[:notice] = t(:user_logged_out) + flash[:notice] = t(:logged_out,:scope=>:user) redirect_to :action => "login" end @@ -44,19 +44,19 @@ class UserController < ApplicationController def create @user = User.new - @user.email = params["user_email"] - @user.first_name = params["user_first_name"] - @user.last_name = params["user_last_name"] + @user.email = params[:user][:email] + @user.first_name = params[:user][:first_name] + @user.last_name = params[:user][:last_name] @server = Server.new - @server.name = params["server_name"] + @server.name = params[:server][:name] if @user.valid? and @server.valid? @user.save @server.user_id = @user.id @server.save Prefs.create_default(@user.id) - flash[:notice] = t(:setup_done) + flash[:notice] = t(:setup_done,:scope=>:user) redirect_to :action => 'login' else render "setup" diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9dee009..4bafdea 100755 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,7 +1,7 @@ module ApplicationHelper def form_field(object,field,flabel,example,val) - + model_name = eval(object.class.model_name) html = "" html << "
" if object.errors[field.to_sym] @@ -10,7 +10,7 @@ def form_field(object,field,flabel,example,val) end html << "
" end - html << "" @@ -43,7 +45,7 @@ def form_button(text,image) html << "\""" html << t(text.to_sym) html << "" @@ -66,7 +68,7 @@ end def simple_input_field(name,label,value) html = "" - html << "
" + html << "
" html << "" html << "" html << "
" @@ -80,6 +82,15 @@ def select_field(name,object,label,blank) html << "
" end +def select_field_table(object,field,table_choices,choice,blank) + model_name = eval(object.class.model_name) + html = "" + html << "
" + html << "" + html << select(object.class.to_s.downcase, field, options_for_select(table_choices,choice), {:include_blank => blank}) + html << "
" +end + #def form_simle_field(name,label,value) # html = "" # html << "
" @@ -89,23 +100,23 @@ end #end def nav_to_folders - link_to( t(:folders), :controller=>:folders, :action=>:index ) + link_to( t(:folders,:scope=>:folder), :controller=>:folders, :action=>:index ) end def nav_to_messages - link_to( t(:messages), :controller=>:messages, :action=>:index ) + link_to( t(:messages,:scope=>:message), :controller=>:messages, :action=>:index ) end def nav_to_compose - link_to( t(:compose), :controller=>:messages, :action=>:compose ) + link_to( t(:compose,:scope=>:compose), :controller=>:messages, :action=>:compose ) end def nav_to_contacts - link_to( t(:contacts), :controller=>:contacts, :action=>:index ) + link_to( t(:contacts,:scope=>:contact), contacts_path ) end def nav_to_prefs - link_to( t(:preferences), :controller=>:prefs, :action=>:index ) + link_to( t(:prefs,:scope=>:prefs), prefs_path ) end def main_navigation(active) diff --git a/app/helpers/contacts_helper.rb b/app/helpers/contacts_helper.rb index 593025b..7632685 100755 --- a/app/helpers/contacts_helper.rb +++ b/app/helpers/contacts_helper.rb @@ -1,2 +1,17 @@ module ContactsHelper + + def contacts_table_header + html = "" + $defaults["contacts_table_fields"].each do |f| + html << "" + if params[:sort_field] == f + params[:sort_dir].nil? ? dir = 'desc' : dir = nil + end + + html << link_to(Contact.human_attribute_name(f), {:controller => 'contacts',:action => 'index',:sort_field => f,:sort_dir => dir}, {:class=>"header"}) + html << "" + end + html + end + end diff --git a/app/helpers/folder_helper.rb b/app/helpers/folder_helper.rb index f678764..4a4d477 100755 --- a/app/helpers/folder_helper.rb +++ b/app/helpers/folder_helper.rb @@ -1,24 +1,40 @@ module FolderHelper def folder_link(folder) + folder.parent.empty? ? name = folder.name : name = folder.parent.gsub(/\./,'#') + "#" + folder.name - s = link_to folder.name.capitalize, :controller => 'messages', :action => 'folder', :id => name - if !folder.unseen.zero? - s += ' (' + folder.unseen.to_s + ')' + s = link_to folder.name.capitalize, messages_folder_path(:id => name) + + if folder.full_name.downcase == $defaults["mailbox_trash"].downcase + if not folder.total.zero? + s <<' (' + s << link_to(t(:emptybin,:scope=>:folder),messages_emptybin_path) + s << ')' + end + else + if !folder.unseen.zero? + s += ' (' + folder.unseen.to_s + ')' + end end s end def pretty_folder_name(folder) - folder.nil? ? t(:no_folder_selected) : folder.name.capitalize + folder.nil? ? t(:no_selected,:scope=>:folder) : folder.name.capitalize end def select_for_folders(name,id,object,label,blank) html = "" html << "
" html << "" - html << select(name, id, object.all.collect {|p| [ p.parent.empty? ? p.name : p.parent+p.delim+p.name, p.id ] }, { :include_blank => (blank == true ? true : false)}) + html << simple_select_for_folders(name,id,object,blank) html << "
" end + def simple_select_for_folders(name,id,object,blank) + html = "" + html << select(name, id, object.all.collect {|p| [ p.parent.empty? ? p.name : p.parent+p.delim+p.name, p.id ] }, { :include_blank => (blank == true ? true : false)}) + html + end + end diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb index f878a99..135c25a 100755 --- a/app/helpers/messages_helper.rb +++ b/app/helpers/messages_helper.rb @@ -19,9 +19,12 @@ module MessagesHelper end def subject_formatter(message) - length = $defaults["msg_subject_length"].to_i - logger.custom('l',length) - message.subject.length >= length ? s = message.subject[0,length]+"..." : s = message.subject + if message.subject.size.zero? + s = t(:no_subject,:scope=>:message) + else + 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 end @@ -29,5 +32,26 @@ module MessagesHelper message.content_type == 'text' ? "" : "A" end + def headers_links + + if @current_folder.hasFullName?($defaults["mailbox_sent"]) + fields = $defaults["msgs_sent_view_fields"] + else + fields = $defaults["msgs_inbox_view_fields"] + end + + html = "" + fields.each do |f| + html << "" + if params[:sort_field] == f + params[:sort_dir].nil? ? dir = 'desc' : dir = nil + end + + html << link_to(Message.human_attribute_name(f), {:controller => 'messages',:action => 'index',:sort_field => f,:sort_dir => dir}, {:class=>"header"}) + html << "" + end + html + end + end diff --git a/app/models/contact.rb b/app/models/contact.rb new file mode 100755 index 0000000..6f5c693 --- /dev/null +++ b/app/models/contact.rb @@ -0,0 +1,35 @@ +class Contact < ActiveRecord::Base + + validates_length_of :nick, :within => 5..15 + validates_length_of :first_name,:last_name, :within => 3..20 + validates_length_of :email, :within => 5..50 + validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i + validates_length_of :info, :maximum => 50 + validate_on_create :check_unique_nick + + belongs_to :user + + def self.getPageForUser(user,page,sort_field,sort_dir) + + order = 'last_name asc' + if sort_field + if Contact.attribute_method?(sort_field) == true + order = sort_field + sort_dir == 'desc' ? order += ' desc' : sort_dir + end + end + + Contact.paginate :page => page , :per_page => $defaults["contacts_per_page"], :conditions=> ['user_id = ?', user.id],:order => order + end + + def full_name + first_name + ' ' + last_name + end + + def check_unique_nick + if !Contact.where('upper(nick) = ? and user_id = ?',nick.upcase,user_id).size.zero? + errors.add(:nick, :not_unique) + end + end + +end diff --git a/app/models/folder.rb b/app/models/folder.rb index 0f0935f..3f2f33e 100755 --- a/app/models/folder.rb +++ b/app/models/folder.rb @@ -3,6 +3,7 @@ class Folder < ActiveRecord::Base belongs_to :user validates_presence_of :name, :on => :create before_save :check_fill_params, :on => :create + has_many :messages, :dependent => :destroy def full_name if parent.empty? @@ -22,12 +23,23 @@ class Folder < ActiveRecord::Base (fields[1].downcase == name.downcase) && (fields[0].downcase == parent.downcase) end + def update_stats + unseen = messages.where(:unseen => true).count + total = messages.count + update_attributes(:unseen => unseen, :total => total) + end + + def hasFullName?(folder_name) + full_name.downcase == folder_name.downcase + end + + ############################################## private section ##################################### + private def check_fill_params - self.messages.nil? ? self.messages = 0 : self.messages + self.total.nil? ? self.total = 0 : self.total self.unseen.nil? ? self.unseen = 0 : self.unseen - self.msgs_updated_at.nil? ? self.msgs_updated_at = (DateTime.now-1) : self.msgs_updated_at end def self.createBulk(user,imapFolders) @@ -43,14 +55,22 @@ class Folder < ActiveRecord::Base parent = "" end - user.folders.create(:name=>name,:parent=>parent,:haschildren=>has_children,:delim=>data.delim,:messages => data.messages,:unseen => data.unseen) + user.folders.create( + :msgs_updated_at => DateTime.now-1, + :name => name, + :parent => parent, + :haschildren => has_children, + :delim => data.delim, + :total => data.messages, + :unseen => data.unseen) end end - def self.current(data) - folder = data.split("#") - nam = folder.delete_at(folder.size - 1) - folder.size.zero? == true ? par = "" : par = folder.join(".") + def self.find_by_full_name(data) + folder = data.gsub(/\./,'#') + fields = folder.split("#") + nam = fields.delete_at(fields.size - 1) + fields.size.zero? == true ? par = "" : par = fields.join(".") where(['name = ? and parent = ?',nam,par]).first end @@ -64,4 +84,6 @@ class Folder < ActiveRecord::Base Folder.createBulk(user,folders) end + + end diff --git a/app/models/message.rb b/app/models/message.rb index eb79905..3a51d40 100755 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -1,13 +1,37 @@ class Message < ActiveRecord::Base belongs_to :user + belongs_to :folder - #cattr_reader :per_page - #@@per_page = $defaults["msgs_per_page"] + def self.getPageForUser(user,folder,page,sort_field,sort_dir) - def self.getPageForUser(user,page,order = "date desc") - #Message.paginate :page => page , :per_page => user.prefs.msgs_per_page.to_i, :conditions=> ['user_id = ?', user.id],:order => order + order = 'date desc' + if sort_field + if Message.attribute_method?(sort_field) == true + order = sort_field + sort_dir == 'desc' ? order += ' desc' : sort_dir + end + end - Message.paginate :page => page , :per_page => 50, :conditions=> ['user_id = ?', user.id],:order => order + 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) + 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, + :subject => mess.subject, + :content_type => mess.content_type, + :date => mess.date, + :unseen => mess.unseen, + :size => mess.size) + end + + def change_folder(folder) + update_attributes(:folder_id => folder.id) end end diff --git a/app/models/prefs.rb b/app/models/prefs.rb index 35cee51..e495248 100755 --- a/app/models/prefs.rb +++ b/app/models/prefs.rb @@ -15,3 +15,5 @@ class Prefs < ActiveRecord::Base ) end end + +# TODO move refresh to prefs and make refresh page with messages diff --git a/app/models/user.rb b/app/models/user.rb index cd63207..cb11571 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,6 +8,7 @@ class User < ActiveRecord::Base has_one :prefs, :dependent => :destroy has_many :folders, :dependent => :destroy has_many :messages, :dependent => :destroy + has_many :contacts, :dependent => :destroy def set_cached_password(session,password) if $defaults['session_encryption'] diff --git a/config/defaults.yml b/config/defaults.yml index d3da44e..afbae6e 100755 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -1,12 +1,23 @@ theme: olive -locale: en +locale: pl + +themes: [olive] +locales: [en, pl] +msgs_per_page_table: [15, 20, 25, 30, 35, 40, 45, 50] +msg_send_type: [html, text] + +contacts_table_fields: [nick, first_name, last_name, email, info] +contacts_per_page: 25 msgs_per_page: 20 msgs_refresh_time: 300 msgs_send_type: html -msgs_update_time: 300 +msgs_update_time: 600 +msgs_inbox_view_fields: [from_addr, subject, date, size] +msgs_sent_view_fields: [to_addr, subject, date, size] msg_subject_length: 45 +msg_search_fields: [subject, from, to] imap_debug: true imap_use_ssl: 'false' @@ -20,7 +31,7 @@ session_password: asDD3s2@sAdc983# mailbox_max_parent_folder_depth: 3 mailbox_inbox: INBOX -mailbox_trash: Trash -mailbox_sent: Sent -mailbox_drafts: Drafts +mailbox_trash: INBOX.Trash +mailbox_sent: INBOX.sent +mailbox_drafts: INBOX.drafts diff --git a/config/locales/en.yml b/config/locales/en.yml index de8b24d..0ca154d 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,102 +1,63 @@ en: - mailr: Mailr - email: Email - password: Password - log_in: Log In - wrong_email_or_password: Wrong email or password specified. - mailbox: Mailbox - folders: Folders - folder: Folder - empty: Empty - logout: Logout - compose: Compose - preferences: Preferences - filters: Filters - contacts: Contacts - search: Search - search_txt: Search in message field - refresh: Refresh - operations: Operations - operations_txt: Operations on marked messages - delete: delete - copy: copy - move: move - mark_read: mark read - mark_unread: mark unread - destination_txt: Destination for move and copy operations - for: for - to: To - subject: Subject - date: Date - size: Size - from: From - show_all: Show all - pages: Pages - first: First - prev: Prev - next: Next - last: Last - back_to_list: Back to list - back_to_message: Back to message - reply: Reply - forward: Forward - delete: Delete - view_source: View source - add_filter: Add filter - cc: CC - bcc: BCC - send: Send - choose_address: Choose addresses from contacts - compose_txt: Compose new mail - attachment: Attachment - add: Add - first_name: First name - last_name: Last name - send_type: Send type message - messages_per_page: Messages per page - check_external_mail: Check external mail? - check_external_mail_txt: Note that by selecting this option webmail system will try to log you using your original email on a local server. - save: Save - cancel: Cancel - add_one_contact: Add one contact - add_multiple: Add multiple - name: name - add_folder: Add folder - total_messages: Total messages - unseen: Unseen - please_login: Log in - site_link: https://github.com/lmanolov/mailr - user_logged_out: User was logged out - unknown_user_title: Unknown user - unknown_user_flash: Your email identifier was not found in database - unknown_user_login: Go to login page and try to login once more. - unknown_user_setup: Go to setup page and do the setup of Your mail account. - setup_title: Setup + activerecord: + attributes: + prefs: + theme: Theme + locale: Locale + msgs_per_page: Messages per page + msg_send_type: Message send format + contact: + compose_to_selected: Compose to selected + delete_selected: Delete selected + modifying: Modifying contact + creating_new: Creating new contact + create_new: Create new contact + contacts: Contacts + contact: Contact + no_selected: No contact selected + total_entries: Total contacts entries + no_entries: No contacts + was_created: Contact was created + are_you_sure_to_delete_contact: Are You sure to delete contact? + + prefs: + prefs: Preferences + + folder: + folders: Folders + no_shown: No folders shown + parent: Parent folder + to_create: Folder to create + to_delete: Folder to delete + shown: Shown folders + emptybin: Empty + current: Current folder + no_selected: No folder selected + to_create_empty: No folder name + max_depth: Maximum folder depth reached + can_not_create: Can not create folder + was_created: Folder was created + to_delete_empty: No folder to delete + can_not_delete: Can not delete folder + was_deleted: Folder was deleted + + message: + messages: Messages + + compose: + compose: Compose + + user: + login_failure: Login failure. Bad email or password + logged_out: User was logged out + setup_done: Setup done. Please login in + + must_be_unique: must be unique + some_add_info: some additional information example: example - server_name: Server name - setup_done: Setup done. Please log in - login_failure: Login failure. Bad email or password - general_error: General error - unspecified_error: Unspecified error occured - imap_error: Imap Error - folder_to_create: Folder to create + refresh: Refresh create: Create - subscribe_unsubscribe: (Un)Subscribe - folders_subscribed_selected: Folders subscribed - messages: Messages - folder_to_create_empty: Folder to create is empty - folder_was_created: Folder was created - can_not_create_folder: Can not create folder - folder_max_depth: Maximum folder depth reached - folder_to_delete_empty: Folder to delete empty - folder_was_deleted: Folder was deleted - can_not_delete_folder: Can not delete folder - system_folder: System folder - refresh_folders: Refresh folders + delete: Delete show_hide: Show/Hide - page_not_found: Page not found - bytes: Bytes - kbytes: Kb - mbytes: MB - previous_page: Previous page - next_page: Next page + mailr: Mailr + save: Save diff --git a/config/locales/en.yml.old b/config/locales/en.yml.old new file mode 100755 index 0000000..3c785e8 --- /dev/null +++ b/config/locales/en.yml.old @@ -0,0 +1,160 @@ +en: + activerecord: + attributes: + prefs: + theme: Theme + locale: Locale + msgs_per_page: Messages per page + msg_send_type: Message send format + contact: + compose_to_selected: Compose to selected + delete_selected: Delete selected + modifying: Modifying contact + creating_new: Creating new contact + create_new: Create new contact + contacts: Contacts + contact: Contact + no_selected: No contact selected + total_entries: Total contacts entries + no_entries: No contacts + was_created: Contact was created + are_you_sure_to_delete_contact: Are You sure to delete contact? + + prefs: + prefs: Preferences + + folder: + folders: Folders + no_shown: No folders shown + parent: Parent folder + to_create: Folder to create + to_delete: Folder to delete + shown: Shown folders + emptybin: Empty + current: Current folder + no_selected: No folder selected + + message: + messages: Messages + + compose: + compose: Compose + + must_be_unique: must be unique + some_add_info: some additional information + example: example + refresh: Refresh + create: Create + delete: Delete + show_hide: Show/Hide + + mailr: Mailr + email: Email + password: Password + log_in: Log In + wrong_email_or_password: Wrong email or password specified. + mailbox: Mailbox + empty: Empty + logout: Logout + filters: Filters + search: Search + search_txt: Search in message field + operations: Operations + operations_txt: Operations on marked messages + copy: copy + move: move + mark_read: mark read + mark_unread: mark unread + destination_txt: Destination for move and copy operations + for: for + to: To + subject: Subject + date: Date + size: Size + from: From + show_all: Show all + pages: Pages + first: First + prev: Prev + next: Next + last: Last + back_to_list: Back to list + back_to_message: Back to message + reply: Reply + forward: Forward + delete: Delete + view_source: View source + add_filter: Add filter + cc: CC + bcc: BCC + send: Send + choose_address: Choose addresses from contacts + compose_txt: Compose new mail + attachment: Attachment + add: Add + first_name: First name + last_name: Last name + send_type: Send type message + messages_per_page: Messages per page + check_external_mail: Check external mail? + check_external_mail_txt: Note that by selecting this option webmail system will try to log you using your original email on a local server. + save: Save + cancel: Cancel + add_one_contact: Add one contact + add_multiple: Add multiple + name: name + add_folder: Add folder + total_messages: Total messages + unseen: Unseen + please_login: Log in + site_link: https://github.com/lmanolov/mailr + user_logged_out: User was logged out + unknown_user_title: Unknown user + unknown_user_flash: Your email identifier was not found in database + unknown_user_login: Go to login page and try to login once more. + unknown_user_setup: Go to setup page and do the setup of Your mail account. + setup_title: Setup + server_name: Server name + setup_done: Setup done. Please log in + login_failure: Login failure. Bad email or password + general_error: General error + unspecified_error: Unspecified error occured + imap_error: IMAP Error + folder_to_create: Folder to create + subscribe_unsubscribe: (Un)Subscribe + folders_subscribed_selected: Folders subscribed + messages: Messages + folder_to_create_empty: Folder to create is empty + folder_was_created: Folder was created + can_not_create_folder: Can not create folder + folder_max_depth: Maximum folder depth reached + folder_to_delete_empty: Folder to delete empty + folder_was_deleted: Folder was deleted + can_not_delete_folder: Can not delete folder + system_folder: System folder + refresh_folders: Refresh folders + show_hide: Show/Hide + page_not_found: Page not found + bytes: Bytes + kbytes: Kb + mbytes: MB + previous_page: Previous page + next_page: Next page + copy: Copy + move: Move + checked_messages: checked messages + to: to + to_folder: folder + set_read: Set read + set_unread: Set unread + search: Search + in_message_field: in message field + string: string + total_messages: Total messages + no_messages_in: No messages in folder + no_subject: No subject + no_messages_selected: No messages selected + + + + diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 145ae75..d9f2003 100755 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1,77 +1,122 @@ pl: - mailr: Mailr - email: E-mail - password: Hasło - log_in: Zaloguj - wrong_email_or_password: Podano nieprawidłowy login lub hasło - mailbox: Poczta - folders: Foldery - folder: Folder - empty: Opróżnij - logout: Wyloguj - compose: Nowa wiadomość - preferences: Ustawienia - filters: Filtry - contacts: Kontakty - search: Szukaj - search_txt: ciąg znaków - refresh: Odśwież - operations: Akcje - operations_txt: Akcje na zaznaczonych wiadomościach - delete: Usuń - copy: Skopiuj - move: Przenieś - mark_read: Zaznacz jako przeczytane - mark_unread: Zaznacz jako nieprzeczytane - destination_txt: Miejsce docelowe dla akcji - for: ciągu znaków - to: Do - subject: Temat - date: Data - size: Rozmiar - from: Od - show_all: Pokaż wszystkie - pages: Strony - first: Pierwsza - prev: Poprzednia - next: Następna - last: Ostatnia - back_to_list: Powrót do listy - back_to_message: Powrót do wiadomości - reply: Odpowiedz - forward: Przekaż - delete: Usuń - view_source: Pokaż źródło - add_filter: Dodaj filtr - cc: Cc - bcc: Bcc - send: Wyślij - choose_address: Wybierz adres z kontaktów - compose_txt: Utwórz nową wiadomość - attachment: Załącznik - add: Dodaj - first_name: Imię - last_name: Nazwisko - send_type: Format wiadomości wychodzącej - messages_per_page: Ilość wiadomości na stronie - check_external_mail: Check external mail? - check_external_mail_txt: Note that by selecting this option webmail system will try to log you using your original email on a local server. - save: Zapisz - cancel: Anuluj - add_one_contact: Dodaj jeden kontakt - add_multiple: Dodaj wiele - name: Nazwa - add_folder: Dodaj folder - total_messages: Total messages - unseen: Unseen - add_edit_folder: Zarządzaj - user_logged_out: Użytkownik został wylogowany - please_login: Logowanie - add_to_contacts: Dodaj do kontaktów - want_to_empty_trash_message: Czy chcesz opróznic kosz? - site_link: https://github.com/lmanolov/mailr - marked_messages: zaznaczone wiadomości - to_folder: do folderu - message_field: Pole wiadomości - no_messages_found: Nie znaleziono żadnych wiadomości + activerecord: + errors: + messages: + blank: "nie może być pust(a/e/y) " + too_short: "za krótki(e) (min. %{count} znak(i/ów)) " + too_long: "za długi(e) (max. %{count} znak(i/ów)) " + invalid: "ma niepoprawny format " + not_unique: "musi być unikalny " + taken: "musi być unikalny" + models: + contact: Kontakt + attributes: + contact: + nick: Pseudonim + first_name: Imię + last_name: Nazwisko + email: E-mail + info: Informacje dodatkowe + prefs: + theme: Temat + locale: Ustawienia językowe + msgs_per_page: Ilość wiadomości wyświetlanych na stronie + msg_send_type: Format wysyłanej wiadomości + message: + from_addr: Od + to_addr: Do + subject: Temat + size: Rozmiar + date: Data + user: + email: E-mail + password: Hasło + first_name: Imię + last_name: Nazwisko + server: + name: Nazwa serwera + + contact: + compose_to_selected: Napisz do wybranych + delete_selected: Usuń wybrane + modifying: Modyfikacja kontaktu + creating_new: Tworzenie nowego kontaktu + create_new: Utwórz nowy kontakt + contacts: Kontakty + contact: Kontakt + no_selected: Nie wybrano żadnego kontaktu + total_entries: Liczba kontaktów + no_entries: Brak kontaktów + was_created: Kontakt został utworzony + are_you_sure_to_delete_contact: Czy na pewno chcesz usunąć kontakt? + + prefs: + prefs: Ustawienia + + folder: + folders: Foldery + no_shown: Żadnych pokazanych folderów + parent: Folder nadrzędny + to_create: Folder do utworzenia + to_delete: Folder do usunięcia + shown: Foldery pokazane + emptybin: Opróżnij + current: Folder bieżący + no_selected: Nie wybrano żadnego folderu + to_create_empty: Nie podano nazwy folderu + max_depth: Osiągnięto maksymalne zagnieżdzenie fodlderów + can_not_create: Nie można utworzyć folderu + was_created: Folder został utworzony + to_delete_empty: Nie wybrano folderu do usunięcia + can_not_delete: Nie można usunąć folderu + was_deleted: Folder został usunięty + to_folder: do folderu + + message: + messages: Wiadomości + no_selected: Nie wybrano żadnej wiadomości + total: Liczba wszystkich wiadomości + checked: zaznaczone wiadomości + set_read: Ustaw jako przeczytane + set_unread: Ustaw jako nieprzeczytane + no_in: Nie ma żadnych wiadomości w bieżącym folderze + no_subject: Brak tematu + + compose: + compose: Nowa wiadomość + + user: + login_failure: Nieudane logowanie. Podano błędny e-mail lub hasło. + logged_out: Użytkownik wylogowany + setup_done: Konfiguracja zakończona. Proszę się zalogować. + please_login: Logowanie + unknown_title: Nieznany użytkownik + unknown_flash: Twój identyfikator użytkownika nie został odnaleziony w bazie + unknown_login: Idź do strony logowania i zaloguj sie jeszcze raz + unknown_setup: Idź do strony konfiguracyjnej i skonfiguruj swój dostęp + setup: Konfiguracja + login: Logowanie + + must_be_unique: musi być unikalny + some_add_info: jakieś dodatkowe informacje + example: przykład + refresh: Odśwież + create: Utwórz + delete: Usuń + show_hide: Pokaż/Ukryj + mailr: Mailr + save: Zapisz + imap_error: Błąd protokołu IMAP + unspecified_error: Nieoczekiwany błąd + page_not_found: Nie znaleziono żadanej strony + copy: Skopiuj + move: Przenieś + to: do + previous_page: Poprzednia + next_page: Następna + bytes: B + kbytes: kB + mbytes: MB + site_link: https://github.com/lmanolov/mailr + send: Wyślij diff --git a/config/routes.rb b/config/routes.rb index 1965c0e..a0c179a 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,13 @@ Mailr::Application.routes.draw do - get "prefs/index" + match "prefs/index" => "prefs#index", :as => :prefs + post "prefs/update" - get "contacts/index" + resources :contacts + post "contacts/ops" + + #resources :folders get "folders/index" post "folders/create" post "folders/delete" @@ -18,11 +22,12 @@ Mailr::Application.routes.draw do root :to => "messages#index" get "messages/index" get "messages/refresh" - match 'messages/folder/:id' => 'messages#folder' + match 'messages/folder/:id' => 'messages#folder', :as => :messages_folder post "messages/ops" get "messages/compose" get "messages/refresh" match "messages/show/:id" => 'messages#show' + get "messages/emptybin" get "user/logout" post "user/authenticate" diff --git a/db/migrate/20110803115924_rename_m_essages_in_folder.rb b/db/migrate/20110803115924_rename_m_essages_in_folder.rb new file mode 100755 index 0000000..a56b1e4 --- /dev/null +++ b/db/migrate/20110803115924_rename_m_essages_in_folder.rb @@ -0,0 +1,9 @@ +class RenameMEssagesInFolder < ActiveRecord::Migration + def self.up + rename_column :folders,:messages,:total + end + + def self.down + rename_column :folders,:total,:messages + end +end diff --git a/db/migrate/20110804130051_rename_unseen_in_message.rb b/db/migrate/20110804130051_rename_unseen_in_message.rb new file mode 100755 index 0000000..cbc909b --- /dev/null +++ b/db/migrate/20110804130051_rename_unseen_in_message.rb @@ -0,0 +1,9 @@ +class RenameUnseenInMessage < ActiveRecord::Migration + def self.up + rename_column :messages, :unread, :unseen + end + + def self.down + rename_column :messages, :unseen, :unread + end +end diff --git a/db/migrate/20110810073021_create_contacts.rb b/db/migrate/20110810073021_create_contacts.rb new file mode 100755 index 0000000..9121cef --- /dev/null +++ b/db/migrate/20110810073021_create_contacts.rb @@ -0,0 +1,17 @@ +class CreateContacts < ActiveRecord::Migration + def self.up + create_table :contacts do |t| + t.string :nick + t.string :email + t.string :first_name + t.string :last_name + t.string :info + t.references :user + t.timestamps + end + end + + def self.down + drop_table :contacts + end +end diff --git a/db/migrate/20110816093648_rename_from_column_in_messages.rb b/db/migrate/20110816093648_rename_from_column_in_messages.rb new file mode 100755 index 0000000..c191d46 --- /dev/null +++ b/db/migrate/20110816093648_rename_from_column_in_messages.rb @@ -0,0 +1,11 @@ +class RenameFromColumnInMessages < ActiveRecord::Migration + def self.up + rename_column :messages, :from, :from_addr + rename_column :messages, :to, :to_addr + end + + def self.down + rename_column :messages, :from_addr, :from + rename_column :messages, :to_addr, :to + end +end diff --git a/db/migrate/20110816120258_remove_msgs_update_from_messages.rb b/db/migrate/20110816120258_remove_msgs_update_from_messages.rb new file mode 100755 index 0000000..9582b84 --- /dev/null +++ b/db/migrate/20110816120258_remove_msgs_update_from_messages.rb @@ -0,0 +1,9 @@ +class RemoveMsgsUpdateFromMessages < ActiveRecord::Migration + def self.up + remove_column :folders, :msgs_updated_at + end + + def self.down + add_column :folders, :msgs_updated_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index d0a3afe..046f187 100755 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,19 +10,29 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110731185416) do +ActiveRecord::Schema.define(:version => 20110816120258) do + + create_table "contacts", :force => true do |t| + t.string "nick" + t.string "email" + t.string "first_name" + t.string "last_name" + t.string "info" + t.integer "user_id" + t.datetime "created_at" + t.datetime "updated_at" + end create_table "folders", :force => true do |t| t.string "name" t.string "delim" t.boolean "haschildren" - t.integer "messages" + t.integer "total" t.integer "unseen" t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" t.string "parent" - t.datetime "msgs_updated_at" t.boolean "shown" t.string "alter_name" end @@ -31,13 +41,13 @@ ActiveRecord::Schema.define(:version => 20110731185416) do t.integer "folder_id" t.integer "user_id" t.string "msg_id" - t.string "from" - t.string "to" + t.string "from_addr" + t.string "to_addr" t.string "subject" t.string "content_type" t.integer "uid" t.integer "size" - t.boolean "unread" + t.boolean "unseen" t.datetime "date" t.datetime "created_at" t.datetime "updated_at" diff --git a/lib/imap_mailbox.rb b/lib/imap_mailbox.rb index dc23106..aa4b319 100755 --- a/lib/imap_mailbox.rb +++ b/lib/imap_mailbox.rb @@ -9,11 +9,11 @@ end class IMAPMailbox attr_reader :connected - attr_accessor :selected_folder + attr_accessor :sfolder attr_accessor :logger def initialize(logger) - @selected_folder = '' + @sfolder = '' @folders = {} @connected = false @logger = logger @@ -80,6 +80,19 @@ class IMAPMailbox end end + def fetch_uids + begin + uids = [] + imap_uids = @imap.fetch(1..-1, "UID") + imap_uids.each do |u| + uids << u.attr['UID'] + end + return uids + rescue Exception => e + raise e + end + end + def delete_folder(name) begin @imap.delete(Net::IMAP.decode_utf7(name)) @@ -88,18 +101,16 @@ class IMAPMailbox end end - def fetch(folder_name,range,attribs) + def fetch(range,attribs) begin - set_folder(folder_name) @imap.fetch(range,attribs) rescue Exception => e raise e end end - def uid_fetch(folder_name,range,attribs) + def uid_fetch(range,attribs) begin - set_folder(folder_name) @imap.uid_fetch(range,attribs) rescue Exception => e raise e @@ -107,18 +118,79 @@ class IMAPMailbox end def set_folder(folder_name) - if folder_name.downcase != @selected_folder.downcase - @imap.select(folder_name) - @selected_folder = folder_name + begin + if folder_name != @sfolder + @imap.select(folder_name) + @sfolder = folder_name + end + rescue Exception => e + raise e end end - def status(folder_name) - @imap.status(folder_name, ["MESSAGES", "RECENT", "UNSEEN"]) + def status + begin + @imap.status(@sfolder, ["MESSAGES", "RECENT", "UNSEEN"]) + rescue Exception => e + raise e + end end - def fetch_body(folder_name,uid) - uid_fetch(folder_name,uid,"BODY[]").first.attr["BODY[]"] + def fetch_body(uid) + begin + uid_fetch(uid,"BODY[]").first.attr["BODY[]"] + rescue Exception => e + raise e + end + end + + def delete_message(uid) + begin + @imap.uid_store(uid.to_i, "+FLAGS", :Deleted) + rescue Exception => e + raise e + end + end + + def expunge + begin + @imap.expunge + rescue Exception => e + raise e + end + end + + def set_read(uid) + begin + @imap.uid_store(uid.to_i, "+FLAGS", :Seen) + rescue Exception => e + raise e + end + end + + def set_unread(uid) + begin + @imap.uid_store(uid.to_i, "-FLAGS", :Seen) + rescue Exception => e + raise e + end + end + + def copy_message(uid,dest_folder) + begin + @imap.uid_copy(uid.to_i, dest_folder) + rescue Exception => e + raise e + end + end + + def move_message(uid,dest_folder) + begin + copy_message(uid,dest_folder) + delete_message(uid) + rescue Exception => e + raise e + end end end diff --git a/lib/imap_message.rb b/lib/imap_message.rb index f62e137..d72f1f2 100755 --- a/lib/imap_message.rb +++ b/lib/imap_message.rb @@ -43,5 +43,42 @@ class IMAPAddress end +class IMAPMessage + + @@fetch_attr = ['ENVELOPE','BODYSTRUCTURE', '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.to = envelope.to + 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 + end + + def self.fetch_attr + @@fetch_attr + end + + def from_to_db + from.to_db + end + +end + + end diff --git a/lib/imap_session.rb b/lib/imap_session.rb index d299823..4e5042a 100755 --- a/lib/imap_session.rb +++ b/lib/imap_session.rb @@ -18,4 +18,8 @@ def close_imap_session @mailbox = nil end +def select_imap_folder + @mailbox.set_folder(@current_folder.full_name) if not @current_folder.nil? +end + end diff --git a/test/fixtures/contacts.yml b/test/fixtures/contacts.yml new file mode 100755 index 0000000..8c98048 --- /dev/null +++ b/test/fixtures/contacts.yml @@ -0,0 +1,15 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + nick: MyString + mail: MyString + fname: MyString + lname: MyString + info: MyString + +two: + nick: MyString + mail: MyString + fname: MyString + lname: MyString + info: MyString diff --git a/test/unit/contact_test.rb b/test/unit/contact_test.rb new file mode 100755 index 0000000..ee7d2ca --- /dev/null +++ b/test/unit/contact_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class ContactTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/themes/olive/javascripts/mailr.js b/themes/olive/javascripts/mailr.js new file mode 100755 index 0000000..feb8cd5 --- /dev/null +++ b/themes/olive/javascripts/mailr.js @@ -0,0 +1,16 @@ + +function toggleCheckBoxes(formName){ + + // toggle Check Boxes using Prototype Library + var form=$(formName); + var i=form.getElements('checkbox'); + i.each(function(item) + { + item.checked = !item.checked; + + } + ); + // set our toggle box + $('togglechkbox').checked = !$('togglechkbox').checked; + +} diff --git a/themes/olive/stylesheets/base.css b/themes/olive/stylesheets/base.css index d0a0439..53eec45 100755 --- a/themes/olive/stylesheets/base.css +++ b/themes/olive/stylesheets/base.css @@ -110,7 +110,7 @@ body { } #main .block .content .inner { - padding: 0 15px 15px; + padding: 5px; } #main .main p.first { @@ -243,7 +243,7 @@ input.checkbox { } .form div.right { - width: 75%; + width: 70%; float: right; } diff --git a/themes/olive/stylesheets/style.css b/themes/olive/stylesheets/style.css index 6d8229d..1905386 100755 --- a/themes/olive/stylesheets/style.css +++ b/themes/olive/stylesheets/style.css @@ -25,6 +25,9 @@ } a:link, a:visited, a:hover, a:active, h1, h2, h3 { color: #A3AB74; } + +#sidebar ul li.selected a { color: #5E634E; } + a { -moz-outline: none; } body { @@ -365,6 +368,79 @@ input,select { color: grey; } -tr.unread td { +tr.unseen td { font-weight:bold; } + +div.ops { + border: 1px solid #DACF77; + padding: 5px; + margin: 3px 0; +} + +div.actions-bar div.header_info { + float: left; + color: #5E634E; + font-size: 22px; + margin: 0 10px; + font-weight: normal; +} + +div.actions-bar div.header_info .other_info { + font-size: 12px; +} + +th a.header { + color: white; +} + +ul.navigation { + color: #A3AB74; +} + +ul.folders { + font-size: 14px; +} + +li.selected { + color: #5E634E; + font-weight: bold; +} + +div.param_group { + margin: 5px 0; + font-size: 14px; + padding: 3px 0; +} + +div.param_group label.label { + margin-right: 5px; +} + +div.params { + margin-bottom: 15px; +} + +div.params div.group { + margin-bottom:5px; +} + +div.params div.group div.fieldWithErrors label.label { + font-weight: bold; + font-size: 14px; +} + +div.params input.text_field, div.params textarea.text_area { + width: 100%; + border:1px solid #CFCFCF; +} + +div.params div.group .description { + font-style: italic; + color: #8C8C8C; + font-size: .9em; +} + +div.params div.group .fieldWithErrors .error { + color: red; +} diff --git a/themes/olive/views/contacts/_left.html.erb b/themes/olive/views/contacts/_left.html.erb new file mode 100755 index 0000000..bb434a6 --- /dev/null +++ b/themes/olive/views/contacts/_left.html.erb @@ -0,0 +1,9 @@ + +
+<%= raw form_field(@contact,"nick",nil,"joe"+', '+t(:must_be_unique),@contact.nick) %> +<%= raw form_field(@contact,"first_name",nil,"Joe",@contact.first_name) %> +<%= raw form_field(@contact,"last_name",nil,"Doe",@contact.last_name) %> +<%= raw form_field(@contact,"email",nil,"joe.doe@domain.com",@contact.email) %> +<%= raw form_field(@contact,"info",nil,t(:some_add_info),@contact.info) %> +
+<%= raw form_button('save','tick.png') %> diff --git a/themes/olive/views/contacts/_list.html.erb b/themes/olive/views/contacts/_list.html.erb new file mode 100755 index 0000000..40324c0 --- /dev/null +++ b/themes/olive/views/contacts/_list.html.erb @@ -0,0 +1,31 @@ + +
+ +
+ <%= t(:total_entries,:scope=>:contact) %>: <%= @contacts.total_entries %> / <%= link_to t(:create_new,:scope=>:contact), new_contact_path %> +
+ <%= will_paginate @contacts %> +
+ + + + + + <%= raw contacts_table_header %> + + + <% trclass = :even %> + <% @contacts.each do |c| %> + + <%= render :partial => 'contacts/row', :object => c %> + + <% trclass == :even ? trclass = :odd : trclass = :even %> + <% end %> + +
+ +
+ <%= will_paginate @contacts %> +
+ +
diff --git a/themes/olive/views/contacts/_ops.html.erb b/themes/olive/views/contacts/_ops.html.erb new file mode 100755 index 0000000..d9b1a34 --- /dev/null +++ b/themes/olive/views/contacts/_ops.html.erb @@ -0,0 +1,6 @@ +
+

+ <%= submit_tag(t(:compose_to_selected,:scope => :contact), :name=> 'compose')%> + <%= submit_tag(t(:delete_selected,:scope => :contact), :name=>'delete')%> +

+
diff --git a/themes/olive/views/contacts/_right.html.erb b/themes/olive/views/contacts/_right.html.erb new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/themes/olive/views/contacts/_right.html.erb @@ -0,0 +1 @@ + diff --git a/themes/olive/views/contacts/_row.html.erb b/themes/olive/views/contacts/_row.html.erb new file mode 100755 index 0000000..a219657 --- /dev/null +++ b/themes/olive/views/contacts/_row.html.erb @@ -0,0 +1,7 @@ +<%= check_box_tag "cids[]", row.id %> +<%= link_to row.nick,edit_contact_path(row) %> +<%= row.first_name %> +<%= row.last_name %> +<%= link_to row.email, {:controller => 'messages',:action => 'compose' , :cids => row.id.to_a} %> +<%= row.info %> + diff --git a/themes/olive/views/contacts/edit.html.erb b/themes/olive/views/contacts/edit.html.erb new file mode 100755 index 0000000..17c279e --- /dev/null +++ b/themes/olive/views/contacts/edit.html.erb @@ -0,0 +1,30 @@ +<% content_for :sidebar do %> +<%= render :partial => 'folders/list' %> +<% end %> + +<% content_for :title do %> +- <%= t(:contacts,:scope=>:contact) %> +<% end %> + +
+
+ <%= raw main_navigation(:contacts) %> +
+
+
+
+
<%= t(:modifying,:scope=>:contact) %>
+
+ <%= form_for(@contact) do |f| %> +
+
+ <%= render :partial => 'left' %> +
+
+ <%= render :partial => 'right' %> +
+
+ <% end %> +
+
+
diff --git a/themes/olive/views/contacts/index.html.erb b/themes/olive/views/contacts/index.html.erb index e19d127..2bd8fbc 100755 --- a/themes/olive/views/contacts/index.html.erb +++ b/themes/olive/views/contacts/index.html.erb @@ -3,7 +3,7 @@ <% end %> <% content_for :title do %> -- <%= t(:contacts) %> +- <%= t(:contacts,:scope=>:contact) %> <% end %>
@@ -11,8 +11,19 @@ <%= raw main_navigation(:contacts) %>
- <%= form_tag({:controller=>'messages', :action=>'ops'})%> + <%= form_tag(contacts_ops_path,{:name=>'contacts'})%> + + <% if @contacts.size.zero? %> +
+
<%= t(:no_entries,:scope=>:contact) %> + <%= content_tag(:span, link_to(raw('('+t(:create_new,:scope=>:contact)+')'),new_contact_path),:class=>"other_info") %> +
+ <% else %> + <%= render :partial => 'ops' %> + <%= render :partial => 'list' %> + <% end %>
+ diff --git a/themes/olive/views/contacts/new.html.erb b/themes/olive/views/contacts/new.html.erb new file mode 100755 index 0000000..a6cd57d --- /dev/null +++ b/themes/olive/views/contacts/new.html.erb @@ -0,0 +1,30 @@ +<% content_for :sidebar do %> +<%= render :partial => 'folders/list' %> +<% end %> + +<% content_for :title do %> +- <%= t(:contacts,:scope=>:contact) %> +<% end %> + +
+
+ <%= raw main_navigation(:contacts) %> +
+
+
+
+
<%= t(:creating_new,:scope=>:contact) %>
+
+ <%= form_for(@contact) do |f| %> +
+
+ <%= render :partial => 'left' %> +
+
+ <%= render :partial => 'right' %> +
+
+ <% end %> +
+
+
diff --git a/themes/olive/views/folders/_list.html.erb b/themes/olive/views/folders/_list.html.erb index 6e8e22b..c3078c1 100755 --- a/themes/olive/views/folders/_list.html.erb +++ b/themes/olive/views/folders/_list.html.erb @@ -1,13 +1,13 @@
-

<%=t (:folders) %> <%= link_to t(:refresh), {:controller => 'messages', :action => 'refresh'}, :class=>'minor' %>

+

<%=t(:folders,:scope=>:folder) %> <%= link_to t(:refresh), messages_refresh_path, :class=>'minor' %>

<% if @folders_shown.size.zero? %> -

<%= t(:no_folders_shown) %>

+

<%= t(:no_shown,:scope=>:folder) %>

<% else %> -
diff --git a/themes/olive/views/folders/index.html.erb b/themes/olive/views/folders/index.html.erb index 8c5c14a..64a8511 100755 --- a/themes/olive/views/folders/index.html.erb +++ b/themes/olive/views/folders/index.html.erb @@ -3,7 +3,7 @@ <% end %> <% content_for :title do %> -- <%= t(:folders) %> +- <%= t(:folders,:scope=>:folder) %> <% end %>
@@ -14,23 +14,23 @@
- <%= form_tag({:controller=>'folders',:action=>'create'},:class=>'form') %> - <%= raw select_for_folders("","parent_folder",@folders,t(:parent_folder),true) %> - <%= raw simple_input_field("folder",t(:folder_to_create),"") %> - <%= raw form_button(t(:create),'tick.png') %> + <%= form_tag(folders_create_path,:class=>'form') %> + <%= raw select_for_folders("","parent_folder",@folders,t(:parent,:scope=>:folder),true) %> + <%= raw simple_input_field("folder",t(:to_create,:scope=>:folder),"") %> + <%= raw form_button('create','tick.png') %> - <%= form_tag({:controller=>'folders',:action=>'delete'},:class=>'form') %> - <%= raw select_for_folders("","folder",@folders,t(:folder_to_delete),true) %> - <%= raw form_button(t(:delete),'cross.png') %> + <%= form_tag(folders_delete_path,:class=>'form') %> + <%= raw select_for_folders("","folder",@folders,t(:to_delete,:scope=>:folder),true) %> + <%= raw form_button('delete','cross.png') %>
- <%= form_tag({:controller=>'folders',:action=>'refresh'},:class=>'form') %> - <%= raw form_button(t(:refresh_folders),'tick.png') %> + <%= form_tag(folders_refresh_path,:class=>'form') %> + <%= raw form_button('refresh','tick.png') %> - <%= form_tag({:controller=>'folders',:action=>'show_hide'},:class=>'form') %> - <%= raw multi_select("", 'folders_to_show[]', @folders, @folders_shown,t(:folders_shown),:id,"",{:text => [:parent,:delim,:name]}) %> - <%= raw form_button(t(:show_hide),'tick.png') %> + <%= form_tag(folders_show_hide_path,:class=>'form') %> + <%= raw multi_select("", 'folders_to_show[]', @folders, @folders_shown,t(:shown,:scope=>:folder),:id,"",{:text => [:parent,:delim,:name]}) %> + <%= raw form_button('show_hide','tick.png') %>
diff --git a/themes/olive/views/layouts/application.html.erb b/themes/olive/views/layouts/application.html.erb index d0a257b..3501360 100755 --- a/themes/olive/views/layouts/application.html.erb +++ b/themes/olive/views/layouts/application.html.erb @@ -13,6 +13,7 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" <%=stylesheet_link_tag current_theme_stylesheet_path('style') %> <%=javascript_include_tag :defaults %> + <%=javascript_include_tag current_theme_javascript_path('mailr') %> diff --git a/themes/olive/views/messages/_list.html.erb b/themes/olive/views/messages/_list.html.erb index 4c09fab..82b29b2 100755 --- a/themes/olive/views/messages/_list.html.erb +++ b/themes/olive/views/messages/_list.html.erb @@ -1,35 +1,30 @@
-<% WillPaginate::ViewHelpers.pagination_options[:previous_label] = t(:previous_page) %> -<% WillPaginate::ViewHelpers.pagination_options[:next_label] = t(:next_page) %> -
+
<%= t(:current,:scope=>:folder) %>: <%= pretty_folder_name(@current_folder) %> + (<%= t(:total,:scope=>:message) %>: <%= @messages.total_entries %>) +
<%= will_paginate @messages %>
-
- + - - - - + <%= raw headers_links %> <% trclass = :even %> <% @messages.each do |m| %> - <% m.unread == true ? unread = "unread" : unread = "" %> - + <% m.unseen == true ? unseen = "unseen" : unseen = "" %> + <%= render :partial => 'messages/row', :object => m %> <% trclass == :even ? trclass = :odd : trclass = :even %> <% end %>
<%= raw(' ') %><%= t(:from) %><%= t(:subject) %><%= t(:date) %><%= t(:size) %>
-
<%= will_paginate @messages %> diff --git a/themes/olive/views/messages/_ops.html.erb b/themes/olive/views/messages/_ops.html.erb index 3293480..0b0d547 100755 --- a/themes/olive/views/messages/_ops.html.erb +++ b/themes/olive/views/messages/_ops.html.erb @@ -1,15 +1,14 @@ -
+

- <%= submit_tag(t(:copy), :name=> 'op')%> - <%= submit_tag(t(:move), :name=>'op')%> - <%= t :marked_messages %> - <%= t :to_folder %> - <%= raw select_for_folders("","parent_folder",@folders_shown,t(:parent_folder),true) %> -

-

- <%= t :marked_messages %> - <%= submit_tag(t(:delete), :name=>'op')%> - <%= submit_tag(t(:mark_read), :name=>'op')%> - <%= submit_tag(t(:mark_unread), :name=>'op')%> + <%= submit_tag(t(:copy), :name=> 'copy')%> + <%= submit_tag(t(:move), :name=>'move')%> + <%= t(:checked,:scope=>:message) %> + <%= t(:to_folder,:scope=>:folder) %> + <%= raw simple_select_for_folders("","dest_folder",@folders_shown,true) %> +
+ <%= submit_tag(t(:delete), :name=>'trash')%> + <%= submit_tag(t(:set_read,:scope=>:message), :name=>'set_read')%> + <%= submit_tag(t(:set_unread,:scope=>:message), :name=>'set_unread')%> + <%= t(:checked,:scope=>:message) %>

diff --git a/themes/olive/views/messages/_row.html.erb b/themes/olive/views/messages/_row.html.erb index 8861d12..55bcbea 100755 --- a/themes/olive/views/messages/_row.html.erb +++ b/themes/olive/views/messages/_row.html.erb @@ -1,6 +1,6 @@ <%= check_box_tag "uids[]", row.uid %> <%= attachment_formatter(row) %> -<%= address_formatter(row.from) %> +<%= address_formatter(row.from_addr) %> <%= subject_formatter(row) %> <%= date_formatter(row.date) %> <%= size_formatter(row.size) %><%= raw(' ') %> diff --git a/themes/olive/views/messages/_search.html.erb b/themes/olive/views/messages/_search.html.erb index bcbd6f4..cee5c10 100755 --- a/themes/olive/views/messages/_search.html.erb +++ b/themes/olive/views/messages/_search.html.erb @@ -1,7 +1,10 @@ + diff --git a/themes/olive/views/messages/compose.html.erb b/themes/olive/views/messages/compose.html.erb index 12e8795..6d6bd45 100755 --- a/themes/olive/views/messages/compose.html.erb +++ b/themes/olive/views/messages/compose.html.erb @@ -3,15 +3,15 @@ <% end %> <% content_for :title do %> -- <%= t(:compose) %> +- <%= t(:compose,:scope=>:compose) %> <% end %>
<%= raw main_navigation(:compose) %>
-
- <%= form_tag({:controller=>'messages', :action=>'ops'})%> +
<%= params.inspect %> + <%= form_tag(messages_ops_path)%>
diff --git a/themes/olive/views/messages/index.html.erb b/themes/olive/views/messages/index.html.erb index f5a296a..dcdc886 100755 --- a/themes/olive/views/messages/index.html.erb +++ b/themes/olive/views/messages/index.html.erb @@ -3,7 +3,7 @@ <% end %> <% content_for :title do %> -- <%= t(:messages) %> +- <%= t(:messages,:scope=>:message) %> <% end %>
@@ -11,22 +11,18 @@ <%= raw main_navigation(:messages) %>
- <%= form_tag({:controller=>'messages', :action=>'ops'})%> - - <% #render :partial => 'search' %> - <%= render :partial => 'ops' %> - - <%= raw form_button(t(:ops),'tick.png') %> + <%= form_tag({:controller=>'messages', :action=>'ops'},{:name=>'messages'})%> <% if @current_folder.nil? %> -

<%= t(:no_folder_selected) %>

- <% else %> -

<%= t(:current) %>: <%= pretty_folder_name(@current_folder) %>

+

<%= t(:no_selected,:scope=>:folder) %>

<% end %> <% if @messages.size.zero? %> - <%= t(:no_messages) %> +
+
<%= t(:no_in,:scope=>:message) %>
+
<% else %> + <%= render :partial => 'ops' %> <%= render :partial => 'list' %> <% end %> diff --git a/themes/olive/views/prefs/_left.html.erb b/themes/olive/views/prefs/_left.html.erb new file mode 100755 index 0000000..94505fe --- /dev/null +++ b/themes/olive/views/prefs/_left.html.erb @@ -0,0 +1,8 @@ + +
+<%= raw select_field_table(@prefs, "msgs_per_page", $defaults["msgs_per_page_table"],@prefs.msgs_per_page,false) %> +<%= raw select_field_table(@prefs, "theme", $defaults["themes"],@prefs.theme,false) %> +<%= raw select_field_table(@prefs, "locale", $defaults["locales"],@prefs.locale,false) %> +<%= raw select_field_table(@prefs, "msg_send_type", $defaults["msg_send_type"],@prefs.msg_send_type,false) %> +
+<%= raw form_button('save','tick.png') %> diff --git a/themes/olive/views/prefs/_right.html.erb b/themes/olive/views/prefs/_right.html.erb new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/themes/olive/views/prefs/_right.html.erb @@ -0,0 +1 @@ + diff --git a/themes/olive/views/prefs/index.html.erb b/themes/olive/views/prefs/index.html.erb index ce76fec..478b69c 100755 --- a/themes/olive/views/prefs/index.html.erb +++ b/themes/olive/views/prefs/index.html.erb @@ -3,7 +3,7 @@ <% end %> <% content_for :title do %> -- <%= t(:preferences) %> +- <%= t(:prefs,:scope=>:prefs) %> <% end %>
@@ -11,10 +11,15 @@ <%= raw main_navigation(:prefs) %>
- <%= form_tag({:controller=>'messages', :action=>'ops'})%> - - - <%= @prefs.inspect %> - +
<%= form_tag(prefs_update_path,:name=>'prefs') %> +
+
+ <%= render :partial => 'prefs/left' %> +
+
+ <%= render :partial => 'prefs/right' %> +
+
+
diff --git a/themes/olive/views/user/login.html.erb b/themes/olive/views/user/login.html.erb index b28867c..2a839d9 100755 --- a/themes/olive/views/user/login.html.erb +++ b/themes/olive/views/user/login.html.erb @@ -1,12 +1,12 @@ <% content_for :title do %> - <%= t(:please_login) %> + <%= t(:login,:scope=>:user) %> <% end %>
-

<%= t(:please_login) %>

+

<%= t(:login,:scope=>:user) %>