diff options
Diffstat (limited to 'addons/mail')
58 files changed, 353 insertions, 524 deletions
diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index cdd7eb12c69..8e52f7e1f7d 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -53,7 +53,7 @@ <!-- Admin should not receivve emails at creation --> <record id="base.partner_root" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <!-- Catchall Email Alias --> diff --git a/addons/mail/data/mail_demo.xml b/addons/mail/data/mail_demo.xml index dde8d1d9804..09415ba89e0 100644 --- a/addons/mail/data/mail_demo.xml +++ b/addons/mail/data/mail_demo.xml @@ -4,76 +4,76 @@ <!-- Update 'Demo user' and partners email preferences to avoid mail bombing --> <record id="base.partner_demo" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_1" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_2" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_3" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_4" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_5" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_6" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_7" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_8" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_9" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_10" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_11" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_12" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_13" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_14" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_15" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_16" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_17" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_18" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_19" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_20" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_21" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_22" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <record id="base.res_partner_23" model="res.partner"> - <field name="notification_email_send">none</field> + <field name="notify_email">none</field> </record> <!-- Discussion: attachments and spec [DEMO: search on has_attachments --> diff --git a/addons/mail/i18n/ar.po b/addons/mail/i18n/ar.po index 660c6d30aa2..dff9a37498a 100644 --- a/addons/mail/i18n/ar.po +++ b/addons/mail/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/bg.po b/addons/mail/i18n/bg.po index a907bb44a3c..983abf5d57a 100644 --- a/addons/mail/i18n/bg.po +++ b/addons/mail/i18n/bg.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/bs.po b/addons/mail/i18n/bs.po index 499d2bb03ad..eb76645da89 100644 --- a/addons/mail/i18n/bs.po +++ b/addons/mail/i18n/bs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/ca.po b/addons/mail/i18n/ca.po index 1e774770274..412f16330e2 100644 --- a/addons/mail/i18n/ca.po +++ b/addons/mail/i18n/ca.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/cs.po b/addons/mail/i18n/cs.po index c2850c42237..ecfcc03e820 100644 --- a/addons/mail/i18n/cs.po +++ b/addons/mail/i18n/cs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/da.po b/addons/mail/i18n/da.po index 122800b5aa6..259be11c1dc 100644 --- a/addons/mail/i18n/da.po +++ b/addons/mail/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/de.po b/addons/mail/i18n/de.po index c9d7ec0ec06..379d2f9d04a 100644 --- a/addons/mail/i18n/de.po +++ b/addons/mail/i18n/de.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/es.po b/addons/mail/i18n/es.po index 221c62a59cd..9010e1b7beb 100644 --- a/addons/mail/i18n/es.po +++ b/addons/mail/i18n/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/es_CR.po b/addons/mail/i18n/es_CR.po index 2234b60436e..68deb811c3b 100644 --- a/addons/mail/i18n/es_CR.po +++ b/addons/mail/i18n/es_CR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" "Language: es\n" #. module: mail diff --git a/addons/mail/i18n/es_MX.po b/addons/mail/i18n/es_MX.po index 332f1a0751c..05cca870e25 100644 --- a/addons/mail/i18n/es_MX.po +++ b/addons/mail/i18n/es_MX.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/es_PY.po b/addons/mail/i18n/es_PY.po index fae6311e235..9889f3cc961 100644 --- a/addons/mail/i18n/es_PY.po +++ b/addons/mail/i18n/es_PY.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/es_VE.po b/addons/mail/i18n/es_VE.po index 70f0995cce4..bf28fe82dc3 100644 --- a/addons/mail/i18n/es_VE.po +++ b/addons/mail/i18n/es_VE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/et.po b/addons/mail/i18n/et.po index cfc6ddc4ad3..7c1cdb1caaa 100644 --- a/addons/mail/i18n/et.po +++ b/addons/mail/i18n/et.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/fi.po b/addons/mail/i18n/fi.po index 6ea227fe890..a5a13c3e112 100644 --- a/addons/mail/i18n/fi.po +++ b/addons/mail/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/fr.po b/addons/mail/i18n/fr.po index 4bc7a7cf5bf..da0536beae3 100644 --- a/addons/mail/i18n/fr.po +++ b/addons/mail/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 @@ -1238,7 +1238,7 @@ msgstr "Favori" #: code:addons/mail/static/src/xml/mail.xml:313 #, python-format msgid "more messages" -msgstr "plus de messages" +msgstr "messages supplémentaires" #. module: mail #: code:addons/mail/update.py:93 diff --git a/addons/mail/i18n/gl.po b/addons/mail/i18n/gl.po index 1ac16163418..9e00af100f4 100644 --- a/addons/mail/i18n/gl.po +++ b/addons/mail/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/he.po b/addons/mail/i18n/he.po index 07ac78a819b..c55a34fd29a 100644 --- a/addons/mail/i18n/he.po +++ b/addons/mail/i18n/he.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/hr.po b/addons/mail/i18n/hr.po index 7c5aa4d0c11..4cc04439627 100644 --- a/addons/mail/i18n/hr.po +++ b/addons/mail/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/hu.po b/addons/mail/i18n/hu.po index 0b0e10cf810..df72b962c4b 100644 --- a/addons/mail/i18n/hu.po +++ b/addons/mail/i18n/hu.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/it.po b/addons/mail/i18n/it.po index 228fd135aac..6860879c137 100644 --- a/addons/mail/i18n/it.po +++ b/addons/mail/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/ja.po b/addons/mail/i18n/ja.po index be6ef9c4426..649b0ddd794 100644 --- a/addons/mail/i18n/ja.po +++ b/addons/mail/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/ko.po b/addons/mail/i18n/ko.po index e1cc4bc0608..9fe1610a6dd 100644 --- a/addons/mail/i18n/ko.po +++ b/addons/mail/i18n/ko.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/lt.po b/addons/mail/i18n/lt.po index 59acc32f0c3..f3bc8cb4262 100644 --- a/addons/mail/i18n/lt.po +++ b/addons/mail/i18n/lt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/lv.po b/addons/mail/i18n/lv.po index 2c0b9ef39a8..4e2fb780288 100644 --- a/addons/mail/i18n/lv.po +++ b/addons/mail/i18n/lv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/mk.po b/addons/mail/i18n/mk.po index 96c3a55d192..d8c8658cc3c 100644 --- a/addons/mail/i18n/mk.po +++ b/addons/mail/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/mn.po b/addons/mail/i18n/mn.po index 9fff5ef7d81..f607929b80a 100644 --- a/addons/mail/i18n/mn.po +++ b/addons/mail/i18n/mn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/nl.po b/addons/mail/i18n/nl.po index cf8024bdd26..8213fbd11e7 100644 --- a/addons/mail/i18n/nl.po +++ b/addons/mail/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:20+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:42+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/pl.po b/addons/mail/i18n/pl.po index ef4568d5a33..5cacc26f18c 100644 --- a/addons/mail/i18n/pl.po +++ b/addons/mail/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/pt.po b/addons/mail/i18n/pt.po index f4e407562a0..a5eeb6db6eb 100644 --- a/addons/mail/i18n/pt.po +++ b/addons/mail/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/pt_BR.po b/addons/mail/i18n/pt_BR.po index 1bd0a00f4a6..94c350a7781 100644 --- a/addons/mail/i18n/pt_BR.po +++ b/addons/mail/i18n/pt_BR.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/ro.po b/addons/mail/i18n/ro.po index 9bfb9331b80..2605e26660a 100644 --- a/addons/mail/i18n/ro.po +++ b/addons/mail/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/ru.po b/addons/mail/i18n/ru.po index 70267a398db..819035082dd 100644 --- a/addons/mail/i18n/ru.po +++ b/addons/mail/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/sl.po b/addons/mail/i18n/sl.po index 91145244cda..0674e2410bd 100644 --- a/addons/mail/i18n/sl.po +++ b/addons/mail/i18n/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/sr@latin.po b/addons/mail/i18n/sr@latin.po index 1bff0193658..d0694a48ccc 100644 --- a/addons/mail/i18n/sr@latin.po +++ b/addons/mail/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/sv.po b/addons/mail/i18n/sv.po index 5ed6764f98f..6565aaf3b2f 100644 --- a/addons/mail/i18n/sv.po +++ b/addons/mail/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/th.po b/addons/mail/i18n/th.po index 54483c96055..bd2b2d7edd9 100644 --- a/addons/mail/i18n/th.po +++ b/addons/mail/i18n/th.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/tr.po b/addons/mail/i18n/tr.po index 02a88e33789..f3ef77a2241 100644 --- a/addons/mail/i18n/tr.po +++ b/addons/mail/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/vi.po b/addons/mail/i18n/vi.po index d234db7afc6..b64082ee258 100644 --- a/addons/mail/i18n/vi.po +++ b/addons/mail/i18n/vi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:21+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/zh_CN.po b/addons/mail/i18n/zh_CN.po index b1ae0e6ea58..a9829f57c1e 100644 --- a/addons/mail/i18n/zh_CN.po +++ b/addons/mail/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/i18n/zh_TW.po b/addons/mail/i18n/zh_TW.po index e66d773e10c..69cb75db37e 100644 --- a/addons/mail/i18n/zh_TW.po +++ b/addons/mail/i18n/zh_TW.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-12 08:22+0000\n" -"X-Generator: Launchpad (build 16976)\n" +"X-Launchpad-Export-Date: 2014-04-22 07:43+0000\n" +"X-Generator: Launchpad (build 16985)\n" #. module: mail #: view:mail.followers:0 diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index 0059df90530..33f5f1f8a83 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -96,13 +96,7 @@ class mail_notification(osv.Model): if message.author_id and message.author_id.email == partner.email: continue # Partner does not want to receive any emails or is opt-out - if partner.notification_email_send == 'none': - continue - # Partner wants to receive only emails and comments - if partner.notification_email_send == 'comment' and message.type not in ('email', 'comment'): - continue - # Partner wants to receive only emails - if partner.notification_email_send == 'email' and message.type != 'email': + if partner.notify_email == 'none': continue notify_pids.append(partner.id) return notify_pids @@ -115,8 +109,7 @@ class mail_notification(osv.Model): Administrator </p> <div> - <small>Sent by <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> OR - <small>Sent by Administrator using <a ...>OpenERP</a>.</small> + <small>Sent from <a ...>Your Company</a> using <a ...>OpenERP</a>.</small> </div> """ footer = "" @@ -138,7 +131,7 @@ class mail_notification(osv.Model): company = "<a style='color:inherit' href='%s'>%s</a>" % (website_url, user.company_id.name) else: company = user.company_id.name - sent_by = _('Sent by %(company)s using %(openerp)s.') + sent_by = _('Sent from %(company)s using %(openerp)s') signature_company = '<small>%s</small>' % (sent_by % { 'company': company, 'openerp': "<a style='color:inherit' href='https://www.openerp.com/'>OpenERP</a>" diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index a33eaaea15d..ebce0988dd3 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -126,7 +126,7 @@ class mail_mail(osv.Model): _logger.exception("Failed processing mail queue") return res - def _postprocess_sent_message(self, cr, uid, mail, context=None): + def _postprocess_sent_message(self, cr, uid, mail, context=None, mail_sent=True): """Perform any post-processing necessary after sending ``mail`` successfully, including deleting it completely along with its attachment if the ``auto_delete`` flag of the mail was set. @@ -145,9 +145,10 @@ class mail_mail(osv.Model): #------------------------------------------------------ def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None): - """ Generate URLs for links in mails: - - partner is an user and has read access to the document: direct link to document with model, res_id - """ + """Generate URLs for links in mails: partner has access (is user): + link to action_mail_redirect action that will redirect to doc or Inbox """ + if context is None: + context = {} if partner and partner.user_ids: base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') # the parameters to encode for the query and fragment part of url @@ -162,16 +163,15 @@ class mail_mail(osv.Model): fragment.update(model=mail.model, res_id=mail.res_id) url = urljoin(base_url, "/web?%s#%s" % (urlencode(query), urlencode(fragment))) - return _("""<span class='oe_mail_footer_access'><small>Access your messages and documents <a style='color:inherit' href="%s">in OpenERP</a></small></span>""") % url + return _("""<span class='oe_mail_footer_access'><small>about <a style='color:inherit' href="%s">%s %s</a></small></span>""") % (url, context.get('model_name', ''), mail.record_name) else: return None def send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None): - """ If subject is void and record_name defined: '<Author> posted on <Resource>' + """If subject is void, set the subject as 'Re: <Resource>' or + 'Re: <mail.parent_id.subject>' :param boolean force: force the subject replacement - :param browse_record mail: mail.mail browse_record - :param browse_record partner: specific recipient partner """ if (force or not mail.subject) and mail.record_name: return 'Re: %s' % (mail.record_name) @@ -180,12 +180,8 @@ class mail_mail(osv.Model): return mail.subject def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): - """ Return a specific ir_email body. The main purpose of this method - is to be inherited to add custom content depending on some module. - - :param browse_record mail: mail.mail browse_record - :param browse_record partner: specific recipient partner - """ + """Return a specific ir_email body. The main purpose of this method + is to be inherited to add custom content depending on some module.""" body = mail.body_html # generate footer @@ -194,34 +190,34 @@ class mail_mail(osv.Model): body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div') return body - def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): - """ Return a dictionary for specific email values, depending on a - partner, or generic to the whole recipients given by mail.email_to. - - :param browse_record mail: mail.mail browse_record - :param browse_record partner: specific recipient partner - """ - body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) - subject = self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context) - body_alternative = tools.html2plaintext(body) - - # generate email_to, heuristic: - # 1. if 'partner' is specified and there is a related document: Followers of 'Doc' <email> - # 2. if 'partner' is specified, but no related document: Partner Name <email> - # 3; fallback on mail.email_to that we split to have an email addresses list - if partner and mail.record_name: + def send_get_mail_to(self, cr, uid, mail, partner=None, context=None): + """Forge the email_to with the following heuristic: + - if 'partner' and mail is a notification on a document: followers (Followers of 'Doc' <email>) + - elif 'partner', no notificatoin or no doc: recipient specific (Partner Name <email>) + - else fallback on mail.email_to splitting """ + if partner and mail.notification and mail.record_name: sanitized_record_name = re.sub(r'[^\w+.]+', '-', mail.record_name) email_to = [_('"Followers of %s" <%s>') % (sanitized_record_name, partner.email)] elif partner: email_to = ['%s <%s>' % (partner.name, partner.email)] else: email_to = tools.email_split(mail.email_to) + return email_to + def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): + """Return a dictionary for specific email values, depending on a + partner, or generic to the whole recipients given by mail.email_to. + + :param browse_record mail: mail.mail browse_record + :param browse_record partner: specific recipient partner + """ + body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) + body_alternative = tools.html2plaintext(body) return { 'body': body, 'body_alternative': body_alternative, - 'subject': subject, - 'email_to': email_to, + 'subject': self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context), + 'email_to': self.send_get_mail_to(cr, uid, mail, partner=partner, context=context), } def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None): @@ -239,10 +235,19 @@ class mail_mail(osv.Model): email sending process has failed :return: True """ + if context is None: + context = {} ir_mail_server = self.pool.get('ir.mail_server') - for mail in self.browse(cr, SUPERUSER_ID, ids, context=context): try: + # TDE note: remove me when model_id field is present on mail.message - done here to avoid doing it multiple times in the sub method + if mail.model: + model_id = self.pool['ir.model'].search(cr, SUPERUSER_ID, [('model', '=', mail.model)], context=context)[0] + model = self.pool['ir.model'].browse(cr, SUPERUSER_ID, model_id, context=context) + else: + model = None + if model: + context['model_name'] = model.name # handle attachments attachments = [] for attach in mail.attachment_ids: @@ -284,7 +289,7 @@ class mail_mail(osv.Model): res = ir_mail_server.send_email(cr, uid, msg, mail_server_id=mail.mail_server_id.id, context=context) - + if res: mail.write({'state': 'sent', 'message_id': res}) mail_sent = True @@ -294,11 +299,11 @@ class mail_mail(osv.Model): # /!\ can't use mail.state here, as mail.refresh() will cause an error # see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1 - if mail_sent: - self._postprocess_sent_message(cr, uid, mail, context=context) + self._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=mail_sent) except Exception as e: _logger.exception('failed sending mail.mail %s', mail.id) mail.write({'state': 'exception'}) + self._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=False) if raise_exception: if isinstance(e, AssertionError): # get the args of the original error, wrap into a value and throw a MailDeliveryException @@ -307,6 +312,6 @@ class mail_mail(osv.Model): raise MailDeliveryException(_("Mail Delivery Failed"), value) raise - if auto_commit == True: + if auto_commit is True: cr.commit() return True diff --git a/addons/mail/mail_mail_view.xml b/addons/mail/mail_mail_view.xml index cf3dd1e8233..e259d28a2b7 100644 --- a/addons/mail/mail_mail_view.xml +++ b/addons/mail/mail_mail_view.xml @@ -36,6 +36,7 @@ <div> <group string="Status"> <field name="auto_delete"/> + <field name="notification"/> <field name="type"/> <field name="state"/> <field name="mail_server_id"/> diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 4c05d7a6d1f..5b716a14ef2 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -81,22 +81,6 @@ class mail_message(osv.Model): context = dict(context, default_type=None) return super(mail_message, self).default_get(cr, uid, fields, context=context) - def _shorten_name(self, name): - if len(name) <= (self._message_record_name_length + 3): - return name - return name[:self._message_record_name_length] + '...' - - def _get_record_name(self, cr, uid, ids, name, arg, context=None): - """ Return the related document name, using name_get. It is done using - SUPERUSER_ID, to be sure to have the record name correctly stored. """ - # TDE note: regroup by model/ids, to have less queries to perform - result = dict.fromkeys(ids, False) - for message in self.read(cr, uid, ids, ['model', 'res_id'], context=context): - if not message.get('model') or not message.get('res_id') or message['model'] not in self.pool: - continue - result[message['id']] = self.pool[message['model']].name_get(cr, SUPERUSER_ID, [message['res_id']], context=context)[0][1] - return result - def _get_to_read(self, cr, uid, ids, name, arg, context=None): """ Compute if the message is unread by the current user. """ res = dict((id, False) for id in ids) @@ -135,16 +119,6 @@ class mail_message(osv.Model): inversed because we search unread message on a read column. """ return ['&', ('notification_ids.partner_id.user_ids', 'in', [uid]), ('notification_ids.starred', '=', domain[0][2])] - def name_get(self, cr, uid, ids, context=None): - # name_get may receive int id instead of an id list - if isinstance(ids, (int, long)): - ids = [ids] - res = [] - for message in self.browse(cr, uid, ids, context=context): - name = '%s: %s' % (message.subject or '', strip_tags(message.body or '') or '') - res.append((message.id, self._shorten_name(name.lstrip(' :')))) - return res - _columns = { 'type': fields.selection([ ('email', 'Email'), @@ -172,9 +146,7 @@ class mail_message(osv.Model): '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='char', - store=True, string='Message Record Name', - help="Name get of the related document."), + 'record_name': fields.char('Message Record Name', help="Name get of the related document."), 'notification_ids': fields.one2many('mail.notification', 'message_id', string='Notifications', auto_join=True, help='Technical field holding the message notifications. Use notified_partner_ids to access notified partners.'), @@ -783,6 +755,13 @@ class mail_message(osv.Model): _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % \ (self._description, operation)) + def _get_record_name(self, cr, uid, values, context=None): + """ Return the related document name, using name_get. It is done using + SUPERUSER_ID, to be sure to have the record name correctly stored. """ + if not values.get('model') or not values.get('res_id') or values['model'] not in self.pool: + return False + return self.pool[values['model']].name_get(cr, SUPERUSER_ID, [values['res_id']], context=context)[0][1] + def _get_reply_to(self, cr, uid, values, context=None): """ Return a specific reply_to: alias of the document through message_get_reply_to or take the email_from @@ -841,8 +820,11 @@ class mail_message(osv.Model): values['message_id'] = self._get_message_id(cr, uid, values, context=context) if 'reply_to' not in values: values['reply_to'] = self._get_reply_to(cr, uid, values, context=context) + if 'record_name' not in values and 'default_record_name' not in context: + values['record_name'] = self._get_record_name(cr, uid, values, context=context) newid = super(mail_message, self).create(cr, uid, values, context) + self._notify(cr, uid, newid, context=context, force_send=context.get('mail_notify_force_send', True), user_signature=context.get('mail_notify_user_signature', True)) @@ -887,78 +869,6 @@ class mail_message(osv.Model): # Messaging API #------------------------------------------------------ - # TDE note: this code is not used currently, will be improved in a future merge, when quoted context - # will be added to email send for notifications. Currently only WIP. - MAIL_TEMPLATE = """<div> - % if message: - ${display_message(message)} - % endif - % for ctx_msg in context_messages: - ${display_message(ctx_msg)} - % endfor - % if add_expandable: - ${display_expandable()} - % endif - ${display_message(header_message)} - </div> - - <%def name="display_message(message)"> - <div> - Subject: ${message.subject}<br /> - Body: ${message.body} - </div> - </%def> - - <%def name="display_expandable()"> - <div>This is an expandable.</div> - </%def> - """ - - def message_quote_context(self, cr, uid, id, context=None, limit=3, add_original=False): - """ - 1. message.parent_id = False: new thread, no quote_context - 2. get the lasts messages in the thread before message - 3. get the message header - 4. add an expandable between them - - :param dict quote_context: options for quoting - :return string: html quote - """ - add_expandable = False - - message = self.browse(cr, uid, id, context=context) - if not message.parent_id: - return '' - context_ids = self.search(cr, uid, [ - ('parent_id', '=', message.parent_id.id), - ('id', '<', message.id), - ], limit=limit, context=context) - - if len(context_ids) >= limit: - add_expandable = True - context_ids = context_ids[0:-1] - - context_ids.append(message.parent_id.id) - context_messages = self.browse(cr, uid, context_ids, context=context) - header_message = context_messages.pop() - - try: - if not add_original: - message = False - result = MakoTemplate(self.MAIL_TEMPLATE).render_unicode(message=message, - context_messages=context_messages, - header_message=header_message, - add_expandable=add_expandable, - # context kw would clash with mako internals - ctx=context, - format_exceptions=True) - result = result.strip() - return result - except Exception: - _logger.exception("failed to render mako template for quoting message") - return '' - return result - def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True): """ Add the related record followers to the destination partner_ids if is not a private message. Call mail_notification.notify to manage the email sending @@ -975,9 +885,11 @@ class mail_message(osv.Model): cr, SUPERUSER_ID, [ ('res_model', '=', message.model), ('res_id', '=', message.res_id), - ('subtype_ids', 'in', message.subtype_id.id) ], context=context) - partners_to_notify |= set(fo.partner_id.id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)) + partners_to_notify |= set( + fo.partner_id.id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context) + if message.subtype_id.id in [st.id for st in fo.subtype_ids] + ) # remove me from notified partners, unless the message is written on my own wall if message.subtype_id and message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id: partners_to_notify |= set([message.author_id.id]) @@ -1006,25 +918,3 @@ class mail_message(osv.Model): 'partner_id': partner.id, 'read': True, }, context=context) - - #------------------------------------------------------ - # Tools - #------------------------------------------------------ - - def check_partners_email(self, cr, uid, partner_ids, context=None): - """ Verify that selected partner_ids have an email_address defined. - Otherwise throw a warning. """ - 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 {} - 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) - return {'warning': { - 'title': _('Partners email addresses not found'), - 'message': warning_msg, - } - } diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 812ff91be90..112dff6bac6 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -97,6 +97,9 @@ class mail_thread(osv.AbstractModel): # :param function lambda: returns whether the tracking should record using this subtype _track = {} + # Mass mailing feature + _mail_mass_mailing = False + def get_empty_list_help(self, cr, uid, help, context=None): """ Override of BaseModel.get_empty_list_help() to generate an help message that adds alias information. """ @@ -585,23 +588,6 @@ class mail_thread(osv.AbstractModel): model_obj.check_access_rights(cr, uid, check_operation) model_obj.check_access_rule(cr, uid, mids, check_operation, context=context) - def _get_formview_action(self, cr, uid, id, model=None, context=None): - """ Return an action to open the document. This method is meant to be - overridden in addons that want to give specific view ids for example. - - :param int id: id of the document to open - :param string model: specific model that overrides self._name - """ - return { - 'type': 'ir.actions.act_window', - 'res_model': model or self._name, - 'view_type': 'form', - 'view_mode': 'form', - 'views': [(False, 'form')], - 'target': 'current', - 'res_id': id, - } - def _get_inbox_action_xml_id(self, cr, uid, context=None): """ When redirecting towards the Inbox, choose which action xml_id has to be fetched. This method is meant to be inherited, at least in portal @@ -644,10 +630,7 @@ class mail_thread(osv.AbstractModel): if model_obj.check_access_rights(cr, uid, 'read', raise_exception=False): try: model_obj.check_access_rule(cr, uid, [res_id], 'read', context=context) - if not hasattr(model_obj, '_get_formview_action'): - action = self.pool.get('mail.thread')._get_formview_action(cr, uid, res_id, model=model, context=context) - else: - action = model_obj._get_formview_action(cr, uid, res_id, context=context) + action = model_obj.get_formview_action(cr, uid, res_id, context=context) except (osv.except_osv, orm.except_orm): pass action.update({ @@ -662,15 +645,31 @@ class mail_thread(osv.AbstractModel): # Email specific #------------------------------------------------------ + def message_get_default_recipients(self, cr, uid, ids, context=None): + if context and context.get('thread_model') and context['thread_model'] in self.pool and context['thread_model'] != self._name: + sub_ctx = dict(context) + sub_ctx.pop('thread_model') + return self.pool[context['thread_model']].message_get_default_recipients(cr, uid, ids, context=sub_ctx) + res = {} + for record in self.browse(cr, SUPERUSER_ID, ids, context=context): + recipient_ids, email_to, email_cc = set(), False, False + if 'partner_id' in self._all_columns and record.partner_id: + recipient_ids.add(record.partner_id.id) + elif 'email_from' in self._all_columns and record.email_from: + email_to = record.email_from + elif 'email' in self._all_columns: + email_to = record.email + res[record.id] = {'partner_ids': list(recipient_ids), 'email_to': email_to, 'email_cc': email_cc} + return res + def message_get_reply_to(self, cr, uid, ids, context=None): """ Returns the preferred reply-to email address that is basically the alias of the document, if it exists. """ if not self._inherits.get('mail.alias'): return [False for id in ids] - return ["%s@%s" % (record['alias_name'], record['alias_domain']) - if record.get('alias_domain') and record.get('alias_name') - else False - for record in self.read(cr, SUPERUSER_ID, ids, ['alias_name', 'alias_domain'], context=context)] + return ["%s@%s" % (record.alias_name, record.alias_domain) + if record.alias_domain and record.alias_name else False + for record in self.browse(cr, SUPERUSER_ID, ids, context=context)] #------------------------------------------------------ # Mail gateway diff --git a/addons/mail/res_partner.py b/addons/mail/res_partner.py index 8da2441f3bc..bf801511761 100644 --- a/addons/mail/res_partner.py +++ b/addons/mail/res_partner.py @@ -28,23 +28,21 @@ class res_partner_mail(osv.Model): _name = "res.partner" _inherit = ['res.partner', 'mail.thread'] _mail_flat_thread = False + _mail_mass_mailing = _('Customers') _columns = { - 'notification_email_send': fields.selection([ + 'notify_email': fields.selection([ ('none', 'Never'), - ('email', 'Incoming Emails only'), - ('comment', 'Incoming Emails and Discussions'), - ('all', 'All Messages (discussions, emails, followed system notifications)'), - ], 'Receive Messages by Email', required=True, + ('always', 'All Messages'), + ], 'Receive Inbox Notifications by Email', required=True, + oldname='notification_email_send', help="Policy to receive emails for new messages pushed to your personal Inbox:\n" "- Never: no emails are sent\n" - "- Incoming Emails only: for messages received by the system via email\n" - "- Incoming Emails and Discussions: for incoming emails along with internal discussions\n" "- All Messages: for every notification you receive in your Inbox"), } _defaults = { - 'notification_email_send': lambda *args: 'comment' + 'notify_email': lambda *args: 'always' } def message_get_suggested_recipients(self, cr, uid, ids, context=None): @@ -53,4 +51,5 @@ class res_partner_mail(osv.Model): self._message_add_suggested_recipient(cr, uid, recipients, partner, partner=partner, reason=_('Partner Profile')) return recipients -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + def message_get_default_recipients(self, cr, uid, ids, context=None): + return dict((id, {'partner_ids': [id], 'email_to': False, 'email_cc': False}) for id in ids) diff --git a/addons/mail/res_partner_view.xml b/addons/mail/res_partner_view.xml index 7df5d27c9d0..5066d85e682 100644 --- a/addons/mail/res_partner_view.xml +++ b/addons/mail/res_partner_view.xml @@ -8,7 +8,7 @@ <field name="inherit_id" ref="base.view_partner_form"/> <field name="arch" type="xml"> <xpath expr="//field[@name='active']" position="after"> - <field name='notification_email_send'/> + <field name='notify_email' widget="radio"/> </xpath> <xpath expr="//sheet" position="after"> <div class="oe_chatter"> diff --git a/addons/mail/res_users.py b/addons/mail/res_users.py index 42e739d8051..8fe1482b427 100644 --- a/addons/mail/res_users.py +++ b/addons/mail/res_users.py @@ -54,10 +54,10 @@ class res_users(osv.Model): init_res = super(res_users, self).__init__(pool, cr) # duplicate list to avoid modifying the original reference self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS) - self.SELF_WRITEABLE_FIELDS.extend(['notification_email_send', 'display_groups_suggestions']) + self.SELF_WRITEABLE_FIELDS.extend(['notify_email', 'display_groups_suggestions']) # duplicate list to avoid modifying the original reference self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS) - self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name', 'display_groups_suggestions']) + self.SELF_READABLE_FIELDS.extend(['notify_email', 'alias_domain', 'alias_name', 'display_groups_suggestions']) return init_res def _auto_init(self, cr, context=None): diff --git a/addons/mail/res_users_view.xml b/addons/mail/res_users_view.xml index 2bf54b4bafd..eef2924134f 100644 --- a/addons/mail/res_users_view.xml +++ b/addons/mail/res_users_view.xml @@ -10,7 +10,7 @@ <field name="arch" type="xml"> <data> <field name="email" position="before"> - <field name="notification_email_send" readonly="0"/> + <field name="notify_email" widget="radio" readonly="0"/> </field> </data> </field> @@ -24,7 +24,7 @@ <field name="arch" type="xml"> <data> <field name="signature" position="before"> - <field name="notification_email_send"/> + <field name="notify_email" widget="radio"/> </field> <field name="signature" position="before"> <label for="alias_id" string="Messaging Alias" class="oe_read_only" diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 17dd4b57cd0..99a7751e15e 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -507,18 +507,15 @@ openerp.mail = function (session) { } $.when(recipient_done).done(function (partner_ids) { var context = { - 'default_composition_mode': default_composition_mode, 'default_parent_id': self.id, 'default_body': mail.ChatterUtils.get_text2html(self.$el ? (self.$el.find('textarea:not(.oe_compact)').val() || '') : ''), 'default_attachment_ids': _.map(self.attachment_ids, function (file) {return file.id;}), 'default_partner_ids': partner_ids, + 'default_is_log': self.is_log, 'mail_post_autofollow': true, 'mail_post_autofollow_partner_ids': partner_ids, 'is_private': self.is_private }; - if (self.is_log) { - _.extend(context, {'mail_compose_log': true}); - } if (default_composition_mode != 'reply' && self.context.default_model && self.context.default_res_id) { context.default_model = self.context.default_model; context.default_res_id = self.context.default_res_id; diff --git a/addons/mail/static/src/js/many2many_tags_email.js b/addons/mail/static/src/js/many2many_tags_email.js index cc701e8a585..5d36262f5b9 100644 --- a/addons/mail/static/src/js/many2many_tags_email.js +++ b/addons/mail/static/src/js/many2many_tags_email.js @@ -44,7 +44,7 @@ instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags new instance.web.Model('res.partner').call("search", [[ ["id", "in", ids], ["email", "=", false], - ["notification_email_send", "in", ['all', 'comment']] ]], + ["notify_email", "=", 'always'] ]], {context: this.build_context()}) .then(function (record_ids) { // valid partner diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 28cbbca1f2c..06af2303239 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -189,17 +189,6 @@ </td> <td><div class="oe_view_manager_view_search" t-opentag="true"/></td> </tr> - <tr class="oe_header_row" t-if="widget.action.params.view_inbox and widget.action.params.show_compose_message" > - <td colspan="2"> - <button type="button" class="oe_write_full oe_highlight"> - Compose a new message - </button> - <span class='oe_alternative'> - or - <a href='#' class='oe_write_onwall oe_bold' help='Your followers can read this message'>Write to my followers</a> - </span> - </td> - </tr> </tbody> </table> <div class="oe_mail-placeholder"></div> diff --git a/addons/mail/tests/common.py b/addons/mail/tests/common.py index 68a329e043a..d53a8078c96 100644 --- a/addons/mail/tests/common.py +++ b/addons/mail/tests/common.py @@ -77,7 +77,7 @@ class TestMail(common.TransactionCase): 'alias_name': 'ernest', 'email': 'e.e@example.com', 'signature': '--\nErnest', - 'notification_email_send': 'comment', + 'notify_email': 'always', 'groups_id': [(6, 0, [self.group_employee_id])] }, {'no_reset_password': True}) self.user_noone_id = self.res_users.create(cr, uid, { @@ -86,7 +86,7 @@ class TestMail(common.TransactionCase): 'alias_name': 'noemie', 'email': 'n.n@example.com', 'signature': '--\nNoemie', - 'notification_email_send': 'comment', + 'notify_email': 'always', 'groups_id': [(6, 0, [])] }, {'no_reset_password': True}) diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py index c7f1056c59a..0a481c78eca 100644 --- a/addons/mail/tests/test_mail_features.py +++ b/addons/mail/tests/test_mail_features.py @@ -210,24 +210,6 @@ class test_mail(TestMail): self.assertTrue(subtype_data['mt_mg_nodef']['followed'], 'Admin should follow mt_mg_nodef in pigs') self.assertTrue(subtype_data['mt_all_nodef']['followed'], 'Admin should follow mt_all_nodef in pigs') - def test_10_message_quote_context(self): - """ Tests designed for message_post. """ - cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs - - msg1_id = self.mail_message.create(cr, uid, {'body': 'Thread header about Zap Brannigan', 'subject': 'My subject'}) - msg2_id = self.mail_message.create(cr, uid, {'body': 'First answer, should not be displayed', 'subject': 'Re: My subject', 'parent_id': msg1_id}) - msg3_id = self.mail_message.create(cr, uid, {'body': 'Second answer', 'subject': 'Re: My subject', 'parent_id': msg1_id}) - msg4_id = self.mail_message.create(cr, uid, {'body': 'Third answer', 'subject': 'Re: My subject', 'parent_id': msg1_id}) - msg_new_id = self.mail_message.create(cr, uid, {'body': 'My answer I am propagating', 'subject': 'Re: My subject', 'parent_id': msg1_id}) - - result = self.mail_message.message_quote_context(cr, uid, msg_new_id, limit=3) - self.assertIn('Thread header about Zap Brannigan', result, 'Thread header content should be in quote.') - self.assertIn('Second answer', result, 'Answer should be in quote.') - self.assertIn('Third answer', result, 'Answer should be in quote.') - self.assertIn('expandable', result, 'Expandable should be present.') - self.assertNotIn('First answer, should not be displayed', result, 'Old answer should not be in quote.') - self.assertNotIn('My answer I am propagating', result, 'Thread header content should be in quote.') - def test_11_notification_url(self): """ Tests designed to test the URL added in notification emails. """ cr, uid, group_pigs = self.cr, self.uid, self.group_pigs @@ -366,14 +348,14 @@ class test_mail(TestMail): # Data creation # -------------------------------------------------- # 0 - Update existing users-partners - self.res_users.write(cr, uid, [uid], {'email': 'a@a', 'notification_email_send': 'comment'}) + self.res_users.write(cr, uid, [uid], {'email': 'a@a', 'notify_email': 'always'}) self.res_users.write(cr, uid, [self.user_raoul_id], {'email': 'r@r'}) # 1 - Bert Tartopoils, with email, should receive emails for comments and emails p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) # 2 - Carine Poilvache, with email, should receive emails for emails - p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'}) + p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notify_email': 'none'}) # 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message - p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notification_email_send': 'all'}) + p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notify_email': 'always'}) # 4 - Attachments attach1_id = self.ir_attachment.create(cr, user_raoul.id, { 'name': 'Attach1', 'datas_fname': 'Attach1', @@ -600,9 +582,9 @@ class test_mail(TestMail): # 1 - Bert Tartopoils, with email, should receive emails for comments and emails p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) # 2 - Carine Poilvache, with email, should receive emails for emails - p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'}) + p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notify_email': 'always'}) # 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message - p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notification_email_send': 'all'}) + p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notify_email': 'always'}) # 4 - Create a Bird mail.group, that will be used to test mass mailing group_bird_id = self.mail_group.create(cr, uid, { @@ -674,7 +656,6 @@ class test_mail(TestMail): 'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])] }, context={ 'default_composition_mode': 'reply', - 'default_model': 'mail.thread', 'default_res_id': self.group_pigs_id, 'default_parent_id': message.id }) @@ -699,11 +680,10 @@ class test_mail(TestMail): # -------------------------------------------------- # Do: Compose in mass_mail_mode on pigs and bird - compose_id = mail_compose.create(cr, user_raoul.id, - { + compose_id = mail_compose.create( + cr, user_raoul.id, { 'subject': _subject, 'body': '${object.description}', - 'post': True, 'partner_ids': [(4, p_c_id), (4, p_d_id)], }, context={ 'default_composition_mode': 'mass_mail', @@ -718,6 +698,13 @@ class test_mail(TestMail): 'default_res_id': -1, 'active_ids': [self.group_pigs_id, group_bird_id] }) + # check mail_mail + mail_mail_ids = self.mail_mail.search(cr, uid, [('subject', '=', _subject)]) + for mail_mail in self.mail_mail.browse(cr, uid, mail_mail_ids): + self.assertEqual(set([p.id for p in mail_mail.recipient_ids]), set([p_c_id, p_d_id]), + 'compose wizard: mail_mail mass mailing: mail.mail in mass mail incorrect recipients') + + # check logged messages group_pigs.refresh() group_bird.refresh() message1 = group_pigs.message_ids[0] @@ -733,14 +720,14 @@ class test_mail(TestMail): 'compose wizard: message_post: mail.message in mass mail subject incorrect') self.assertEqual(message1.body, '<p>%s</p>' % group_pigs.description, 'compose wizard: message_post: mail.message in mass mail body incorrect') - self.assertEqual(set([p.id for p in message1.notified_partner_ids]), set([p_c_id, p_d_id]), - 'compose wizard: message_post: mail.message in mass mail incorrect notified partners') + # self.assertEqual(set([p.id for p in message1.notified_partner_ids]), set([p_c_id, p_d_id]), + # 'compose wizard: message_post: mail.message in mass mail incorrect notified partners') self.assertEqual(message2.subject, _subject, 'compose wizard: message_post: mail.message in mass mail subject incorrect') self.assertEqual(message2.body, '<p>%s</p>' % group_bird.description, 'compose wizard: message_post: mail.message in mass mail body incorrect') - self.assertEqual(set([p.id for p in message2.notified_partner_ids]), set([p_c_id, p_d_id]), - 'compose wizard: message_post: mail.message in mass mail incorrect notified partners') + # self.assertEqual(set([p.id for p in message2.notified_partner_ids]), set([p_c_id, p_d_id]), + # 'compose wizard: message_post: mail.message in mass mail incorrect notified partners') # Test: mail.group followers: author not added as follower in mass mail mode pigs_pids = [p.id for p in group_pigs.message_follower_ids] @@ -757,7 +744,6 @@ class test_mail(TestMail): { 'subject': _subject, 'body': '${object.description}', - 'post': True, 'partner_ids': [(4, p_c_id), (4, p_d_id)], }, context={ 'default_composition_mode': 'mass_mail', diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index e5ff2b51fcd..e14a8f3dfe5 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -38,10 +38,7 @@ class mail_compose_message(osv.TransientModel): at model and view levels to provide specific features. The behavior of the wizard depends on the composition_mode field: - - '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`` + - 'comment': 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. @@ -50,6 +47,7 @@ class mail_compose_message(osv.TransientModel): _inherit = 'mail.message' _description = 'Email composition wizard' _log_access = True + _batch_size = 500 def default_get(self, cr, uid, fields, context=None): """ Handle composition mode. Some details about context keys: @@ -68,28 +66,22 @@ class mail_compose_message(osv.TransientModel): if context is None: context = {} result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context) - # get some important values from context - composition_mode = context.get('default_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')) - message_id = context.get('default_parent_id', context.get('message_id', context.get('active_id'))) - active_ids = context.get('active_ids') + + # v6.1 compatibility mode + result['composition_mode'] = result.get('composition_mode', context.get('mail.compose.message.mode')) + result['model'] = result.get('model', context.get('active_model')) + result['res_id'] = result.get('res_id', context.get('active_id')) + result['parent_id'] = result.get('parent_id', context.get('message_id')) + + # default values according to composition mode - NOTE: reply is deprecated, fall back on comment + if result['composition_mode'] == 'reply': + result['composition_mode'] = 'comment' + vals = {} if 'active_domain' in context: # not context.get() because we want to keep global [] domains - result['use_active_domain'] = True - result['active_domain'] = '%s' % context.get('active_domain') - elif not result.get('active_domain'): - result['active_domain'] = '' - # get default values according to the composition mode - if composition_mode == 'reply': - vals = self.get_message_data(cr, uid, message_id, context=context) - elif composition_mode == 'comment' and model and res_id: - vals = self.get_record_data(cr, uid, model, res_id, context=context) - elif composition_mode == 'mass_mail' and model and active_ids: - vals = {'model': model, 'res_id': res_id} - else: - vals = {'model': model, 'res_id': res_id} - if composition_mode: - vals['composition_mode'] = composition_mode + vals['use_active_domain'] = True + vals['active_domain'] = '%s' % context.get('active_domain') + if result['composition_mode'] == 'comment': + vals.update(self.get_record_data(cr, uid, result, context=context)) for field in vals: if field in fields: @@ -102,13 +94,15 @@ class mail_compose_message(osv.TransientModel): # but when creating the mail.message to create the mail.compose.message # access rights issues may rise # We therefore directly change the model and res_id - if result.get('model') == 'res.users' and result.get('res_id') == uid: + if result['model'] == 'res.users' and result['res_id'] == uid: result['model'] = 'res.partner' result['res_id'] = self.pool.get('res.users').browse(cr, uid, uid).partner_id.id 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')] + return [('comment', 'Post on a document'), + ('mass_mail', 'Email Mass Mailing'), + ('mass_post', 'Post on Multiple Documents')] _columns = { 'composition_mode': fields.selection( @@ -116,19 +110,19 @@ class mail_compose_message(osv.TransientModel): string='Composition mode'), 'partner_ids': fields.many2many('res.partner', 'mail_compose_message_res_partner_rel', - 'wizard_id', 'partner_id', 'Additional contacts'), + 'wizard_id', 'partner_id', 'Additional Contacts'), 'use_active_domain': fields.boolean('Use active domain'), 'active_domain': fields.char('Active domain', readonly=True), - 'post': fields.boolean('Post a copy in the document', - help='Post a copy of the message on the document communication history.'), - 'notify': fields.boolean('Notify followers', - help='Notify followers of the document'), - 'same_thread': fields.boolean('Replies in the document', - help='Replies to the messages will go into the selected document.'), 'attachment_ids': fields.many2many('ir.attachment', 'mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', 'Attachments'), - 'filter_id': fields.many2one('ir.filters', 'Filters'), + 'is_log': fields.boolean('Log an Internal Note', + help='Whether the message is an internal note (comment mode only)'), + # mass mode options + 'notify': fields.boolean('Notify followers', + help='Notify followers of the document (mass post only)'), + 'same_thread': fields.boolean('Replies in the document', + help='Replies to the messages will go into the selected document (mass mail only)'), } #TODO change same_thread to False in trunk (Require view update) _defaults = { @@ -136,8 +130,6 @@ class mail_compose_message(osv.TransientModel): 'body': lambda self, cr, uid, ctx={}: '', 'subject': lambda self, cr, uid, ctx={}: False, 'partner_ids': lambda self, cr, uid, ctx={}: [], - 'post': False, - 'notify': False, 'same_thread': True, } @@ -169,61 +161,36 @@ class mail_compose_message(osv.TransientModel): 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``. - - :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 - """ - doc_name_get = self.pool[model].name_get(cr, uid, [res_id], context=context) - record_name = False - if doc_name_get: - record_name = doc_name_get[0][1] - values = { - 'model': model, - 'res_id': res_id, - 'record_name': record_name, - } - if record_name: - values['subject'] = 'Re: %s' % record_name - return values - - def get_message_data(self, cr, uid, message_id, context=None): + def get_record_data(self, cr, uid, values, 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 recipients). - - :param int message_id: id of the mail.message to which the user - is replying. - """ - if not message_id: - return {} + wizard when sending an email related a previous email (parent_id) or + a document (model, res_id). This is based on previously computed default + values. """ if context is None: context = {} - message_data = self.pool.get('mail.message').browse(cr, uid, message_id, context=context) + result, subject = {}, False + if values.get('parent_id'): + parent = self.pool.get('mail.message').browse(cr, uid, values.get('parent_id'), context=context) + result['record_name'] = parent.record_name, + subject = tools.ustr(parent.subject or parent.record_name or '') + if not values.get('model'): + result['model'] = parent.model + if not values.get('res_id'): + result['res_id'] = parent.res_id + partner_ids = values.get('partner_ids', list()) + [partner.id for partner in parent.partner_ids] + if context.get('is_private') and parent.author_id: # check message is private then add author also in partner list. + partner_ids += [parent.author_id.id] + result['partner_ids'] = partner_ids + elif values.get('model') and values.get('res_id'): + doc_name_get = self.pool[values.get('model')].name_get(cr, uid, [values.get('res_id')], context=context) + result['record_name'] = doc_name_get and doc_name_get[0][1] or '' + subject = tools.ustr(result['record_name']) - # create subject re_prefix = _('Re:') - reply_subject = tools.ustr(message_data.subject or message_data.record_name or '') - if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject: - reply_subject = "%s %s" % (re_prefix, reply_subject) - # get partner_ids from original message - partner_ids = [partner.id for partner in message_data.partner_ids] if message_data.partner_ids else [] - partner_ids += context.get('default_partner_ids', []) - if context.get('is_private',False) and message_data.author_id : #check message is private then add author also in partner list. - partner_ids += [message_data.author_id.id] - # update the result - result = { - 'record_name': message_data.record_name, - 'model': message_data.model, - 'res_id': message_data.res_id, - 'parent_id': message_data.id, - 'subject': reply_subject, - 'partner_ids': partner_ids, - } + if subject and not (subject.startswith('Re:') or subject.startswith(re_prefix)): + subject = "%s %s" % (re_prefix, subject) + result['subject'] = subject + return result #------------------------------------------------------ @@ -235,53 +202,42 @@ class mail_compose_message(osv.TransientModel): email(s), rendering any template patterns on the fly if needed. """ if context is None: context = {} + # clean the context (hint: mass mailing sets some default values that # could be wrongly interpreted by mail_mail) context.pop('default_email_to', None) context.pop('default_partner_ids', None) - active_ids = context.get('active_ids') - is_log = context.get('mail_compose_log', False) - for wizard in self.browse(cr, uid, ids, context=context): - mass_mail_mode = wizard.composition_mode == 'mass_mail' + mass_mode = wizard.composition_mode in ('mass_mail', 'mass_post') active_model_pool = self.pool[wizard.model if wizard.model else 'mail.thread'] if not hasattr(active_model_pool, 'message_post'): context['thread_model'] = wizard.model active_model_pool = self.pool['mail.thread'] # wizard works in batch mode: [res_id] or active_ids or active_domain - if mass_mail_mode and wizard.use_active_domain and wizard.model: + if mass_mode and wizard.use_active_domain and wizard.model: res_ids = self.pool[wizard.model].search(cr, uid, eval(wizard.active_domain), context=context) - elif mass_mail_mode and wizard.model and active_ids: - res_ids = active_ids + elif mass_mode and wizard.model and context.get('active_ids'): + res_ids = context['active_ids'] else: res_ids = [wizard.res_id] - all_mail_values = self.get_mail_values(cr, uid, wizard, res_ids, context=context) - - for res_id, mail_values in all_mail_values.iteritems(): - if mass_mail_mode and not wizard.post: - m2m_attachment_ids = self.pool['mail.thread']._message_preprocess_attachments( - cr, uid, mail_values.pop('attachments', []), - mail_values.pop('attachment_ids', []), - 'mail.message', 0, - context=context) - mail_values['attachment_ids'] = m2m_attachment_ids - if not mail_values.get('reply_to'): - mail_values['reply_to'] = mail_values['email_from'] - self.pool.get('mail.mail').create(cr, uid, mail_values, context=context) - else: - subtype = 'mail.mt_comment' - if is_log: # log a note: subtype is False - subtype = False - elif mass_mail_mode: # mass mail: is a log pushed to recipients unless specified, author not added - if not wizard.notify: + sliced_res_ids = [res_ids[i:i + self._batch_size] for i in range(0, len(res_ids), self._batch_size)] + for res_ids in sliced_res_ids: + all_mail_values = self.get_mail_values(cr, uid, wizard, res_ids, context=context) + for res_id, mail_values in all_mail_values.iteritems(): + if wizard.composition_mode == 'mass_mail': + self.pool['mail.mail'].create(cr, uid, mail_values, context=context) + else: + subtype = 'mail.mt_comment' + if context.get('mail_compose_log') or (wizard.composition_mode == 'mass_post' and not wizard.notify): # log a note: subtype is False subtype = False - context = dict(context, - mail_notify_force_send=False, # do not send emails directly but use the queue instead - mail_create_nosubscribe=True) # add context key to avoid subscribing the author - active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **mail_values) + if wizard.composition_mode == 'mass_post': + context = dict(context, + mail_notify_force_send=False, # do not send emails directly but use the queue instead + mail_create_nosubscribe=True) # add context key to avoid subscribing the author + active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **mail_values) return {'type': 'ir.actions.act_window_close'} @@ -289,6 +245,7 @@ class mail_compose_message(osv.TransientModel): """Generate the values that will be used by send_mail to create mail_messages or mail_mails. """ results = dict.fromkeys(res_ids, False) + rendered_values, default_recipients = {}, {} mass_mail_mode = wizard.composition_mode == 'mass_mail' # render all template-based value at once @@ -303,40 +260,46 @@ class mail_compose_message(osv.TransientModel): 'parent_id': wizard.parent_id and wizard.parent_id.id, 'partner_ids': [partner.id for partner in wizard.partner_ids], 'attachment_ids': [attach.id for attach in wizard.attachment_ids], + 'author_id': wizard.author_id.id, + 'email_from': wizard.email_from, + 'record_name': wizard.record_name, } # mass mailing: rendering override wizard static values if mass_mail_mode and wizard.model: + # always keep a copy, reset record name (avoid browsing records) + mail_values.update(notification=True, model=wizard.model, res_id=res_id, record_name=False) + # auto deletion of mail_mail + if 'mail_auto_delete' in context: + mail_values['auto_delete'] = context.get('mail_auto_delete') + # rendered values using template email_dict = rendered_values[res_id] mail_values['partner_ids'] += email_dict.pop('partner_ids', []) + mail_values.update(email_dict) + if wizard.same_thread: + mail_values.pop('reply_to') + elif not mail_values.get('reply_to'): + mail_values['reply_to'] = mail_values['email_from'] + # mail_mail values: body -> body_html, partner_ids -> recipient_ids + mail_values['body_html'] = mail_values.get('body', '') + mail_values['recipient_ids'] = [(4, id) for id in mail_values.pop('partner_ids', [])] + # process attachments: should not be encoded before being processed by message_post / mail_mail create - attachments = [] - if email_dict.get('attachments'): - for name, enc_cont in email_dict.pop('attachments'): - attachments.append((name, base64.b64decode(enc_cont))) - mail_values['attachments'] = attachments + mail_values['attachments'] = [(name, base64.b64decode(enc_cont)) for name, enc_cont in email_dict.pop('attachments', list())] attachment_ids = [] for attach_id in mail_values.pop('attachment_ids'): new_attach_id = self.pool.get('ir.attachment').copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context) attachment_ids.append(new_attach_id) - mail_values['attachment_ids'] = attachment_ids - # email_from: mass mailing only can specify another email_from - if email_dict.get('email_from'): - mail_values['email_from'] = email_dict.pop('email_from') - # replies redirection: mass mailing only - if wizard.same_thread and wizard.post: - email_dict.pop('reply_to', None) - else: - mail_values['reply_to'] = email_dict.pop('reply_to', None) - mail_values.update(email_dict) - # mass mailing without post: mail_mail values - if mass_mail_mode and not wizard.post: - if 'mail_auto_delete' in context: - mail_values['auto_delete'] = context.get('mail_auto_delete') - mail_values['body_html'] = mail_values.get('body', '') - mail_values['recipient_ids'] = [(4, id) for id in mail_values.pop('partner_ids', [])] + mail_values['attachment_ids'] = self.pool['mail.thread']._message_preprocess_attachments( + cr, uid, mail_values.pop('attachments', []), + attachment_ids, 'mail.message', 0, context=context) + results[res_id] = mail_values return results + #------------------------------------------------------ + # Template rendering + #------------------------------------------------------ + def render_message_batch(self, cr, uid, wizard, res_ids, context=None): """Generate template-based values of wizard, for the document records given by res_ids. This method is meant to be inherited by email_template that @@ -346,6 +309,10 @@ class mail_compose_message(osv.TransientModel): once, and render it multiple times. This is useful for mass mailing where template rendering represent a significant part of the process. + Default recipients are also computed, based on mail_thread method + message_get_default_recipients. This allows to ensure a mass mailing has + always some recipients specified. + :param browse wizard: current mail.compose.message browse record :param list res_ids: list of record ids @@ -357,6 +324,9 @@ class mail_compose_message(osv.TransientModel): emails_from = self.render_template_batch(cr, uid, wizard.email_from, wizard.model, res_ids, context=context) replies_to = self.render_template_batch(cr, uid, wizard.reply_to, wizard.model, res_ids, context=context) + ctx = dict(context, thread_model=wizard.model) + default_recipients = self.pool['mail.thread'].message_get_default_recipients(cr, uid, res_ids, context=ctx) + results = dict.fromkeys(res_ids, False) for res_id in res_ids: results[res_id] = { @@ -365,6 +335,7 @@ class mail_compose_message(osv.TransientModel): 'email_from': emails_from[res_id], 'reply_to': replies_to[res_id], } + results[res_id].update(default_recipients.get(res_id, dict())) return results def render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False): diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml index 23931649402..5b6bfc50439 100644 --- a/addons/mail/wizard/mail_compose_message_view.xml +++ b/addons/mail/wizard/mail_compose_message_view.xml @@ -11,6 +11,7 @@ <field name="composition_mode" invisible="1"/> <field name="model" invisible="1"/> <field name="res_id" invisible="1"/> + <field name="is_log" invisible="1"/> <field name="parent_id" invisible="1"/> <field name="mail_server_id" invisible="1"/> <!-- Various warnings --> @@ -28,29 +29,27 @@ <field name="email_from" attrs="{'invisible':[('composition_mode', '!=', 'mass_mail')]}"/> <field name="subject" placeholder="Subject..." required="True"/> - <!-- classic message composer --> - <label for="partner_ids" string="Recipients" - attrs="{'invisible':[('composition_mode', '=', 'mass_mail')]}"/> - <div groups="base.group_user" - attrs="{'invisible':[('composition_mode', '=', 'mass_mail')]}"> - <span attrs="{'invisible':[('model', '=', False)]}"> - Followers of - <field name="record_name" readonly="1" class="oe_inline oe_compose_recipients"/> - and + <!-- recipients --> + <label for="partner_ids" string="Recipients" attrs="{'invisible': [('is_log', '=', True)]}" groups="base.group_user"/> + <div groups="base.group_user" attrs="{'invisible': [('is_log', '=', True)]}"> + <span attrs="{'invisible': [('composition_mode', '!=', 'mass_mail')]}"> + <strong>Email mass mailing</strong> on + <span attrs="{'invisible': [('use_active_domain', '=', True)]}">the selected records</span> + <span attrs="{'invisible': [('use_active_domain', '=', False)]}">the current search filter</span>. </span> + <span attrs="{'invisible':[('composition_mode', '!=', 'comment')]}">Followers of the document and</span> <field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..." - context="{'force_email':True, 'show_email':True}"/> + context="{'force_email':True, 'show_email':True}" + attrs="{'invisible': [('composition_mode', '!=', 'comment')]}"/> </div> - <!-- mass post / mass mailing --> - <field name="post" - attrs="{'invisible':[('composition_mode', '!=', 'mass_mail')]}"/> + <!-- mass post --> <field name="notify" - attrs="{'invisible':['|', ('post', '!=', True), ('composition_mode', '!=', 'mass_mail')]}"/> - <field name="same_thread" - attrs="{'invisible':['|', ('composition_mode', '!=', 'mass_mail'), ('post', '=', False)]}"/> - <field name="reply_to" placeholder="Email address te redirect replies..." - attrs="{'invisible':['|', '&', ('same_thread', '=', True), ('post', '=', True), ('composition_mode', '!=', 'mass_mail')], - 'required':['&', '|', ('post', '=', False), ('same_thread', '=', False), ('composition_mode', '=', 'mass_mail')]}"/> + attrs="{'invisible':['|', ('composition_mode', '!=', 'mass_post')]}"/> + <!-- mass mailing --> + <field name="same_thread" attrs="{'invisible':[('composition_mode', '!=', 'mass_mail')]}"/> + <field name="reply_to" placeholder="Email address to redirect replies..." + attrs="{'invisible':['|', ('same_thread', '=', True), ('composition_mode', '!=', 'mass_mail')], + 'required':[('same_thread', '!=', True), ('composition_mode', '=', 'mass_mail')]}"/> </group> <field name="body"/> <field name="attachment_ids" widget="many2many_binary" string="Attach a file"/> |
