new stuff

This commit is contained in:
Wojciech Todryk 2011-08-02 23:12:17 +02:00
parent 65472c55cc
commit 68b925ea5e
29 changed files with 368 additions and 33 deletions

View file

@ -8,9 +8,10 @@ gem 'rails', '3.0.7'
#gem 'sqlite3-ruby',:require => 'sqlite3' #gem 'sqlite3-ruby',:require => 'sqlite3'
gem 'arel' gem 'arel'
gem 'mysql2' , '0.2.7' gem 'mysql2' , '0.2.7'
gem 'will_paginate' gem 'will_paginate', '~> 3.0.beta'
gem 'themes_for_rails' gem 'themes_for_rails'
gem "ezcrypto", "~> 0.7.2" gem "ezcrypto", "~> 0.7.2"
gem "mail"
#gem 'tmail' #gem 'tmail'
# Use unicorn as the web server # Use unicorn as the web server

View file

@ -66,7 +66,7 @@ GEM
treetop (1.4.9) treetop (1.4.9)
polyglot (>= 0.3.1) polyglot (>= 0.3.1)
tzinfo (0.3.29) tzinfo (0.3.29)
will_paginate (2.3.15) will_paginate (3.0.pre4)
PLATFORMS PLATFORMS
ruby ruby
@ -74,7 +74,8 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
arel arel
ezcrypto (~> 0.7.2) ezcrypto (~> 0.7.2)
mail
mysql2 (= 0.2.7) mysql2 (= 0.2.7)
rails (= 3.0.7) rails (= 3.0.7)
themes_for_rails themes_for_rails
will_paginate will_paginate (~> 3.0.beta)

View file

@ -2,9 +2,16 @@ require 'yaml'
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
#unless config.consider_all_requests_local
# #rescue_from ActionController::RoutingError, :with => :route_not_found
# rescue_from ActiveRecord::RecordNotFound, :with => :route_not_found
#end
protect_from_forgery protect_from_forgery
before_filter :load_defaults,:set_locale,:current_user before_filter :load_defaults,:set_locale,:current_user
################################# protected section ###########################################
protected protected
def load_defaults def load_defaults
@ -48,4 +55,12 @@ class ApplicationController < ActionController::Base
@current_folder = @current_user.folders.current(@selected_folder) @current_folder = @current_user.folders.current(@selected_folder)
end end
##################################### private section ##########################################
#private
#def route_not_found
# render :text => 'What the fuck are you looking for ?', :status => :not_found
#end
end end

View file

@ -81,9 +81,10 @@ class FoldersController < ApplicationController
def refresh def refresh
Folder.refresh(@mailbox,@current_user) Folder.refresh(@mailbox,@current_user)
if params[:flash] flash.keep
flash[params[:type]] = params[:flash] #if params[:flash]
end # flash[params[:type]] = params[:flash]
#end
redirect_to :action => 'index' redirect_to :action => 'index'
end end

View file

@ -4,9 +4,7 @@ class InternalController < ApplicationController
layout "simple" layout "simple"
def error def error
@title = params[:title] || t(:general_error)
@error = params[:error] || t(:unspecified_error)
logger.error "!!! InternalControllerError: " + @error
end end
def imaperror def imaperror
@ -16,6 +14,13 @@ class InternalController < ApplicationController
render 'error' render 'error'
end end
def page_not_found
@title = t(:page_not_found)
@error = t(:page_not_found)
logger.error "!!! InternalControllerError: " + @error
render 'error'
end
def loginfailure def loginfailure
reset_session reset_session
flash[:error] = t(:login_failure) flash[:error] = t(:login_failure)

View file

@ -1,22 +1,85 @@
require 'imap_session' require 'imap_session'
require 'imap_mailbox' require 'imap_mailbox'
require 'imap_message'
class MessagesController < ApplicationController class MessagesController < ApplicationController
include ImapMailboxModule include ImapMailboxModule
include ImapSessionModule include ImapSessionModule
include ImapMessageModule
include MessagesHelper
before_filter :check_current_user ,:selected_folder before_filter :check_current_user ,:selected_folder
before_filter :get_current_folders, :only => [:index,:compose] before_filter :get_current_folders, :only => [:index,:compose,:show]
before_filter :open_imap_session, :only => :refresh before_filter :open_imap_session, :only => :refresh
after_filter :close_imap_session, :only => :refresh after_filter :close_imap_session, :only => :refresh
theme :theme_resolver theme :theme_resolver
@@fetch_attr = ['ENVELOPE','BODYSTRUCTURE', 'FLAGS', 'UID', 'RFC822.SIZE']
def index def index
flash[:notice] = 'Not implemented yet'
open_imap_session
####################
@messages = []
folder_status = @mailbox.status(@current_folder.full_name)
@current_folder.update_attributes(:messages => folder_status['MESSAGES'], :unseen => folder_status['UNSEEN'])
if folder_status['MESSAGES'].zero?
return
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)
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)
end
end
@messages = Message.getPageForUser(@current_user,params['page'])
###############
close_imap_session
end end
def folder def folder
@ -32,4 +95,17 @@ class MessagesController < ApplicationController
redirect_to :action => 'index' redirect_to :action => 'index'
end end
def ops
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
end
end end

View file

@ -8,6 +8,8 @@ class PrefsController < ApplicationController
def index def index
flash[:notice] = 'Not implemented yet' flash[:notice] = 'Not implemented yet'
@prefs = @current_user.prefs
end end
end end

View file

@ -1,4 +1,33 @@
module MessagesHelper module MessagesHelper
def size_formatter(size)
if size <= 2**10
"#{size} #{t(:bytes)}"
elsif size <= 2**20
sprintf("%.1f #{t(:kbytes)}",size.to_f/2**10)
else
sprintf("%.1f #{t(:mbytes)}",size.to_f/2**20)
end
end
def date_formatter(date)
date.strftime("%Y-%m-%d %H:%M")
end
def address_formatter(addr)
ImapMessageModule::IMAPAddress.parse(addr).friendly
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
link_to s,:controller => 'messages', :action => 'show', :id => message.id
end
def attachment_formatter(message)
message.content_type == 'text' ? "" : "A"
end
end end

View file

@ -1,2 +1,13 @@
class Message < ActiveRecord::Base class Message < ActiveRecord::Base
belongs_to :user
#cattr_reader :per_page
#@@per_page = $defaults["msgs_per_page"]
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
Message.paginate :page => page , :per_page => 50, :conditions=> ['user_id = ?', user.id],:order => order
end
end end

View file

@ -7,6 +7,7 @@ class User < ActiveRecord::Base
has_many :servers, :dependent => :destroy has_many :servers, :dependent => :destroy
has_one :prefs, :dependent => :destroy has_one :prefs, :dependent => :destroy
has_many :folders, :dependent => :destroy has_many :folders, :dependent => :destroy
has_many :messages, :dependent => :destroy
def set_cached_password(session,password) def set_cached_password(session,password)
if $defaults['session_encryption'] if $defaults['session_encryption']

View file

@ -40,3 +40,12 @@ module Mailr
config.filter_parameters += [:password] config.filter_parameters += [:password]
end end
end end
class ActiveSupport::BufferedLogger
def custom(desc,t)
info "\n**** #{desc} *****"
info t
info "**********************\n\n"
end
end

View file

@ -3,13 +3,17 @@ locale: en
msgs_per_page: 20 msgs_per_page: 20
msgs_refresh_time: 300 msgs_refresh_time: 300
msg_send_type: html msgs_send_type: html
msgs_update_time: 300
msg_subject_length: 45
imap_debug: true imap_debug: true
imap_use_ssl: 'false' imap_use_ssl: 'false'
imap_port: 143 imap_port: 143
imap_ssl_port: 993 imap_ssl_port: 993
imap_bye_timeout_retry_seconds: 2 imap_bye_timeout_retry_seconds: 2
imap_fetch_slice: 20
session_encryption: true session_encryption: true
session_password: asDD3s2@sAdc983# session_password: asDD3s2@sAdc983#

View file

@ -3,3 +3,4 @@ require File.expand_path('../application', __FILE__)
# Initialize the rails application # Initialize the rails application
Mailr::Application.initialize! Mailr::Application.initialize!

View file

@ -10,7 +10,7 @@ Mailr::Application.configure do
config.whiny_nils = true config.whiny_nils = true
# Show full error reports and disable caching # Show full error reports and disable caching
config.consider_all_requests_local = true config.consider_all_requests_local = false
config.action_view.debug_rjs = true config.action_view.debug_rjs = true
config.action_controller.perform_caching = false config.action_controller.perform_caching = false

View file

@ -94,3 +94,9 @@ en:
system_folder: System folder system_folder: System folder
refresh_folders: Refresh folders refresh_folders: Refresh folders
show_hide: Show/Hide show_hide: Show/Hide
page_not_found: Page not found
bytes: Bytes
kbytes: Kb
mbytes: MB
previous_page: Previous page
next_page: Next page

View file

@ -22,6 +22,7 @@ Mailr::Application.routes.draw do
post "messages/ops" post "messages/ops"
get "messages/compose" get "messages/compose"
get "messages/refresh" get "messages/refresh"
match "messages/show/:id" => 'messages#show'
get "user/logout" get "user/logout"
post "user/authenticate" post "user/authenticate"
@ -33,6 +34,8 @@ Mailr::Application.routes.draw do
themes_for_rails themes_for_rails
match '*a', :to => 'internal#page_not_found'
# The priority is based upon order of creation: # The priority is based upon order of creation:
# first created -> highest priority. # first created -> highest priority.

0
db/migrate/20110731185416_add_shown_to_folders.rb Normal file → Executable file
View file

View file

@ -30,7 +30,7 @@ class IMAPMailbox
@imap = Net::IMAP.new(server_name, server_port, server_use_ssl) @imap = Net::IMAP.new(server_name, server_port, server_use_ssl)
rescue Net::IMAP::ByeResponseError => bye rescue Net::IMAP::ByeResponseError => bye
begin begin
System.sleep($defaults['imap_bye_timeout_retry_seconds']) System.sleep($defaults["imap_bye_timeout_retry_seconds"])
@imap = Net::IMAP.new(server_name, server_port, server_use_ssl) @imap = Net::IMAP.new(server_name, server_port, server_use_ssl)
rescue Exception => ex rescue Exception => ex
raise IMAPError, ex.inspect raise IMAPError, ex.inspect
@ -87,6 +87,40 @@ class IMAPMailbox
raise e raise e
end end
end end
def fetch(folder_name,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)
begin
set_folder(folder_name)
@imap.uid_fetch(range,attribs)
rescue Exception => e
raise e
end
end
def set_folder(folder_name)
if folder_name.downcase != @selected_folder.downcase
@imap.select(folder_name)
@selected_folder = folder_name
end
end
def status(folder_name)
@imap.status(folder_name, ["MESSAGES", "RECENT", "UNSEEN"])
end
def fetch_body(folder_name,uid)
uid_fetch(folder_name,uid,"BODY[]").first.attr["BODY[]"]
end
end end
end end

View file

@ -1,5 +1,47 @@
require 'net/imap' require 'net/imap'
module ImapMessageModule module ImapMessageModule
class IMAPAddress
attr_accessor :name,:mailbox,:host
def initialize()
name = ""
mailbox = ""
host = ""
end
def self.from_address(addr)
a = IMAPAddress.new()
a.name = addr.name || ""
a.mailbox = addr.mailbox || ""
a.host = addr.host || ""
a
end
def to_db
name + "#" + mailbox + "#" + host
end
def self.parse(addr)
a = IMAPAddress.new()
f = addr.split("#")
a.name = f[0]
a.mailbox = f[1]
a.host = f[2]
a
end
def friendly
if name.empty?
mailbox + host
else
name
end
end
end
end end

2
lib/tasks/clear_db.rake Normal file → Executable file
View file

@ -1,5 +1,5 @@
namespace :db do namespace :db do
desc "Clears all date in db" desc "Clears all data in db"
task :clear_data => :environment do task :clear_data => :environment do
users = User.all users = User.all
puts "Number of users in db: #{users.size}" puts "Number of users in db: #{users.size}"

View file

@ -218,7 +218,8 @@ body {
} }
.table td { .table td {
padding: 5px; padding: 2px 10px;
color: #5E634E;
} }
.table td.last { .table td.last {

View file

@ -365,3 +365,6 @@ input,select {
color: grey; color: grey;
} }
tr.unread td {
font-weight:bold;
}

View file

@ -0,0 +1,38 @@
<div class="inner">
<% WillPaginate::ViewHelpers.pagination_options[:previous_label] = t(:previous_page) %>
<% WillPaginate::ViewHelpers.pagination_options[:next_label] = t(:next_page) %>
<div class="actions-bar wat-cf">
<%= will_paginate @messages %>
</div>
<form>
<table class="table">
<tbody>
<tr>
<th class="first"><input class="checkbox toggle" type="checkbox"></th>
<th><%= raw('&nbsp;') %></th>
<th><%= t(:from) %></th>
<th><%= t(:subject) %></th>
<th><%= t(:date) %></th>
<th><%= t(:size) %></th>
<th class="last"></th>
</tr>
<% trclass = :even %>
<% @messages.each do |m| %>
<% m.unread == true ? unread = "unread" : unread = "" %>
<tr class="<%= trclass.to_s %> <%= unread %>">
<%= render :partial => 'messages/row', :object => m %>
</tr>
<% trclass == :even ? trclass = :odd : trclass = :even %>
<% end %>
</tbody>
</table>
</form>
<div class="actions-bar wat-cf">
<%= will_paginate @messages %>
</div>
</div>

View file

@ -0,0 +1,15 @@
<div id="ops">
<p>
<%= 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) %>
</p>
<p>
<%= t :marked_messages %>
<%= submit_tag(t(:delete), :name=>'op')%>
<%= submit_tag(t(:mark_read), :name=>'op')%>
<%= submit_tag(t(:mark_unread), :name=>'op')%>
</p>
</div>

View file

@ -0,0 +1,6 @@
<td><%= check_box_tag "uids[]", row.uid %></td>
<td><%= attachment_formatter(row) %></td>
<td nowrap="nowrap"><%= address_formatter(row.from) %></td>
<td nowrap="nowrap"><%= subject_formatter(row) %></td>
<td nowrap="nowrap"><%= date_formatter(row.date) %></td>
</td><td nowrap="nowrap"><%= size_formatter(row.size) %></td><td><%= raw('&nbsp;') %>

View file

@ -0,0 +1,7 @@
<p>
<%= t :message_field %>
<select name="search_field">
<%= options_for_select(CDF::CONFIG[:mail_search_fields], @search_field)%>
</select> <label for="search_value"> <%= t :search_txt %>
</label> <input type="text" name="search_value" value="<%=@search_value%>" size='16' id='search_value'/> <%= submit_tag(t(:search), :name=>'op')%> <%= submit_tag(t(:show_all), :name=>'op')%>
</p>

View file

@ -13,21 +13,24 @@
<div class="content"> <div class="content">
<%= form_tag({:controller=>'messages', :action=>'ops'})%> <%= form_tag({:controller=>'messages', :action=>'ops'})%>
</form> <% #render :partial => 'search' %>
<%= render :partial => 'ops' %>
<%= raw form_button(t(:ops),'tick.png') %>
<% if @current_folder.nil? %> <% if @current_folder.nil? %>
<%= t(:no_folder_selected) %> <h2><%= t(:no_folder_selected) %></h2>
<% else %> <% else %>
<h2><%= t(:current) %>: <%= pretty_folder_name(@current_folder) %></h2>
<h1>Current: <%= pretty_folder_name(@current_folder) %></h1>
<%= @current_folder.inspect %>
<%= Time.now - @current_folder.msgs_updated_at %>
<% end %> <% end %>
<% if @messages.size.zero? %>
<%= t(:no_messages) %>
<% else %>
<%= render :partial => 'list' %>
<% end %>
</form>
</div> </div>
</div> </div>

View file

@ -0,0 +1,19 @@
<% content_for :sidebar do %>
<%= render :partial => 'folders/list' %>
<% end %>
<% content_for :title do %>
- <%= @message.subject %>
<% end %>
<div class="block" id="block-tables">
<div class="secondary-navigation">
<%= raw main_navigation(:show) %>
</div>
<div class="content">
<p><%= @message.inspect %></p>
<p><%= @body.inspect %></p>
</div>
</div>

View file

@ -13,6 +13,8 @@
<div class="content"> <div class="content">
<%= form_tag({:controller=>'messages', :action=>'ops'})%> <%= form_tag({:controller=>'messages', :action=>'ops'})%>
</form>
<%= @prefs.inspect %>
</div> </div>
</div> </div>