[REVIEW+IMP] email_template: inherit related improvement

bzr revid: hmo@tinyerp.com-20110214194936-92himmpn80ytmjim
This commit is contained in:
Harry (OpenERP) 2011-02-15 01:19:36 +05:30
parent 824c7f56c9
commit 72220cb09b
11 changed files with 395 additions and 638 deletions

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
# Copyright (C) 2010-Today 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
@ -19,9 +19,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
import mako_template
import email_template
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2011 OpenERP SA (<http://www.openerp.com>)
# Copyright (C) 2010-Today 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
@ -31,90 +31,46 @@ from tools.translate import _
import tools
import pooler
try:
from mako.template import Template as MakoTemplate
except ImportError:
logging.getLogger('init').warning("module email_template: Mako templates not installed")
def get_value(cursor, user, recid, message=None, template=None, context=None):
"""
Evaluates an expression and returns its value
@param cursor: Database Cursor
@param user: ID of current user
@param recid: ID of the target record under evaluation
@param message: The expression to be evaluated
@param template: BrowseRecord object of the current template
@param context: OpenERP Context
@return: Computed message (unicode) or u""
"""
pool = pooler.get_pool(cursor.dbname)
if message is None:
message = {}
#Returns the computed expression
if message:
try:
message = tools.ustr(message)
object = pool.get(template.model_int_name).browse(cursor, user, recid, context=context)
env = {
'user':pool.get('res.users').browse(cursor, user, user, context=context),
'db':cursor.dbname
}
templ = MakoTemplate(message, input_encoding='utf-8')
reply = MakoTemplate(message).render_unicode(object=object, peobject=object, env=env, format_exceptions=True)
return reply or False
except Exception:
logging.exception("can't render %r", message)
return u""
else:
return message
class email_template(osv.osv):
"Templates for sending Email"
_inherit = 'email.message'
_name = "email.template"
_description = 'Email Templates for Models'
def change_model(self, cursor, user, ids, object_name, context=None):
def get_template_value(self, cr, uid, message=None, model=None, record_id=None, context=None):
import mako_template
return mako_template.get_value(cr, uid, message=message, model=model, record_id=record_id, context=context)
def get_email_template(self, cr, uid, template_id=False, record_id=None, context=None):
"Return Template Object"
if context is None:
context = {}
if not template_id:
template_id = context.get('template_id', False)
if not template_id:
return False
template_pool = self.pool.get('email.template')
template = template_pool.browse(cr, uid, int(template_id), context)
lang = self.get_template_value(cr, uid, template.lang, template.model, record_id, context)
if lang:
# Use translated template if necessary
ctx = context.copy()
ctx['lang'] = lang
template = self.browse(cr, uid, template.id, ctx)
return template
def onchange_model_id(self, cr, uid, ids, model_id, context=None):
mod_name = False
if object_name:
mod_name = self.pool.get('ir.model').browse(cursor, user, object_name, context).model
return {'value':{'model_int_name':mod_name}}
if model_id:
mod_name = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
return {'value':{'model':mod_name}}
_columns = {
'name' : fields.char('Name', size=100, required=True),
'object_name':fields.many2one('ir.model', 'Resource'),
'model_int_name':fields.char('Model Internal Name', size=200,),
'smtp_server_id':fields.many2one(
'email.smtp_server',
string="SMTP Server",
help="Emails will be sent from this SMTP Server."),
'def_to':fields.char(
'Recipient (To)',
size=250,
help="The Recipient of email. "
"Placeholders can be used here. "
"e.g. ${object.email_to}"),
'def_cc':fields.char(
'CC',
size=250,
help="Carbon Copy address(es), comma-separated."
" Placeholders can be used here. "
"e.g. ${object.email_cc}"),
'def_bcc':fields.char(
'BCC',
size=250,
help="Blind Carbon Copy address(es), comma-separated."
" Placeholders can be used here. "
"e.g. ${object.email_bcc}"),
'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. "
"e.g. ${object.email_reply_to}"),
'message_id':fields.char('Message-ID',
size=250,
help="Specify the Message-ID SMTP header to use in outgoing emails. Please note that this overrides the Resource tracking option! Placeholders can be used here."),
'name': fields.char('Name', size=250, required=True),
'model_id':fields.many2one('ir.model', 'Resource'),
'model': fields.related('model_id', 'model', string='Model', type="char", size=128, store=True, readonly=True),
'track_campaign_item':fields.boolean('Resource Tracking',
help="Enable this is you wish to include a special \
tracking marker in outgoing emails so you can identify replies and link \
@ -126,25 +82,25 @@ This is useful for CRM leads for example"),
help="The default language for the email."
" Placeholders can be used here. "
"eg. ${object.partner_id.lang}"),
'def_subject':fields.char(
'subject':fields.char(
'Subject',
size=200,
help="The subject of email."
" Placeholders can be used here.",
translate=True),
'def_body_text':fields.text(
'description':fields.text(
'Standard Body (Text)',
help="The text version of the mail",
translate=True),
'def_body_html':fields.text(
'body_html':fields.text(
'Body (Text-Web Client Only)',
help="The text version of the mail",
translate=True),
'use_sign':fields.boolean(
'user_signature':fields.boolean(
'Signature',
help="the signature from the User details"
" will be appended to the mail"),
'file_name':fields.char(
'report_name':fields.char(
'Report Filename',
size=200,
help="Name of the generated report file. Placeholders can be used in the filename. eg: 2009_SO003.pdf",
@ -226,7 +182,7 @@ This is useful for CRM leads for example"),
context = {}
action_obj = self.pool.get('ir.actions.act_window')
for template in self.browse(cr, uid, ids, context=context):
src_obj = template.object_name.model
src_obj = template.model_id.model
vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
'name': template.name,
'type': 'ir.actions.act_window',
@ -401,197 +357,106 @@ This is useful for CRM leads for example"),
})
return {'value':result}
def _add_attachment(self, cursor, user, mailbox_id, name, data, filename, context=None):
"""
Add an attachment to a given mailbox entry.
:param data: base64 encoded attachment data to store
"""
attachment_obj = self.pool.get('ir.attachment')
attachment_data = {
'name': (name or '') + _(' (Email Attachment)'),
'datas': data,
'datas_fname': filename,
'description': name or _('No Description'),
'res_model':'email.message',
'res_id': mailbox_id,
}
attachment_id = attachment_obj.create(cursor, user, attachment_data, context)
if attachment_id:
self.pool.get('email.message').write(cursor, user, mailbox_id,
{
'attachments_ids':[(4, attachment_id)],
'mail_type':'multipart/mixed'
},
context)
def generate_attach_reports(self, cursor, user, template, record_id, mail, context=None):
"""
Generate report to be attached and attach it
to the email, and add any directly attached files as well.
@param cursor: Database Cursor
@param user: ID of User
@param template: Browse record of
template
@param record_id: ID of the target model
for which this mail has
to be generated
@param mail: Browse record of email object
@return: True
"""
if template.report_template:
reportname = 'report.' + self.pool.get('ir.actions.report.xml').browse(cursor,
user, template.report_template.id, context).report_name
service = netsvc.LocalService(reportname)
data = {}
data['model'] = template.model_int_name
(result, format) = service.create(cursor, user, [record_id], data, context)
fname = tools.ustr(get_value(cursor, user, record_id,
template.file_name, template, context)
or 'Report')
ext = '.' + format
if not fname.endswith(ext):
fname += ext
self._add_attachment(cursor, user, mail.id, mail.subject, base64.b64encode(result), fname, context)
if template.attachment_ids:
for attachment in template.attachment_ids:
self._add_attachment(cursor, user, mail.id, attachment.name, attachment.datas, attachment.datas_fname, context)
return True
def _generate_mailbox_item_from_template(self, cursor, user, template, record_id, context=None):
def _generate_email(self, cr, uid, template_id, record_id, context=None):
"""
Generates an email from the template for
record record_id of target object
@param cursor: Database Cursor
@param user: ID of User
@param template: Browse record of
template
@param record_id: ID of the target model
for which this mail has
to be generated
@return: ID of created object
"""
if context is None:
context = {}
#If account to send from is in context select it, else use enforced account
if 'account_id' in context.keys():
smtp_server_id = self.pool.get('email.smtp_server').read(cursor, user, context.get('account_id'), ['name', 'email_id'], context)
else:
smtp_server_id = {
'id':template.smtp_server_id.id,
'name':template.smtp_server_id.name,
'email_id':template.smtp_server_id.email_id
}
lang = get_value(cursor, user, record_id, template.lang, template, context)
if lang:
ctx = context.copy()
ctx.update({'lang':lang})
template = self.browse(cursor, user, template.id, context=ctx)
# determine name of sender, either it is specified in email_id or we
# use the account name
email_id = smtp_server_id['email_id'].strip()
smtp_pool = self.pool.get('email.smtp_server')
email_message_pool = self.pool.get('email.message')
report_xml_pool = self.pool.get('ir.actions.report.xml')
template = self.get_email_template(cr, uid, template_id, record_id, context)
smtp_server_id = context.get('smtp_server_id', False)
if not smtp_server_id:
smtp_server_id = template.smtp_server_id.id
smtp_server = smtp_pool.browse(cr, uid, smtp_server_id, context=context)
# determine name of sender, either it is specified in email_id
email_id = smtp_server.email_id.strip()
email_from = re.findall(r'([^ ,<@]+@[^> ,]+)', email_id)[0]
if email_from != email_id:
# we should keep it all, name is probably specified in the address
email_from = smtp_server_id['email_id']
email_from = smtp_server.email_id
else:
email_from = tools.ustr(smtp_server_id['name']) + "<" + tools.ustr(email_id) + ">"
email_from = tools.ustr(smtp_server.name) + "<" + tools.ustr(email_id) + ">"
# FIXME: should do this in a loop and rename template fields to the corresponding
# mailbox fields. (makes no sense to have different names I think.
mailbox_values = {
model = template.model
values = {
'email_from': email_from,
'email_to':get_value(cursor,
user,
record_id,
template.def_to,
template,
context),
'email_cc':get_value(cursor,
user,
record_id,
template.def_cc,
template,
context),
'email_bcc':get_value(cursor,
user,
record_id,
template.def_bcc,
template,
context),
'reply_to':get_value(cursor,
user,
record_id,
template.reply_to,
template,
context),
'subject':get_value(cursor,
user,
record_id,
template.def_subject,
template,
context),
'body_text':get_value(cursor,
user,
record_id,
template.def_body_text,
template,
context),
'body_html':get_value(cursor,
user,
record_id,
template.def_body_html,
template,
context),
#This is a mandatory field when automatic emails are sent
'state':'na',
'folder':'drafts',
'mail_type':'multipart/alternative',
'template_id': template.id
'email_to': self.get_template_value(cr, uid, template.email_to, model, record_id, context),
'email_cc': self.get_template_value(cr, uid, template.email_cc, model, record_id, context),
'email_bcc': self.get_template_value(cr, uid, template.email_bcc, model, record_id, context),
'reply_to': self.get_template_value(cr, uid, template.reply_to, model, record_id, context),
'name': self.get_template_value(cr, uid, template.subject, model, record_id, context),
'description': self.get_template_value(cr, uid, template.description, model, record_id, context),
#'body_html': self.get_template_value(cr, uid, template.body_html, model, record_id, context),
}
if template['message_id']:
if template.message_id:
# use provided message_id with placeholders
mailbox_values.update({'message_id': get_value(cursor, user, record_id, template['message_id'], template, context)})
values.update({'message_id': self.get_template_value(cr, uid, template.message_id, model, record_id, context)})
elif template['track_campaign_item']:
# get appropriate message-id
mailbox_values.update({'message_id': tools.misc.generate_tracking_message_id(record_id)})
#
# if not mailbox_values['account_id']:
# raise Exception("Unable to send the mail. No account linked to the template.")
values.update({'message_id': tools.misc.generate_tracking_message_id(record_id)})
#Use signatures if allowed
if template.use_sign:
sign = self.pool.get('res.users').read(cursor, user, user, ['signature'], context)['signature']
if mailbox_values['body_text']:
mailbox_values['body_text'] += sign
if mailbox_values['body_html']:
mailbox_values['body_html'] += sign
mailbox_id = self.pool.get('email.message').create(cursor, user, mailbox_values, context)
if template.user_signature:
sign = self.pool.get('res.users').read(cr, uid, uid, ['signature'], context)['signature']
if values['description']:
values['description'] += sign
#if values['body_html']:
# values['body_html'] += sign
attachment = []
# Add report as a Document
if template.report_template:
report_name = template.report_name
reportname = 'report.' + report_xml_pool.browse(cr, uid, template.report_template.id, context).report_name
data = {}
data['model'] = template.model
return mailbox_id
# Ensure report is rendered using template's language
ctx = context.copy()
if template.lang:
ctx['lang'] = self.get_template_value(cr, uid, template.lang, template.model, record_id, context)
service = netsvc.LocalService(reportname)
(result, format) = service.create(cr, uid, [record_id], data, ctx)
result = base64.b64encode(result)
if not report_name:
report_name = reportname
report_name = report_name + "." + format
attachment.append((report_name, result))
# Add document attachments
for attach in template.attachment_ids:
#attach = attahcment_obj.browse(cr, uid, attachment_id, context)
attachment.append((attach.datas_fname, attach.datas))
#Send emails
email_id = email_message_pool.email_send(cr, uid, values.get('email_from'), values.get('email_to'), values.get('name'), values.get('description'),
model=template.model, email_cc=values.get('email_cc'), email_bcc=values.get('email_bcc'), reply_to=values.get('reply_to'),
attach=attachment, openobject_id=record_id, debug=True, subtype='plain', x_headers={}, priority='3', smtp_server_id=smtp_server.id, context=context)
email_message_pool.write(cr, uid, email_id, {'template_id': template.id})
return email_id
def generate_mail(self, cursor, user, template_id, record_ids, context=None):
def generate_email(self, cr, uid, ids, record_ids, context=None):
if context is None:
context = {}
template = self.browse(cursor, user, template_id, context=context)
if not template:
raise Exception("The requested template could not be loaded")
result = True
mailbox_obj = self.pool.get('email.message')
for record_id in record_ids:
mailbox_id = self._generate_mailbox_item_from_template(cursor, user, template, record_id, context)
mail = mailbox_obj.browse(cursor, user, mailbox_id, context=context)
if template.report_template or template.attachment_ids:
self.generate_attach_reports(cursor, user, template, record_id, mail, context )
mailbox_obj.write(cursor, user, mailbox_id, {'folder':'outbox', 'state': 'waiting'}, context=context)
return result
email_message_pool = self.pool.get('email.message')
email_ids = []
for template in self.browse(cr, uid, ids, context=context):
for record_id in record_ids:
email_id = self._generate_email(cr, uid, template.id, record_id, context)
email_message_pool.write(cr, uid, email_id, {'folder':'outbox', 'state': 'waiting'}, context=context)
email_ids.append(email_id)
return email_ids
email_template()
class email_message(osv.osv):

View File

@ -7,38 +7,38 @@
<field name="model">email.template</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Email Templates">
<form string="Templates">
<field name="name"/>
<field name="object_name" required="1"
on_change="change_model(object_name)"/>
<field name="model_int_name" invisible="1"/>
<field name="model_id" required="1"
on_change="onchange_model_id(model_id)"/>
<field name="model" invisible="1"/>
<notebook colspan="4">
<page string="Mail Details">
<page string="Email Details">
<group col="2" colspan="2">
<separator string="Addresses" colspan="2"/>
<field name="smtp_server_id"/>
<field name="def_to" required="1"/>
<field name="def_cc"/>
<field name="def_bcc"/>
<field name="email_to" required="1"/>
<field name="email_cc"/>
<field name="email_bcc"/>
<field name="reply_to"/>
</group>
<group col="2" colspan="2">
<separator string="Options" colspan="2"/>
<field name="lang" colspan="4" />
<field name="use_sign" colspan="4" />
<field name="user_signature" colspan="4" />
<field name="track_campaign_item" colspan="4"/>
</group>
<group col="2" colspan="2">
<separator colspan="2" string="Email Content"/>
<field name="def_subject" colspan="4" required="1"/>
<field name="subject" colspan="4" required="1"/>
<notebook>
<page string="Body (Text)">
<field name="def_body_text" colspan="4" nolabel="1"/>
<page string="Body">
<field name="description" colspan="4" nolabel="1"/>
</page>
<page string="Body (Raw HTML)">
<!-- <page string="Body (Raw HTML)">
<field name="def_body_html" colspan="4" nolabel="1"/>
<label string="Note: This is Raw HTML." colspan="4"/>
</page>
</page> -->
</notebook>
</group>
<group col="4" colspan="2">
@ -60,7 +60,7 @@
</page>
</notebook>
<button name="%(wizard_email_template_preview)d" string="Preview Template"
type="action" colspan="4" target="new" icon="gtk-zoom-fit"/>
type="action" colspan="4" target="new" icon="gtk-zoom-fit" context="{'template_id':active_id}"/>
</group>
</page>
<page string="Advanced">
@ -86,8 +86,8 @@
</page>
<page string="Report">
<field name="report_template" colspan="4"
domain="[('model','=',model_int_name)]"/>
<field name="file_name" colspan="4" />
domain="[('model','=',model)]"/>
<field name="report_name" colspan="4" />
</page>
</notebook>
</group>
@ -102,16 +102,16 @@
<field name="model">email.template</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Email Templates">
<tree string="Templates">
<field name="name"/>
<field name="smtp_server_id"/>
<field name="object_name"/>
<field name="def_to"/>
<field name="def_cc"/>
<field name="def_bcc"/>
<field name="def_subject"/>
<field name="use_sign"/>
<field name="file_name"/>
<field name="model_id"/>
<field name="email_to"/>
<field name="email_cc"/>
<field name="email_bcc"/>
<field name="subject"/>
<field name="user_signature"/>
<field name="report_name"/>
<button name="%(wizard_email_template_preview)d" string="Preview Template"
type="action" target="new" icon="gtk-zoom-fit"/>
</tree>
@ -126,25 +126,25 @@
<search string="Templates">
<group col="13" colspan="4">
<field name="name"/>
<field name="object_name"/>
<field name="def_to"/>
<field name="model_id"/>
<field name="email_to"/>
<separator orientation="vertical"/>
<field name="lang"/>
<field name="def_subject"/>
<field name="file_name"/>
<field name="subject"/>
<field name="report_name"/>
</group>
<newline/>
<group expand="0" string="Group by..." colspan="4" col="10">
<filter string="Account" domain="[]" context="{'group_by':'smtp_server_id'}" icon="terp-folder-orange"/>
<filter string="SMTP Server" domain="[]" context="{'group_by':'smtp_server_id'}" icon="terp-folder-orange"/>
<separator orientation="vertical"/>
<filter string="Resource" domain="[]" context="{'group_by':'object_name'}" icon="terp-accessories-archiver"/>
<filter string="Model" domain="[]" context="{'group_by':'model_id'}" icon="terp-accessories-archiver"/>
</group>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_email_template_tree_all">
<field name="name">Email Templates</field>
<field name="name">Templates</field>
<field name="res_model">email.template</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
# Copyright (C) 2010-Today 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
@ -19,6 +19,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
import email_template_send_wizard
import email_template_preview
import email_template_send_wizard

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
# Copyright (C) 2010-Today 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
@ -22,106 +22,92 @@
from osv import osv, fields
from tools.translate import _
from email_template.email_template import get_value
import tools
class email_template_preview(osv.osv_memory):
_inherit = "email.template"
_name = "email_template.preview"
_description = "Email Template Preview"
_rec_name = "subject"
def _get_model_recs(self, cr, uid, context=None):
def get_email_template(self, cr, uid, template_id=None, record_id=None, 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').browse(cr, uid, context['template_id'], context).object_name.id
ref_obj_name = self.pool.get('ir.model').browse(cr, uid, ref_obj_id, 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 []
template_id = context.get('template_id', False)
record_id = context.get('src_rec_ids',[]) and context.get('src_rec_ids')[0]
return super(email_template_preview, self).get_email_template(cr, uid, template_id, record_id, context=context)
def _get_records(self, cr, uid, context=None):
"""
Return Records of particular Email Template's Model
"""
if context is None:
context = {}
template_id = context.get('template_id', False)
if not template_id:
return []
template_pool = self.pool.get('email.template')
model_pool = self.pool.get('ir.model')
template = template_pool.browse(cr, uid, int(template_id), context=context)
template_object = template.model_id
model = self.pool.get(template_object.model)
record_ids = model.search(cr, uid, [], 0, 20, 'id', context=context)
default_id = context.get('default_res_id')
if default_id and default_id not in record_ids:
record_ids.insert(0, default_id)
return model.name_get(cr, uid, record_ids, context)
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
template_pool = self.pool.get('email.template')
template_id = context.get('template_id',False)
if 'res_id' in fields:
records = self._get_records(cr, uid, context=context)
result['res_id'] = records and records[0][0] or False # select first record as a Default
if template_id and 'model_id' in fields:
result['model_id'] = template_pool.read(cr, uid, int(template_id), ['model_id'], context).get('model_id', 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),
'res_id':fields.selection(_get_records, 'Referred Document'),
}
_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):
def on_change_ref(self, cr, uid, ids, res_id, context=None):
if context is None:
context = {}
if not rel_model_ref:
if not res_id:
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)
context = self.context
template_pool = self.pool.get('email.template')
template = self.get_email_template(cr, uid, context)
model = template.model
vals['email_to'] = self.get_template_value(cr, uid, template.email_to, model, res_id, context)
vals['email_cc'] = self.get_template_value(cr, uid, template.email_cc, model, res_id, context)
vals['email_bcc'] = self.get_template_value(cr, uid, template.email_bcc, model, res_id, context)
vals['reply_to'] = self.get_template_value(cr, uid, template.reply_to, model, res_id, context)
if template.message_id:
vals['message_id'] = get_value(cr, uid, rel_model_ref, template.message_id, template, context)
vals['message_id'] = self.get_template_value(cr, uid, message_id, model, res_id, 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)
vals['subject'] = self.get_template_value(cr, uid, template.subject, model, res_id, context)
vals['description'] = self.get_template_value(cr, uid, template.description, model, res_id, context)
vals['body_html'] = self.get_template_value(cr, uid, template.body_html, model, res_id, context)
vals['report_name'] = self.get_template_value(cr, uid, template.report_name, model, res_id, context)
return {'value':vals}
email_template_preview()

View File

@ -9,25 +9,25 @@
<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)"/>
<field name="model_id" readonly="1"/>
<field name="res_id" on_change="on_change_ref(res_id, 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"/>
<field name="email_to" readonly="1"/>
<field name="email_cc" readonly="1"/>
<field name="email_bcc" readonly="1"/>
<field name="reply_to" readonly="1"/>
<field name="message_id" readonly="1" attrs="{'invisible':[('message_id','=',False)]}" groups="base.group_extended"/>
<field name="subject" colspan="8" readonly="1"/>
</group>
<group col="4" colspan="4">
<separator string= "Body(Text)" colspan="2"/>
<separator string= "Body(Html)" colspan="2"/>
<separator string= "Body" 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"/>
<field name="description" nolabel="1" colspan="2" readonly="1"/>
<!-- <field name="body_html" nolabel="1" colspan="2" readonly="1"/>-->
</group>
<field name="report" colspan="2"/>
<field name="report_name" colspan="2" readonly="1"/>
<button icon="gtk-ok" special="cancel" string="OK" colspan="1"/>
</form>
</field>
@ -46,4 +46,4 @@
</record>
</data>
</openerp>
</openerp>

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2009 Sharoon Thomas
# Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
# Copyright (C) 2010-Today 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
@ -21,167 +21,118 @@
##############################################################################
from osv import osv, fields
from mako.template import Template
from mako import exceptions
import netsvc
import base64
from tools.translate import _
import tools
from email_template.email_template import get_value
## FIXME: this wizard duplicates a lot of features of the email template preview,
## one of the 2 should inherit from the other!
class email_template_send_wizard(osv.osv_memory):
_name = 'email_template.send.wizard'
_inherit = 'email_template.preview'
_description = 'This is the wizard for sending mail'
_rec_name = "subject"
def _get_accounts(self, cr, uid, context=None):
if context is None:
context = {}
template = self._get_template(cr, uid, context)
if not template:
return []
logger = netsvc.Logger()
if template.smtp_server_id:
return [(template.smtp_server_id.id, '%s (%s)' % (template.smtp_server_id.name, template.smtp_server_id.email_id))]
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."))
raise osv.except_osv(_("Missing mail account"),_("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."))
def get_value(self, cursor, user, template, message, context=None, id=None):
"""Gets the value of the message parsed with the content of object id (or the first 'src_rec_ids' if id is not given)"""
if context is None:
context = {}
if not message:
return ''
if not id:
id = context.get('src_rec_ids',[]) and context.get('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 = {}
email_temp_obj = self.pool.get('email.template')
if not 'template' in context and not 'template_id' in context:
return None
if 'template_id' in context.keys():
template_ids = email_temp_obj.search(cr, uid, [('id','=',context['template_id'])], context=context)
elif 'template' in context.keys():
# Old versions of email_template used the name of the template. This caused
# problems when the user changed the name of the template, but we keep the code
# for compatibility with those versions.
template_ids = email_temp_obj.search(cr, uid, [('name','=',context['template'])], context=context)
if not template_ids:
return None
template = email_temp_obj.browse(cr, uid, template_ids[0], context)
lang = self.get_value(cr, uid, template, template.lang, context)
if lang:
# Use translated template if necessary
ctx = context.copy()
ctx['lang'] = lang
template = email_temp_obj.browse(cr, uid, template.id, ctx)
return template
def _get_template_value(self, cr, uid, field, context=None):
if context is None:
context = {}
template = self._get_template(cr, uid, context)
if not template:
return False
if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets original template values for multiple email change
return getattr(template, field)
else: # Simple Mail: Gets computed template values
return self.get_value(cr, uid, template, getattr(template, field), context)
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
result = super(email_template_send_wizard, self).default_get(cr, uid, fields, context=context)
if 'template_id' in context and context.get('template_id'):
temp_data = self.pool.get('email.template').read(cr, uid, int(context.get('template_id')), ['attachment_ids'])
result['attachment_ids'] = temp_data['attachment_ids']
template_pool = self.pool.get('email.template')
model_pool = self.pool.get('ir.model')
template_id=context.get('template_id', False)
template = self.get_email_template(cr, uid, template_id=template_id, context=context)
def _get_template_value(field):
if not template:
return False
if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets original template values for multiple email change
return getattr(template, field)
else: # Simple Mail: Gets computed template values
return self.get_template_value(cr, uid, getattr(template, field), template.model, context)
if 'user_signature' in fields:
result['user_signature'] = template.user_signature
if 'template_id' in fields:
result['template_id'] = template.id
if 'smtp_server_id' in fields:
result['smtp_server_id'] = template.smtp_server_id.id
if 'attachment_ids' in fields:
result['attachment_ids'] = template_pool.read(cr, uid, template.id, ['attachment_ids'])['attachment_ids']
if 'requested' in fields:
result['requested'] = len(context.get('src_rec_ids',''))
if 'state' in fields:
result['state'] = len(context.get('src_rec_ids','')) > 1 and 'multi' or 'single'
if 'model_id' in fields:
result['model_id'] = model_pool.search(cr, uid, [('model','=',context.get('src_model'))],context=context)[0]
if 'res_id' in fields:
result['res_id'] = context['active_id']
if 'email_to' in fields:
result['email_to'] = _get_template_value('email_to')
if 'email_cc' in fields:
result['email_cc'] = _get_template_value('email_cc')
if 'email_bcc' in fields:
result['email_bcc'] = _get_template_value('email_bcc')
if 'subject' in fields:
result['subject'] = _get_template_value('subject')
if 'description' in fields:
result['description'] = _get_template_value('description')
#if 'body_html' in fields:
# result['body_html'] = _get_template_value('body_html')
if 'reply_to' in fields:
result['reply_to'] = _get_template_value('reply_to')
if 'report_name' in fields:
result['report_name'] = _get_template_value('report_name')
return result
_columns = {
'state':fields.selection([
('single','Simple Mail Wizard Step 1'),
('multi','Multiple Mail Wizard Step 1'),
('done','Wizard Complete')
],'Status',readonly=True),
'ref_template':fields.many2one('email.template','Template',readonly=True),
'rel_model':fields.many2one('ir.model','Model',readonly=True),
'rel_model_ref':fields.integer('Referred Document',readonly=True),
'from':fields.selection(_get_accounts,'From Account',select=True),
'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,
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),
'body_text':fields.text('Body',),
'body_html':fields.text('Body',),
'report':fields.char('Report File Name',size=100,),
'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),
'full_success':fields.boolean('Complete Success',readonly=True),
'attachment_ids': fields.many2many('ir.attachment','send_wizard_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'),
'state':fields.selection([
('single','Simple Mail Wizard Step 1'),
('multi','Multiple Mail Wizard Step 1'),
('done','Wizard Complete')
],'State',readonly=True),
}
#FIXME: probably better by overriding default_get directly
_defaults = {
'state': lambda self,cr,uid,ctx: len(ctx.get('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.get('src_model'))],context=ctx)[0],
'rel_model_ref': lambda self,cr,uid,ctx: ctx['active_id'],
'to': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_to', ctx),
'cc': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_cc', ctx),
'bcc': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_bcc', ctx),
'subject':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_subject', ctx),
'body_text':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_body_text', ctx),
'body_html':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_body_html', ctx),
'report': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'file_name', ctx),
'signature': lambda self,cr,uid,ctx: self._get_template(cr, uid, ctx).use_sign,
'ref_template':lambda self,cr,uid,ctx: self._get_template(cr, uid, ctx).id,
'reply_to': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'reply_to', ctx),
'reply_to': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'reply_to', ctx),
'requested':lambda self,cr,uid,ctx: len(ctx.get('src_rec_ids','')),
}
def fields_get(self, cr, uid, fields=None, context=None, write_access=True):
if context is None:
context = {}
result = super(email_template_send_wizard, self).fields_get(cr, uid, fields, context, write_access)
if 'attachment_ids' in result and 'src_model' in context:
result['attachment_ids']['domain'] = [('res_model','=',context['src_model']),('res_id','=',context['active_id'])]
return result
#def fields_get(self, cr, uid, fields=None, context=None, write_access=True):
# if context is None:
# context = {}
# result = super(email_template_send_wizard, self).fields_get(cr, uid, fields, context, write_access)
# if 'attachment_ids' in result and 'src_model' in context:
# result['attachment_ids']['domain'] = [('res_model','=',context['src_model']),('res_id','=',context['active_id'])]
# return result
def sav_to_drafts(self, cr, uid, ids, context=None):
def save_to_drafts(self, cr, uid, ids, context=None):
if context is None:
context = {}
mailid = self.save_to_mailbox(cr, uid, ids, context=context)
self.pool.get('email.message').write(cr, uid, mailid, {'folder':'drafts', 'state': 'na'}, context)
self.pool.get('email.message').write(cr, uid, mailid, {'folder':'drafts', 'state': 'draft'}, context)
return {}
def send_mail(self, cr, uid, ids, context=None):
if context is None:
context = {}
mailid = self.save_to_mailbox(cr, uid, ids, context)
self.pool.get('email.message').write(cr, uid, mailid, {'folder':'outbox', 'state': 'waiting'}, context)
return {}
def get_generated(self, cr, uid, ids=None, context=None):
@ -194,7 +145,6 @@ class email_template_send_wizard(osv.osv_memory):
#Means there are multiple items selected for email.
mail_ids = self.save_to_mailbox(cr, uid, ids, context)
if mail_ids:
self.pool.get('email.message').write(cr, uid, mail_ids, {'folder':'outbox', 'state': 'waiting'}, context)
logger.notifyChannel("email-template", netsvc.LOG_INFO, _("Emails for multiple items saved in outbox."))
self.write(cr, uid, ids, {
'generated':len(mail_ids),
@ -205,75 +155,18 @@ class email_template_send_wizard(osv.osv_memory):
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
return self.get_value(cr, uid, template, value, context, id)
else:
return value
if context is None:
context = {}
mail_ids = []
email_message_obj = self.pool.get('email.message')
attahcment_obj = self.pool.get('ir.attachment')
smtp_obj = self.pool.get('email.smtp_server')
user_obj = self.pool.get('res.users')
report_xml_obj = self.pool.get('ir.actions.report.xml')
model_obj = self.pool.get('ir.model')
template = self._get_template(cr, uid, context)
for id in context.get('src_rec_ids',[]):
screen_vals = self.read(cr, uid, ids[0], [], context)
smtp_data = smtp_obj.browse(cr, uid, screen_vals['from'], context=context)
vals = {
'email_from': tools.ustr(smtp_data.name) + "<" + tools.ustr(smtp_data.email_id) + ">",
'email_to': get_end_value(id, screen_vals['to']),
'email_cc': get_end_value(id, screen_vals['cc']),
'email_bcc': get_end_value(id, screen_vals['bcc']),
'name': get_end_value(id, screen_vals['subject']),
'description': get_end_value(id, screen_vals['body_text']) + "\n" + get_end_value(id, screen_vals['body_html'] or ''),
'state':'na',
}
if screen_vals['signature']:
signature = user_obj.browse(cr, uid, uid, context).signature
if signature:
vals['description'] = tools.ustr(vals['description'] or '') + signature
attachment_ids = []
#Create partly the mail and later update attachments
mail_id = email_message_obj.create(cr, uid, vals, context)
mail_ids.append(mail_id)
if template.report_template:
reportname = 'report.' + report_xml_obj.browse(cr, uid, template.report_template.id, context).report_name
data = {}
data['model'] = model_obj.browse(cr, uid, screen_vals['rel_model'], context).model
# Ensure report is rendered using template's language
ctx = context.copy()
if template.lang:
ctx['lang'] = self.get_value(cr, uid, template, template.lang, context, id)
service = netsvc.LocalService(reportname)
(result, format) = service.create(cr, uid, [id], data, ctx)
attachment_id = attahcment_obj.create(cr, uid, {
'name': _('%s (Email Attachment)') % tools.ustr(vals['name']),
'datas': base64.b64encode(result),
'datas_fname': tools.ustr(get_end_value(id, screen_vals['report']) or _('Report')) + "." + format,
'description': vals['description'] or _("No Description"),
'res_model': 'email.message',
'res_id': mail_id
}, context)
attachment_ids.append(attachment_id)
# Add document attachments
for attachment_id in screen_vals.get('attachment_ids',[]):
new_id = attahcment_obj.copy(cr, uid, attachment_id, {
'res_model': 'email.message',
'res_id': mail_id,
}, context)
attachment_ids.append(new_id)
if attachment_ids:
email_message_obj.write(cr, uid, mail_id, {
'attachment_ids': [[6, 0, attachment_ids]],
}, context)
return mail_ids
#def get_end_value(id, value):
# if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets value from the template
# return self.get_value(cr, uid, template, value, context, id)
# else:
# return value
email_ids = []
for template in self.browse(cr, uid, ids, context=context):
for record_id in context.get('src_rec_ids',[]):
email_id = self._generate_email(cr, uid, template.id, record_id, context)
email_ids.append(email_id)
return email_ids
email_template_send_wizard()

View File

@ -7,53 +7,60 @@
<field name="model">email_template.send.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Send mail Wizard">
<form string="Send Email Wizard">
<group col="4" colspan="4">
<field name="rel_model" colspan="2"/>
<field name="from" required="1" colspan="2"/>
<field name="smtp_server_id" widget="selection" required="1" colspan="4"/>
</group>
<group col="4" colspan="4">
<group col="6" colspan="4">
<field name="to" colspan="4"/>
<field name="cc" colspan="4"/>
<field name="bcc" colspan="4"/>
<field name="email_to" colspan="4"/>
<field name="email_cc" colspan="4"/>
<field name="email_bcc" colspan="4"/>
<field name="subject" colspan="4" attrs="{'required':[('state','=','single')]}"/>
<field name="report" colspan="4"/>
<field name="report_name" colspan="4"/>
<field name="user_signature" colspan="4"/>
</group>
<separator string="" colspan="4"/>
<notebook colspan="4">
<page string="Body (Plain Text)">
<field name="body_text" colspan="4" nolabel="1"/>
<page string="Body">
<field name="description" colspan="4" nolabel="1"/>
</page>
<page string="Body (HTML)">
<!-- <page string="Body (HTML)">
<field name="body_html" colspan="4" nolabel="1"/>
</page>
</page> -->
<page string="Attachments">
<label string="Add here all attachments of the current document you want to include in the Email." colspan="4"/>
<field name="attachment_ids" colspan="4" nolabel="1"/>
</page>
</notebook>
<field name="signature" colspan="4"/>
</group>
<group col="4" colspan="4" attrs="{'invisible':[('state','!=','single')]}">
<button icon="gtk-apply" name="sav_to_drafts" string="Save in Drafts" type="object"/>
<button icon="gtk-ok" name="send_mail" string="Send now" type="object"/>
<button icon="gtk-cancel" special="cancel" string="Discard Mail"/>
</group>
<field name="state" invisible="1"/>
<group col="4" colspan="4" attrs="{'invisible':[('state','=','single')]}">
<label string="Tip: Multiple emails are sent in the same language (the first one is proposed). We suggest you send emails in groups according to language." colspan="4"/>
<field name="requested"/>
<field name="generated"/>
<button icon="gtk-ok" name="get_generated" string="Send all mails" type="object" states="multi" colspan="2"/>
<button icon="gtk-cancel" special="cancel" string="Discard Mail" colspan="2" states="multi"/>
<newline/>
<label string="After clicking Send All, emails will be sent to outbox and cleared in next Send/Recieve" colspan="4"/>
<label string="Tip: Multiple emails are sent in the same language (the first one is proposed). We suggest you send emails in groups according to language." colspan="4"/>
<newline/>
</group>
<button icon="gtk-ok" special="cancel" string="Close" colspan="4" states="done"/>
<field name="state"/>
<newline/>
<label string="After clicking send all mails, mails will be sent to outbox and cleared in next Send/Recieve" colspan="4"/>
<label string="" colspan="2"/>
<group col="4" colspan="2" attrs="{'invisible':[('state','=','single')]}">
<button icon="gtk-cancel" special="cancel" string="Discard" states="multi"/>
<button icon="gtk-ok" name="get_generated" string="Send All" type="object" states="multi"/>
<button icon="gtk-ok" special="cancel" string="Close" states="done"/>
</group>
<group col="4" colspan="2" attrs="{'invisible':[('state','!=','single')]}">
<button icon="gtk-cancel" special="cancel" string="Discard"/>
<button icon="gtk-apply" name="save_to_drafts" string="Save in Drafts" type="object"/>
<button icon="gtk-ok" name="send_mail" string="Send now" type="object"/>
</group>
</form>
</field>
</record>
</data>
</openerp>
</openerp>

View File

@ -153,45 +153,44 @@ class email_message(osv.osv):
return result
_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),
'date': fields.datetime('Date', 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."),
'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),
'name':fields.text('Subject'),
'model': fields.char('Object Name', size=128, select=1),
'res_id': fields.integer('Resource ID', select=1),
'date': fields.datetime('Date'),
'user_id': fields.many2one('res.users', 'User Responsible'),
'message': fields.text('Description'),
'email_from': fields.char('From', size=128, help="Email From"),
'email_to': fields.char('To', help="Email Recipients", size=256),
'email_cc': fields.char('Cc', help="Carbon Copy Email Recipients", size=256),
'email_bcc': fields.char('Bcc', help='Blind Carbon Copy Email Recipients', size=256),
'message_id': fields.char('Message Id', size=1024, help="Message Id on Email.", select=True),
'references': fields.text('References', help="References emails."),
'partner_id': fields.many2one('res.partner', 'Partner'),
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'),
'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),
'sub_type': fields.char('Sub Type', size=32, readonly=True),
'headers': fields.char('x_headers',size=256, readonly=True),
'priority':fields.integer('Priority', readonly=True),
'reply_to':fields.char('Reply-To', size=250),
'sub_type': fields.char('Sub Type', size=32),
'headers': fields.char('x_headers',size=256),
'priority':fields.integer('Priority'),
'debug':fields.boolean('Debug', readonly=True),
'history': fields.boolean('History', readonly=True),
'description': fields.text('Description', readonly=True),
#I like GMAIL which allows putting same mail in many folders
#Lets plan it for 0.9
'description': fields.text('Description'),
'smtp_server_id':fields.many2one('email.smtp_server', 'SMTP Server'),
'folder':fields.selection([
('drafts', 'Drafts'),
('outbox', 'Outbox'),
('trash', 'Trash'),
('sent', 'Sent Items'),
], 'Folder', readonly=True),
], 'Folder'),
'state':fields.selection([
('na', 'Not Applicable'),
('draft', 'Draft'),
('sending', 'Sending'),
('waiting', 'Waiting'),
], 'State', readonly=True),
}
_defaults = {
'state': lambda * a: 'na',
'state': lambda * a: 'draft',
'folder': lambda * a: 'outbox',
}
@ -237,8 +236,16 @@ class email_message(osv.osv):
_("Error sending mail: %s") % e)
def email_send(self, cr, uid, email_from, email_to, subject, body, model=False, email_cc=None, email_bcc=None, reply_to=False, attach=None,
openobject_id=False, debug=False, subtype='plain', x_headers={}, priority='3', context=None):
openobject_id=False, debug=False, subtype='plain', x_headers={}, priority='3', smtp_server_id=False, context=None):
attachment_obj = self.pool.get('ir.attachment')
if type(email_to) != list:
email_to = [email_to]
if type(email_cc) != list:
email_cc = [email_cc]
if type(email_bcc) != list:
email_bcc = [email_bcc]
if type(reply_to) != list:
reply_to = [reply_to]
msg_vals = {
'name': subject,
'model': model or '',
@ -256,6 +263,8 @@ class email_message(osv.osv):
'priority': priority,
'debug': debug,
'folder': 'outbox',
'history': True,
'smtp_server_id': smtp_server_id,
'state': 'waiting',
}
email_msg_id = self.create(cr, uid, msg_vals, context)
@ -273,7 +282,7 @@ class email_message(osv.osv):
attachment_ids.append(attachment_obj.create(cr, uid, attachment_data, context))
self.write(cr, uid, email_msg_id,
{ 'attachment_ids': [[6, 0, attachment_ids]] }, context)
return True
return email_msg_id
def process_email_queue(self, cr, uid, ids=None, context=None):
if ids is None:
@ -281,7 +290,7 @@ class email_message(osv.osv):
if context is None:
context = {}
attachment_obj = self.pool.get('ir.attachment')
account_obj = self.pool.get('email.smtp_server')
smtp_server_obj = self.pool.get('email.smtp_server')
if not ids:
filters = [('folder', '=', 'outbox'), ('state', '!=', 'sending')]
if 'filters' in context:
@ -293,10 +302,11 @@ class email_message(osv.osv):
attachments = []
for attach in message.attachment_ids:
attachments.append((attach.datas_fname ,attach.datas))
smtp_account = False
smtp_ids = account_obj.search(cr, uid, [('default','=',True)])
if smtp_ids:
smtp_account = account_obj.browse(cr, uid, smtp_ids, context)[0]
smtp_server = message.smtp_server_id
if not smtp_server:
smtp_ids = smtp_server_obj.search(cr, uid, [('default','=',True)])
if smtp_ids:
smtp_server = smtp_server_obj.browse(cr, uid, smtp_ids, context)[0]
tools.email_send(message.email_from,
message.email_to and message.email_to.split(',') or [],
message.name, message.description,

View File

@ -133,10 +133,8 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
default_ids = self.search(cr, uid, [('default','=',True)])
if len(default_ids) > 1:
return False
elif not default_ids:
return False
else:
return True
return True
_constraints = [
(_constraint_unique,

View File

@ -160,7 +160,6 @@
<separator string="" colspan="4"/>
<label string="" colspan="2"/>
<button name="test_smtp_connection" type="object" string="Test Connection" icon="gtk-network" colspan="2"/>
</page>
</notebook>
</form>
@ -172,12 +171,12 @@
<field name="model">email.smtp_server</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Email Accounts">
<tree string="SMTP Server">
<field name="name"/>
<field name="email_id"/>
<field name="smtpuname"/>
<field name="smtpserver"/>
<field name="smtpport"/>
<field name="default"/>
<button name="test_smtp_connection" type="object" string="Test Connection" icon="gtk-network"/>
</tree>
</field>
</record>
@ -187,7 +186,7 @@
<field name="model">email.smtp_server</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Email Smtp Server">
<search string="Smtp Server">
<field name="name"/>
<field name="email_id"/>
</search>