diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index 372b9a2566c..fea3d603f6a 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -59,7 +59,7 @@ The main features of the module are: """, 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', - 'depends': ['base', 'base_tools'], + 'depends': ['base', 'base_tools', 'base_setup'], 'data': [ 'wizard/mail_compose_message_view.xml', 'res_config_view.xml', diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index c4d8990f44a..77169e7f27e 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -25,9 +25,7 @@ import openerp.tools as tools from operator import itemgetter from osv import osv from osv import fields -import tools from tools.translate import _ -from lxml import etree class mail_group(osv.osv): """ @@ -78,7 +76,6 @@ class mail_group(osv.osv): def get_last_month_msg_nbr(self, cr, uid, ids, name, args, context=None): result = {} - message_obj = self.pool.get('mail.message') for id in ids: lower_date = (DT.datetime.now() - DT.timedelta(days=30)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT) result[id] = self.message_search(cr, uid, [id], limit=None, domain=[('date', '>=', lower_date)], count=True, context=context) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 3a2c79bbe58..294a3bdaf30 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -614,7 +614,7 @@ class mail_thread(osv.Model): model_pool = self.pool.get(model) if thread_id and model and model_pool and model_pool.exists(cr, uid, thread_id) \ and hasattr(model_pool, 'message_update'): - _logger.debug('Routing mail with Message-Id %s: direct reply to model:%s, thread_id:%s, custom_values:%s, uid:%s', + _logger.debug('Routing mail with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s', message_id, model, thread_id, custom_values, uid) return [(model, thread_id, custom_values, uid)] @@ -622,9 +622,11 @@ class mail_thread(osv.Model): # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value. rcpt_tos = decode_header(message, 'Delivered-To') or \ - (decode_header(message, 'To') + decode_header(message, 'Cc') \ - + decode_header(message, 'Resent-To') + decode_header(message, 'Resent-Cc')) - local_parts = [e.split('@')[0] for e in to_email(','.join(rcpt_tos))] + ','.join([decode_header(message, 'To'), + decode_header(message, 'Cc'), + decode_header(message, 'Resent-To'), + decode_header(message, 'Resent-Cc')]) + local_parts = [e.split('@')[0] for e in to_email(rcpt_tos)] if local_parts: mail_alias = self.pool.get('mail.alias') alias_ids = mail_alias.search(cr, uid, [('alias_name', 'in', local_parts)]) @@ -647,7 +649,7 @@ class mail_thread(osv.Model): thread_id = match and match.group(1) assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ "No possible route found for incoming message with Message-Id %s. " \ - "Create an appropriate mail.alias or force the destination model." + "Create an appropriate mail.alias or force the destination model." % message_id if thread_id and not model_pool.exists(cr, uid, thread_id): _logger.warning('Received mail reply to missing document %s! Ignoring and creating new document instead for Message-Id %s', thread_id, message_id) @@ -756,7 +758,7 @@ class mail_thread(osv.Model): fields = model_pool.fields_get(cr, uid, context=context) data = model_pool.default_get(cr, uid, fields, context=context) if 'name' in fields and not data.get('name'): - data['name'] = msg_dict.get('from', '') + data['name'] = msg_dict.get('subject', '') if custom_values and isinstance(custom_values, dict): data.update(custom_values) res_id = model_pool.create(cr, uid, data, context=context) diff --git a/addons/mail/tests/__init__.py b/addons/mail/tests/__init__.py new file mode 100644 index 00000000000..d63c5634cc3 --- /dev/null +++ b/addons/mail/tests/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# 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 . +# +############################################################################## +from . import test_mail + +checks = [ + test_mail, +] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py new file mode 100644 index 00000000000..0940d72c490 --- /dev/null +++ b/addons/mail/tests/test_mail.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# 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 . +# +############################################################################## + +from openerp.tests import common + +MAIL_TEMPLATE = """Return-Path: +To: {to} +Received: by mail1.openerp.com (Postfix, from userid 10002) + id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST) +From: Sylvie Lelitre +Subject: {subject} +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="----=_Part_4200734_24778174.1344608186754" +Date: Fri, 10 Aug 2012 14:16:26 +0000 +Message-ID: <1198923581.41972151344608186760.JavaMail@agrolait.com> +{extra} +------=_Part_4200734_24778174.1344608186754 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +Please call me as soon as possible this afternoon! + +-- +Sylvie +------=_Part_4200734_24778174.1344608186754 +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + + + + =20 + + =20 + =20 + +

Please call me as soon as possible this afternoon!

+ +

--
+ Sylvie +

+ + +------=_Part_4200734_24778174.1344608186754-- +""" + + +class test_mail(common.TransactionCase): + + def setUp(self): + super(test_mail, self).setUp() + self.ir_model = self.registry('ir.model') + self.mail_alias = self.registry('mail.alias') + self.mail_thread = self.registry('mail.thread') + self.mail_group = self.registry('mail.group') + self.res_users = self.registry('res.users') + + # groups@.. will cause the creation of new mail groups + self.mail_group_model_id = self.ir_model.search(self.cr, self.uid, [('model','=', 'mail.group')])[0] + self.mail_alias.create(self.cr, self.uid, {'alias_name': 'groups', + 'alias_model_id': self.mail_group_model_id}) + + # tech@... will append new messages to the 'tech' group + self.group_tech_id = self.mail_group.create(self.cr, self.uid, {'name': 'tech'}) + + def test_message_process(self): + # Incoming mail creates a new mail_group "frogs" + self.assertEqual(self.mail_group.search(self.cr, self.uid, [('name','=','frogs')]), []) + mail_frogs = MAIL_TEMPLATE.format(to='groups@example.com, other@gmail.com', subject='frogs', extra='') + self.mail_thread.message_process(self.cr, self.uid, None, mail_frogs) + frog_groups = self.mail_group.search(self.cr, self.uid, [('name','=','frogs')]) + self.assertTrue(len(frog_groups) == 1) + + # Previously-created group can be emailed now - it should have an implicit alias group+frogs@... + frog_group = self.mail_group.browse(self.cr, self.uid, frog_groups[0]) + group_messages = frog_group.message_ids + self.assertTrue(len(group_messages) == 1, 'New group should only have the original message') + mail_frog_news = MAIL_TEMPLATE.format(to='Friendly Frogs ', subject='news', extra='') + self.mail_thread.message_process(self.cr, self.uid, None, mail_frog_news) + frog_group.refresh() + self.assertTrue(len(frog_group.message_ids) == 2, 'Group should contain 2 messages now') + + # Even with a wrong destination, a reply should end up in the correct thread + mail_reply = MAIL_TEMPLATE.format(to='erroneous@example.com>', subject='Re: news', + extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n'%frog_group.id) + self.mail_thread.message_process(self.cr, self.uid, None, mail_reply) + frog_group.refresh() + self.assertTrue(len(frog_group.message_ids) == 3, 'Group should contain 3 messages now') + + # No model passed and no matching alias must raise + mail_spam = MAIL_TEMPLATE.format(to='noone@example.com', subject='spam', extra='') + self.assertRaises(Exception, + self.mail_thread.message_process, + self.cr, self.uid, None, mail_spam)