diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index db5fd57b0a9..321aff950ad 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -165,13 +165,11 @@ class hr_applicant(base_stage, osv.Model): date_create = datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S") date_open = datetime.strptime(issue.date_open, "%Y-%m-%d %H:%M:%S") ans = date_open - date_create - date_until = issue.date_open elif field in ['day_close']: if issue.date_closed: date_create = datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S") date_close = datetime.strptime(issue.date_closed, "%Y-%m-%d %H:%M:%S") - date_until = issue.date_closed ans = date_close - date_create if ans: duration = float(ans.days) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 46bfd25e1be..79e7eb81456 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -19,16 +19,10 @@ # ############################################################################## -import dateutil.parser -import email import logging -import re -import time from email.header import decode_header -from email.message import Message -from osv import osv -from osv import fields +from osv import osv, fields import tools _logger = logging.getLogger(__name__) @@ -84,31 +78,22 @@ class mail_message(osv.Model): ('notification', 'System notification'), ], 'Type', help="Message type: email for email message, notification for system "\ - "message, comment for other messages such as user replies"), - + "message, comment for other messages such as user replies"), 'author_id': fields.many2one('res.partner', 'Author', required=True), - 'partner_ids': fields.many2many('res.partner', - 'mail_notification', 'message_id', 'partner_id', - 'Recipients'), - - 'attachment_ids': fields.one2many('ir.attachment', 'res_id', - 'Attachments', domain=[('res_model','=','mail.message')]), - - 'parent_id': fields.many2one('mail.message', 'Parent Message', - select=True, ondelete='set null', - help="Initial thread message."), + 'partner_ids': fields.many2many('res.partner', 'mail_notification', 'message_id', 'partner_id', 'Recipients'), + 'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', + 'message_id', 'attachment_id', 'Attachments'), + 'parent_id': fields.many2one('mail.message', 'Parent Message', select=True, ondelete='set null', help="Initial thread message."), 'child_ids': fields.one2many('mail.message', 'parent_id', 'Child Messages'), - 'model': fields.char('Related Document Model', size=128, select=1), 'res_id': fields.integer('Related Document ID', select=1), 'record_name': fields.function(get_record_name, type='string', string='Message Record Name', help="Name get of the related document."), - 'notification_ids': fields.one2many('mail.notification', 'message_id', 'Notifications'), - 'subject': fields.char('Subject', size=128), + 'subject': fields.char('Subject'), 'date': fields.datetime('Date'), - 'message_id': fields.char('Message-Id', size=256, help='Message unique identifier', select=1, readonly=1), + 'message_id': fields.char('Message-Id', help='Message unique identifier', select=1, readonly=1), 'body': fields.html('Content'), } @@ -118,7 +103,6 @@ class mail_message(osv.Model): return [('notification_ids.partner_id','=',partner_id),('notification_ids.read','=',False)] return [] - def _get_default_author(self, cr, uid, context={}): return self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id @@ -233,7 +217,6 @@ class mail_message(osv.Model): ('partner_id', '=', partner_id), ('message_id', 'in', ids), ], context=context) - notifications = {} for notification in not_obj.browse(cr, uid, not_ids, context=context): if notification.message_id.id in ids: pass diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 4493b226b18..12dab7dfe92 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -19,19 +19,23 @@ # ############################################################################## +import base64 import dateutil import email import logging +import pytz +import re +import time +import xmlrpclib from email.utils import parsedate from email.message import Message -from osv import osv, fields -from mail_message import decode -import time + import tools +from mail_message import decode +from osv import osv, fields from tools.translate import _ from tools.safe_eval import safe_eval as eval -import pytz -import xmlrpclib + _logger = logging.getLogger(__name__) @@ -372,9 +376,8 @@ class mail_thread(osv.Model): routes = self.message_route(cr, uid, msg_txt, model, thread_id, custom_values, context=context) - msg = self.parse_message(cr, uid, msg_txt, save_original=save_original, context=context) - if strip_attachments and 'attachments' in msg: - del msg['attachments'] + msg = self.message_parse(cr, uid, msg_txt, save_original=save_original, context=context) + if strip_attachments: msg.pop('attachments', None) for model, thread_id, custom_values, user_id in routes: if self._name != model: context.update({'thread_model': model}) @@ -445,7 +448,50 @@ class mail_thread(osv.Model): self.write(cr, uid, ids, update_vals, context=context) return True - def parse_message(self, cr, uid, message, save_original=False, context=None): + + def _message_extract_payload(self, message, save_original=False): + """Extract body as HTML and attachments from the mail message""" + attachments = [] + body = u'' + if save_original: + attachments.append(('original_email.eml', message.as_string())) + if not message.is_multipart() or 'text/' in message.get('content-type', ''): + encoding = message.get_content_charset() + body = message.get_payload(decode=True) + body = tools.ustr(body, encoding, errors='replace') + else: + alternative = (message.get_content_type() == 'multipart/alternative') + for part in message.walk(): + if part.get_content_maintype() == 'multipart': + continue # skip container + filename = part.get_filename() # None if normal part + encoding = part.get_content_charset() # None if attachment + # 1) Explicit Attachments -> attachments + if filename or part.get('content-disposition','').strip().startswith('attachment'): + attachments.append((filename or 'attachment', part.get_payload(decode=True))) + continue + # 2) text/plain ->
+ if part.get_content_type() == 'text/plain' and (not alternative or not body): + insertion_point = body.find('