init import from old mailr project (http://svn.littlegreen.org/mailr/trunk)

This commit is contained in:
Eugene Korbut 2009-01-08 05:27:12 +10:00
commit 51b79e7298
640 changed files with 34651 additions and 0 deletions

View file

@ -0,0 +1,68 @@
require 'cdfutils'
require_association 'contact_group'
class Contact < ActiveRecord::Base
has_and_belongs_to_many :groups, :class_name => "ContactGroup", :join_table => "contact_contact_groups", :association_foreign_key => "contact_group_id", :foreign_key => "contact_id"
# Finder methods follow
def Contact.find_by_user(user_id)
find(:all, :conditions => ["customer_id = ?", user_id], :order => "fname asc", :limit => 10)
end
def Contact.find_by_user_email(user_id, email)
find(:first, :conditions => ["customer_id = #{user_id} and email = ?", email])
end
def Contact.find_by_group_user(user_id, grp_id)
result = Array.new
find(:all, :conditions => ["customer_id = ?", user_id], :order => "fname asc").each { |c|
begin
c.groups.find(grp_id)
result << c
rescue ActiveRecord::RecordNotFound
end
}
result
end
def Contact.find_by_user_letter(user_id, letter)
find_by_sql("select * from contacts where customer_id=#{user_id} and substr(UPPER(fname),1,1) = '#{letter}' order by fname")
end
def full_name
"#{fname}&nbsp;#{lname}"
end
def show_name
"#{fname} #{lname}"
end
def full_address
"#{fname} #{lname}<#{email}>"
end
protected
def validate
errors.add 'fname', _('Please enter your first name (2 to 20 characters).') unless self.fname =~ /^.{2,20}$/i
errors.add 'lname', _('Please enter your surname (2 to 20 characters).') unless self.lname =~ /^.{2,20}$/i
# Contact e-mail cannot be changed
unless self.new_record?
old_record = Contact.find(self.id)
errors.add 'email', _('Contacts email cannot be changed.') unless old_record.email == self.email
end
end
def validate_on_create
# Contact e-mail cannot be changed, so we only need to validate it on create
errors.add 'email', _('Please enter a valid email address.') unless valid_email?(self.email)
# Already existing e-mail in contacts for this user is not allowed
if self.new_record?
if Contact.find_first("email = '#{email}' and customer_id = #{customer_id}")
errors.add('email', _('An account for your email address already exists.'))
end
end
end
end

View file

@ -0,0 +1,79 @@
<h1><%=_('Edit/Create contact')%></h1>
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><span><%= _('Contacts') %></span>
<ul id="secondary">
<li><%=link_contact_list%></li>
<% if ret = @session["return_to"] %>
<li><%=link_to(_('Back to message'), ret) %></li>
<% end %>
</ul>
</li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<%=
form_tag(
link_contact_save,
'method' => 'post',
'class' => 'two_columns'
)
%>
<%= form_input(:hidden_field, 'contact', 'id') %>
<%= form_input(:hidden_field, 'contact', 'customer_id') %>
<table>
<%= form_input(:text_field, 'contact', 'fname', _('First name'), 'class'=>'two_columns') %>
<%= form_input(:text_field, 'contact', 'lname', _('Last name'), 'class'=>'two_columns') %>
<%= form_input((@contact.new_record? ? :text_field : :read_only_field), 'contact', 'email', _('E-mail'), 'class'=>'two_columns')%>
</table>
<% for group in @contactgroups %>
<input id="groups[<%=group.id%>]" type="hidden" name="groups[<%=group.id%>]" value="<%=@groups[group.id]%>">
<% end %>
<% if not(@contactgroups.empty?) %>
<%=_('Contact belong to these groups')%>:
<table class="list">
<tr>
<%
end
col = 1
for group in @contactgroups %>
<th>
<input id="groups[<%=group.id%>]" type="checkbox" name="groups[<%=group.id%>]" value="<%=@groups[group.id]%>" onclick="toggleCheckbox(this)"
<%=@groups[group.id] == 1 ? " checked " : " " %> >
&nbsp;<%=group.name %>
</th>
<% if col%2 == 0 %>
</tr>
<tr>
<% end
col = col + 1 %>
<% end %>
<% if col%2 == 0 and not(@contactgroups.empty?) %>
<th>&nbsp;</th>
<% end %>
<% if not(@contactgroups.empty?) %>
</tr>
</table>
<% end %>
<table class="edit">
<tr>
<td colspan=2 class="buttonBar">
<input type="submit" name="paction" value="<%=_('Save')%>"/>
<input type="submit" name="paction" value="<%=_('Save and add another')%>"/>
</td>
</tr>
</table>
<%= end_form_tag %>
</div>
</div>

View file

@ -0,0 +1,26 @@
<h1><%=_('Add multiple contacts')%></h1>
<% if @flash["errors"] and not @flash["errors"].empty?%>
<%= _('Errors')%>
<ul>
<% @flash["errors"].each do |message| %>
<li><%= message %>
<% end %>
</ul>
<% end %>
<form action="<%=link_import_preview%>" enctype="multipart/form-data" method="post">
<%= radio_button("contact", "file_type", "1")%> <%= _('Comma-separated (CSV) file')%>
<%= radio_button("contact", "file_type", "2")%> <%= _('Tab-delimited text file')%>
<table>
<tr>
<th><label for="contact[data]"><%=_('Select file')%></label></th>
<td><input type="file" name="contact[data]"/></td>
</tr>
<tr>
<td colspan=2>
<input type="submit" value="<%=_('Import')%>"/>
<input type="button" value="<%= _('Back to contacts')%>" onclick="window.location='<%=link_contact_list%>'">
<input type="button" value="<%= _('Back to folders')%>" onclick="window.location='<%=link_main_index%>'">
</td>
</tr>
</table>
</form>

View file

@ -0,0 +1,11 @@
<script language="javascript">
<% for to in @tos %>
respondTo("<%=to.full_address%>", "<%=to.id%>");
<% end %>
<% for cc in @ccs %>
respondCC("<%=cc.full_address%>");
<% end %>
<% for bcc in @bccs %>
respondBCC("<%=bcc.full_address%>");
<% end %>
</script>

View file

@ -0,0 +1,43 @@
<h1><%= _('Contacts You Are About To Import')%></h1>
<% if @flash["errors"] and not @flash["errors"].empty?%>
<%= _('Errors')%>
<ul>
<% @flash["errors"].each do |message| %>
<li><%= message %>
<% end %>
</ul>
<% end %>
<form action="<%=link_contact_import%>" method="post">
<table class="list">
<tr>
<th>&nbsp;</th>
<th width="100px"><%= _('First name')%></th>
<th width="100px"><%= _('Last name')%></th>
<th><%= _('E-mail')%></th>
</tr>
<%
for i in 0...@contacts.length
contact = @contacts[i]
%>
<tr class="<%= alternator %>">
<td><%=i+1%></td>
<td><input type="text" name="contact[<%=i%>][fname]" value="<%=contact.fname%>" size="15" /></td>
<td><input type="text" name="contact[<%=i%>][lname]" value="<%=contact.lname%>" size="15" /></td>
<td><input type="text" name="contact[<%=i%>][email]" value="<%=contact.email%>" size="45" /></td>
</tr>
<% end %>
<tr>
<td colspan=4 class="buttonBar">
<input type="submit" value="<%= _('Import')%>">
<input type="button" value="<%= _('Choose another file')%>" onclick="window.location='<%=link_contact_add_multiple%>'">
<input type="button" value="<%= _('Back to contacts')%>" onclick="window.location='<%=link_contact_list%>'">
<input type="button" value="<%= _('Back to folders')%>" onclick="window.location='<%=link_main_index%>'">
</td>
</tr>
</table>
</form>

View file

@ -0,0 +1,114 @@
<h1><%= _('Contacts')%></h1>
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><span><%= _('Contacts') %></span>
<ul id="secondary">
<li><%=link_contact_add_one%></li>
<li><%=link_contact_add_multiple%></li>
<% if ret = @session["return_to"] %>
<li><%=link_to(_('Back to message'), ret) %></li>
<% end %>
</ul>
</li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<% if @flash["alert"] %><ul><li><%= @flash["alert"] %></li></ul><% end %>
<form action="<%=link_contact_choose%>?mode=<%=@mode%>" method="post">
<input type="hidden" name="mode" value="<%=@mode%>"/>
<% if @group_id and not @group_id.nil? %>
<input type="hidden" name="group_id" value="<%=@group_id%>"/>
<% end %>
<table class="list">
<tr>
<td colspan="4" id="alphaListHeader">
<%
letters = CDF::CONFIG[:contact_letters]
for letterIndex in 0...letters.size
letter = letters[letterIndex] %>
<%= link_to(letter, :controller=>"contact", :action=>"listLetter", :id=>letterIndex, :params=>{"mode"=>@mode, "group_id"=>(@group_id ? @group_id : nil)}) %>
<% end %>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<%= link_to(_('Show all'), :controller=>"contact", :action=>"list", :id=>(@group_id ? @group_id : nil), :params=>{"mode"=>@mode})%>
</td>
</tr>
<tr>
<td colspan="3"><%= @contact_pages.basic_html(self, 2, false, {"mode"=>@mode}) %></td>
</tr>
<% if @mode == "choose" %>
<tr>
<th><%= _('To&nbsp;CC&nbsp;BCC')%></th>
<th><%= _('Name')%></th>
<th><%= _('E-mail')%></th>
</tr>
<% for contact in @contacts %>
<tr class="<%= alternator %>">
<td><input type="checkbox" name="contacts_to[<%=contact.id%>]" value="1"/>
<input type="checkbox" name="contacts_cc[<%=contact.id%>]" value="1"/>
<input type="checkbox" name="contacts_bcc[<%=contact.id%>]" value="1"/></td>
<td><%=contact.full_name%></td>
<td><%=contact.email%></td>
</tr>
<% end %>
<tr class="rowsep"><td colspan="3"><%=_('Groups')%>:</td></tr>
<% for group in @contactgroups %>
<tr class="<%= alternator %>">
<td><input type="checkbox" name="groups_to[<%=group.id%>]" value="1"/>
<input type="checkbox" name="groups_cc[<%=group.id%>]" value="1"/>
<input type="checkbox" name="groups_bcc[<%=group.id%>]" value="1"/></td>
<td><%=group.name%></td>
<td>&nbsp;</td>
</tr>
<% end %>
<tr>
<td colspan=3 class="buttonBar">
<input type="submit" value="<%= _('choose')%>">
<input type="button" value="<%= _('cancel')%>" onclick="javascript:window.close();">
</td>
</tr>
<% elsif @mode == "groups"%>
<tr>
<th></th>
<th width="200px"><%= _('Name')%></th>
<th><%= _('E-mail')%></th>
</tr>
<% for contact in @contacts %>
<input type="hidden" id="contacts_for_group[<%=contact.id%>]" name="contacts_for_group[<%=contact.id%>]" value="<%=@contacts_for_group[contact.id]%>" >
<tr class="<%= alternator %>">
<td><input type="checkbox" id="contacts_for_group[<%=contact.id%>]" name="contacts_for_group[<%=contact.id%>]"
value="<%=@contacts_for_group[contact.id]%>" onclick="toggleCheckbox(this)"
<%=@contacts_for_group[contact.id] == 1 ? " checked " : " " %> ></td>
<td><%=contact.full_name%></td>
<td><%=contact.email%></td>
</tr>
<% end %>
<tr>
<td colspan=2 class="buttonBar">
<input type="submit" value="<%= _('Save')%>">
<input type="button" value="<%= _('Back to groups')%>" onclick="window.location='<%=link_contact_group_list%>'">
</td>
</tr>
<% else %>
<tr>
<th width="200px"><%= _('Name')%></th>
<th><%= _('E-mail')%></th>
<th>&nbsp;</th>
</tr>
<% for contact in @contacts %>
<tr class="<%= alternator %>">
<td><%= link_to(contact.full_name, :controller=>"/contacts/contact", :action => "edit", :id => contact.id ) %></td>
<td><%= link_to( contact.email, :controller => "/webmail", :action => "compose", :params => { "mail[to]" => contact.email } ) %></td>
<td><%= link_to(_('delete'), {:controller=>'/contacts/contact', :action=>'delete', :id=>contact.id}, {:confirm=>sprintf(_('DELETE CONTACT?\r\n\Name - %s\r\nE-mail - %s'), contact.show_name, contact.email)})%></td>
</tr>
<% end %>
<% end %>
</table>
</form>
</div>
</div>

View file

@ -0,0 +1,398 @@
class Contacts::ContactController < ApplicationController
uses_component_template_root
model :customer
model :contact
model :contact_group
helper :pagination
layout :select_layout
def index
redirect_to(:action =>"list")
end
def list
@contact_pages = Paginator.new(self, Contact.count("customer_id = #{logged_user}"), CDF::CONFIG[:contacts_per_page], @params['page'])
@contacts = Contact.find(:all, :conditions=>["customer_id = #{logged_user}"], :order=>['fname'], :limit=>CDF::CONFIG[:contacts_per_page], :offset=>@contact_pages.current.offset)
if @params["mode"] == "groups"
if @params["id"] and not @params["id"].nil? and not @params["id"] == ''
@group_id = @params["id"].to_i
@contacts_for_group = Hash.new
for contact in @contacts
@contacts_for_group[contact.id] = 0 # initialize
for gr in contact.groups
if gr.contact_group_id.to_i == @group_id
@contacts_for_group[contact.id] = 1 # checked
end
end
end
end
end
end
def listLetter
letters = CDF::CONFIG[:contact_letters]
@contact_pages = Paginator.new(self, Contact.count(
["customer_id = %s and substr(UPPER(fname),1,1) = '%s'", logged_user, letters[@params['id'].to_i]]), CDF::CONFIG[:contacts_per_page], @params['page'])
@contacts = Contact.find(:all, :conditions=>["customer_id = %s and substr(UPPER(fname),1,1) = '%s'", logged_user, letters[@params['id'].to_i]],
:order=>['fname'], :limit=>CDF::CONFIG[:contacts_per_page], :offset=>@contact_pages.current.offset)
if @params["mode"] == "groups"
if @params["group_id"] and not @params["group_id"].nil? and not @params["group_id"] == ''
@group_id = @params["group_id"].to_i
@contacts_for_group = Hash.new
for contact in @contacts
@contacts_for_group[contact.id] = 0 # initialize
for gr in contact.groups
if gr.contact_group_id.to_i == @group_id
@contacts_for_group[contact.id] = 1 # checked
end
end
end
end
end
render :action => "list"
end
def add
@contact = Contact.new
@contact.customer_id = logged_user
# load related lists
loadLists
# Init groups: because of checkbox
# Set all to 0 => unchecked
@groups = Hash.new
@contactgroups.each {|g|
@groups[g.id] = 0
}
end
def add_multiple
@contact = Contact.new
@contact["file_type"] = "1"
end
def add_from_mail
cstr = @params['cstr']
retmsg = @params['retmsg']
@session["return_to"] = url_for(:controller=>'/webmail/webmail',
:action=>'folders',
:msg_id=>retmsg)
# parse string
if i = cstr.index("<")
name, email = cstr.slice(0, i), cstr.slice((i+1)..(cstr.strip().index(">")-1))
fname = name.split().first
lname = name.split().last if name.split().size() > 1
else
fname, lname, email = "", "", cstr
end
if @contact = Contact.find_by_user_email(logged_user, email)
# load related lists
loadLists
@contact.fname, @contact.lname = fname, lname
# groups = @contact.groups
@groups = Hash.new
@contactgroups.each {|g|
groupSelected = false
@contact.groups.each {|gr|
if gr.contact_group_id.to_i == g.id.to_i
groupSelected = true
break
end
}
if groupSelected
@groups[g.id] = 1 # checked
else
@groups[g.id] = 0 # unchecked
end
}
else
@contact = Contact.new("fname"=>fname, "lname" => lname, "email" => email)
@contact.customer_id = logged_user
# load related lists
loadLists
# Init groups: because of checkbox
# Set all to 0 => unchecked
@groups = Hash.new
@contactgroups.each {|g|
@groups[g.id] = 0
}
end
render :action => "add"
end
def import_preview
file = @params["contact"]["data"]
flash["errors"] = Array.new
if file.size == 0
flash["errors"] << _('You haven\'t selected file or the file is empty')
@contact = Contact.new
@contact["file_type"] = @params["contact"]["file_type"]
render :action => "add_multiple"
end
file_type = @params["contact"]["file_type"]
if file_type.nil? or file_type == '1'
separator = ','
else
separator = /\t/
end
@contacts = Array.new
emails = Array.new
file.each {|line|
cdata = line.strip.chomp.split(separator)
cont = Contact.new
cont.fname = cdata[0].to_s.strip.chomp
cont.lname = cdata[1].to_s.strip.chomp
cont.email = cdata[2].to_s.strip.chomp
# Check for duplicate emails in the file
if emails.include?(cont.email)
flash["errors"] << sprintf(_('Contact %'), file.lineno.to_s) + ": " + _('The e-mail duplicates the e-mail of another record!')
else
emails << cont.email
end
@contacts << cont
}
end
def import
contacts_count = @params["contact"].length
contacts_to_import = @params["contact"]
@contacts = Array.new
emails = Array.new
flash["errors"] = Array.new
for i in 0...contacts_count
contact = Contact.new
contact.customer_id = logged_user
contact.fname = contacts_to_import[i.to_s]["fname"]
contact.lname = contacts_to_import[i.to_s]["lname"]
contact.email = contacts_to_import[i.to_s]["email"]
begin
# Check for duplicate emails in the submitted data
if emails.include?(contact.email)
flash["errors"] << sprintf(_('Contact %'), (i+1).to_s) + ": " + _('The e-mail duplicates the e-mail of another record!')
else
emails << contact.email
end
# Check if contact is valid
contact.valid?
rescue CDF::ValidationError => e
if not contact.errors.empty?
["fname", "lname", "email"].each do |attr|
attr_errors = contact.errors.on(attr)
attr_errors = [attr_errors] unless attr_errors.nil? or attr_errors.is_a? Array
if not attr_errors.nil?
attr_errors.each do |msg|
flash["errors"] << l(:contact_addmultiple_errorforcontact, (i+1).to_s) + ": " + l(msg)
end
end
end
end
end # rescue
@contacts << contact
end # for
# If there are validation errors - display them
if not flash["errors"].nil? and not flash["errors"].empty?
render :action => "import_preview"
else
# save
begin
for contact in @contacts
Contact.create(contact.attributes)
end
# Set message for successful import
flash["alert"] = Array.new
flash["alert"] << l(:contact_addmultiple_success, @contacts.length.to_s)
keep_flash()
redirect_to(:action=>"list")
rescue Exception => exc
flash["errors"] << exc
render :action => "import_preview"
end
end
end
def choose
if @params["mode"] == "groups"
save_groups
end
@tos, @ccs, @bccs = Array.new, Array.new, Array.new
@params["contacts_to"].each{ |id,value| @tos << Contact.find(id) if value == "1" } if @params["contacts_to"]
@params["contacts_cc"].each{ |id,value| @ccs << Contact.find(id) if value == "1" } if @params["contacts_cc"]
@params["contacts_bcc"].each{ |id,value| @bccs << Contact.find(id) if value == "1" } if @params["contacts_bcc"]
@params["groups_to"].each{ |id,value|
ContactGroup.find(id).contacts.each {|c| @tos << c} if value == "1" } if @params["groups_to"]
@params["groups_cc"].each{ |id,value|
ContactGroup.find(id).contacts.each {|c| @ccs << c} if value == "1" } if @params["groups_cc"]
@params["groups_bcc"].each{ |id,value|
ContactGroup.find(id).contacts.each {|c| @bccs << c} if value == "1" } if @params["groups_bcc"]
end
def save_groups
contacts_for_group = @params["contacts_for_group"]
group_id = @params["group_id"]
contact_group = ContactGroup.find(group_id)
contacts_for_group.each { |contact_id,value|
contact = Contact.find(contact_id)
if value == "1" and not contact_group.contacts.include?(contact)
contact_group.contacts << contact
end
if value == "0" and contact_group.contacts.include?(contact)
contact_group.contacts.delete(contact)
end
}
redirect_to(:action=>"list", :id=>group_id, :params=>{"mode"=>@params["mode"]})
end
def edit
@contact = Contact.find(@params["id"])
# load related lists
loadLists
# groups = @contact.groups
@groups = Hash.new
@contactgroups.each {|g|
groupSelected = false
@contact.groups.each {|gr|
if gr.contact_group_id.to_i == g.id.to_i
groupSelected = true
break
end
}
if groupSelected
@groups[g.id] = 1 # checked
else
@groups[g.id] = 0 # unchecked
end
}
render :action => "add"
end
# Insert or update
def save
logger.info("BEGIN")
if @params["contact"]["id"] == ""
# New contact
@contact = Contact.create(@params["contact"])
else
# Edit existing
@contact = Contact.find(@params["contact"]["id"])
@contact.attributes = @params["contact"]
end
@contactgroups = ContactGroup.find_by_user(logged_user)
# Groups displayed
groups = @params['groups']
tempGroups = Array.new
tempGroups.concat(@contact.groups)
@contactgroups.each { |cgroup|
includesCGroup = false
tempGroups.each {|gr|
if gr.contact_group_id.to_i == cgroup.id.to_i
includesCGroup = true
break
end
}
if groups["#{cgroup.id}"] == "1" and not includesCGroup
@contact.groups << cgroup
end
if groups["#{cgroup.id}"] == "0" and includesCGroup
@contact.groups.delete(cgroup)
end
}
if @contact.save
if @params["paction"] == _('Save')
redirect_to :controller => "/contacts/contact", :action =>"list"
else
redirect_to :controller => "/contacts/contact", :action =>"add"
end
else
loadLists
@groups = Hash.new
@contactgroups.each {|g|
if @contact.groups.include?(g)
@groups[g.id] = 1
else
@groups[g.id] = 0
end
}
render :action => "add"
end
end
def delete
Contact.destroy(@params['id'])
redirect_to(:action=>'list')
end
protected
def secure_user?() true end
def additional_scripts()
add_s = ''
if action_name == "choose"
add_s<<'<script type="text/javascript" src="/javascripts/global.js"></script>'
add_s<<'<script type="text/javascript" src="/javascripts/contact_choose.js"></script>'
end
add_s
end
def onload_function()
if action_name == "choose"
"javascript:respondToCaller();"
else
""
end
end
private
def select_layout
if @params["mode"] == "choose"
@mode = "choose"
@contactgroups = ContactGroup.find_by_user(logged_user)
'chooser'
elsif @params["mode"] == "groups"
@mode = "groups"
'public'
else
@mode = "normal"
'public'
end
end
def loadLists
if @contactgroups.nil?
@contactgroups = ContactGroup.find_by_user(logged_user)
end
end
end

View file

@ -0,0 +1,25 @@
class ContactGroup < ActiveRecord::Base
has_and_belongs_to_many :contacts, :class_name => "Contact", :join_table => "contact_contact_groups", :association_foreign_key => "contact_id", :foreign_key => "contact_group_id"
def ContactGroup.find_by_user(user_id)
find_by_sql("select * from contact_groups where customer_id = #{user_id} order by name asc")
end
protected
def validate
errors.add('name', :contactgroup_name_invalid) unless self.name =~ /^.{1,50}$/i
end
def validate_on_create
if ContactGroup.find_first(["name = '#{name}' and customer_id = #{user_id}"])
errors.add("name", _('Please enter group name (1 to 50 characters)'))
end
end
def validate_on_update
if ContactGroup.find_first(["name = '#{name}' and customer_id = #{user_id} and id <> #{id}"])
errors.add("name", _('You already have contact group with this name'))
end
end
end

View file

@ -0,0 +1,24 @@
<h1><%=_('Edit/Create Contact Group')%></h1>
<%=
form_tag(
link_save,
'method' => 'post',
'class' => 'two_columns'
)
%>
<%= form_input(:hidden_field, 'contactgroup', 'id') %>
<%= form_input(:hidden_field, 'contactgroup', 'customer_id') %>
<table>
<%= form_input(:text_field, 'contactgroup', 'name', _('Name'), 'class'=>'two_columns') %>
</table>
<table>
<tr>
<td colspan=2 class="buttonBar">
<input type="submit" name="Save" value="<%=_('Save')%>"/>
<input type="button" value="<%=_('Back to groups')%>" onclick="window.location='<%=link_list%>'"/>
</td>
</tr>
</table>
<%= end_form_tag %>

View file

@ -0,0 +1,26 @@
<h1><%=_('Contact Groups')%></h1>
<form action="/contact_group/add" method="post">
<%= hidden_field "contactgroup", "user_id" %>
<table class="list">
<tr>
<th><%=_('Name')%></th>
<th colspan=3>&nbsp;</th>
</tr>
<%
for contactgroup in @contactgroups %>
<tr class="even">
<td><%= contactgroup.name %></td>
<td><%= link_to(_('members'), :controller=>'contact', :action=>'list', :id=>contactgroup.id, :params=>{"mode"=>"groups"}) %></td>
<td><%= link_to(_('edit'), :controller=>'/contacts/contact_group', :action=>'edit', :id=>contactgroup.id) %></td>
<td><%= link_to(_('delete'), {:controller=>'/contacts/contact_group', :action=>'delete', :id=>contactgroup.id}, {:confirm=>sprintf(_('DELETE CONTACT GROUP \'%s\'?'), contactgroup.name)})%></td>
</tr>
<% end %>
<tr>
<td colspan=2 class="buttonBar">
<input type="submit" value="<%=_('Add Contact Group')%>"/>
<input type="button" value="<%=_('Back to folders')%>" onclick="window.location='/webmail/folders'">
</td>
</tr>
</table>
</form>

View file

@ -0,0 +1,60 @@
class Contacts::ContactGroupController < ApplicationController
uses_component_template_root
model :contact_group
layout 'public'
def index
redirect_to(:action=>"list")
end
def list
@contactgroup = ContactGroup.new
@contactgroup.customer_id = logged_user
@contactgroups = ContactGroup.find_by_user(logged_user)
end
def add
@contactgroup = ContactGroup.new
@contactgroup.customer_id = logged_user
render("/contact_group/edit")
end
def delete
contactgroup = ContactGroup.find(@params["id"])
contactgroup.destroy
redirect_to(:action=>"list")
end
def edit
@contactgroup = ContactGroup.find(@params["id"])
end
def save
begin
if @params["contactgroup"]["id"].nil? or @params["contactgroup"]["id"] == ""
# New contactgroup
@contactgroup = ContactGroup.create(@params["contactgroup"])
else
# Edit existing
@contactgroup = ContactGroup.find(@params["contactgroup"]["id"])
@contactgroup.attributes = @params["contactgroup"]
end
if @contactgroup.save
redirect_to(:action=>"list")
else
render "/contact_group/edit"
end
rescue CDF::ValidationError => e
logger.info("RESCUE")
@contactgroup = e.entity
render("/contact_group/edit")
end
end
protected
def secure_user?() true end
end

View file

@ -0,0 +1,4 @@
module ContactGroupHelper
def link_save() "/contact_group/save" end
def link_list() "/contact_group/list" end
end

View file

@ -0,0 +1,40 @@
module Contacts::ContactHelper
def link_import_preview() "/contacts/contact/import_preview" end
def link_main_index() "/webmail/webmail/folders" end
def link_contact_save() "/contacts/contact/save" end
def link_contact_import() "/contacts/contact/import" end
def link_contact_choose() "/contacts/contact/choose" end
def link_contact_list
link_to(_('List'), :controller => "/contacts/contact", :action => "list")
end
def link_contact_add_one
link_to(_('Add one contact'), :controller => "/contacts/contact", :action => "add")
end
def link_contact_add_multiple
link_to(_('Add multiple'), :controller => "/contacts/contact", :action => "add_multiple")
end
def link_contact_group_list
link_to(_('Groups'), :controller => "/contacts/contact_group", :action => "list")
end
def link_folders
link_to(_('Folders'), :controller=>"/webmail/webmail", :action=>"messages")
end
def link_send_mail
link_to(_('Compose'), :controller=>"/webmail/webmail", :action=>"compose")
end
def link_mail_prefs
link_to(_('Preferences'), :controller=>"/webmail/webmail", :action=>"prefs")
end
def link_mail_filters
link_to(_('Filters'), :controller=>"/webmail/webmail", :action=>"filters")
end
end

View file

@ -0,0 +1,32 @@
require_dependency 'maildropserializator'
class Customer < ActiveRecord::Base
include MaildropSerializator
has_many :filters, :order => "order_num"
has_one :mail_pref
attr_accessor :password
def mail_temporary_path
"#{CDF::CONFIG[:mail_temp_path]}/#{self.email}"
end
def friendlly_local_email
encode_email("#{self.fname} #{self.lname}", check_for_domain(email))
end
def mail_filter_path
"#{CDF::CONFIG[:mail_filters_path]}/#{self.email}"
end
def local_email
self.email
end
def check_for_domain(email)
if email and !email.nil? and !email.include?("@")
email + "@" + CDF::CONFIG[:send_from_domain]
else
email
end
end
end

View file

@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= @htmllang %>" lang="<%= @htmllang %>">
<head>
<title><%=@title%></title>
<meta http-equiv="content-type" content="text/html; charset=<%= @charset %>" />
<script type="text/javascript" src="/javascripts/global.js"></script>
<link rel="stylesheet" href="/stylesheets/admin.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/stylesheets/tabs.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/stylesheets/mailr.css" type="text/css" media="screen" />
<%=@additional_scripts%>
</head>
<body id="bodyID" onload="<%=@onload_function%>">
<%= @content_for_layout %>
</body>
</html>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= @htmllang %>" lang="<%= @htmllang %>">
<head>
<title><%=_('Mailr')%></title>
<meta http-equiv="content-type" content="text/html; charset=<%= @charset %>" />
<link rel="stylesheet" href="/stylesheets/admin.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/stylesheets/tabs.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/stylesheets/mailr.css" type="text/css" media="screen" />
<script type="text/javascript" src="/javascripts/global.js"></script>
<script type="text/javascript" src="/javascripts/prototype.js"></script>
<%=(@content_for_scripts ? @content_for_scripts : @additional_scripts )%>
</head>
<body id="bodyID" onload="<%=@onload_function%>">
<div id="wholepage">
<div id="container">
<div id="logout"><%= link_to _('[Logout]'), :controller=>'/login', :action=>'logout' %></div>
<div id="sidebar_outer">
<div id="sidebar"><%= @content_for_sidebar %></div>
</div>
<div id="content"><%= @content_for_layout %></div>
<br class="clear"/>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,8 @@
class BouncedMail < ActiveRecord::Base
belongs_to :customer
belongs_to :contact
def BouncedMail.find_by_customer_contact(cust_id, contact_id)
find_all(["customer_id = ? and contact_id = ?", cust_id, cotact_id], ["msg_date desc"])
end
end

View file

@ -0,0 +1,303 @@
require 'tmail'
require 'net/smtp'
require 'mail_transform'
class CDF::Mail
include ActionMailer::Quoting
def initialize(senderTempLocation)
@attachments = Array.new
@sender_temp_location = senderTempLocation
@to_contacts = Array.new
end
def customer_id() @customer_id end
def customer_id=(arg) @customer_id = arg end
def from() @from end
def from=(arg) @from = arg end
def to() @to end
def to=(arg) @to = arg end
def to_contacts() @to_contacts end
def to_contacts=(arg) @to_contacts = arg end
def toc=(arg)
@to_contacts = Array.new
arg.split(",").each { |token| @to_contacts << token.to_i unless token == "" or token.strip() == "undefined"} unless arg.nil? or arg == "undefined"
end
def toc
ret = String.new
@to_contacts.each { |contact|
ret << "," unless ret == ""
if contact.kind_of?(Integer)
ret << contact.to_s unless contact.nil? or contact == 0
else
ret << contact.id.to_s unless contact.nil? or contact.id.nil?
end
}
ret
end
def bcc() @bcc end
def bcc=(arg) @bcc = arg end
def cc() @cc end
def cc=(arg) @cc = arg end
def subject() @subject end
def subject=(arg) @subject = arg end
def attachments
@attachments
end
def add_attachment(attachment)
@attachments << attachment
end
def multipart?
@attachments && @attachments.size > 0
end
def delete_attachment(att_filename)
@attachments.each { |att| att.delete_temp_data() if arr.filename == att_filename }
@attachments.delete_if() { |att| att.filename == att_filename }
end
def delete_attachments()
@attachments.each { |att| att.delete_temp_data() }
@attachments = Array.new
end
def body() @body end
def body=(arg) @body = arg end
def content_type() @content_type end
def content_type=(arg) @content_type = arg end
def temp_location() @sender_temp_location end
def send_mail(db_msg_id = 0)
m = TMail::Mail.new
m.from, m.body = self.from, self.body
m.date = Time.now
m.subject, = quote_any_if_necessary("UTF-8", self.subject)
m.to = decode_addresses(self.to)
m.cc, m.bcc = decode_addresses(self.cc), decode_addresses(self.bcc)
if multipart?
m.set_content_type("multipart/mixed")
p = TMail::Mail.new(TMail::StringPort.new(""))
if @content_type.include?("text/plain") # here maybe we should encode in 7bit??!!
prepare_text(p, self.content_type, self.body)
elsif self.content_type.include?("text/html")
prepare_html(p, self.content_type, self.body)
elsif self.content_type.include?("multipart")
prepare_alternative(p, self.body)
end
m.parts << p
else
if @content_type.include?("text/plain") # here maybe we should encode in 7bit??!!
prepare_text(m, self.content_type, self.body)
elsif self.content_type.include?("text/html")
prepare_html(m, self.content_type, self.body)
elsif self.content_type.include?("multipart")
prepare_alternative(m, self.body)
end
end
# attachments
@attachments.each { |a|
m.parts << a.encoded
}
encmail = m.encoded
RAILS_DEFAULT_LOGGER.debug("Sending message \n #{encmail}")
Net::SMTP.start(ActionMailer::Base.server_settings[:address], ActionMailer::Base.server_settings[:port],
ActionMailer::Base.server_settings[:domain], ActionMailer::Base.server_settings[:user_name],
ActionMailer::Base.server_settings[:password], ActionMailer::Base.server_settings[:authentication]) do |smtp|
smtp.sendmail(encmail, m.from, m.destinations)
end
return encmail
end
def forward(tmail, fb)
decoded_subject = mime_encoded?(tmail.subject) ? mime_decode(tmail.subject) : tmail.subject
self.subject = "[Fwd: #{decoded_subject}]"
attachment = CDF::Attachment.new(self)
attachment.body(tmail, fb)
end
def reply(tmail, fb, type)
decoded_subject = mime_encoded?(tmail.subject) ? mime_decode(tmail.subject) : tmail.subject
self.subject = "[Re: #{decoded_subject}]"
tm = tmail.setup_reply(tmail)
self.to = tm.to
footer = ""
msg_id = ""
mt = MailTransform.new
self.body = mt.get_body(tmail, type)
end
private
def delimeter
if self.content_type == "text/plain"
"\n"
else
"<br/>"
end
end
def text2html(str) CGI.escapeHTML(str).gsub("\n", "<br/>") end
def html2text(txt)
clear_html(txt)
end
def prepare_text(msg, ctype, bdy)
msg.set_content_type(ctype, nil, {"charset"=>"utf-8"})
msg.transfer_encoding = "8bit"
msg.body = bdy
end
def prepare_html(msg, ctype, bdy)
msg.set_content_type(ctype, nil, {"charset"=>"utf8"})
msg.transfer_encoding = "8bit"
msg.body = bdy
end
def prepare_alternative(msg, bdy)
bound = ::TMail.new_boundary
msg.set_content_type("multipart/alternative", nil, {"charset"=>"utf8", "boundary"=>bound})
msg.transfer_encoding = "8bit"
ptext = TMail::Mail.new(TMail::StringPort.new(""))
phtml = TMail::Mail.new(TMail::StringPort.new(""))
prepare_text(ptext, "text/plain", html2text(bdy))
prepare_html(phtml, "text/html", bdy)
msg.parts << ptext
msg.parts << phtml
end
def decode_addresses(str)
ret = String.new
str.split(",").each { |addr|
if addr.slice(0,4) == "Grp+"
grp_id = addr.scan(/Grp\+([0-9]*):(.*)/)[0][0]
ContactGroup.find(:first, :conditions=>['customer_id = ? and id = ?', @customer_id, grp_id]).contacts.each { |contact|
ret << "," if not(ret == "")
@to_contacts << contact unless contact.nil?
ret << contact.full_address
ad, = quote_any_address_if_necessary(CDF::CONFIG[:mail_charset], contact.full_address)
ret << ad
}
else
ret << "," if not(ret == "")
ad, = quote_any_address_if_necessary(CDF::CONFIG[:mail_charset], addr) if not(addr.nil? or addr == "")
ret << ad if not(addr.nil? or addr == "")
end
} unless str.nil? or str.strip() == ""
ret
end
end
class CDF::Attachment
def initialize(arg)
@mail = arg
@mail.add_attachment(self)
@index = @mail.attachments.size - 1
end
def filename=(arg)
@filename = arg.tr('\\/:*?"\'<>|', '__________')
end
def filename() @filename end
def temp_filename=(arg) @temp_filename = arg end
def temp_filename() @temp_filename end
def content_type=(arg) @content_type = arg end
def content_type() @content_type end
def delete_temp_data()
File.delete(self.temp_filename)
end
def file
File.open(self.temp_filename, "rb") { |fp| fp.read }
end
def file=(data)
return if data.size == 0
@content_type = data.content_type
self.filename = data.original_filename.scan(/[^\\]*$/).first
self.temp_filename = "#{@mail.temp_location}/#{@filename}"
check_store_path
data.rewind
File.open(@temp_filename, "wb") { |f| f.write(data.read) }
end
def body(data, fb)
@content_type = "message/rfc822"
filename = data.content_type['filename']
self.filename = filename.nil? ? (mime_encoded?(data.subject) ? mime_decode(data.subject) : data.subject) : filename
self.temp_filename = "#{@mail.temp_location}/#{@filename}"
check_store_path
File.open(@temp_filename, "wb") { |f| f.write(fb) }
end
def check_store_path()
path = ""
"#{@mail.temp_location}".split(File::SEPARATOR).each { |p|
path << p
begin
Dir.mkdir(path)
rescue
end
path << File::SEPARATOR
}
end
def encoded
p = TMail::Mail.new(TMail::StringPort.new(""))
data = self.file
p.body = data
if @content_type.include?("text/plain") # here maybe we should encode in 7bit??!!
p.set_content_type(@content_type, nil, {"charset"=>"utf-8"})
p.transfer_encoding = "8bit"
elsif @content_type.include?("text/html")
p.set_content_type(@content_type, nil, {"charset"=>"utf8"})
p.transfer_encoding = "8bit"
elsif @content_type.include?("rfc822")
p.set_content_type(@content_type, nil, {"charset"=>"utf8"})
p.set_disposition("inline;")
p.transfer_encoding = "8bit"
else
p.set_content_type(@content_type, nil, {"name"=>@filename})
p.set_disposition("inline; filename=#{@filename}") unless @filename.nil?
p.set_disposition("inline;") if @filename.nil?
p.transfer_encoding='Base64'
p.body = TMail::Base64.folding_encode(data)
end
return p
end
end

View file

@ -0,0 +1,5 @@
require 'maildropserializator'
Customer.class_eval do
include MaildropSerializator
has_many :filters, :order => "order_num", :dependent => true
end

View file

@ -0,0 +1,2 @@
class Expression < ActiveRecord::Base
end

View file

@ -0,0 +1,3 @@
class Filter < ActiveRecord::Base
has_many :expressions
end

View file

@ -0,0 +1,38 @@
require 'mail2screen'
class ImapMessage < ActiveRecord::Base
include Mail2Screen
def set_folder(folder)
@folder = folder
end
def full_body
@folder.mailbox.imap.uid_fetch(uid, "BODY[]").first.attr["BODY[]"]
end
def from_addr=(fa)
self.from = fa.to_yaml
self.from_flat = short_address(fa)
end
def from_addr
begin
YAML::load(from)
rescue Object
from
end
end
def to_addr=(ta)
self.to = ta.to_yaml
self.to_flat = short_address(ta)
end
def to_addr
begin
YAML::load(to)
rescue Object
to
end
end
end

View file

@ -0,0 +1,497 @@
# Copyright (c) 2005, Benjamin Stiglitz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Modifications (c) 2005 by littlegreen
#
require 'net/imap'
Net::IMAP.debug = true if CDF::CONFIG[:debug_imap]
class Net::IMAP
class PlainAuthenticator
def process(data)
return "\0#{@user}\0#{@password}"
end
private
def initialize(user, password)
@user = user
@password = password
end
end
add_authenticator('PLAIN', PlainAuthenticator)
class Address
def to_s
if(name)
"#{name} #{mailbox}@#{host}"
else
"#{mailbox}@#{host}"
end
end
end
end
class AuthenticationError < RuntimeError
end
class IMAPMailbox
attr_reader :connected
attr_accessor :selected_mailbox
cattr_accessor :logger
def initialize
@selected_mailbox = ''
@folders = {}
@connected = false
end
def connect(username, password)
unless @connected
use_ssl = CDF::CONFIG[:imap_use_ssl] ? true : false
port = CDF::CONFIG[:imap_port] || (use_ssl ? 993 : 143)
begin
@imap = Net::IMAP.new(CDF::CONFIG[:imap_server], port, use_ssl)
rescue Net::IMAP::ByeResponseError => bye
# make a timeout and retry
begin
System.sleep(CDF::CONFIG[:imap_bye_timeout_retry_seconds])
@imap = Net::IMAP.new(CDF::CONFIG[:imap_server], port, use_ssl)
rescue Error => ex
logger.error "Error on authentication!"
logger.error bye.backtrace.join("\n")
raise AuthenticationError.new
end
rescue Net::IMAP::NoResponseError => noresp
logger.error "Error on authentication!"
logger.error noresp.backtrace.join("\n")
raise AuthenticationError.new
rescue Net::IMAP::BadResponseError => bad
logger.error "Error on authentication!"
logger.error bad.backtrace.join("\n")
raise AuthenticationError.new
rescue Net::IMAP::ResponseError => resp
logger.error "Error on authentication!"
logger.error resp.backtrace.join("\n")
raise AuthenticationError.new
end
@username = username
begin
logger.error "IMAP authentication - #{CDF::CONFIG[:imap_auth]}."
if CDF::CONFIG[:imap_auth] == 'NOAUTH'
@imap.login(username, password)
else
@imap.authenticate(CDF::CONFIG[:imap_auth], username, password)
end
@connected = true
rescue Exception => ex
logger.error "Error on authentication!"
logger.error ex.backtrace.join("\n")
raise AuthenticationError.new
end
end
end
def imap
@imap
end
# Function chnage password works only if root has run imap_backend
# and users courier-authlib utility authtest - from courier-imap version 4.0.1
def change_password(username, password, new_password)
ret = ""
cin, cout, cerr = Open3.popen3("/usr/sbin/authtest #{username} #{password} #{new_password}")
ret << cerr.gets
if ret.include?("Password change succeeded.")
return true
else
logger.error "[!] Error on change password! - #{ret}"
return false
end
end
def disconnect
if @connected
@imap.logout
@imap.disconnect
@imap = nil
@connected = false
end
end
def [](mailboxname)
@last_folder = IMAPFolderList.new(self, @username)[mailboxname]
end
def folders
# reference just to stop GC
@folder_list ||= IMAPFolderList.new(self, @username)
@folder_list
end
def reload
@folder_list.reload if @folder_list
end
def create_folder(name)
begin
@imap.create(name)
reload
rescue Exception=>e
end
end
def delete_folder(name)
begin
@imap.delete(name)
reload
rescue Exception=>e
logger.error("Exception on delete #{name} folder #{e}")
end
end
def message_sent(message)
# ensure we have sent folder
begin
@imap.create(CDF::CONFIG[:mail_sent])
rescue Exception=>e
end
begin
@imap.append(CDF::CONFIG[:mail_sent], message)
folders[CDF::CONFIG[:mail_sent]].cached = false if folders[CDF::CONFIG[:mail_sent]]
rescue Exception=>e
logger.error("Error on append - #{e}")
end
end
def message_bulk(message)
# ensure we have sent folder
begin
@imap.create(CDF::CONFIG[:mail_bulk_sent])
rescue Exception=>e
end
begin
@imap.append(CDF::CONFIG[:mail_bulk_sent], message)
folders[CDF::CONFIG[:mail_sent]].cached = false if folders[CDF::CONFIG[:mail_bulk_sent]]
rescue Exception=>e
logger.error("Error on bulk - #{e}")
end
end
end
class IMAPFolderList
include Enumerable
cattr_accessor :logger
def initialize(mailbox, username)
@mailbox = mailbox
@folders = Hash.new
@username = username
end
def each
refresh if @folders.empty?
#@folders.each_value { |folder| yield folder }
# We want to allow sorted access; for now only (FIXME)
@folders.sort.each { |pair| yield pair.last }
end
def reload
refresh
end
def [](name)
refresh if @folders.empty?
@folders[name]
end
private
def refresh
@folders = {}
result = @mailbox.imap.list('', '*')
if result
result.each do |info|
@folders[info.name] = IMAPFolder.new(@mailbox, info.name, @username, info.attr, info.delim)
end
else
# if there are no folders subscribe to INBOX - this is on first use
@mailbox.imap.subscribe(CDF::CONFIG[:mail_inbox])
# try again to list them - we should find INBOX
@mailbox.imap.list('', '*').each do |info|
@folders[info.name] = IMAPFolder.new(@mailbox, info.name, @username, info.attr, info.delim)
end
end
@folders
end
end
class IMAPFolder
attr_reader :mailbox
attr_reader :name
attr_reader :username
attr_reader :delim
attr_reader :attribs
attr_writer :cached
attr_writer :mcached
cattr_accessor :logger
@@fetch_attr = ['ENVELOPE','BODYSTRUCTURE', 'FLAGS', 'UID', 'RFC822.SIZE']
def initialize(mailbox, name, username, attribs, delim)
@mailbox = mailbox
@name = name
@username = username
@messages = Array.new
@delim = delim
@attribs = attribs
@cached = false
@mcached = false
end
def activate
if(@mailbox.selected_mailbox != @name)
@mailbox.selected_mailbox = @name
@mailbox.imap.select(@name)
load_total_unseen if !@cached
end
end
# Just delete message without interaction with Trash folder
def delete(message)
uid = (message.kind_of?(Integer) ? message : message.uid)
@mailbox.imap.uid_store(uid, "+FLAGS", :Deleted)
@mailbox.imap.expunge
# Sync with trash cannot be made - new uid generated - so just delete message from current folder
ImapMessage.delete_all(["username = ? and folder_name = ? and uid = ?", @username, @name, uid])
@cached = false
end
# Deleted messages - move to trash folder
def delete_multiple(uids)
# ensure we have trash folder
begin
@mailbox.imap.create(CDF::CONFIG[:mail_trash])
rescue
end
move_multiple(uids, CDF::CONFIG[:mail_trash])
end
def copy(message, dst_folder)
uid = (message.kind_of?(Integer) ? message : message.uid)
activate
@mailbox.imap.uid_copy(uid, dst_folder)
@mailbox.folders[dst_folder].cached = false if @mailbox.folders[dst_folder]
@mailbox.folders[dst_folder].mcached = false if @mailbox.folders[dst_folder]
end
def copy_multiple(message_uids, dst_folder)
activate
@mailbox.imap.uid_copy(message_uids, dst_folder)
@mailbox.folders[dst_folder].cached = false if @mailbox.folders[dst_folder]
@mailbox.folders[dst_folder].mcached = false if @mailbox.folders[dst_folder]
end
def move(message, dst_folder)
uid = (message.kind_of?(Integer) ? message : message.uid)
activate
@mailbox.imap.uid_copy(uid, dst_folder)
@mailbox.imap.uid_store(uid, "+FLAGS", :Deleted)
@mailbox.folders[dst_folder].cached = false if @mailbox.folders[dst_folder]
@mailbox.folders[dst_folder].mcached = false if @mailbox.folders[dst_folder]
@mailbox.imap.expunge
ImapMessage.delete_all(["username = ? and folder_name = ? and uid = ? ", @username, @name, uid])
@cached = false
@mcached = false
end
def move_multiple(message_uids, dst_folder)
activate
@mailbox.imap.uid_copy(message_uids, dst_folder)
@mailbox.imap.uid_store(message_uids, "+FLAGS", :Deleted)
@mailbox.folders[dst_folder].cached = false if @mailbox.folders[dst_folder]
@mailbox.folders[dst_folder].mcached = false if @mailbox.folders[dst_folder]
@mailbox.imap.expunge
ImapMessage.delete_all(["username = ? and folder_name = ? and uid in ( ? )", @username, @name, message_uids])
@cached = false
@mcached = false
end
def mark_read(message_uid)
activate
cached = ImapMessage.find(:first, :conditions => ["username = ? and folder_name = ? and uid = ?", @username, @name, message_uid])
if cached.unread
cached.unread = false
cached.save
@mailbox.imap.select(@name)
@mailbox.imap.uid_store(message_uid, "+FLAGS", :Seen)
@unseen_messages = @unseen_messages - 1
end
end
def mark_unread(message_uid)
activate
cached = ImapMessage.find(:first, :conditions => ["username = ? and folder_name = ? and uid = ?", @username, @name, message_uid])
if !cached.unread
cached.unread = true
cached.save
@mailbox.imap.select(@name)
@mailbox.imap.uid_store(message_uid, "-FLAGS", :Seen)
@unseen_messages = @unseen_messages + 1
end
end
def expunge
activate
@mailbox.imap.expunge
end
def synchronize_cache
startSync = Time.now
activate
startUidFetch = Time.now
server_messages = @mailbox.imap.uid_fetch(1..-1, ['UID', 'FLAGS'])
startDbFetch = Time.now
cached_messages = ImapMessage.find(:all, :conditions => ["username = ? and folder_name = ?", @username, @name])
cached_unread_uids = Array.new
cached_read_uids = Array.new
uids_to_be_deleted = Array.new
cached_messages.each { |msg|
cached_unread_uids << msg.uid if msg.unread
cached_read_uids << msg.uid unless msg.unread
uids_to_be_deleted << msg.uid
}
uids_to_be_fetched = Array.new
server_msg_uids = Array.new
uids_unread = Array.new
uids_read = Array.new
server_messages.each { |server_msg|
uid, flags = server_msg.attr['UID'], server_msg.attr['FLAGS']
server_msg_uids << uid
unless uids_to_be_deleted.include?(uid)
uids_to_be_fetched << uid
else
if flags.member?(:Seen) && cached_unread_uids.include?(uid)
uids_read << uid
elsif !flags.member?(:Seen) && cached_read_uids.include?(uid)
uids_unread << uid
end
end
uids_to_be_deleted.delete(uid)
} unless server_messages.nil?
ImapMessage.delete_all(["username = ? and folder_name = ? and uid in ( ? )", @username, @name, uids_to_be_deleted]) unless uids_to_be_deleted.empty?
ImapMessage.update_all('unread = 0', ["username = ? and folder_name = ? and uid in ( ? )", @username, @name, uids_read]) unless uids_read.empty?
ImapMessage.update_all('unread = 1', ["username = ? and folder_name = ? and uid in ( ? )", @username, @name, uids_unread]) unless uids_unread.empty?
# fetch and store not cached messages
unless uids_to_be_fetched.empty?
imapres = @mailbox.imap.uid_fetch(uids_to_be_fetched, @@fetch_attr)
imapres.each { |cache|
envelope = cache.attr['ENVELOPE'];
message = ImapMessage.create( :folder_name => @name,
:username => @username,
:msg_id => envelope.message_id,
:uid => cache.attr['UID'],
:from_addr => envelope.from,
:to_addr => envelope.to,
:subject => envelope.subject,
:content_type => cache.attr['BODYSTRUCTURE'].multipart? ? 'multipart' : 'text',
:date => envelope.date,
:unread => !(cache.attr['FLAGS'].member? :Seen),
:size => cache.attr['RFC822.SIZE'])
}
end
@mcached = true
logger.debug("Synchonization done for folder #{@name} in #{Time.now - startSync} ms.")
end
def messages(offset = 0, limit = 10, sort = 'date desc')
# Synchronize first retrieval time
synchronize_cache unless @mcached
if limit == -1
@messages = ImapMessage.find(:all, :conditions => ["username = ? and folder_name = ?", @username, @name], :order => sort)
else
@messages = ImapMessage.find(:all, :conditions => ["username = ? and folder_name = ?", @username, @name], :order => sort, :limit => limit, :offset => offset )
end
end
def messages_search(query = ["ALL"], sort = 'date desc')
activate
uids = @mailbox.imap.uid_search(query)
if uids.size > 1
ImapMessage.find(:all, :conditions => ["username = ? and folder_name = ? and uid in ( ? )", @username, @name, uids], :order => sort )
elsif uids.size == 1
ImapMessage.find(:all, :conditions => ["username = ? and folder_name = ? and uid = ? ", @username, @name, uids.first], :order => sort )
else
return Array.new
end
end
def message(uid)
activate
message = ImapMessage.find(:first, :conditions => ["username = ? and folder_name = ? and uid = ?", @username, @name, uid])
message.set_folder(self)
message
end
def unseen
activate
load_total_unseen if !@cached
@unseen_messages
end
def total
activate
load_total_unseen if !@cached
@total_messages
end
def load_total_unseen
stat = @mailbox.imap.status(@name, ["MESSAGES", "UNSEEN"])
@total_messages, @unseen_messages = stat["MESSAGES"], stat['UNSEEN']
@cached = true
end
def update_status
@status ||= @mailbox.imap.status(@name, ["MESSAGES"])
end
def subscribe
@mailbox.imap.subscribe(@name)
end
end

View file

@ -0,0 +1,167 @@
require 'cdfutils'
module Mail2Screen
def mail2html(mail, msg_id)
footer = ""
parsed_body = create_body(mail, msg_id, footer)
ret = "<table class='messageheader' border='0' cellpadding='0' cellspacing='0' >\n"
ret << "<tbody>\n"
ret << " <tr><td class='label' nowrap='nowrap'>#{_('From')}:</td><td>#{address(mail.from_addrs, @msg_id)}</td></tr>\n"
ret << " <tr><td class='label' nowrap='nowrap'>#{_('To')}:</td><td>#{address(mail.to_addrs, @msg_id)}</td></tr>\n"
if @mail.cc_addrs
ret << " <tr><td class='label' nowrap='nowrap'>#{_('CC')}:</td><td>#{address(mail.cc_addrs, @msg_id)}</td></tr>\n"
end
if @mail.bcc_addrs
ret << " <tr><td class='label' nowrap='nowrap'>#{_('BCC')}:</td><td>#{address(mail.bcc_addrs, @msg_id)}</td></tr>\n"
end
ret << " <tr><td class='label' nowrap='nowrap'>#{_('Subject')}:</td><td>#{h(mime_encoded?(mail.subject) ? mime_decode(mail.subject) : mail.subject)}</dd>\n"
ret << " <tr><td class='label' nowrap='nowrap'>#{_('Date')}:</td><td>#{h message_date(mail.date)}</td></tr>\n"
if footer != ''
ret << " <tr><td class='label' nowrap='nowrap'>#{image_tag('attachment.png')}</td><td>#{footer}</td></tr>\n"
end
ret << " </tbody>\n"
ret << "</table>\n"
ret << "<div class='msgpart'>\n"
ret << parsed_body
ret << "</div>\n"
end
def create_body(mail, msg_id, footer)
charset = (mail.charset.nil? ? 'iso-8859-1' : mail.charset)
if mail.multipart?
ret = ""
if mail.content_type == 'multipart/alternative'
# take only HTML part
mail.parts.each { |part|
if part.content_type == "text/html" or part.multipart?
ret << create_body(part, msg_id, footer)
end
}
return ret
else
mail.parts.each { |part|
if part.multipart?
ret << create_body(part, msg_id, footer)
else
footer << ", " if footer != ''
footer << add_attachment(part.header['content-type'], msg_id)
if part.content_type == "text/plain" or part.content_type.nil?
charset = (part.charset.nil? ? charset : mail.charset)
ret << add_text(part, part.transfer_encoding, charset)
elsif part.content_type == "text/html"
charset = (part.charset.nil? ? charset : mail.charset)
ret << add_html(part, part.transfer_encoding, charset)
elsif part.content_type.include?("image/")
ctype = part.header['content-type']
ret << add_image(ctype, msg_id)
elsif part.content_type.include?("message/rfc822")
ret << "<br/>#{_('Follows attached message')}:<hr/>" << mail2html(TMail::Mail.parse(part.body), msg_id)
end
end
}
return ret
end
else
ret = ""
if mail.content_type == "text/plain" or mail.content_type.nil?
ret << add_text(mail, mail.transfer_encoding, charset)
elsif mail.content_type == "text/html"
ret << add_html(mail, mail.transfer_encoding, charset)
end
return ret
end
end
def add_text(part, encoding, charset)
CGI.escapeHTML(decode_part_text("#{part}", encoding, charset)).gsub(/\r\n/,"<br/>").gsub(/\r/, "<br/>").gsub(/\n/,"<br/>")
end
def add_html(part, encoding, charset)
strip_html(decode_part_text("#{part}", encoding, charset))
end
def decode_part_text(part_str, encoding, charset)
# Parse mail
header, text = "", ""
# Get header and body
#Content-type: text/plain; charset="ISO-8859-1"
#Content-transfer-encoding: quoted-printable
isBody = false
part_str.each_line { |line|
if isBody
text << line
else
if line.strip == ""
isBody = true
else
header << line
end
end
}
# Manage encoding
if not(encoding.nil?) and encoding.downcase == "quoted-printable"
ret = from_qp(text)
elsif not(encoding.nil?) and encoding.downcase == "base64"
ret = "#{text.unpack("m")}"
else
ret = text
end
# manage charset
if ret.nil? or charset.nil? or charset.downcase == "utf-8"
return ret
else
begin
return Iconv.conv("UTF-8",charset.downcase, ret)
rescue Exception => ex
RAILS_DEFAULT_LOGGER.debug("Exception occured #{ex}\n#{ex.backtrace.join('\n')}")
return ret
end
end
end
def add_attachment(content_type, msg_id)
filename = (content_type.nil? or content_type['name'].nil? ? "" : content_type['name'])
if filename == ""
""
else
"<span class='attachment'>&nbsp;<a href='/webmail/webmail/download?msg_id=#{msg_id}&ctype=" << CGI.escape(filename) << "'>#{filename}</a></span>"
end
end
def add_image(content_type, msg_id)
filename = (content_type.nil? or content_type['name'].nil? ? "" : content_type['name'])
"<hr/><span class='attachment'><br/><img src='/webmail/webmail/download?msg_id=#{msg_id}&ctype=" << CGI.escape(filename) << "' alt='#{filename}'/></span>"
end
def friendly_address(addr)
addr.kind_of?(Net::IMAP::Address) ? ((addr.name.nil? or addr.name.strip == "") ? "#{addr.mailbox}@#{addr.host}" : "#{(mime_encoded?(addr.name.strip) ? mime_decode(addr.name.to_s): addr.name.to_s)}<#{addr.mailbox}@#{addr.host}>") : ((addr.name.nil? or addr.name.strip == "") ? "#{addr.spec}" : "#{(mime_encoded?(addr.name.strip) ? mime_decode(addr.name.to_s): addr.name.to_s)}<#{addr.spec}>")
end
def friendly_address_or_name(addr)
addr.kind_of?(Net::IMAP::Address) ? ((addr.name.nil? or addr.name.to_s == "") ? "#{addr.mailbox}@#{addr.host}" : (mime_encoded?(addr.name.to_s) ? mime_decode(addr.name.to_s): addr.name.to_s)) : ((addr.name.nil? or addr.name.to_s == "") ? "#{addr.spec}" : (mime_encoded?(addr.name.to_s) ? mime_decode(addr.name.to_s): addr.name.to_s))
end
def add_to_contact(addr, msg_id)
"&nbsp;<a href='/contacts/contact/add_from_mail?cstr=#{CGI.escape(friendly_address(addr))}&retmsg=#{msg_id}'>Add to contacts</a>"
end
def short_address(addresses)
ret = ""
addresses.each { |addr| #split(/,\s*/)
ret << "," unless ret == ""
ret << CGI.escapeHTML(friendly_address_or_name(addr))
} unless addresses.nil?
ret
end
def address(addresses, msg_id)
ret = ""
addresses.each { |addr| #split(/,\s*/)
ret << "," unless ret == ""
ret << CGI.escapeHTML(friendly_address_or_name(addr)) << add_to_contact(addr, msg_id)
} unless addresses.nil?
return ret
end
end

View file

@ -0,0 +1,9 @@
require_association 'customer'
class MailPref < ActiveRecord::Base
belongs_to :customer
def MailPref.find_by_customer(customer_id)
find_first(["customer_id = #{customer_id}"])
end
end

View file

@ -0,0 +1,75 @@
require 'mail2screen'
class MailTransform
include Mail2Screen
def get_body(tmail, type)
@mail = tmail
footer = ""
msg_id = ""
ret = mail2html(tmail, msg_id)
ret = ret.gsub(/<br\/>/,"\n").gsub(/&nbsp;/, " ").gsub(/&lt;/, "<").gsub(/&gt;/, ">").gsub(/&amp;/, "&").gsub(/<hr\/>/, "\n").gsub(/\n/, "\n> ") if type == 'text/plain'
ret = ret.gsub(/\r\n/,"<br/>").gsub(/\r/, "<br/>").gsub(/\n/,"<br/>").gsub(/<br\/>/, "<br/>&gt;&nbsp;") unless type == 'text/plain'
return ret
end
def mail2html(mail, msg_id)
footer = ""
parsed_body = create_body(mail, msg_id, footer)
ret = "-----Original Message-----\n#{_('From')}:#{address(mail.from_addrs, @msg_id)}\n"
ret << "#{_('To')}:#{address(mail.to_addrs, @msg_id)}\n"
if @mail.cc_addrs
ret << " #{_('CC')}:#{address(mail.cc_addrs, @msg_id)}\n"
end
if @mail.bcc_addrs
ret << "#{_('BCC')}:#{address(mail.bcc_addrs, @msg_id)}\n"
end
ret << "#{_('Subject')}:#{mime_encoded?(mail.subject) ? mime_decode(mail.subject) : mail.subject}\n"
ret << "#{_('Date')}:#{message_date(mail.date)}\n"
ret << "\n"
ret << "\n"
ret << parsed_body
ret << "\n"
end
def message_date(datestr)
t = Time.now
begin
if datestr.kind_of?(String)
d = (Time.rfc2822(datestr) rescue Time.parse(value)).localtime
else
d = datestr
end
if d.day == t.day and d.month == t.month and d.year == t.year
d.strftime("%H:%M")
else
d.strftime("%Y-%m-%d")
end
rescue
begin
d = imap2time(datestr)
if d.day == t.day and d.month == t.month and d.year == t.year
d.strftime("%H:%M")
else
d.strftime("%Y-%m-%d")
end
rescue
datestr
end
end
end
# Overwrite some staff
def add_to_contact(addr, msg_id)
""
end
def add_attachment(content_type, msg_id)
""
end
def add_image(content_type, msg_id)
""
end
end

View file

@ -0,0 +1,51 @@
module MaildropSerializator
def serialize_to_file
mail_drop_filter = File.new(self.mail_filter_path, "w")
for filter in filters
mail_drop_filter << "# filter '#{filter.name}'\n"
mail_drop_filter << "if (#{filter_expressions(filter)})\n"
mail_drop_filter << "{\n"
mail_drop_filter << " exception {\n"
mail_drop_filter << " to #{dest_folder(filter)}\n"
mail_drop_filter << " }\n"
mail_drop_filter << "}\n"
end
mail_drop_filter.close()
end
private
def dest_folder(filter)
'$DEFAULT/'<<filter.destination_folder.sub(Regexp.new("(#{CDF::CONFIG[:mail_inbox]})(.*)"), '\2')<<"/"
end
def escape_expr_value(text)
text.gsub(".", "\\.").gsub("*", "\\*").gsub("[", "\\[").gsub("]", "\\]").gsub("(", "\\(").gsub(")", "\\)").
gsub("?", "\\?")
end
def filter_expressions(filter)
fe = ""
for exp in filter.expressions
post_flag = "h"
fe << " && " unless fe == ""
if exp.field_name == "^Body"
fe << "/"
post_flag = "b"
else
fe << "/#{exp.field_name}:"
end
if exp.operator == 'contains'
fe << ".*(#{escape_expr_value(exp.expr_value)})/"
else
# starts with
fe << "[ ]*(#{escape_expr_value(exp.expr_value)}).*/"
end
if exp.case_sensitive == 1
fe << "D" << post_flag
else
fe << post_flag
end
end
fe
end
end

View file

@ -0,0 +1,4 @@
# Webmail mapping
map.connect 'webmail', :controller => 'webmail/webmail', :action => 'messages'

View file

@ -0,0 +1,3 @@
class VirtualEmail < ActiveRecord::Base
def self.table_name() "cdf.wm_virtual" end
end

View file

@ -0,0 +1,5 @@
<ul class="contacts">
<% for contact in @contacts do -%>
<li class="contact"><%=h contact.fname %> <%= h contact.lname %> <div class='email'><div class="notviscode">&amp;lt;</div><%= h contact.email %><div class="notviscode">&amp;gt;</div></div></li>
<% end -%>
</ul>

View file

@ -0,0 +1,18 @@
<% @expression = @expressions[expr_counter] %>
<tr>
<td>
<select name="expression[<%=expr_counter%>][field_name]">
<%= options_for_select(CDF::CONFIG[:mail_filters_fields], @expressions[expr_counter].field_name)%>
</select></td>
<td>
<select name="expression[<%=expr_counter%>][operator]">
<%= options_for_select(CDF::CONFIG[:mail_filters_expressions], @expressions[expr_counter].operator)%>
</select></td>
<td>
<%= text_field 'expression', 'expr_value', 'index'=>expr_counter %>
</td>
<td>
<%= hidden_field "expression", 'case_sensitive', 'index'=>expr_counter %>
<%= check_box "expression", 'case_sensitive', {'onclick'=>'toggleCheckbox(this)', "index"=>expr_counter } %>&nbsp; <%= _('case sensitive') %>
</td>
</tr>

View file

@ -0,0 +1,19 @@
<tr>
<td><%=h @user.filters[filter_counter].name%></th>
<td>
<% if filter_counter > 0 %>
<%=link_filter_up(@user.filters[filter_counter].id)%>
<% else %>
&nbsp;
<% end %>
</td>
<td>
<% if filter_counter < @user.filters.size - 1 %>
<%=link_filter_down(@user.filters[filter_counter].id)%>
<% else %>
&nbsp;
<% end %>
</td>
<td><%=link_filter_edit(@user.filters[filter_counter].id)%></td>
<td><%=link_filter_delete(@user.filters[filter_counter].id)%></td>
</tr>

View file

@ -0,0 +1,14 @@
<tr class="<%= message_row.unread ? 'notseen': 'seen' %>">
<td class="mark"><input type="checkbox" name="messages[<%= message_row.uid %>]"/></td>
<% if @folder_name == CDF::CONFIG[:mail_sent] %>
<td class="to"><%= short_address(message_row.to_addr) %></td>
<% else %>
<td class="from"><%= short_address(message_row.from_addr) %></td>
<% end %>
<td class="subject"><div class='cutField'>
<%= link_to(parse_subject(message_row.subject) << "&nbsp;" , :controller=>'webmail', :action=>'message', :msg_id=>message_row.uid)%>
</td>
<td class="date"><%= message_date(message_row.date) %></td>
<td class="size"><%= message_size(message_row.size) %></td>
<td class="attachind"><%= message_row.content_type == 'multipart' ? image_tag('attachment.png') : '&nbsp;' %></td>
</tr>

View file

@ -0,0 +1,13 @@
<a href='#' onclick='toggle_msg_search(true);'>
<%=_('Search')%><img id='img_msg_search' alt='open' src='/images/list_<%=@srch_img_src%>.gif'/>
</a>
<div id="msg_search" class='<%=@srch_class%>'>
<%=_('Search in message field')%>&nbsp;
<select name="search_field">
<%= options_for_select(CDF::CONFIG[:mail_search_fields], @search_field)%>
</select>&nbsp;
<label for="search_value"><%=_('for')%></label>&nbsp;
<input type="text" name="search_value" value="<%=@search_value%>" size='16' id='search_value'/>&nbsp;
<%= submit_tag(_('Search'), :name=>'op')%>&nbsp;
<%= submit_tag(_('Show all'), :name=>'op')%>
</div>

View file

@ -0,0 +1,67 @@
<h1><%=_('Mailbox')%></h1>
<form name="composeMail" id='composeMail' action="/webmail/webmail/compose" enctype="multipart/form-data" method="post">
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><span><%= _('Compose') %></span>
<ul id="secondary">
<li><%=link_compose_new%></li>
<li><a href='#' onclick="getFormField('composeMail').submit();"><%=_('Send')%></a></li>
<li><a href="#" onclick="chooseContacts();"><%= _('Choose addresses from contacts') %></a></li>
</ul>
</li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<div id="msg-compose">
<input type="hidden" id="mail_toc" name="mail[toc]" value="<%=@mail.toc%>"/>
<input type="hidden" id="mail_op" name="op" value="<%=_('Send')%>"/>
<div id="msghdr">
<table>
<tr><td><label for=''><%=_('To')%></label></td><td><%= text_field_with_auto_complete(:mail, :to, {"size"=>65}, :skip_style => true, :tokens=> ",") %></td></tr>
<tr><td><label for=''><%=_('CC')%></label></td><td><%= text_field_with_auto_complete(:mail, :cc, {"size"=>65}, :skip_style => true, :tokens=> ",") %></td></tr>
<tr><td><label for=''><%=_('BCC')%></label></td><td><%= text_field_with_auto_complete(:mail, :bcc, {"size"=>65}, :skip_style => true, :tokens=> ",") %></td></tr>
<tr><td><label for=''><%=_('Subject')%></label></td><td><%= text_field('mail', 'subject', {"size"=>65}) %></td></tr>
</table>
<%= hidden_field('mail', 'from') %>
<%= hidden_field('mail', 'content_type') %>
</div>
<div class="msgpart ct-text-plain">
<%= text_area "mail", "body", "rows"=>20, "cols"=>75 %>
</div>
<div class="msgpart">
<% if @mail.attachments and @mail.attachments.size > 0%>
<table class="attachments">
<% i = 0
@mail.attachments.each { |att| %>
<tr><td><%=attachment(att, i)%></td></tr>
<% i = i + 1
}%>
</table>
<% end %>
<hr/>
<label for="attachment"><%=_('Attachment')%>:</label><%=%><input type="file" name="attachment"/>
<input type="button" name="mail_add_attachement" value="<%=_('Add')%>"
onclick="getFormField('mail_op').value='<%=_('Add')%>';getFormField('composeMail').submit();">
</div>
</div>
</div></div>
</form>
<% content_for("scripts") { %>
<%= @additional_scripts %>
<% if ['text/html', 'multipart'].include?(@mail.content_type) %>
<%= include_tinymce %>
<% end %>
<%= javascript_include_tag "controls" %>
<%= javascript_include_tag "dragdrop" %>
<%= javascript_include_tag "effects" %>
<% %>
<% } %>

View file

@ -0,0 +1,28 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><span><%= _('Folders') %></span>
<ul id="secondary">
<li><%=link_refresh%></li>
</ul>
</li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<% content_for('sidebar') { %>
<div id="folders">
<h4><%=_('Folders')%><br/><%=link_manage_folders%></h4>
<hr/>
<%=_('Error occured obtaining connection to mail server. Please excuse us!')%>
</div>
<% } %>
<div id="messages">
</div>
</div></div>

View file

@ -0,0 +1,41 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><span><%= _('Filters') %></span></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<div id="filters">
<form action="/webmail/webmail/filter" method="post">
<%=hidden_field 'filter', 'id' %>
<table class="list" width='100%'>
<tr>
<td><label for="filter[name]"><%=_('Filter name')%></label></td>
<td colspan='3'><%=text_field 'filter', 'name' %></td>
</tr>
<tr><td colspan="4"><%=_('Messages matching')%></td></tr>
<%= render_partial_collection "expr", @expressions %>
<tr><td colspan="4"><input type="submit" name="op" value="<%=_('Add')%>"/></td></tr>
<tr>
<td><label for="filter[destination_folder]"><%=_('Will be placed in')%></label></td>
<td colspan='3'>
<select name="filter[destination_folder]">
<%= options_from_collection_for_select(@destfolders, 'name', 'name', @filter.destination_folder) %>
</select>
</td>
</tr>
<tr><td colspan="4">
<input type="submit" name="op" value="<%=_('Save')%>"/>
<input type="button" name="op" value="<%=_('Cancel')%>" onclick="changeLoc('/webmail/webmail/filters');"/>
</td></tr>
</table>
</form>
</div>
</div></div>

View file

@ -0,0 +1,39 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><span><%= _('Filters') %></span>
<ul id="secondary">
<li><%=link_filter_add%></li>
</ul>
</li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<div id="filters">
<form action="/webmail/webmail/filters" method="post">
<% if @user.filters and @user.filters.size > 0 %>
<table class="list">
<tr>
<th><%=_('Filter name')%></th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
<%= render_partial_collection "filter", @user.filters %>
</table>
<% end %>
</form>
<% if @flash['error'] %>
<div id="SystemError"><%= @flash['error'] %></div>
<% elsif @flash['status'] %>
<div id="SystemStatus"><%= @flash['status'] %></div>
<% end %>
</div>
</div></div>

View file

@ -0,0 +1,35 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><span><%= _('Folders') %></span>
<ul id="secondary">
<li><%=link_refresh%></li>
</ul>
</li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<% content_for('sidebar') { %>
<div id="folders">
<h4><%=_('Folders')%><br/><%=link_manage_folders%></h4>
<hr/>
<ul> <% for folder in @folders %>
<li><%=folder_link(folder)%></li> <% end %>
</ul>
</div>
<% } %>
<div id="messages">
<% if not(@request['msg_id'] == '') %>
<%= render_component(:controller => "webmail/webmail", :action => "message", :params => { 'msg_id' => @request['msg_id']})%>
<% else %>
<%= render_component(:controller => "webmail/webmail", :action => "messages") %>
<% end %>
</div>
</div></div>

View file

@ -0,0 +1,31 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><span><%= _('Compose') %></span>
<ul id="secondary">
<li><%=link_compose_new%></li>
</ul>
</li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<div class="msghdr">
<dl>
<dt><%=_('To')%></dt><dd><%= CGI.escapeHTML(@mail.to) %></dd>
<% if @mail.cc %>
<dt><%=_('CC')%></dt><dd><%= CGI.escapeHTML(@mail.cc) %></dd>
<% end
if @mail.bcc %>
<dt><%=_('BCC')%></dt><dd><%= CGI.escapeHTML(@mail.bcc) %></dd>
<% end %>
<dt><%=_('Subject')%></dt><dd><%= CGI.escapeHTML(@mail.subject) %></dd>
</dl>
</div>
</div>
</div>

View file

@ -0,0 +1,48 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><span><%= _('Folders') %></span>
<ul id="secondary">
<li><%=link_back_to_messages%></li>
</ul>
</li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<% content_for('sidebar') { %>
<div id="folders">
<h4><%=_('Add folder')%></h4>
<hr/>
<form action="/webmail/webmail/manage_folders" method="post">
<ul>
<li><label for='folder_name'><%=_('Name')%>:</label></li>
<li><input type="text" name="folder_name" value="" size="18" id='folder_name'/></li>
<li><input type="submit" name="op" value="<%=_('Add folder')%>"/></li>
</ul>
</form>
</div>
<% } %>
<div id="messages">
<div id='msg-fl-list'>
<table>
<thead><tr><th><%=_('Folder')%></th><th><%= _('Total messages') %></th><th><%= _('Unseen') %></th></tr></thead>
<tbody>
<% for folder in @folders %>
<tr>
<td><%=folder_manage_link(folder)%></td>
<td><%= folder.total %></td>
<td><%= folder.unseen > 0 ? "<b>#{folder.unseen}</b>" : "#{folder.unseen}" %></td></tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,48 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><span><%= _('Folders') %></span>
<ul id="secondary">
<li><%=link_refresh%></li>
</ul>
</li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<% content_for('sidebar') { %>
<div id="folders">
<h4><%=_('Folders')%><br/><%=link_manage_folders%></h4>
<hr/>
<ul> <% for folder in @folders %>
<li><%=folder_link(folder)%></li> <% end %>
</ul>
</div>
<% } %>
<div id="messages">
<div id="msgshow">
<div id="topmenu">
<ul class="actionmenu">
<li>
<%= link_to(_("&#171; Back to list"), :controller=>"/webmail/webmail", :action=>"messages") %>
</li>
<li><%=link_reply_to_sender(@msg_id)%></li>
<li><%=link_forward_message(@msg_id)%></li>
<li><%=link_flag_for_deletion(@msg_id)%></li>
<li><%=link_view_source(@msg_id)%></li>
</ul>
</div>
<%= mail2html(@mail, @msg_id) %>
</div>
</div>
</div></div>

View file

@ -0,0 +1,89 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><span><%= _('Folders') %></span>
<ul id="secondary">
<li><%=link_refresh%></li>
</ul>
</li>
<li><%=link_send_mail%></li>
<li><%=link_mail_prefs%></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<% content_for('sidebar') { %>
<div id="folders">
<h4><%=_('Folders')%><br/><%=link_manage_folders%></h4>
<hr/>
<ul> <% for folder in @folders %>
<li><%=folder_link(folder)%></li> <% end %>
</ul>
</div>
<div style="text-align: center; padding: 10px;">
<input type="button" value="<%= _('Logout')%>" onclick="window.location='/login/logout'">
</div>
<% } %>
<div id="messages">
<div id="msglist">
<h2><%= @folder_name %></h2>
<%= start_form_tag({:controller=>'/webmail/webmail', :action=>'messages'})%>
<div class='notviscode'><input type="submit" name="op" value="<%=_('Search')%>" /></div>
<input type="hidden" name="page" value="<%=@page%>"/>
<a href='#' onclick='toggle_msg_operations(true);'>
<%=_('Operations')%><img id='img_msgops' alt='open' src='/images/list_<%=@ops_img_src%>.gif'/>
</a>
<div id="msgops" class='<%=@ops_class%>'>
<h4><%=_('Operations on marked messages')%></h4>
<span id="opch">
<%= submit_tag(_('delete'), :name=>'op')%>
<%= submit_tag(_('copy'), :name=> 'op')%>
<%= submit_tag(_('move'), :name=>'op')%>
<%= submit_tag(_('mark read'), :name=>'op')%>
<%= submit_tag(_('mark unread'), :name=>'op')%>
</span><br/>
<span id="destp">
<%=_('Destination for move and copy operations')%>&nbsp;
<select name="cpdest" size="1">
<% for folder in @folders %>
<option value="<%=folder.name%>"><%=folder.name%></option>
<% end %>
</select>
</span>
</div>
<%= render_partial "search" %>
<%= page_navigation_webmail @pages if @pages.page_count > 1 %>
<table width='98%'>
<thead>
<tr>
<th width="1%"><input type="checkbox" name="allbox" onclick="checkAll(this.form)" style="margin: 0 0 0 4px" /></th>
<% if @folder_name == CDF::CONFIG[:mail_sent] %>
<th width="20%"><%= link_to(_('To'), :controller=>'/webmail/webmail', :action=>'messages', :op=>'SORT', :page=>@page, :scc=>'to_flat')%></th>
<% else %>
<th width="20%"><%= link_to(_('From'), :controller=>'/webmail/webmail', :action=>'messages', :op=>'SORT', :page=>@page, :scc=>'from_flat')%></th>
<% end%>
<th width='60%'><%= link_to(_('Subject'), :controller=>'/webmail/webmail', :action=>'messages', :op=>'SORT', :page=>@page, :scc=>'subject')%></th>
<th><%= link_to(_('Date'), :controller=>'/webmail/webmail', :action=>'messages', :op=>'SORT', :page=>@page, :scc=>'date')%></th>
<th><%= link_to(_('Size'), :controller=>'/webmail/webmail', :action=>'messages', :op=>'SORT', :page=>@page, :scc=>'size')%></th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<% for message in @messages %>
<%= render_partial 'webmail/webmail/message_row', message %>
<% end %>
</tbody>
</table>
<%= page_navigation_webmail @pages if @pages.page_count > 1 %>
</form>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1 @@
No attachment found!

View file

@ -0,0 +1,52 @@
<h1><%=_('Mailbox')%></h1>
<div id="header">
<ul id="primary">
<li><%=link_folders%></li>
<li><%=link_send_mail%></li>
<li><span><%= _('Preferences') %></span></li>
<li><%=link_mail_filters%></li>
<li><%=link_main%></li>
</ul>
</div>
<div id="tab_main">
<div id="tab_content">
<div id="prefs">
<form action="/webmail/webmail/prefs" method="post">
<%= hidden_field "mailpref", "id" %>
<%= hidden_field "mailpref", "customer_id" %>
<table class="edit">
<%= form_input(:text_field, 'customer', 'fname', _('First name'), 'class'=>'two_columns') %>
<%= form_input(:text_field, 'customer', 'lname', _('Last name'), 'class'=>'two_columns') %>
<tr class="two_rows">
<td><label><%=_('Send type message')%></label></td>
<td><select name="mailpref[mail_type]">
<%= options_for_select(CDF::CONFIG[:mail_send_types], @mailpref.mail_type)%>
</select></td>
</tr>
<tr class="two_rows">
<td><label><%=_('Messages per page')%></label></td>
<td><select name="mailpref[wm_rows]">
<%= options_for_select(CDF::CONFIG[:mail_message_rows], @mailpref.wm_rows)%>
</select></td>
</tr>
<tr class="two_rows">
<td><label for="mailpref_check_external_mail"><%=_('Check external mail?')%></label></td>
<td>
<%=check_box('mailpref', 'check_external_mail')%>
<%=_('Note that by selecting this option webmail system will try to log you using your original email on a local server.')%>
</td>
</tr>
<tr class="two_rows">
<td colspan='2' class="buttonBar">
<input type="submit" name="op" value="<%=_('Save')%>"/>
<input type="button" value="<%=_('Cancel')%>" onclick="window.location='/webmail/webmail/folders'"/>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><%=_('Mailr')%></title>
<link rel="stylesheet" href="/stylesheets/webmail/webmail.css" type="text/css" media="screen" />
</head>
<body>
<div id="msg_source">
<%=@msg_source%>
</div>
</body>
</html>

View file

@ -0,0 +1,494 @@
require 'cdfmail'
require 'net/smtp'
require 'net/imap'
require 'mail2screen'
require 'ezcrypto'
class Webmail::WebmailController < ApplicationController
uses_component_template_root
# Administrative functions
before_filter :login_required
before_filter :obtain_cookies_for_search_and_nav, :only=>[:messages]
layout "public", :except => [:view_source, :download]
before_filter :load_imap_session
after_filter :close_imap_session
model :filter, :expression, :mail_pref, :customer
BOOL_ON = "on"
def index
redirect_to(:action=>"messages")
end
def error_connection
end
def refresh
@mailbox.reload
@folders = @mailbox.folders
redirect_to(:action=>'messages')
end
def manage_folders
if operation_param == _('Add folder')
@mailbox.create_folder(CDF::CONFIG[:mail_inbox]+"."+@params["folder_name"])
elsif operation_param == _('(Delete)')
@mailbox.delete_folder(@params["folder_name"])
elsif operation_param == _('(Subscribe)')
elsif operation_param == _('(Select)')
end
@folders = @mailbox.folders
end
def messages
@session["return_to"] = nil
@search_field = @params['search_field']
@search_value = @params['search_value']
# handle sorting - tsort session field contains last reverse or no for field
# and lsort - last sort field
if @session['tsort'].nil? or @session['lsort'].nil?
@session['lsort'] = "DATE"
@session['tsort'] = {"DATE" => true, "FROM" => true, "SUBJECT" => true, "TO" => false}
end
case operation_param
when _('copy') # copy
msg_ids = []
messages_param.each { |msg_id, bool|
msg_ids << msg_id.to_i if bool == BOOL_ON and dst_folder != @folder_name } if messages_param
folder.copy_multiple(msg_ids, dst_folder) if msg_ids.size > 0
when _('move') # move
msg_ids = []
messages_param.each { |msg_id, bool|
msg_ids << msg_id.to_i if bool == BOOL_ON and dst_folder != @folder_name } if messages_param
folder.move_multiple(msg_ids, dst_folder) if msg_ids.size > 0
when _('delete') # delete
msg_ids = []
messages_param.each { |msg_id, bool| msg_ids << msg_id.to_i if bool == BOOL_ON } if messages_param
folder.delete_multiple(msg_ids) if msg_ids.size > 0
when _('mark read') # mark as read
messages_param.each { |msg_id, bool| msg = folder.mark_read(msg_id.to_i) if bool == BOOL_ON } if messages_param
when _('mark unread') # mark as unread
messages_param.each { |msg_id, bool| msg = folder.mark_unread(msg_id.to_i) if bool == BOOL_ON } if messages_param
when "SORT"
@session['lsort'] = sort_query = @params["scc"]
@session['tsort'][sort_query] = (@session['tsort'][sort_query]? false : true)
@search_field, @search_value = @session['search_field'], @session['search_value']
when _('Search') # search
@session['search_field'] = @search_field
@session['search_value'] = @search_value
when _('Show all') # search
@session['search_field'] = @search_field = nil
@session['search_value'] = @search_value = nil
else
# get search criteria from session
@search_field = @session['search_field']
@search_value = @session['search_value']
end
sort_query = @session['lsort']
reverse_sort = @session['tsort'][sort_query]
query = ["ALL"]
@page = @params["page"]
@page ||= @session['page']
@session['page'] = @page
if @search_field and @search_value and not(@search_field.strip() == "") and not(@search_value.strip() == "")
@pages = Paginator.new self, 0, get_mail_prefs.wm_rows, @page
@messages = folder.messages_search([@search_field, @search_value], sort_query + (reverse_sort ? ' desc' : ' asc'))
else
@pages = Paginator.new self, folder.total, get_mail_prefs.wm_rows, @page
@messages = folder.messages(@pages.current.first_item - 1, get_mail_prefs.wm_rows, sort_query + (reverse_sort ? ' desc' : ' asc'))
end
end
def delete
@msg_id = msg_id_param.to_i
folder.messages().delete(@msg_id)
redirect_to(:action=>"messages")
end
def reply # not ready at all
@msg_id = msg_id_param.to_i
@imapmail = folder.message(@msg_id)
fb = @imapmail.full_body
@tmail = TMail::Mail.parse(fb)
@mail = prepare_mail
@mail.reply(@tmail, fb, get_mail_prefs.mail_type)
render_action("compose")
end
def forward
@msg_id = msg_id_param.to_i
@imapmail = folder.message(@msg_id)
fb = @imapmail.full_body
@tmail = TMail::Mail.parse(fb)
@mail = prepare_mail
@mail.forward(@tmail, fb)
render_action("compose")
end
def compose
if @mail.nil?
operation = operation_param
if operation == _('Send')
@mail = create_mail
encmail = @mail.send_mail
get_imap_session
@mailbox.message_sent(encmail)
# delete temporary files (attachments)
@mail.delete_attachments()
return render("webmail/webmail/mailsent")
elsif operation == _('Add')
@mail = create_mail
attachment = CDF::Attachment.new(@mail)
attachment.file = @params['attachment']
else
# default - new email create
@mail = create_mail
end
end
end
def empty # empty trash folder (works for any one else :-))
folder.messages(0, -1).each{ |message|
folder.delete(message)
}
folder.expunge
redirect_to(:action=>"messages")
end
def message
@msg_id = msg_id_param
@imapmail = folder.message(@msg_id)
folder.mark_read(@imapmail.uid) if @imapmail.unread
@mail = TMail::Mail.parse(@imapmail.full_body)
end
def download
msg_id = msg_id_param
imapmail = folder.message(msg_id)
mail = TMail::Mail.parse(imapmail.full_body)
if mail.multipart?
get_parts(mail).each { |part|
return send_part(part) if part.header and part.header['content-type']['name'] == @params['ctype']
}
render("webmail/webmail/noattachment")
else
render("webmail/webmail/noattachment")
end
end
def prefs
@customer = Customer.find(logged_customer)
if not(@mailpref = MailPref.find_by_customer(logged_customer))
@mailpref = MailPref.create("customer_id"=>logged_customer)
end
if @params['op'] == _('Save')
if @params['customer']
@customer.fname = @params['customer']['fname']
@customer.lname = @params['customer']['lname']
@customer.save
end
@mailpref.attributes = @params["mailpref"]
@mailpref.save
@session["wmimapseskey"] = nil
redirect_to(:action=>"messages")
end
end
# Message filters management
def filters
end
def filter
if @params['op']
@filter = Filter.new(@params['filter'])
@filter.customer_id = logged_customer
@params['expression'].each { |index, expr| @filter.expressions << Expression.new(expr) unless expr["expr_value"].nil? or expr["expr_value"].strip == "" }
case @params['op']
when _('Add')
@filter.expressions << Expression.new
when _('Save')
if @params['filter']['id'] and @params['filter']['id'] != ""
@sf = Filter.find(@params['filter']['id'])
@sf.name, @sf.destination_folder = @filter.name, @filter.destination_folder
@sf.expressions.each{|expr| Expression.delete(expr.id) }
@filter.expressions.each {|expr| @sf.expressions << Expression.create(expr.attributes) }
else
@sf = Filter.create(@filter.attributes)
@sf.order_num = @user.filters.size
@filter.expressions.each {|expr| @sf.expressions << Expression.create(expr.attributes) }
end
# may be some validation will be needed
@sf.save
@user.serialize_to_file
return redirect_to(:action=>"filters")
end
@expressions = @filter.expressions
else
@filter = Filter.find(@params["id"]) if @params["id"]
@expressions = @filter.expressions
end
@destfolders = get_to_folders
end
def filter_delete
Filter.delete(@params["id"])
# reindex other filters
@user = Customer.find(logged_customer)
findex = 0
@user.filters.each { |filter|
findex = findex + 1
filter.order_num = findex
filter.save
}
@user.serialize_to_file
redirect_to :action=>"filters"
end
def filter_up
filt = @user.filters.find(@params['id'])
ufilt = @user.filters.find_all("order_num = #{filt.order_num - 1}").first
ufilt.order_num = ufilt.order_num + 1
filt.order_num = filt.order_num - 1
ufilt.save
filt.save
@user.serialize_to_file
redirect_to :action=>"filters"
end
def filter_down
filt = Filter.find(@params["id"])
dfilt = @user.filters[filt.order_num]
dfilt.order_num = dfilt.order_num - 1
filt.order_num = filt.order_num + 1
dfilt.save
filt.save
@user.serialize_to_file
redirect_to :action=>"filters"
end
def filter_add
@filter = Filter.new
@filter.expressions << Expression.new
@expressions = @filter.expressions
@destfolders = get_to_folders
render_action("filter")
end
# end of filters
def view_source
@msg_id = msg_id_param.to_i
@imapmail = folder.message(@msg_id)
@msg_source = CGI.escapeHTML(@imapmail.full_body).gsub("\n", "<br/>")
end
def auto_complete_for_mail_to
auto_complete_responder_for_contacts params[:mail][:to]
end
def auto_complete_for_mail_cc
auto_complete_responder_for_contacts params[:mail][:cc]
end
def auto_complete_for_mail_bcc
auto_complete_responder_for_contacts params[:mail][:bcc]
end
private
def auto_complete_responder_for_contacts(value)
# first split by "," and take last name
searchName = value.split(',').last.strip
# if there are 2 names search by them
if searchName.split.size > 1
fname, lname = searchName.split.first, searchName.split.last
conditions = ['customer_id = ? and LOWER(fname) LIKE ? and LOWER(lname) like ?', logged_customer, fname.downcase + '%', lname.downcase + '%']
else
conditions = ['customer_id = ? and LOWER(fname) LIKE ?', logged_customer, searchName.downcase + '%']
end
@contacts = Contact.find(:all, :conditions => conditions, :order => 'fname ASC',:limit => 8)
render :partial => 'contacts'
end
protected
def additional_scripts()
'<link rel="stylesheet" href="/stylesheets/webmail/webmail.css" type="text/css" media="screen" />'<<
'<script type="text/javascript" src="/javascripts/webmail.js"></script>'
end
private
def get_upass
if CDF::CONFIG[:crypt_session_pass]
EzCrypto::Key.decrypt_with_password(CDF::CONFIG[:encryption_password], CDF::CONFIG[:encryption_salt], @session["wmp"])
else
# retrun it plain
@session["wmp"]
end
end
def get_to_folders
res = Array.new
@folders.each{|f| res << f unless f.name == CDF::CONFIG[:mail_sent] or f.name == CDF::CONFIG[:mail_inbox] }
res
end
def load_imap_session
return if ['compose', 'prefs', 'error_connection'].include?(action_name)
get_imap_session
end
def get_imap_session
begin
@mailbox = IMAPMailbox.new
uname = (get_mail_prefs.check_external_mail == 1 ? user.email : user.local_email)
upass = get_upass
@mailbox.connect(uname, upass)
load_folders
rescue Exception => ex
logger.error("Exception on loggin webmail session - #{ex} - #{ex.backtrace.join("\t\n")}")
render_action "error_connection"
end
end
def close_imap_session
return if @mailbox.nil? or not(@mailbox.connected)
@mailbox.disconnect
@mailbox = nil
end
def have_to_load_folders?
return true if ['messages', 'delete', 'reply', 'forward', 'empty', 'message', 'download',
'filter', 'filter_add', 'view_source'].include?(action_name)
return false
end
def load_folders
if have_to_load_folders?()
if @params["folder_name"]
@folder_name = @params["folder_name"]
else
@folder_name = @session["folder_name"] ? @session["folder_name"] : CDF::CONFIG[:mail_inbox]
end
@session["folder_name"] = @folder_name
@folders = @mailbox.folders if @folders.nil?
end
end
def create_mail
m = CDF::Mail.new(user.mail_temporary_path)
if @params["mail"]
ma = @params["mail"]
m.body, m.content_type, m.from, m.to, m.cc, m.bcc, m.subject = ma["body"], ma["content_type"], ma["from"], ma["to"], ma["cc"], ma["bcc"], ma["subject"]
if @params["att_files"]
att_files, att_tfiles, att_ctypes = @params["att_files"], @params["att_tfiles"], @params["att_ctypes"]
att_files.each {|i, value|
att = CDF::Attachment.new(m)
att.filename, att.temp_filename, att.content_type = value, att_tfiles[i], att_ctypes[i]
}
end
else
m.from, m.content_type = user.friendlly_local_email, get_mail_prefs.mail_type
end
m.customer_id = logged_customer
m
end
def prepare_mail
m = CDF::Mail.new(user.mail_temporary_path)
m.from, m.content_type = user.friendlly_local_email, get_mail_prefs.mail_type
m
end
def user
@user = Customer.find(logged_customer) if @user.nil?
@user
end
def get_mail_prefs
if not(@mailprefs)
if not(@mailprefs = MailPref.find_by_customer(logged_customer))
@mailprefs = MailPref.create("customer_id"=>logged_customer)
end
end
@mailprefs
end
def send_part(part)
if part.content_type == "text/html"
disposition = "inline"
elsif part.content_type.include?("image/")
disposition = "inline"
else
disposition = "attachment"
end
@headers['Content-Length'] = part.body.size
@response.headers['Accept-Ranges'] = 'bytes'
@headers['Content-type'] = part.content_type.strip
@headers['Content-Disposition'] = disposition << %(; filename="#{part.header['content-type']['name']}")
render_text part.body
end
def get_parts(mail)
parts = Array.new
parts << mail
mail.parts.each { |part|
if part.multipart?
parts = parts.concat(get_parts(part))
elsif part.content_type and part.content_type.include?("rfc822")
parts = parts.concat(get_parts(TMail::Mail.parse(part.body))) << part
else
parts << part
end
}
parts
end
def obtain_cookies_for_search_and_nav
@srch_class = ((cookies['_wmlms'] and cookies['_wmlms'] == 'closed') ? 'closed' : 'open')
@srch_img_src = ((cookies['_wmlms'] and cookies['_wmlms'] == 'closed') ? 'closed' : 'opened')
@ops_class = ((cookies['_wmlmo'] and cookies['_wmlmo'] == 'closed') ? 'closed' : 'open')
@ops_img_src = ((cookies['_wmlmo'] and cookies['_wmlmo'] == 'closed') ? 'closed' : 'opened')
end
###################################################################
### Some fixed parameters and session variables
###################################################################
def folder
@folders[@folder_name]
end
def msg_id_param
@params["msg_id"]
end
def messages_param
@params["messages"]
end
def dst_folder
@params["cpdest"]
end
def operation_param
@params["op"]
end
end

View file

@ -0,0 +1,211 @@
require 'cdfutils'
require 'mail2screen'
module Webmail::WebmailHelper
include Mail2Screen
def link_folders
link_to(_('Folders'), :controller=>"/webmail/webmail", :action=>"messages")
end
def link_send_mail
link_to(_('Compose'), :controller=>"/webmail/webmail", :action=>"compose")
end
def link_compose_new
link_to(_('Compose new mail'), :controller=>"/webmail/webmail", :action=>"compose")
end
def link_refresh
link_to(_('Refresh'), :controller=>"/webmail/webmail", :action=>"refresh")
end
def link_message_list
link_to(_('Message list'), :controller=>"/webmail/webmail", :action=>"messages")
end
def link_reply_to_sender(msg_id)
link_to(_('Reply'), :controller=>"/webmail/webmail", :action=>"reply", :params=>{"msg_id"=>msg_id})
end
def link_forward_message(msg_id)
link_to(_('Forward'), :controller=>"/webmail/webmail", :action=>"forward", :params=>{"msg_id"=>msg_id})
end
def link_flag_for_deletion(msg_id)
link_to(_('Delete'), :controller=>"/webmail/webmail", :action=>"delete", :params=>{"msg_id"=>msg_id})
end
def link_view_source(msg_id)
link_to(_('View source'), {:controller=>"/webmail/webmail", :action=>"view_source", :params=>{"msg_id"=>msg_id}}, {'target'=>"_blank"})
end
def link_manage_folders
link_to(_('add/edit'), :controller=>"/webmail/webmail", :action=>"manage_folders")
end
def link_back_to_messages
link_to("&#171;" << _('Back to messages'), :controller=>"/webmail/webmail", :action=>"messages")
end
def link_mail_prefs
link_to(_('Preferences'), :controller=>"/webmail/webmail", :action=>"prefs")
end
def link_mail_filters
link_to(_('Filters'), :controller=>"/webmail/webmail", :action=>"filters")
end
def link_filter_add
link_to(_('Add filter'), :controller=>'/webmail/webmail', :action=>'filter_add')
end
def folder_link(folder)
if folder.attribs.include? :Noselect
return folder.name
end
unseen_messages = folder.unseen
if unseen_messages > 0
fn = "#{short_fn(folder)} (#{folder.unseen})"
else
fn = "#{short_fn(folder)}"
end
if folder.name == CDF::CONFIG[:mail_trash]
(unseen_messages > 0 ? "<b>" : "" ) <<
link_to( fn, :controller=>"/webmail/webmail", :action=>"messages", :params=>{"folder_name"=>folder.name}) <<
"&nbsp;" << link_to(_('(Empty)'), {:controller=>"/webmail/webmail", :action=>"empty", :params=>{"folder_name"=>folder.name}}, :confirm => _('Do you really want to empty trash?')) <<
(unseen_messages > 0 ? "</b>" : "" )
else
(unseen_messages > 0 ? "<b>" : "" ) <<
link_to( fn, :controller=>"/webmail/webmail", :action=>"messages", :params=>{"folder_name"=>folder.name}) <<
(unseen_messages > 0 ? "</b>" : "" )
end
end
def short_fn(folder)
if folder.name.include? folder.delim
"&nbsp; &nbsp;" + folder.name.split(folder.delim).last
else
folder.name
end
end
def folder_manage_link(folder)
if folder.name == CDF::CONFIG[:mail_trash] or folder.name == CDF::CONFIG[:mail_inbox] or folder.name == CDF::CONFIG[:mail_sent]
short_fn(folder)
else
return short_fn(folder) +
("&nbsp;" + link_to(_('(Delete)'), :controller=>"/webmail/webmail", :action=>"manage_folders", :params=>{"op"=>_('(Delete)'), "folder_name"=>folder.name}))
end
end
def message_date(datestr)
t = Time.now
begin
if datestr.kind_of?(String)
d = (Time.rfc2822(datestr) rescue Time.parse(value)).localtime
else
d = datestr
end
if d.day == t.day and d.month == t.month and d.year == t.year
d.strftime("%H:%M")
else
d.strftime("%Y-%m-%d")
end
rescue
begin
d = imap2time(datestr)
if d.day == t.day and d.month == t.month and d.year == t.year
d.strftime("%H:%M")
else
d.strftime("%Y-%m-%d")
end
rescue
datestr
end
end
end
def attachment(att, index)
ret = "#{att.filename}"
# todo: add link to delete attachment
#ret <<
ret << "<input type='hidden' name='att_files[#{index}]' value='#{att.filename}'/>"
ret << "<input type='hidden' name='att_tfiles[#{index}]' value='#{att.temp_filename}'/>"
ret << "<input type='hidden' name='att_ctypes[#{index}]' value='#{att.content_type}'/>"
end
def link_filter_up(filter_id)
link_to(_('Up'), :controller=>"/webmail/webmail", :action=>"filter_up", :id=>filter_id)
end
def link_filter_down(filter_id)
link_to(_('Down'), :controller=>"/webmail/webmail", :action=>"filter_down", :id=>filter_id)
end
def link_filter_edit(filter_id)
link_to(_('Edit'), :controller=>"/webmail/webmail", :action=>"filter", :id=>filter_id)
end
def link_filter_delete(filter_id)
link_to(_('Delete'), :controller=>"/webmail/webmail", :action=>"filter_delete", :id=>filter_id)
end
def page_navigation_webmail(pages)
nav = "<p class='paginator'><small>"
nav << "(#{pages.length} #{_('Pages')}) &nbsp; "
window_pages = pages.current.window.pages
nav << "..." unless window_pages[0].first?
for page in window_pages
if pages.current == page
nav << page.number.to_s << " "
else
nav << link_to(page.number, :controller=>"/webmail/webmail", :action=>'messages', :page=>page.number) << " "
end
end
nav << "..." unless window_pages[-1].last?
nav << " &nbsp; "
nav << link_to(_('First'), :controller=>"/webmail/webmail", :action=>'messages', :page=>@pages.first.number) << " | " unless @pages.current.first?
nav << link_to(_('Prev'), :controller=>"/webmail/webmail", :action=>'messages', :page=>@pages.current.previous.number) << " | " if @pages.current.previous
nav << link_to(_('Next'), :controller=>"/webmail/webmail", :action=>'messages', :page=>@pages.current.next.number) << " | " if @pages.current.next
nav << link_to(_('Last'), :controller=>"/webmail/webmail", :action=>'messages', :page=>@pages.last.number) << " | " unless @pages.current.last?
nav << "</small></p>"
return nav
end
def parse_subject(subject)
begin
if mime_encoded?(subject)
if mime_decode(subject) == ''
_('(No subject)')
else
mime_decode(subject)
end
else
if from_qp(subject) == ''
_('(No subject)')
else
from_qp(subject)
end
end
rescue Exception => ex
RAILS_DEFAULT_LOGGER.debug('Exception occured - #{ex}')
return ""
end
end
def message_size(size)
if size / (1024*1024) > 0
return "#{(size / (1024*1024)).round}&nbsp;MB"
elsif size / 1024 > 0
return "#{(size / (1024)).round}&nbsp;KB"
else
return "#{size}&nbsp;B"
end
end
end