summaryrefslogtreecommitdiff
path: root/addons/mail/wizard/mail_compose_message.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/mail/wizard/mail_compose_message.py')
-rw-r--r--addons/mail/wizard/mail_compose_message.py490
1 files changed, 179 insertions, 311 deletions
diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index fe87b7584e0..96ce253c2a8 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -19,7 +19,6 @@
#
##############################################################################
-import ast
import re
import tools
@@ -28,158 +27,120 @@ from osv import fields
from tools.safe_eval import safe_eval as eval
from tools.translate import _
-from ..mail_message import to_email
-
# main mako-like expression pattern
EXPRESSION_PATTERN = re.compile('(\$\{.+?\})')
class mail_compose_message(osv.TransientModel):
- """Generic Email composition wizard. This wizard is meant to be inherited
- at model and view level to provide specific wizard features.
-
- The behavior of the wizard can be modified through the use of context
- parameters, among which are:
-
- * mail.compose.message.mode: if set to 'reply', the wizard is in
- reply to a previous message mode and pre-populated with the original
- quote. If set to 'comment', it means you are writing a new message to
- be attached to a document. If set to 'mass_mail', the wizard is in
- mass mailing where the mail details can contain template placeholders
- that will be merged with actual data before being sent to each
- recipient.
- * active_model: model name of the document to which the mail being
- composed is related
- * active_id: id of the document to which the mail being composed is
- related, or id of the message to which user is replying,
- in case ``mail.compose.message.mode == 'reply'``
- * active_ids: ids of the documents to which the mail being composed is
- related, in case ``mail.compose.message.mode == 'mass_mail'``.
+ """ Generic message composition wizard. You may inherit from this wizard
+ at model and view levels to provide specific features.
+
+ The behavior of the wizard can be modified through the context key
+ mail.compose.message.mode:
+ - 'reply': reply to a previous message. The wizard is pre-populated
+ via ``get_message_data``.
+ - 'comment': new post on a record. The wizard is pre-populated via
+ ``get_record_data``
+ - 'mass_mail': wizard in mass mailing mode where the mail details can
+ contain template placeholders that will be merged with actual data
+ before being sent to each recipient.
"""
_name = 'mail.compose.message'
- _inherit = 'mail.message.common'
+ _inherit = 'mail.message'
_description = 'Email composition wizard'
+ _log_access = True
def default_get(self, cr, uid, fields, context=None):
- """ Overridden to provide specific defaults depending on the context
- parameters.
-
- Composition mode
- - comment: default mode; active_model, active_id = model and ID of a
- document we are commenting,
- - reply: active_id = ID of a mail.message to which we are replying.
- From this message we can find the related model and res_id,
- - mass_mailing mode: active_model, active_id = model and ID of a
- document we are commenting,
-
- :param dict context: several context values will modify the behavior
- of the wizard, cfr. the class description.
+ """ Handle composition mode. Some details about context keys:
+ - comment: default mode, model and ID of a record the user comments
+ - default_model or active_model
+ - default_res_id or active_id
+ - reply: active_id of a message the user replies to
+ - active_id: ID of a mail.message to which we are replying
+ - message.res_model or default_model
+ - message.res_id or default_res_id
+ - mass_mailing mode: model and IDs of records the user mass-mails
+ - active_ids: record IDs
+ - default_model or active_model
"""
+ # get some important values from context
if context is None:
context = {}
- compose_mode = context.get('mail.compose.message.mode', 'comment')
- active_model = context.get('active_model')
- active_id = context.get('active_id')
result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
+ # get some important values from context
+ composition_mode = context.get('mail.compose.message.mode')
+ model = context.get('default_model', context.get('active_model'))
+ res_id = context.get('default_res_id', context.get('active_id'))
+ active_id = context.get('active_id')
+ active_ids = context.get('active_ids')
+
# get default values according to the composition mode
- vals = {}
- if compose_mode in ['reply']:
- vals = self.get_message_data(cr, uid, int(context['active_id']), context=context)
- elif compose_mode in ['comment', 'mass_mail'] and active_model and active_id:
- vals = self.get_value(cr, uid, active_model, active_id, context)
+ if composition_mode in ['reply']:
+ vals = self.get_message_data(cr, uid, active_id, context=context)
+ elif composition_mode in ['comment', 'mass_mail'] and model and res_id:
+ vals = self.get_record_data(cr, uid, model, res_id, context=context)
+ else:
+ vals = {'model': model, 'res_id': res_id}
+ if composition_mode:
+ vals['composition_mode'] = composition_mode
+
for field in vals:
if field in fields:
result[field] = vals[field]
-
- # link to model and record if not done yet
- if not result.get('model') and active_model:
- result['model'] = active_model
- if not result.get('res_id') and active_id:
- result['res_id'] = active_id
-
- # Try to provide default email_from if not specified yet
- if not result.get('email_from'):
- current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
- result['email_from'] = current_user.email or False
return result
+ def _get_composition_mode_selection(self, cr, uid, context=None):
+ return [('comment', 'Comment a document'), ('reply', 'Reply to a message'), ('mass_mail', 'Mass mailing')]
+
_columns = {
- 'dest_partner_ids': fields.many2many('res.partner',
- 'email_message_send_partner_rel',
- 'wizard_id', 'partner_id', 'Destination partners',
- help="When sending emails through the social network composition wizard"\
- "you may choose to send a copy of the mail to partners."),
- 'attachment_ids': fields.many2many('ir.attachment','email_message_send_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'),
- 'auto_delete': fields.boolean('Auto Delete', help="Permanently delete emails after sending"),
+ 'composition_mode': fields.selection(
+ lambda s, *a, **k: s._get_composition_mode_selection(*a, **k),
+ string='Composition mode'),
+ 'partner_ids': fields.many2many('res.partner',
+ 'mail_compose_message_res_partner_rel',
+ 'wizard_id', 'partner_id', 'Additional contacts'),
+ 'attachment_ids': fields.many2many('ir.attachment',
+ 'mail_compose_message_ir_attachments_rel',
+ 'wizard_id', 'attachment_id', 'Attachments'),
'filter_id': fields.many2one('ir.filters', 'Filters'),
+ 'body_text': fields.text('Plain-text editor body'),
+ 'content_subtype': fields.char('Message content subtype', size=32, readonly=1,
+ help="Type of message, usually 'html' or 'plain', used to select "\
+ "plain-text or rich-text contents accordingly"),
+ }
+
+ _defaults = {
+ 'composition_mode': 'comment',
+ 'content_subtype': lambda self,cr, uid, context={}: 'plain',
+ 'body_text': lambda self,cr, uid, context={}: False,
+ 'body': lambda self,cr, uid, context={}: '',
+ 'subject': lambda self,cr, uid, context={}: False,
+ 'partner_ids': [],
}
- def get_value(self, cr, uid, model, res_id, context=None):
+ def notify(self, cr, uid, newid, context=None):
+ """ Override specific notify method of mail.message, because we do
+ not want that feature in the wizard. """
+ return
+
+ def get_record_data(self, cr, uid, model, res_id, context=None):
""" Returns a defaults-like dict with initial values for the composition
wizard when sending an email related to the document record
identified by ``model`` and ``res_id``.
- The default implementation returns an empty dictionary, and is meant
- to be overridden by subclasses.
-
:param str model: model name of the document record this mail is
related to.
- :param int res_id: id of the document record this mail is related to.
- :param dict context: several context values will modify the behavior
- of the wizard, cfr. the class description.
+ :param int res_id: id of the document record this mail is related to
"""
- result = {}
- user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
- result.update({
- 'model': model,
- 'res_id': res_id,
- 'email_from': user.email or tools.config.get('email_from', False),
- 'body_html': False,
- 'body_text': False,
- 'subject': False,
- 'dest_partner_ids': [],
- })
- return result
-
- def onchange_email_mode(self, cr, uid, ids, value, model, res_id, context=None):
- """ email_mode (values: True or False). This onchange on the email mode
- allows to have some specific behavior when going in email mode, or
- when going out of email mode.
- Basically, dest_partner_ids is reset when going out of email
- mode.
- This method can be overridden for models that want to have their
- specific behavior.
- Note that currently, this onchange is used in mail.js and called
- manually on the form instantiated in the Chatter.
- """
- if not value:
- return {'value': {'dest_partner_ids': []}}
- return {'value': {}}
-
- def onchange_formatting(self, cr, uid, ids, value, model, res_id, context=None):
- """ onchange_formatting (values: True or False). This onchange on the
- formatting allows to have some specific behavior when going in
- formatting mode, or when going out of formatting.
- Basically, subject is reset when going out of formatting mode.
- This method can be overridden for models that want to have their
- specific behavior.
- Note that currently, this onchange is used in mail.js and called
- manually on the form instantiated in the Chatter.
- """
- if not value:
- return {'value': {'subject': False}}
- return {'value': {}}
+ return {'model': model, 'res_id': res_id}
def get_message_data(self, cr, uid, message_id, context=None):
""" Returns a defaults-like dict with initial values for the composition
wizard when replying to the given message (e.g. including the quote
- of the initial message, and the correct recipient). It should not be
- called unless ``context['mail.compose.message.mode'] == 'reply'``.
+ of the initial message, and the correct recipients).
:param int message_id: id of the mail.message to which the user
is replying.
- :param dict context: several context values will modify the behavior
- of the wizard, cfr. the class description.
"""
if context is None:
context = {}
@@ -187,143 +148,116 @@ class mail_compose_message(osv.TransientModel):
if not message_id:
return result
- current_user = self.pool.get('res.users').browse(cr, uid, uid, context)
- message_data = self.pool.get('mail.message').browse(cr, uid, message_id, context)
- # Form the subject
+ current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ message_data = self.pool.get('mail.message').browse(cr, uid, message_id, context=context)
+
+ # create subject
re_prefix = _("Re:")
reply_subject = tools.ustr(message_data.subject or '')
if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)):
reply_subject = "%s %s" % (re_prefix, reply_subject)
- # Form the bodies (text and html). We use the plain text version of the
- # original mail, by default, as it is easier to quote than the HTML
- # version. TODO: make it possible to switch to HTML on the fly
- sent_date = _('On %(date)s, ') % {'date': message_data.date} if message_data.date else ''
- sender = _('%(sender_name)s wrote:') % {'sender_name': tools.ustr(message_data.email_from or _('You'))}
- body_text = message_data.body_text or ''
- body_html = message_data.body_html or ''
- quoted_body_text = '> %s' % tools.ustr(body_text.replace('\n', "\n> ") or '')
- quoted_body_html = '<blockquote>%s</blockquote>' % (tools.ustr(body_html)),
- reply_body_text = '\n%s%s\n%s\n%s' % (sent_date, sender, quoted_body_text, current_user.signature)
- reply_body_html = '<br /><br />%s%s<br />%s<br />%s' % (sent_date, sender, quoted_body_html, current_user.signature)
- # form dest_partner_ids
- dest_partner_ids = [partner.id for partner in message_data.partner_ids]
- # Update header and references
- reply_headers = {}
- reply_references = message_data.references and tools.ustr(message_data.references) or False
- reply_message_id = message_data.message_id or False
- if reply_message_id:
- reply_references = (reply_references or '') + " " + message_data.message_id
- reply_headers['In-Reply-To'] = message_data.message_id
+ # create the reply in the body
+ reply_header = _('On %(date)s, %(sender_name)s wrote:') % {
+ 'date': message_data.date if message_data.date else '',
+ 'sender_name': message_data.author_id.name }
+ reply_body = '<div>%s<blockquote>%s</blockquote></div>%s' % (reply_header, message_data.body, current_user.signature)
+ # get partner_ids from original message
+ partner_ids = [partner.id for partner in message_data.partner_ids] if message_data.partner_ids else []
+
# update the result
result.update({
- 'body_text': reply_body_text,
- 'body_html': reply_body_html,
+ 'model': message_data.model,
+ 'res_id': message_data.res_id,
+ 'parent_id': message_data.id,
+ 'body': reply_body,
'subject': reply_subject,
- 'attachment_ids': [],
- 'dest_partner_ids': dest_partner_ids,
- 'model': message_data.model or False,
- 'res_id': message_data.res_id or False,
- 'email_from': current_user.email or message_data.email_to or False,
- 'email_to': message_data.reply_to or message_data.email_from or False,
- 'email_cc': message_data.email_cc or False,
- 'user_id': uid,
- # pass msg-id and references of mail we're replying to, to construct the
- # new ones later when sending
- 'message_id': reply_message_id,
- 'references': reply_references,
- 'headers': reply_headers,
+ 'partner_ids': partner_ids,
+ 'content_subtype': 'html',
})
return result
+ def toggle_content_subtype(self, cr, uid, ids, context=None):
+ """ hit toggle formatting mode button: calls onchange_formatting to
+ emulate an on_change, then writes the value to update the form. """
+ for record in self.browse(cr, uid, ids, context=context):
+ content_st_new_value = 'plain' if record.content_subtype == 'html' else 'html'
+ onchange_res = self.onchange_content_subtype(cr, uid, ids, content_st_new_value, record.model, record.res_id, context=context)
+ self.write(cr, uid, [record.id], onchange_res['value'], context=context)
+ return True
+
+ def onchange_content_subtype(self, cr, uid, ids, value, model, res_id, context=None):
+ """ onchange_content_subtype (values: 'plain' or 'html'). This onchange
+ on the subtype allows to have some specific behavior when switching
+ between text or html mode.
+ Basically, subject is reset when going out of html mode.
+ This method can be overridden for models that want to have their
+ specific behavior.
+ """
+ return {'value': {'content_subtype': value}}
+
+ def onchange_partner_ids(self, cr, uid, ids, value, context=None):
+ """ onchange_partner_ids (value format: [[6, False, [3, 4]]]). The
+ basic purpose of this method is to check that destination partners
+ effectively have email addresses. Otherwise a warning is thrown.
+ """
+ partner_ids = value[0][2]
+ partner_wo_email_lst = []
+ for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
+ if not partner.email:
+ partner_wo_email_lst.append(partner)
+ if not partner_wo_email_lst:
+ return {'value': {}}
+ warning_msg = _('The following partners chosen as recipients for the email have no email address linked :')
+ for partner in partner_wo_email_lst:
+ warning_msg += '\n- %s' % (partner.name)
+ warning = {
+ 'title': _('Partners email addresses not found'),
+ 'message': warning_msg,
+ }
+ return {'warning': warning, 'value': {}}
+
def send_mail(self, cr, uid, ids, context=None):
- '''Process the wizard contents and proceed with sending the corresponding
- email(s), rendering any template patterns on the fly if needed.
- If the wizard is in mass-mail mode (context['mail.compose.message.mode'] is
- set to ``'mass_mail'``), the resulting email(s) are scheduled for being
- sent the next time the mail.message scheduler runs, or the next time
- ``mail.message.process_email_queue`` is called.
- Otherwise the new message is sent immediately.
-
- :param dict context: several context values will modify the behavior
- of the wizard, cfr. the class description.
- '''
+ """ Process the wizard content and proceed with sending the related
+ email(s), rendering any template patterns on the fly if needed. """
if context is None:
context = {}
- # composition wizard options
- email_mode = context.get('email_mode')
- formatting = context.get('formatting')
- mass_mail_mode = context.get('mail.compose.message.mode') == 'mass_mail'
-
- mail_message_obj = self.pool.get('mail.message')
- for mail_wiz in self.browse(cr, uid, ids, context=context):
- # attachments
+
+ for wizard in self.browse(cr, uid, ids, context=context):
+ mass_mail_mode = wizard.composition_mode == 'mass_mail'
+
attachment = {}
- for attach in mail_wiz.attachment_ids:
- attachment[attach.datas_fname] = attach.datas and attach.datas.decode('base64')
+ for attach in wizard.attachment_ids:
+ attachment[attach.datas_fname] = attach.datas and attach.datas or False
# default values, according to the wizard options
- subject = mail_wiz.subject if formatting else False
- content_subtype = 'html' if formatting else 'plain'
- type = 'email' if email_mode else 'comment'
- state = 'outgoing' if email_mode else False
- partner_ids = [partner.id for partner in mail_wiz.dest_partner_ids]
- references = None
- headers = {}
- body = mail_wiz.body_html if content_subtype == 'html' else mail_wiz.body_text
-
- # get model, active_ids, and check if model is openchatter-enabled
- if mass_mail_mode and context.get('active_ids') and context.get('active_model'):
- active_ids = context['active_ids']
- active_model = context['active_model']
- elif mass_mail_mode:
- active_model = mail_wiz.model
+ subject = wizard.subject if wizard.content_subtype == 'html' else False
+ partner_ids = [(4, partner.id) for partner in wizard.partner_ids]
+ body = wizard.body if wizard.content_subtype == 'html' else wizard.body_text
+
+ active_model_pool = self.pool.get(wizard.model if wizard.model else 'mail.thread')
+
+ #TODO: TDE: WIP: have to check for mass mail and templates - no time anymore today
+ if context.get('mail.compose.message.mode') == 'mass_mail' and context.get('default_model', False) and context.get('default_res_id', False):
+ active_model = context.get('default_model', False)
active_model_pool = self.pool.get(active_model)
- active_ids = active_model_pool.search(cr, uid, ast.literal_eval(mail_wiz.filter_id.domain), context=ast.literal_eval(mail_wiz.filter_id.context))
+ subject = self.render_template(cr, uid, subject, active_model, active_id)
+ body = self.render_template(cr, uid, wizard.body, active_model, active_id)
+
+ # TODO TDE: find partner_ids
+ # if email_to: find or create a partner
+ if values['email_to']:
+ partner_id = self.pool.get('mail.thread').message_partner_by_email(cr, uid, values['email_to'], context=context)['partner_id']
+ if not partner_id:
+ partner_id = self.pool.get('res.partner').name_create(cr, uid, values['email_to'], context=context)
+ values['partner_ids'] = [partner_id]
+
+ # determine the ids we are commenting
+ if mass_mail_mode:
+ res_ids = context.get('active_ids', [])
else:
- active_model = mail_wiz.model
- active_ids = [mail_wiz.res_id]
- active_model_pool = self.pool.get(active_model)
- mail_thread_enabled = hasattr(active_model_pool, 'message_append')
-
- if context.get('mail.compose.message.mode') == 'mass_mail':
- # Mass mailing: must render the template patterns
- for active_id in active_ids:
- rendered_subject = self.render_template(cr, uid, subject, active_model, active_id)
- rendered_body_html = self.render_template(cr, uid, mail_wiz.body_html, active_model, active_id)
- rendered_body_text = self.render_template(cr, uid, mail_wiz.body_text, active_model, active_id)
- email_from = self.render_template(cr, uid, mail_wiz.email_from, active_model, active_id)
- email_to = self.render_template(cr, uid, mail_wiz.email_to, active_model, active_id)
- email_cc = self.render_template(cr, uid, mail_wiz.email_cc, active_model, active_id)
- email_bcc = self.render_template(cr, uid, mail_wiz.email_bcc, active_model, active_id)
- reply_to = self.render_template(cr, uid, mail_wiz.reply_to, active_model, active_id)
-
- # in mass-mailing mode we only schedule the mail for sending, it will be
- # processed as soon as the mail scheduler runs.
- if mail_thread_enabled:
- active_model_pool.message_append(cr, uid, [active_id], rendered_subject, rendered_body_text, rendered_body_html,
- type=type, content_subtype=content_subtype, state=state, partner_ids=partner_ids,
- email_from=email_from, email_to=email_to, email_cc=email_cc, email_bcc=email_bcc,
- reply_to=reply_to, references=references, attachments=attachment, headers=headers, context=context)
- else:
- mail_message_obj.schedule_with_attach(cr, uid, email_from, to_email(email_to), subject, rendered_body_text,
- model=mail_wiz.model, email_cc=to_email(email_cc), email_bcc=to_email(email_bcc), reply_to=reply_to,
- attachments=attachment, references=references, res_id=active_id, partner_ids=partner_ids,
- content_subtype=mail_wiz.content_subtype, headers=headers, context=context)
- else:
- # normal mode - no mass-mailing
- if mail_thread_enabled:
- msg_ids = active_model_pool.message_append(cr, uid, active_ids, subject, mail_wiz.body_text, mail_wiz.body_html,
- type=type, content_subtype=content_subtype, state=state, partner_ids=partner_ids,
- email_from=mail_wiz.email_from, email_to=mail_wiz.email_to, email_cc=mail_wiz.email_cc, email_bcc=mail_wiz.email_bcc,
- reply_to=mail_wiz.reply_to, references=references, attachments=attachment, headers=headers, context=context)
- else:
- msg_ids = [mail_message_obj.schedule_with_attach(cr, uid, mail_wiz.email_from, to_email(mail_wiz.email_to), subject, mail_wiz.body_text,
- type=type, model=mail_wiz.model, email_cc=to_email(mail_wiz.email_cc), email_bcc=to_email(mail_wiz.email_bcc), reply_to=mail_wiz.reply_to,
- attachments=attachment, references=references, res_id=int(mail_wiz.res_id), partner_ids=partner_ids,
- content_subtype=mail_wiz.content_subtype, headers=headers, context=context)]
- # in normal mode, we send the email immediately, as the user expects us to (delay should be sufficiently small)
- if type == 'email':
- mail_message_obj.send(cr, uid, msg_ids, context=context)
+ res_ids = [wizard.res_id]
+ active_model_pool.message_post(cr, uid, res_ids, body=body, subject=subject, msg_type='comment',
+ attachments=attachment, context=context, partner_ids=partner_ids)
return {'type': 'ir.actions.act_window_close'}
@@ -356,80 +290,14 @@ class mail_compose_message(osv.TransientModel):
return tools.ustr(result)
return template and EXPRESSION_PATTERN.sub(merge, template)
-
-class mail_compose_message_extended(osv.TransientModel):
- """ Extension of 'mail.compose.message' to support default field values related
- to CRM-like models that follow the following conventions:
-
- 1. The model object must have an attribute '_mail_compose_message' equal to True.
-
- 2. The model should define the following fields:
- - 'name' as subject of the message (required);
- - 'email_from' as destination email address (required);
- - 'email_cc' as cc email addresses (required);
- - 'section_id.reply_to' as reply-to address (optional).
- """
- _inherit = 'mail.compose.message'
-
- def get_value(self, cr, uid, model, res_id, context=None):
- """ Overrides the default implementation to provide more default field values
- related to the corresponding CRM case.
- """
- result = super(mail_compose_message_extended, self).get_value(cr, uid, model, res_id, context=context)
- model_obj = self.pool.get(model)
- if getattr(model_obj, '_mail_compose_message', False) and res_id:
- data = model_obj.browse(cr, uid , res_id, context)
- result.update({
- 'email_to': data.email_from or False,
- 'email_cc': tools.ustr(data.email_cc or ''),
- 'subject': data.name or False,
- })
- if hasattr(data, 'section_id'):
- result['reply_to'] = data.section_id and data.section_id.reply_to or False
- return result
-
- def onchange_email_mode(self, cr, uid, ids, value, model, res_id, context=None):
- """ Overrides the default implementation to provide default values for
- dest_partner_ids. This method checks that a partner maching the
- ``email_from`` of the record exists. It it does not exist, it
- creates a new partner. The found or created partner is then added
- in dest_partner_ids.
- Partner check/creation valid inly if the value is True, and if
- the model has the ``_mail_compose_message`` attribute.
- """
- result = super(mail_compose_message_extended, self).onchange_email_mode(cr, uid, ids, value, model, res_id, context=context)
- model_obj = self.pool.get(model)
- if not value or not (getattr(model_obj, '_mail_compose_message', False) and res_id):
- return result
- data = model_obj.browse(cr, uid , res_id, context=context)
- partner_obj = self.pool.get('res.partner')
- partner_ids = partner_obj.search(cr, uid, [('email', '=', data.email_from)], context=context)
- if partner_ids:
- partner_id = partner_ids[0]
- else:
- partner_id = partner_obj.name_create(cr, uid, data.email_from, context=context)[0]
- result['value'].update({
- 'dest_partner_ids': [partner_id],
- 'email_cc': tools.ustr(data.email_cc or ''),
- })
- if hasattr(data, 'section_id'):
- result['value']['reply_to'] = data.section_id and data.section_id.reply_to or False
- return result
-
- def onchange_formatting(self, cr, uid, ids, value, model, res_id, context=None):
- """ Overrides the default implementation to provide default values for
- the subject.
- Subject re-creation valid only if the value is True, and if the
- model has the ``_mail_compose_message`` attribute.
- """
- result = super(mail_compose_message_extended, self).onchange_formatting(cr, uid, ids, value, model, res_id, context=context)
- model_obj = self.pool.get(model)
- if not value or not (getattr(model_obj, '_mail_compose_message', False) and res_id):
- return result
- data = model_obj.browse(cr, uid , res_id, context=context)
- result['value'].update({
- 'subject': data.name or False,
- })
- return result
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+ def unlink(self, cr, uid, ids, context=None):
+ # Cascade delete all attachments, as they are owned by the composition wizard
+ for wizard in self.read(cr, uid, ids, ['attachment_ids'], context=context):
+ self.pool.get('ir.attachment').unlink(cr, uid, wizard['attachment_ids'], context=context)
+ return super(mail_compose_message,self).unlink(cr, uid, ids, context=context)
+
+ def dummy(self, cr, uid, ids, context=None):
+ """ TDE: defined to have buttons that do basically nothing. It is
+ currently impossible to have buttons that do nothing special
+ in views (if type not specified, considered as 'object'). """
+ return True