[IMP] clean email_template module, merge email_template and mail_gateway module, developed email_gateway module. task ID-2007.

bzr revid: ysa@tinyerp.com-20110201114308-nwb7qzj8ko99eerw
This commit is contained in:
YSA (Openerp) 2011-02-01 17:13:08 +05:30
parent 91ce37a2ef
commit 1513a9ae77
48 changed files with 705 additions and 710 deletions

View File

@ -19,8 +19,9 @@
#
##############################################################################
import mail_gateway
import emails
import res_partner
import email_smtp_server
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Email Gateway System',
'version': '1.0',
'category': 'Generic Modules/Mail Service',
'description': """The generic email gateway system allows to send and receive emails
* History for Emails
* Easy Integration with any Module""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base', 'base_tools'],
'init_xml': [],
'update_xml': [
"email_view.xml",
"res_partner_view.xml",
'email_smtp_server_view.xml',
'security/ir.model.access.csv',
# 'email_smtp_server_data.xml'
],
'demo_xml': [],
'installable': True,
'active': False,
'certificate': '001056784984222247309',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -65,11 +65,11 @@ def extract_emails_from_dict(addresses={}):
result['all-recipients'].extend(emails)
return result
class email_template_account(osv.osv):
class email_smtp_server(osv.osv):
"""
Object to store email account settings
"""
_name = "email_template.account"
_name = "email.smtp_server"
_known_content_types = ['multipart/mixed',
'multipart/alternative',
'multipart/related',
@ -81,14 +81,8 @@ class email_template_account(osv.osv):
size=64, required=True,
readonly=True, select=True,
help="The description is used as the Sender name along with the provided From Email, \
unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
states={'draft':[('readonly', False)]}),
'auto_delete': fields.boolean('Auto Delete', size=64, readonly=True,
help="Permanently delete emails after sending",
states={'draft':[('readonly', False)]}),
'user':fields.many2one('res.users',
'Related User', required=True,
readonly=True, states={'draft':[('readonly', False)]}),
'email_id': fields.char('From Email',
size=120, required=True,
readonly=True, states={'draft':[('readonly', False)]} ,
@ -112,33 +106,16 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
states={'draft':[('readonly', False)]}),
'smtptls':fields.boolean('TLS',
states={'draft':[('readonly', False)]}, readonly=True),
'smtpssl':fields.boolean('SSL/TLS (only in python 2.6)',
states={'draft':[('readonly', False)]}, readonly=True),
'send_pref':fields.selection([
('html', 'HTML, otherwise Text'),
('text', 'Text, otherwise HTML'),
('alternative', 'Both HTML & Text (Alternative)'),
('mixed', 'Both HTML & Text (Mixed)')
], 'Mail Format', required=True),
'company':fields.selection([
('yes', 'Yes'),
('no', 'No')
], 'Corporate',
readonly=True,
help="Select if this mail account does not belong " \
"to specific user but to the organization as a whole. " \
"eg: info@companydomain.com",
required=True, states={
'draft':[('readonly', False)]
}),
'state':fields.selection([
('draft', 'Initiated'),
('suspended', 'Suspended'),
('approved', 'Approved')
],
'State', required=True, readonly=True),
'default': fields.boolean('Default', help="Only one account can be default at a time"),
}
_defaults = {
@ -154,12 +131,9 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
'state':lambda * a:'draft',
'smtpport':lambda *a:25,
'smtpserver':lambda *a:'localhost',
'company':lambda *a:'yes',
'user':lambda self, cursor, user, context:user,
'send_pref':lambda *a: 'html',
'smtptls':lambda *a:True,
}
_sql_constraints = [
(
'email_uniq',
@ -167,46 +141,34 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
'Another setting already exists with this email ID !')
]
def name_get(self, cr, uid, ids, context=None):
return [(a["id"], "%s (%s)" % (a['email_id'], a['name'])) for a in self.read(cr, uid, ids, ['name', 'email_id'], context=context)]
def _constraint_unique(self, cursor, user, ids, context=None):
"""
This makes sure that you dont give personal
users two accounts with same ID (Validated in sql constaints)
However this constraint exempts company accounts.
Any no of co accounts for a user is allowed
"""
if self.read(cursor, user, ids, ['company'])[0]['company'] == 'no':
accounts = self.search(cursor, user, [
('user', '=', user),
('company', '=', 'no')
])
if len(accounts) > 1 :
return False
else :
return True
def _constraint_unique(self, cr, uid, ids, context=None):
default_ids = self.search(cr, uid, [('default','=',True)])
if len(default_ids) > 1:
return False
else:
return True
_constraints = [
(_constraint_unique,
'Error: You are not allowed to have more than 1 account.',
'Error: You are not allowed to set default more than 1 account.',
[])
]
def name_get(self, cr, uid, ids, context=None):
return [(a["id"], "%s (%s)" % (a['email_id'], a['name'])) for a in self.read(cr, uid, ids, ['name', 'email_id'], context=context)]
def get_outgoing_server(self, cursor, user, ids, context=None):
"""
Returns the Out Going Connection (SMTP) object
@attention: DO NOT USE except_osv IN THIS METHOD
@param cursor: Database Cursor
@param user: ID of current user
@param ids: ID/list of ids of current object for
@param ids: ID/list of ids of current object for
which connection is required
First ID will be chosen from lists
@param context: Context
@return: SMTP server object or Exception
"""
#Type cast ids to integer
@ -214,7 +176,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
ids = ids[0]
this_object = self.browse(cursor, user, ids, context=context)
if this_object:
if this_object.smtpserver and this_object.smtpport:
if this_object.smtpserver and this_object.smtpport:
try:
if this_object.smtpssl:
serv = smtplib.SMTP_SSL(this_object.smtpserver, this_object.smtpport)
@ -234,14 +196,14 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
return serv
raise Exception(_("SMTP SERVER or PORT not specified"))
raise Exception(_("Core connection for the given ID does not exist"))
def check_outgoing_connection(self, cursor, user, ids, context=None):
"""
checks SMTP credentials and confirms if outgoing connection works
(Attached to button)
@param cursor: Database Cursor
@param user: ID of current user
@param ids: list of ids of current object for
@param ids: list of ids of current object for
which connection is required
@param context: Context
"""
@ -255,7 +217,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
_("Out going connection test failed"),
_("Reason: %s") % error
)
def do_approval(self, cr, uid, ids, context=None):
#TODO: Check if user has rights
self.write(cr, uid, ids, {'state':'approved'}, context=context)
@ -279,12 +241,12 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
else:
logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
return False
#**************************** MAIL SENDING FEATURES ***********************#
def send_mail(self, cr, uid, ids, addresses, subject='', body=None, payload=None, message_id=None, context=None):
#TODO: Replace all this with a single email object
if body is None:
@ -294,7 +256,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
if context is None:
context = {}
logger = netsvc.Logger()
for id in ids:
for id in ids:
core_obj = self.browse(cr, uid, id, context)
serv = self.smtp_connection(cr, uid, id)
if serv:
@ -307,7 +269,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
text_part = MIMEMultipart(_subtype=text_subtype)
payload_part.attach(text_part)
else:
# otherwise a single multipart/mixed will do the whole job
# otherwise a single multipart/mixed will do the whole job
payload_part = text_part = MIMEMultipart(_subtype=text_subtype)
if subject:
@ -322,7 +284,7 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
payload_part['From'] = sender_name + " <" + core_obj.email_id + ">"
payload_part['Organization'] = tools.ustr(core_obj.user.company_id.name)
payload_part['Date'] = formatdate()
addresses_l = extract_emails_from_dict(addresses)
addresses_l = extract_emails_from_dict(addresses)
if addresses_l['To']:
payload_part['To'] = u','.join(addresses_l['To'])
if addresses_l['CC']:
@ -430,28 +392,28 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
e)
)
return date_as_date
def send_receive(self, cr, uid, ids, context=None):
for id in ids:
ctx = context.copy()
ctx['filters'] = [('account_id', '=', id)]
self.pool.get('email_template.mailbox').send_all_mail(cr, uid, [], context=ctx)
return True
def decode_header_text(self, text):
""" Decode internationalized headers RFC2822.
To, CC, BCC, Subject fields can contain
To, CC, BCC, Subject fields can contain
text slices with different encodes, like:
=?iso-8859-1?Q?Enric_Mart=ED?= <enricmarti@company.com>,
=?iso-8859-1?Q?Enric_Mart=ED?= <enricmarti@company.com>,
=?Windows-1252?Q?David_G=F3mez?= <david@company.com>
Sometimes they include extra " character at the beginning/
end of the contact name, like:
"=?iso-8859-1?Q?Enric_Mart=ED?=" <enricmarti@company.com>
and decode_header() does not work well, so we use regular
and decode_header() does not work well, so we use regular
expressions (?= ? ? ?=) to split the text slices
"""
if not text:
return text
return text
p = re.compile("(=\?.*?\?.\?.*?\?=)")
text2 = ''
try:
@ -465,6 +427,6 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
return text
return text2
email_template_account()
email_smtp_server()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -2,19 +2,19 @@
<openerp>
<data>
<menuitem name="Marketing" icon="terp-crm" id="base.marketing_menu" sequence="17"
groups="marketing.group_marketing_user,marketing.group_marketing_manager"/>
<menuitem name="Marketing" icon="terp-crm" id="base.marketing_menu" sequence="17"/>
<menuitem name="Emails" id="base.menu_emails" parent="base.marketing_menu" sequence="5"/>
<menuitem name="Email Template" id="menu_email_template" parent="base.menu_emails"/>
<menuitem name="Email Smtp Server" id="menu_email_smtp" parent="base.menu_emails"/>
<record model="ir.ui.view" id="email_template_account_form">
<field name="name">email_template.account.form</field>
<field name="model">email_template.account</field>
<record model="ir.ui.view" id="email_smtp_server_form">
<field name="name">email.smtp_server.form</field>
<field name="model">email.smtp_server</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Email Account Configuration">
<form string="Email Smtp Server Configuration">
<group colspan="2">
<field name="name" select="1" />
<field name="default"/>
</group>
<notebook colspan="4">
<page string="Outgoing">
@ -25,18 +25,14 @@
<field name="smtpport" select="2" />
<field name="smtpssl" select="2" />
<field name="smtptls" select="2" />
<field name="auto_delete" />
</group>
<separator string="User Information" colspan="4" />
<group col="2" colspan="2">
<field name="email_id" select="1" colspan="2" />
<field name="smtppass" password="True" colspan="2" />
<field name="company" select="2" colspan="2" />
</group>
<group col="2" colspan="2">
<field name="smtpuname" select="1" colspan="2" />
<field name="user" select="2" colspan="2" />
<field name="send_pref" colspan="2" />
</group>
</page>
</notebook>
@ -51,53 +47,46 @@
</field>
</record>
<record model="ir.ui.view" id="email_template_account_tree">
<field name="name">email_template.account.tree</field>
<field name="model">email_template.account</field>
<record model="ir.ui.view" id="email_smtp_server_tree">
<field name="name">email.smtp_server.tree</field>
<field name="model">email.smtp_server</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree colors="blue:state in ('draft');black:state in ('suspended','approved')" string="Email Accounts">
<field name="name" />
<field name="email_id" />
<field name="smtpuname" />
<field name="user" />
<field name="smtpserver" />
<field name="smtpport" />
<field name="auto_delete" />
<field name="state" />
</tree>
</field>
</record>
<record id="view_email_template_account_search" model="ir.ui.view">
<field name="name">email_template.account.search</field>
<field name="model">email_template.account</field>
<record id="view_email_smtp_server_search" model="ir.ui.view">
<field name="name">email_smtp.server.search</field>
<field name="model">email.smtp_server</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Email Accounts">
<search string="Email Smtp Server">
<filter icon="terp-document-new" string="Draft" name="draft" domain="[('state','=','draft')]"/>
<filter icon="terp-camera_test" string="Approved" domain="[('state','=','approved')]"/>
<filter icon="terp-emblem-important" string="Suspended" domain="[('state','=','suspended')]"/>
<separator orientation="vertical"/>
<filter icon="terp-go-home" string="Company Accounts" domain="[('company','=','yes')]"/>
<separator orientation="vertical"/>
<field name="user" select="1">
<filter icon="terp-personal" help="My Accounts" name="my" domain="[('user','=',uid)]"/>
</field>
<field name="name" select="1"/>
<field name="email_id" select="1"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_email_template_account_tree_all">
<field name="name">Accounts</field>
<field name="res_model">email_template.account</field>
<record model="ir.actions.act_window" id="action_email_smtp_server_tree_all">
<field name="name">Smtp Server</field>
<field name="res_model">email.smtp_server</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="email_template_account_tree" />
<field name="view_id" ref="email_smtp_server_tree" />
<field name="context">{'group_by': [], 'search_default_draft': 1, 'search_default_my': 1}</field>
<field name="search_view_id" ref="view_email_template_account_search"/>
<field name="search_view_id" ref="view_email_smtp_server_search"/>
</record>
<menuitem name="Configuration" parent="base.marketing_menu"
@ -105,7 +94,7 @@
<menuitem name="Email Template" id="menu_email_template_configuration" parent="base.menu_marketing_config_root" />
<menuitem name="Email Accounts" id="menu_email_template_account_all" parent="menu_email_template_configuration" action="action_email_template_account_tree_all"/>
<menuitem name="Email Smtp Server" id="menu_email_smtp_server_all" parent="menu_email_template_configuration" action="action_email_smtp_server_tree_all"/>
<menuitem name="Configuration" parent="base.menu_tools"
id="base.menu_lunch_survey_root" sequence="20" />
@ -113,8 +102,8 @@
<menuitem name="Email Template" id="menu_email_template_config_tools"
parent="base.menu_lunch_survey_root" />
<menuitem name="Email Accounts" id="menu_email_account_all_tools"
parent="menu_email_template_config_tools" action="action_email_template_account_tree_all" />
<menuitem name="Email Smtp Server" id="menu_email_account_all_tools"
parent="menu_email_template_config_tools" action="action_email_smtp_server_tree_all" />
</data>
</openerp>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="email_smtp_server_administrator0" model="email.smtp_server">
<field name="name">Administrator</field>
<field eval="0" name="default"/>
<field eval="1" name="smtptls"/>
<field name="email_id">example@test.com</field>
<field name="state">draft</field>
<field eval="25" name="smtpport"/>
<field name="smtpserver">localhost</field>
<field eval="0" name="smtpssl"/>
</record>
</data>
</openerp>

View File

@ -220,7 +220,7 @@ class mailgate_message(osv.osv):
action_data = False
action_pool = self.pool.get('ir.actions.act_window')
message_pool = self.browse(cr ,uid, ids, context=context)[0]
att_ids = [x.id for x in message_pool.attachment_ids]
att_ids = [x.id for x in message_pool.attachment_ids]
action_ids = action_pool.search(cr, uid, [('res_model', '=', 'ir.attachment')])
if action_ids:
action_data = action_pool.read(cr, uid, action_ids[0], context=context)

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import email_gateway
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -28,11 +28,10 @@
* Easy Integration with any Module""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base'],
'depends': ['base','email'],
'init_xml': [],
'update_xml': [
"mail_gateway_view.xml",
"res_partner_view.xml",
"email_gateway_view.xml",
'security/ir.model.access.csv'
],

View File

@ -0,0 +1,231 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
from osv import osv, fields
import time
import tools
import binascii
import email
from email.header import decode_header
from email.utils import parsedate
import base64
import re
from tools.translate import _
import logging
import xmlrpclib
_logger = logging.getLogger('mailgate')
def format_date_tz(date, tz=None):
if not date:
return 'n/a'
format = tools.DEFAULT_SERVER_DATETIME_FORMAT
return tools.server_to_local_timestamp(date, format, format, tz)
class email_message(osv.osv):
'''
Mailgateway Message
'''
def open_document(self, cr, uid, ids, context=None):
""" To Open Document
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: the ID of messages
@param context: A standard dictionary
"""
action_data = False
if ids:
message_id = ids[0]
mailgate_data = self.browse(cr, uid, message_id, context=context)
model = mailgate_data.model
res_id = mailgate_data.res_id
action_pool = self.pool.get('ir.actions.act_window')
action_ids = action_pool.search(cr, uid, [('res_model', '=', model)])
if action_ids:
action_data = action_pool.read(cr, uid, action_ids[0], context=context)
action_data.update({
'domain' : "[('id','=',%d)]"%(res_id),
'nodestroy': True,
'context': {}
})
return action_data
def open_attachment(self, cr, uid, ids, context=None):
""" To Open attachments
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: the ID of messages
@param context: A standard dictionary
"""
action_data = False
action_pool = self.pool.get('ir.actions.act_window')
message_pool = self.browse(cr ,uid, ids, context=context)[0]
att_ids = [x.id for x in message_pool.attachment_ids]
action_ids = action_pool.search(cr, uid, [('res_model', '=', 'ir.attachment')])
if action_ids:
action_data = action_pool.read(cr, uid, action_ids[0], context=context)
action_data.update({
'domain': [('id','in',att_ids)],
'nodestroy': True
})
return action_data
def truncate_data(self, cr, uid, data, context=None):
data_list = data and data.split('\n') or []
if len(data_list) > 3:
res = '\n\t'.join(data_list[:3]) + '...'
else:
res = '\n\t'.join(data_list)
return res
def _get_display_text(self, cr, uid, ids, name, arg, context=None):
if context is None:
context = {}
tz = context.get('tz')
result = {}
for message in self.browse(cr, uid, ids, context=context):
msg_txt = ''
if message.history:
msg_txt += (message.email_from or '/') + _(' wrote on ') + format_date_tz(message.date, tz) + ':\n\t'
if message.description:
msg_txt += self.truncate_data(cr, uid, message.description, context=context)
else:
msg_txt = (message.user_id.name or '/') + _(' on ') + format_date_tz(message.date, tz) + ':\n\t'
if message.name == _('Opportunity'):
msg_txt += _("Converted to Opportunity")
elif message.name == _('Note'):
msg_txt = (message.user_id.name or '/') + _(' added note on ') + format_date_tz(message.date, tz) + ':\n\t'
msg_txt += self.truncate_data(cr, uid, message.description, context=context)
elif message.name == _('Stage'):
msg_txt += _("Changed Stage to: ") + message.description
else:
msg_txt += _("Changed Status to: ") + message.name
result[message.id] = msg_txt
return result
_name = 'email.message'
_description = 'Email Message'
_order = 'date desc'
_columns = {
'name':fields.text('Subject', readonly=True),
'model': fields.char('Object Name', size=128, select=1, readonly=True),
'res_id': fields.integer('Resource ID', select=1, readonly=True),
'ref_id': fields.char('Reference Id', size=256, readonly=True, help="Message Id in Email Server.", select=True),
'date': fields.datetime('Date', readonly=True),
'history': fields.boolean('Is History?', readonly=True),
'user_id': fields.many2one('res.users', 'User Responsible', readonly=True),
'message': fields.text('Description', readonly=True),
'email_from': fields.char('From', size=128, help="Email From", readonly=True),
'email_to': fields.char('To', help="Email Recipients", size=256, readonly=True),
'email_cc': fields.char('Cc', help="Carbon Copy Email Recipients", size=256, readonly=True),
'email_bcc': fields.char('Bcc', help='Blind Carbon Copy Email Recipients', size=256, readonly=True),
'message_id': fields.char('Message Id', size=1024, readonly=True, help="Message Id on Email.", select=True),
'references': fields.text('References', readonly=True, help="References emails."),
'description': fields.text('Description', readonly=True),
'partner_id': fields.many2one('res.partner', 'Partner', required=False),
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments', readonly=True),
'display_text': fields.function(_get_display_text, method=True, type='text', size="512", string='Display Text'),
'reply_to':fields.char('Reply-To', size=250, readonly=True),
}
def init(self, cr):
cr.execute("""SELECT indexname
FROM pg_indexes
WHERE indexname = 'mailgate_message_res_id_model_idx'""")
if not cr.fetchone():
cr.execute("""CREATE INDEX mailgate_message_res_id_model_idx
ON mailgate_message (model, res_id)""")
# def run_mail_scheduler(self, cursor, user, context=None):
# """
# This method is called by OpenERP Scheduler
# to periodically send emails
# """
# try:
# self.send_all_mail(cursor, user, context=context)
# except Exception, e:
# LOGGER.notifyChannel(
# "Email Template",
# netsvc.LOG_ERROR,
# _("Error sending mail: %s") % e)
#
# def send_all_mail(self, cr, uid, ids=None, context=None):
# if ids is None:
# ids = []
# if context is None:
# context = {}
# filters = [('folder', '=', 'outbox'), ('state', '!=', 'sending')]
# if 'filters' in context.keys():
# for each_filter in context['filters']:
# filters.append(each_filter)
# ids = self.search(cr, uid, filters, context=context)
# self.write(cr, uid, ids, {'state':'sending'}, context)
# self.send_this_mail(cr, uid, ids, context)
# return True
#
# def send_this_mail(self, cr, uid, ids=None, context=None):
# #previous method to send email (link with email account can be found at the revision 4172 and below
# result = True
# attachment_pool = self.pool.get('ir.attachment')
# for id in (ids or []):
# try:
# account_obj = self.pool.get('email.smtp_server')
# values = self.read(cr, uid, id, [], context)
# payload = {}
# if values['attachments_ids']:
# for attid in values['attachments_ids']:
# attachment = attachment_pool.browse(cr, uid, attid, context)#,['datas_fname','datas'])
# payload[attachment.datas_fname] = attachment.datas
# result = account_obj.send_mail(cr, uid,
# [values['account_id'][0]],
# {'To':values.get('email_to') or u'',
# 'CC':values.get('email_cc') or u'',
# 'BCC':values.get('email_bcc') or u'',
# 'Reply-To':values.get('reply_to') or u''},
# values['subject'] or u'',
# {'text':values.get('body_text') or u'', 'html':values.get('body_html') or u''},
# payload=payload,
# message_id=values['message_id'],
# context=context)
# if result == True:
# account = account_obj.browse(cr, uid, values['account_id'][0], context=context)
# if account.auto_delete:
# self.write(cr, uid, id, {'folder': 'trash'}, context=context)
# self.unlink(cr, uid, [id], context=context)
# # Remove attachments for this mail
# attachment_pool.unlink(cr, uid, values['attachments_ids'], context=context)
# else:
# self.write(cr, uid, id, {'folder':'sent', 'state':'na', 'date_mail':time.strftime("%Y-%m-%d %H:%M:%S")}, context)
# else:
# error = result['error_msg']
#
# except Exception, error:
# logger = netsvc.Logger()
# logger.notifyChannel("email-template", netsvc.LOG_ERROR, _("Sending of Mail %s failed. Probable Reason:Could not login to server\nError: %s") % (id, error))
# self.write(cr, uid, id, {'state':'na'}, context)
# return result
email_message()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,119 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_email_message_form">
<field name="name">email.message.form</field>
<field name="model">email.message</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Email message">
<group colspan="4" col="6">
<field name="name" string="Subject" required="1"/>
<field name="date" required="1"/>
<field name="user_id" string="Owner"/>
<field name="partner_id" readonly="1" />
</group>
<notebook colspan="4">
<page string="Details">
<group col="2" colspan="2">
<separator string="Email Followers" colspan="4"/>
<field name="email_from" />
<field name="email_to"/>
<field name="email_cc"/>
<field name="email_bcc" groups="base.group_extended"/>
<field name="reply_to"/>
</group>
<group col="2" colspan="2">
<separator string="Message Details" colspan="4"/>
<field name="model" readonly="1"/>
<group col="3" colspan="2">
<field name="res_id" readonly="1"/>
<button name="open_document" string="Open Document" type="object" icon="gtk-jump-to"/>
</group>
<field name="message_id"/>
<field name="ref_id"/>
</group>
<separator string="Description" colspan="4"/>
<field name="description" nolabel="1" colspan="4" />
</page>
<page string="Attachments">
<separator string="Attachments" colspan="4"/>
<field name="attachment_ids" nolabel="1" colspan="4" readonly="1"/>
</page>
</notebook>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_email_message_tree">
<field name="name">email.message.tree</field>
<field name="model">email.message</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Emails">
<field name="date" />
<field name="name" string="Subject"/>
<field name="email_from" string="From"/>
<field name="user_id" string="Owner"/>
<field name="message_id" string="Message" invisible="1"/>
<field name="partner_id" invisible="1"/>
<button name="open_document" string="Open Document" type="object" icon="gtk-jump-to"/>
<button name="open_attachment" string="Open Attachments" type="object" icon="gtk-jump-to"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_email_message_search">
<field name="name">email.message.search</field>
<field name="model">email.message</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Email Search">
<field name="name" string="Subject"/>
<field name="date" />
<field name="user_id" string="Owner"/>
<field name="partner_id" string="Partner Name"/>
<newline/>
<group expand="0" string="Group By..." groups="base.group_extended">
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Owner" name="User" icon="terp-personal" context="{'group_by':'user_id'}"/>
<separator orientation="vertical"/>
<filter string="Thread" icon="terp-mail-" domain="[]" context="{'group_by':'message_id'}"/>
<separator orientation="vertical"/>
<filter string="Month" help="Creation Month" icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/>
</group>
</search>
</field>
</record>
<record id="action_view_mail_message" model="ir.actions.act_window">
<field name="name">Messages</field>
<field name="res_model">email.message</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="view_email_message_search"/>
</record>
<act_window domain="[('partner_id', '=', active_id), ('history', '=', True)]"
id="act_res_partner_emails" name="Emails"
res_model="mailgate.message"
src_model="res.partner"
view_id="view_email_message_tree"/>
<act_window
id="act_res_partner_open_email" name="Attachments"
res_model="ir.attachment"
src_model="mailgate.message"
domain="[('res_id', '=', res_id),('res_model','=',model)]"/>
<menuitem name="Email Template" id="menu_email_template_tools"
parent="base.menu_tools" />
<menuitem name="Emails"
id="menu_email_message"
parent="menu_email_template_tools"
action="action_view_mail_message" />
</data>
</openerp>

View File

@ -0,0 +1 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink

View File

@ -20,8 +20,6 @@
#
##############################################################################
import email_template_account
import email_template
import email_template_mailbox
import wizard

View File

@ -26,18 +26,16 @@
"author" : "Openlabs",
"website" : "http://openerp.com",
"category" : "Added functionality",
"depends" : ['marketing', 'base_tools'],
"depends" : ['marketing', 'base_tools', 'email'],
"description": """
Email Template is extraction of Power Email basically just to send the emails.
""",
"init_xml": ['email_template_scheduler_data.xml'],
"update_xml": [
'security/email_template_security.xml',
'email_template_workflow.xml',
'email_template_account_view.xml',
'email_template_view.xml',
'email_template_mailbox_view.xml',
'wizard/email_template_send_wizard_view.xml',
'wizard/email_template_preview_view.xml',
'security/ir.model.access.csv'
],
"installable": True,

View File

@ -36,17 +36,6 @@ try:
TEMPLATE_ENGINES.append(('mako', 'Mako Templates'))
except ImportError:
logging.getLogger('init').warning("module email_template: Mako templates not installed")
try:
from django.template import Context, Template as DjangoTemplate
#Workaround for bug:
#http://code.google.com/p/django-tagging/issues/detail?id=110
from django.conf import settings
settings.configure()
#Workaround ends
TEMPLATE_ENGINES.append(('django', 'Django Template'))
except ImportError:
logging.getLogger('init').warning("module email_template: Django templates not installed")
import tools
import pooler
@ -117,7 +106,7 @@ class email_template(osv.osv):
'object_name':fields.many2one('ir.model', 'Resource'),
'model_int_name':fields.char('Model Internal Name', size=200,),
'from_account':fields.many2one(
'email_template.account',
'email.smtp_server',
string="Email Account",
help="Emails will be sent from this approved account."),
'def_to':fields.char(
@ -250,7 +239,8 @@ This is useful for CRM leads for example"),
TEMPLATE_ENGINES,
'Templating Language',
required=True
)
),
'auto_delete': fields.boolean('Auto Delete', help="Permanently delete emails after sending"),
}
_defaults = {
@ -542,7 +532,7 @@ This is useful for CRM leads for example"),
context = {}
#If account to send from is in context select it, else use enforced account
if 'account_id' in context.keys():
from_account = self.pool.get('email_template.account').read(
from_account = self.pool.get('email.smtp_server').read(
cursor,
user,
context.get('account_id'),
@ -708,115 +698,7 @@ This is useful for CRM leads for example"),
email_template()
## FIXME: this class duplicates a lot of features of the email template send wizard,
## one of the 2 should inherit from the other!
class email_template_preview(osv.osv_memory):
_name = "email_template.preview"
_description = "Email Template Preview"
def _get_model_recs(self, cr, uid, context=None):
if context is None:
context = {}
#Fills up the selection box which allows records from the selected object to be displayed
self.context = context
if 'template_id' in context:
ref_obj_id = self.pool.get('email.template').read(cr, uid, context['template_id'], ['object_name'], context)
ref_obj_name = self.pool.get('ir.model').read(cr, uid, ref_obj_id['object_name'][0], ['model'], context)['model']
model_obj = self.pool.get(ref_obj_name)
ref_obj_ids = model_obj.search(cr, uid, [], 0, 20, 'id', context=context)
if not ref_obj_ids:
ref_obj_ids = []
# also add the default one if requested, otherwise it won't be available for selection:
default_id = context.get('default_rel_model_ref')
if default_id and default_id not in ref_obj_ids:
ref_obj_ids.insert(0, default_id)
return model_obj.name_get(cr, uid, ref_obj_ids, context)
return []
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
result = super(email_template_preview, self).default_get(cr, uid, fields, context=context)
if (not fields or 'rel_model_ref' in fields) and 'template_id' in context \
and not result.get('rel_model_ref'):
selectables = self._get_model_recs(cr, uid, context=context)
result['rel_model_ref'] = selectables and selectables[0][0] or False
return result
def _default_model(self, cursor, user, context=None):
"""
Returns the default value for model field
@param cursor: Database Cursor
@param user: ID of current user
@param context: OpenERP Context
"""
return self.pool.get('email.template').read(
cursor,
user,
context['template_id'],
['object_name'],
context).get('object_name', False)
_columns = {
'ref_template':fields.many2one(
'email.template',
'Template', readonly=True),
'rel_model':fields.many2one('ir.model', 'Model', readonly=True),
'rel_model_ref':fields.selection(_get_model_recs, 'Referred Document'),
'to':fields.char('To', size=250, readonly=True),
'cc':fields.char('CC', size=250, readonly=True),
'bcc':fields.char('BCC', size=250, readonly=True),
'reply_to':fields.char('Reply-To',
size=250,
help="The address recipients should reply to,"
" if different from the From address."
" Placeholders can be used here."),
'message_id':fields.char('Message-ID',
size=250,
help="The Message-ID header value, if you need to"
"specify it, for example to automatically recognize the replies later."
" Placeholders can be used here."),
'subject':fields.char('Subject', size=200, readonly=True),
'body_text':fields.text('Body', readonly=True),
'body_html':fields.text('Body', readonly=True),
'report':fields.char('Report Name', size=100, readonly=True),
}
_defaults = {
'ref_template': lambda self, cr, uid, ctx:ctx['template_id'] or False,
'rel_model': _default_model,
}
def on_change_ref(self, cr, uid, ids, rel_model_ref, context=None):
if context is None:
context = {}
if not rel_model_ref:
return {}
vals = {}
if context == {}:
context = self.context
template = self.pool.get('email.template').browse(cr, uid, context['template_id'], context)
#Search translated template
lang = get_value(cr, uid, rel_model_ref, template.lang, template, context)
if lang:
ctx = context.copy()
ctx.update({'lang':lang})
template = self.pool.get('email.template').browse(cr, uid, context['template_id'], ctx)
vals['to'] = get_value(cr, uid, rel_model_ref, template.def_to, template, context)
vals['cc'] = get_value(cr, uid, rel_model_ref, template.def_cc, template, context)
vals['bcc'] = get_value(cr, uid, rel_model_ref, template.def_bcc, template, context)
vals['reply_to'] = get_value(cr, uid, rel_model_ref, template.reply_to, template, context)
if template.message_id:
vals['message_id'] = get_value(cr, uid, rel_model_ref, template.message_id, template, context)
elif template.track_campaign_item:
vals['message_id'] = tools.misc.generate_tracking_message_id(rel_model_ref)
vals['subject'] = get_value(cr, uid, rel_model_ref, template.def_subject, template, context)
vals['body_text'] = get_value(cr, uid, rel_model_ref, template.def_body_text, template, context)
vals['body_html'] = get_value(cr, uid, rel_model_ref, template.def_body_html, template, context)
vals['report'] = get_value(cr, uid, rel_model_ref, template.file_name, template, context)
return {'value':vals}
email_template_preview()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,213 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
from osv import osv, fields
import time
import netsvc
from tools.translate import _
import tools
LOGGER = netsvc.Logger()
class email_template_mailbox(osv.osv):
_name = "email_template.mailbox"
_description = 'Email Mailbox'
_rec_name = "subject"
_order = "date_mail desc"
def run_mail_scheduler(self, cursor, user, context=None):
"""
This method is called by OpenERP Scheduler
to periodically send emails
"""
try:
self.send_all_mail(cursor, user, context=context)
except Exception, e:
LOGGER.notifyChannel(
"Email Template",
netsvc.LOG_ERROR,
_("Error sending mail: %s") % e)
def send_all_mail(self, cr, uid, ids=None, context=None):
if ids is None:
ids = []
if context is None:
context = {}
filters = [('folder', '=', 'outbox'), ('state', '!=', 'sending')]
if 'filters' in context.keys():
for each_filter in context['filters']:
filters.append(each_filter)
ids = self.search(cr, uid, filters, context=context)
self.write(cr, uid, ids, {'state':'sending'}, context)
self.send_this_mail(cr, uid, ids, context)
return True
def send_this_mail(self, cr, uid, ids=None, context=None):
#previous method to send email (link with email account can be found at the revision 4172 and below
result = True
attachment_pool = self.pool.get('ir.attachment')
for id in (ids or []):
try:
account_obj = self.pool.get('email_template.account')
values = self.read(cr, uid, id, [], context)
payload = {}
if values['attachments_ids']:
for attid in values['attachments_ids']:
attachment = attachment_pool.browse(cr, uid, attid, context)#,['datas_fname','datas'])
payload[attachment.datas_fname] = attachment.datas
result = account_obj.send_mail(cr, uid,
[values['account_id'][0]],
{'To':values.get('email_to') or u'',
'CC':values.get('email_cc') or u'',
'BCC':values.get('email_bcc') or u'',
'Reply-To':values.get('reply_to') or u''},
values['subject'] or u'',
{'text':values.get('body_text') or u'', 'html':values.get('body_html') or u''},
payload=payload,
message_id=values['message_id'],
context=context)
if result == True:
account = account_obj.browse(cr, uid, values['account_id'][0], context=context)
if account.auto_delete:
self.write(cr, uid, id, {'folder': 'trash'}, context=context)
self.unlink(cr, uid, [id], context=context)
# Remove attachments for this mail
attachment_pool.unlink(cr, uid, values['attachments_ids'], context=context)
else:
self.write(cr, uid, id, {'folder':'sent', 'state':'na', 'date_mail':time.strftime("%Y-%m-%d %H:%M:%S")}, context)
self.historise(cr, uid, [id], "Email sent successfully", context)
else:
error = result['error_msg']
self.historise(cr, uid, [id], error, context)
except Exception, error:
logger = netsvc.Logger()
logger.notifyChannel("email-template", netsvc.LOG_ERROR, _("Sending of Mail %s failed. Probable Reason:Could not login to server\nError: %s") % (id, error))
self.historise(cr, uid, [id], error, context)
self.write(cr, uid, id, {'state':'na'}, context)
return result
def historise(self, cr, uid, ids, message='', context=None):
for id in ids:
history = self.read(cr, uid, id, ['history'], context).get('history', '')
self.write(cr, uid, id, {'history': (history or '' )+ "\n" + time.strftime("%Y-%m-%d %H:%M:%S") + ": " + tools.ustr(message)}, context)
_columns = {
'email_from':fields.char(
'From',
size=64),
'email_to':fields.char(
'Recipient (To)',
size=250,),
'email_cc':fields.char(
'CC',
size=250),
'email_bcc':fields.char(
'BCC',
size=250),
'reply_to':fields.char(
'Reply-To',
size=250),
'message_id':fields.char(
'Message-ID',
size=250),
'subject':fields.char(
'Subject',
size=200,),
'body_text':fields.text(
'Standard Body (Text)'),
'body_html':fields.text(
'Body (Rich Text Clients Only)'),
'attachments_ids':fields.many2many(
'ir.attachment',
'mail_attachments_rel',
'mail_id',
'att_id',
'Attachments'),
'account_id' :fields.many2one(
'email_template.account',
'User account',
required=True),
'user':fields.related(
'account_id',
'user',
type="many2one",
relation="res.users",
string="User"),
'server_ref':fields.integer(
'Server Reference of mail',
help="Applicable for inward items only"),
'mail_type':fields.selection([
('multipart/mixed',
'Has Attachments'),
('multipart/alternative',
'Plain Text & HTML with no attachments'),
('multipart/related',
'Intermixed content'),
('text/plain',
'Plain Text'),
('text/html',
'HTML Body'),
], 'Mail Contents'),
#I like GMAIL which allows putting same mail in many folders
#Lets plan it for 0.9
'folder':fields.selection([
('drafts', 'Drafts'),
('outbox', 'Outbox'),
('trash', 'Trash'),
('sent', 'Sent Items'),
], 'Folder', required=True),
'state':fields.selection([
('na', 'Not Applicable'),
('sending', 'Sending'),
], 'Status', required=True),
'date_mail':fields.datetime('Rec/Sent Date', help="Date on which Email Sent or Received"),
'history':fields.text(
'History',
readonly=True,
store=True)
}
_defaults = {
'state': lambda * a: 'na',
'folder': lambda * a: 'outbox',
}
def unlink(self, cr, uid, ids, context=None):
"""
It just changes the folder of the item to "Trash", if it is no in Trash folder yet,
or completely deletes it if it is already in Trash.
"""
to_update = []
to_remove = []
for mail in self.browse(cr, uid, ids, context=context):
if mail.folder == 'trash':
to_remove.append(mail.id)
else:
to_update.append(mail.id)
# Changes the folder to trash
self.write(cr, uid, to_update, {'folder': 'trash'}, context=context)
return super(email_template_mailbox, self).unlink(cr, uid, to_remove, context=context)
email_template_mailbox()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,134 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<!-- Email Template-->
<record model="ir.ui.view" id="email_template_mailbox_form">
<field name="name">email_template.mailbox.form</field>
<field name="model">email_template.mailbox</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Emails">
<group col="4" colspan="4" name="headers">
<field name="email_from" select="1"/>
<field name="email_to" required="1" select="1" />
<field name="reply_to" select="2"/>
<field name="email_cc" select="1"/>
<field name="email_bcc" select="2"/>
<field name="date_mail" select="2"/>
<field name="subject" colspan="4" select="1"/>
</group>
<notebook colspan="4">
<page string="Standard Body">
<separator colspan="4" string="Standard Body" />
<notebook colspan="4">
<page string="Standard Body (Text)">
<field name="body_text" nolabel="1" colspan="4" select="1"/>
</page>
<page string="Body (HTML-Web Client Only)">
<field name="body_html" nolabel="1" colspan="4" />
</page>
</notebook>
<separator colspan="4" string="" />
<group col="4" colspan="4">
<field name="state" readonly="1" string="State"/>
<button name="send_this_mail" type="object" string="Send Mail" icon="terp-mail-message-new"/>
</group>
</page>
<page string="Attachments">
<separator colspan="4" string="Attachments" />
<field name="attachments_ids" colspan="4" nolabel="1" />
</page>
<page string="Advanced">
<field name="account_id" colspan="2" />
<field name="server_ref" colspan="2" />
<field name="mail_type" colspan="2" />
<field name="folder" colspan="2" select="2"/>
<field name="message_id" select="2"/>
<separator string="History" colspan="4" />
<field name="history" nolabel="1" colspan="4"/>
</page>
</notebook>
</form>
</field>
</record>
<!--============================================= TREE VIEWS =============================================-->
<record id="view_email_template_mailbox_tree" model="ir.ui.view">
<field name="name">email_template.mailbox.tree</field>
<field name="model">email_template.mailbox</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Emails" colors="blue:folder=='drafts';grey:folder=='trash'">
<field name="subject" select="1" />
<field name="user" />
<field name="email_from" select="1" />
<field name="email_to"/>
<field name="date_mail" select="2" />
<field name="attachments_ids" select="2" />
<field name="folder" invisible="1"/>
</tree>
</field>
</record>
<record id="view_email_template_mailbox_search" model="ir.ui.view">
<field name="name">email_template.mailbox.search</field>
<field name="model">email_template.mailbox</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Emails">
<filter icon="terp-document-new" string="Drafts" name="draft" domain="[('folder','=','drafts')]"/>
<filter icon="terp-mail-" string="Outbox" name="outbox" domain="[('folder','=','outbox')]"/>
<filter icon="terp-camera_test" string="Sent" domain="[('folder','=','sent')]"/>
<filter icon="terp-mail_delete" string="Trash" domain="[('folder','=','trash')]"/>
<separator orientation="vertical"/>
<filter icon="terp-personal+" string="Personal Emails" name="personal" domain="[('account_id.company','=','no')]"/>
<filter icon="terp-go-home" string="Company Emails" name="company" domain="[('account_id.company','=','yes')]"/>
<separator orientation="vertical"/>
<field name="subject"/>
<field name="email_from"/>
<field name="user">
<filter icon="terp-personal"
string="My Emails" help="My Emails" name="myemails"
domain="[('account_id.user','=', uid)]" />
</field>
<newline/>
<field name="email_to"/>
<field name="date_mail"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_email_template_mailbox">
<field name="name">Emails</field>
<field name="res_model">email_template.mailbox</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_email_template_mailbox_tree" />
<field name="context">{'group_by': [], 'search_default_outbox': 1}</field>
<field name="help">An email template is an email document that will be sent as part of a marketing campaign. You can personalize it according to specific customer profile fields, so that a partner name or other partner related information may be inserted automatically.</field>
<field name="search_view_id" ref="view_email_template_mailbox_search"/>
</record>
<!--======================================== MENUS ========================================-->
<menuitem name="Emails"
id="menu_email_template_personal_mails"
parent="menu_email_template"
action="action_email_template_mailbox" />
<!-- Mailbox menu in Tools -->
<menuitem name="Email Template" id="menu_email_template_tools"
parent="base.menu_tools" />
<menuitem name="Emails"
id="menu_email_template_mails_tools"
parent="menu_email_template_tools"
action="action_email_template_mailbox" />
</data>
</openerp>

View File

@ -1,50 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<!-- Email Template Preview -->
<record model="ir.ui.view" id="email_template_preview_form">
<field name="name">email_template.preview.form</field>
<field name="model">email_template.preview</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Email Preview">
<group col="4" colspan="4">
<field name="rel_model" />
<field name="rel_model_ref" on_change="on_change_ref(rel_model_ref, context)"/>
</group>
<group col="8" colspan="4">
<field name="to" />
<field name="cc" />
<field name="bcc" />
<field name="reply_to" />
<field name="message_id" attrs="{'invisible':[('message_id','=',False)]}" groups="base.group_extended"/>
<field name="subject" colspan="8"/>
</group>
<group col="4" colspan="4">
<separator string= "Body(Text)" colspan="2"/>
<separator string= "Body(Html)" colspan="2"/>
<newline/>
<field name="body_text" nolabel="1" colspan="2"/>
<field name="body_html" nolabel="1" colspan="2"/>
</group>
<field name="report" colspan="2"/>
<button icon="gtk-ok" special="cancel" string="OK" colspan="1"/>
</form>
</field>
</record>
<record id="wizard_email_template_preview" model="ir.actions.act_window">
<field name="name">Template Preview</field>
<field name="res_model">email_template.preview</field>
<field name="src_model">email_template.preview</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="auto_refresh" eval="1" />
<field name="target">new</field>
<field name="context">{'template_id':active_id}</field>
</record>
<!--EMail client Form view -->
<record model="ir.ui.view" id="email_template_form">
@ -124,6 +80,7 @@
<group colspan="2" col="2">
<separator string="Advanced Options" colspan="2"/>
<field name="message_id"/>
<field name="auto_delete"/>
</group>
</group>
<group colspan="2" col="2">
@ -201,11 +158,11 @@
</record>
<menuitem name="Email Templates" id="menu_email_template_all"
parent="menu_email_template_configuration" action="action_email_template_tree_all" />
parent="email.menu_email_template_configuration" action="action_email_template_tree_all" />
<!-- Email Template menu in Tools -->
<menuitem name="Email Templates" id="menu_email_template_all_tools"
parent="menu_email_template_config_tools" action="action_email_template_tree_all" />
parent="email.menu_email_template_config_tools" action="action_email_template_tree_all" />
</data>
</openerp>

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="wkf_email_template_setting" model="workflow">
<field name="name">Email Template Workflow</field>
<field name="osv">email_template.account</field>
<field name="on_create">True</field>
</record>
<!--Activity -->
<record id="act_draft" model="workflow.activity">
<field name="wkf_id" ref="wkf_email_template_setting"/>
<field name="flow_start">True</field>
<field name="name">draft</field>
<field name="kind">function</field>
<field name="action">write({'state':'draft'})</field>
</record>
<record id="act_approved" model="workflow.activity">
<field name="name">approval</field>
<field name="wkf_id" ref="wkf_email_template_setting"/>
<field name="kind">function</field>
<field name="action">do_approval()</field>
</record>
<record id="act_suspended" model="workflow.activity">
<field name="name">suspended</field>
<field name="wkf_id" ref="wkf_email_template_setting"/>
<field name="kind">function</field>
<field name="action">write({'state':'suspended'})</field>
</record>
<record id="act_dummy" model="workflow.activity">
<field name="name">dummy</field>
<field name="wkf_id" ref="wkf_email_template_setting"/>
<field name="flow_stop">True</field>
</record>
<!-- Transition -->
<record id="trans_awaiting_approved" model="workflow.transition">
<field name="act_from" ref="act_draft"/>
<field name="act_to" ref="act_approved"/>
<field name="signal">button_approval</field>
</record>
<record id="trans_approved_suspended" model="workflow.transition">
<field name="act_from" ref="act_approved"/>
<field name="act_to" ref="act_suspended"/>
<field name="signal">button_suspended</field>
</record>
<record id="trans_suspended_reapproved" model="workflow.transition">
<field name="act_from" ref="act_suspended"/>
<field name="act_to" ref="act_draft"/>
<field name="signal">get_reapprove</field>
</record>
<record id="trans_suspended_dummy" model="workflow.transition">
<field name="act_from" ref="act_suspended"/>
<field name="act_to" ref="act_dummy"/>
<field name="signal">get_never</field>
</record>
</data>
</openerp>

View File

@ -1,10 +1,7 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_email_template_account","email_template.account","model_email_template_account","marketing.group_marketing_user",1,0,0,0
"access_email_template","email.template","model_email_template","marketing.group_marketing_user",1,0,0,0
"access_email_template_mailbox","email_template.mailbox","model_email_template_mailbox","marketing.group_marketing_user",1,1,1,1
"access_email_template_account_system","email_template.account system","model_email_template_account","base.group_system",1,1,1,1
"access_email_template_system","email.template system","model_email_template","base.group_system",1,1,1,1
"access_email_template_mailbox_system","email_template.mailbox system","model_email_template_mailbox","base.group_system",1,0,0,0
"access_email_template_account_manager","email_template.account","model_email_template_account","marketing.group_marketing_manager",1,1,1,1
"access_email_template_manager","email.template","model_email_template","marketing.group_marketing_manager",1,1,1,1
"access_email_template_mailbox_manager","email_template.mailbox","model_email_template_mailbox","marketing.group_marketing_manager",1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
access_email_template_account email_template.account model_email_template_account marketing.group_marketing_user 1 0 0 0
2 access_email_template email.template model_email_template marketing.group_marketing_user 1 0 0 0
3 access_email_template_mailbox email_template.mailbox model_email_template_mailbox marketing.group_marketing_user 1 1 1 1
access_email_template_account_system email_template.account system model_email_template_account base.group_system 1 1 1 1
4 access_email_template_system email.template system model_email_template base.group_system 1 1 1 1
5 access_email_template_mailbox_system email_template.mailbox system model_email_template_mailbox base.group_system 1 0 0 0
access_email_template_account_manager email_template.account model_email_template_account marketing.group_marketing_manager 1 1 1 1
6 access_email_template_manager email.template model_email_template marketing.group_marketing_manager 1 1 1 1
7 access_email_template_mailbox_manager email_template.mailbox model_email_template_mailbox marketing.group_marketing_manager 1 1 1 1

View File

@ -21,3 +21,4 @@
##############################################################################
import email_template_send_wizard
import email_template_preview

View File

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
from osv import osv, fields
from tools.translate import _
from email_template.email_template import get_value
class email_template_preview(osv.osv_memory):
_name = "email_template.preview"
_description = "Email Template Preview"
def _get_model_recs(self, cr, uid, context=None):
if context is None:
context = {}
#Fills up the selection box which allows records from the selected object to be displayed
self.context = context
if 'template_id' in context:
ref_obj_id = self.pool.get('email.template').read(cr, uid, context['template_id'], ['object_name'], context)
ref_obj_name = self.pool.get('ir.model').read(cr, uid, ref_obj_id['object_name'][0], ['model'], context)['model']
model_obj = self.pool.get(ref_obj_name)
ref_obj_ids = model_obj.search(cr, uid, [], 0, 20, 'id', context=context)
if not ref_obj_ids:
ref_obj_ids = []
# also add the default one if requested, otherwise it won't be available for selection:
default_id = context.get('default_rel_model_ref')
if default_id and default_id not in ref_obj_ids:
ref_obj_ids.insert(0, default_id)
return model_obj.name_get(cr, uid, ref_obj_ids, context)
return []
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
result = super(email_template_preview, self).default_get(cr, uid, fields, context=context)
if (not fields or 'rel_model_ref' in fields) and 'template_id' in context \
and not result.get('rel_model_ref'):
selectables = self._get_model_recs(cr, uid, context=context)
result['rel_model_ref'] = selectables and selectables[0][0] or False
return result
def _default_model(self, cursor, user, context=None):
"""
Returns the default value for model field
@param cursor: Database Cursor
@param user: ID of current user
@param context: OpenERP Context
"""
return self.pool.get('email.template').read(
cursor,
user,
context['template_id'],
['object_name'],
context).get('object_name', False)
_columns = {
'ref_template':fields.many2one(
'email.template',
'Template', readonly=True),
'rel_model':fields.many2one('ir.model', 'Model', readonly=True),
'rel_model_ref':fields.selection(_get_model_recs, 'Referred Document'),
'to':fields.char('To', size=250, readonly=True),
'cc':fields.char('CC', size=250, readonly=True),
'bcc':fields.char('BCC', size=250, readonly=True),
'reply_to':fields.char('Reply-To',
size=250,
help="The address recipients should reply to,"
" if different from the From address."
" Placeholders can be used here."),
'message_id':fields.char('Message-ID',
size=250,
help="The Message-ID header value, if you need to"
"specify it, for example to automatically recognize the replies later."
" Placeholders can be used here."),
'subject':fields.char('Subject', size=200, readonly=True),
'body_text':fields.text('Body', readonly=True),
'body_html':fields.text('Body', readonly=True),
'report':fields.char('Report Name', size=100, readonly=True),
}
_defaults = {
'ref_template': lambda self, cr, uid, ctx:ctx['template_id'] or False,
'rel_model': _default_model,
}
def on_change_ref(self, cr, uid, ids, rel_model_ref, context=None):
if context is None:
context = {}
if not rel_model_ref:
return {}
vals = {}
if context == {}:
context = self.context
template = self.pool.get('email.template').browse(cr, uid, context['template_id'], context)
#Search translated template
lang = get_value(cr, uid, rel_model_ref, template.lang, template, context)
if lang:
ctx = context.copy()
ctx.update({'lang':lang})
template = self.pool.get('email.template').browse(cr, uid, context['template_id'], ctx)
vals['to'] = get_value(cr, uid, rel_model_ref, template.def_to, template, context)
vals['cc'] = get_value(cr, uid, rel_model_ref, template.def_cc, template, context)
vals['bcc'] = get_value(cr, uid, rel_model_ref, template.def_bcc, template, context)
vals['reply_to'] = get_value(cr, uid, rel_model_ref, template.reply_to, template, context)
if template.message_id:
vals['message_id'] = get_value(cr, uid, rel_model_ref, template.message_id, template, context)
elif template.track_campaign_item:
vals['message_id'] = tools.misc.generate_tracking_message_id(rel_model_ref)
vals['subject'] = get_value(cr, uid, rel_model_ref, template.def_subject, template, context)
vals['body_text'] = get_value(cr, uid, rel_model_ref, template.def_body_text, template, context)
vals['body_html'] = get_value(cr, uid, rel_model_ref, template.def_body_html, template, context)
vals['report'] = get_value(cr, uid, rel_model_ref, template.file_name, template, context)
return {'value':vals}
email_template_preview()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Email Template Preview -->
<record model="ir.ui.view" id="email_template_preview_form">
<field name="name">email_template.preview.form</field>
<field name="model">email_template.preview</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Email Preview">
<group col="4" colspan="4">
<field name="rel_model" />
<field name="rel_model_ref" on_change="on_change_ref(rel_model_ref, context)"/>
</group>
<group col="8" colspan="4">
<field name="to" />
<field name="cc" />
<field name="bcc" />
<field name="reply_to" />
<field name="message_id" attrs="{'invisible':[('message_id','=',False)]}" groups="base.group_extended"/>
<field name="subject" colspan="8"/>
</group>
<group col="4" colspan="4">
<separator string= "Body(Text)" colspan="2"/>
<separator string= "Body(Html)" colspan="2"/>
<newline/>
<field name="body_text" nolabel="1" colspan="2"/>
<field name="body_html" nolabel="1" colspan="2"/>
</group>
<field name="report" colspan="2"/>
<button icon="gtk-ok" special="cancel" string="OK" colspan="1"/>
</form>
</field>
</record>
<record id="wizard_email_template_preview" model="ir.actions.act_window">
<field name="name">Template Preview</field>
<field name="res_model">email_template.preview</field>
<field name="src_model">email_template.preview</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="auto_refresh" eval="1" />
<field name="target">new</field>
<field name="context">{'template_id':active_id}</field>
</record>
</data>
</openerp>

View File

@ -51,9 +51,9 @@ class email_template_send_wizard(osv.osv_memory):
if template.from_account:
return [(template.from_account.id, '%s (%s)' % (template.from_account.name, template.from_account.email_id))]
else:
account_id = self.pool.get('email_template.account').search(cr,uid,[('company','=','no'),('user','=',uid)], context=context)
account_id = self.pool.get('email.smtp_server').search(cr,uid,[('company','=','no'),('user','=',uid)], context=context)
if account_id:
account = self.pool.get('email_template.account').browse(cr,uid,account_id, context)
account = self.pool.get('email.smtp_server').browse(cr,uid,account_id, context)
return [(r.id,r.name + " (" + r.email_id + ")") for r in account]
else:
logger.notifyChannel(_("email-template"), netsvc.LOG_ERROR, _("No personal email accounts are configured for you. \nEither ask admin to enforce an account for this template or get yourself a personal email account."))
@ -66,7 +66,7 @@ class email_template_send_wizard(osv.osv_memory):
if not id:
id = context['src_rec_ids'][0]
return get_value(cursor, user, id, message, template, context)
def _get_template(self, cr, uid, context=None):
if context is None:
context = {}
@ -116,13 +116,13 @@ class email_template_send_wizard(osv.osv_memory):
'to':fields.char('To',size=250,required=True),
'cc':fields.char('CC',size=250,),
'bcc':fields.char('BCC',size=250,),
'reply_to':fields.char('Reply-To',
size=250,
'reply_to':fields.char('Reply-To',
size=250,
help="The address recipients should reply to,"
" if different from the From address."
" Placeholders can be used here."),
'message_id':fields.char('Message-ID',
size=250,
'message_id':fields.char('Message-ID',
size=250,
help="The Message-ID header value, if you need to"
"specify it, for example to automatically recognize the replies later."
" Placeholders can be used here."),
@ -133,12 +133,12 @@ class email_template_send_wizard(osv.osv_memory):
'signature':fields.boolean('Attach my signature to mail'),
#'filename':fields.text('File Name'),
'requested':fields.integer('No of requested Mails',readonly=True),
'generated':fields.integer('No of generated Mails',readonly=True),
'generated':fields.integer('No of generated Mails',readonly=True),
'full_success':fields.boolean('Complete Success',readonly=True),
'attachment_ids': fields.many2many('ir.attachment','send_wizard_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'),
}
#FIXME: probably better by overriding default_get directly
#FIXME: probably better by overriding default_get directly
_defaults = {
'state': lambda self,cr,uid,ctx: len(ctx['src_rec_ids']) > 1 and 'multi' or 'single',
'rel_model': lambda self,cr,uid,ctx: self.pool.get('ir.model').search(cr,uid,[('model','=',ctx['src_model'])],context=ctx)[0],
@ -156,7 +156,7 @@ class email_template_send_wizard(osv.osv_memory):
'reply_to': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'reply_to', ctx),
'requested':lambda self,cr,uid,ctx: len(ctx['src_rec_ids']),
'full_success': False,
'attachment_ids': [],
'attachment_ids': [],
}
def fields_get(self, cr, uid, fields=None, context=None, write_access=True):
@ -200,7 +200,7 @@ class email_template_send_wizard(osv.osv_memory):
else:
raise osv.except_osv(_("Email Template"),_("Email sending failed for one or more objects."))
return True
def save_to_mailbox(self, cr, uid, ids, context=None):
def get_end_value(id, value):
if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets value from the template
@ -214,7 +214,7 @@ class email_template_send_wizard(osv.osv_memory):
template = self._get_template(cr, uid, context)
for id in context['src_rec_ids']:
screen_vals = self.read(cr, uid, ids[0], [],context)
account = self.pool.get('email_template.account').read(cr, uid, screen_vals['from'], context=context)
account = self.pool.get('email.smtp_server').read(cr, uid, screen_vals['from'], context=context)
vals = {
'email_from': tools.ustr(account['name']) + "<" + tools.ustr(account['email_id']) + ">",
'email_to': get_end_value(id, screen_vals['to']),