Commit d4033f8d authored by Gabriel Monnerat's avatar Gabriel Monnerat

merge gabriel branch into master

This merge was done to improve features to send mail using the script Event_send. With this changes, is not needed access all persons to get your email and the method searchAndActivate from catalog to don't create one activity for each destination.
parent 0d1a4056
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>if content_type == \'text/html\':\n
mail_template = context.Event_viewHtmlMimeMessage\n
else:\n
mail_template = context.Event_viewMimeMessage\n
\n
for embedded_file in embedded_file_list:\n
mime_type, content = embedded_file.getMimeTypeAndContent()\n
name = embedded_file.getFilename()\n
\n
attachment_list.append({\'mime_type\':mime_type,\n
\'content\':content,\n
\'name\':name})\n
\n
# Allow to embed image in HTML by setting the relative URL of the image with FCKeditor\n
attachment_url = embedded_file.getRelativeUrl()\n
body = body.replace(\'src="%s"\' % attachment_url, \'src="cid:%s"\' % \'\'.join([\'%s\' % ord(i) for i in name]))\n
\n
multipart = mail_template.as_message(mfrom=from_url,\n
mto=to_url,\n
subject=subject,\n
body=body,\n
encoding=\'utf-8\')\n
for attachment_dict in attachment_list:\n
multipart.add_file(data=attachment_dict[\'content\'],\n
content_type=attachment_dict[\'mime_type\'],\n
filename=attachment_dict[\'name\'])\n
\n
return str(multipart)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>from_url, to_url, subject, body, content_type, attachment_list=[], embedded_file_list=[]</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_createMailMessageAsString</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>from email.utils import formataddr\n
portal = context.getPortalObject()\n
event = portal.restrictedTraverse(event_relative_url)\n
\n
subject = event.getTitle()\n
body = event.getTextContent()\n
sender = event.getSourceValue()\n
if sender is not None:\n
from_url = formataddr((sender.getTitle(), sender.getDefaultEmailText()))\n
else:\n
from_url = portal.portal_preferences.getPreferredEventSenderEmail()\n
\n
to_url = formataddr((context.getTitle(), context.getDefaultEmailText()))\n
\n
document_type_list = list(event.getPortalEmbeddedDocumentTypeList()) + list(event.getPortalDocumentTypeList())\n
embedded_file_list = event.getAggregateValueList(portal_type=document_type_list)\n
\n
content_type = event.getContentType()\n
mail_message = context.Base_createMailMessageAsString(from_url,\n
to_url,\n
subject,\n
body,\n
content_type,\n
attachment_list=[],\n
embedded_file_list=embedded_file_list)\n
\n
event.sendMailHostMessage(mail_message)\n
\n
if not event.hasData():\n
event.setData(mail_message)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>event_relative_url, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Entity_sendEmail</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -51,79 +51,76 @@ ...@@ -51,79 +51,76 @@
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>from email.utils import formataddr\n <value> <string>from email.utils import formataddr\n
from email import message_from_string\n
portal = context.getPortalObject()\n portal = context.getPortalObject()\n
\n \n
if body is None:\n use_activity = False\n
body = context.getTextContent() #XXX This does not support structured text format.\n mail_message = None\n
\n to_url_list = []\n
# Subject\n
if subject is None:\n
subject = context.getTitle()\n
\n
# From\n
if from_url is None:\n
sender = context.getSourceValue()\n
from_url = formataddr((sender.getTitle(), sender.getDefaultEmailText()))\n
\n \n
# Return-Path\n if not context.isTempDocument() and to_url is None:\n
if reply_url is None:\n use_activity = True\n
reply_url = portal.portal_preferences.getPreferredEventSenderEmail()\n
additional_headers = None\n
if reply_url:\n
additional_headers = {\'Return-Path\':reply_url}\n
\n \n
# To (multiple)\n
to_url_list = []\n
to_email_list = []\n
if to_url is None:\n if to_url is None:\n
for recipient in context.getDestinationValueList():\n if use_activity:\n
email = recipient.getDefaultEmailText()\n recipient = context.getDestinationValue()\n
if email:\n to_url_list.append(formataddr((recipient.getTitle(), recipient.getDefaultEmailText())))\n
if email not in to_email_list:\n else:\n
to_email_list = []\n
for recipient in context.getDestinationValueList():\n
email = recipient.getDefaultEmailText()\n
if email:\n
to_email_list.append(email)\n to_email_list.append(email)\n
to_url_list.append(formataddr((recipient.getTitle(), email)))\n to_url_list.append(formataddr((recipient.getTitle(), recipient.getDefaultEmailText())))\n
else:\n else:\n
raise ValueError, \'Recipient %s has no defined email\' % recipient\n raise ValueError("One email must be set to %s" % person.getRelativeUrl())\n
elif same_type(to_url, \'\'):\n else:\n
to_url_list.append(to_url)\n to_url_list.append(to_url)\n
\n \n
# Attachments\n if download or not use_activity:\n
if attachment_list is None:\n for to_url in to_url_list:\n
attachment_list = []\n body = body or context.getTextContent()\n
document_type_list = list(context.getPortalEmbeddedDocumentTypeList()) + list(context.getPortalDocumentTypeList())\n subject = subject or context.getTitle()\n
for attachment in context.getAggregateValueList(portal_type=document_type_list):\n
mime_type, content = attachment.getMimeTypeAndContent()\n
name = attachment.getFilename()\n
\n \n
attachment_list.append({\'mime_type\':mime_type,\n # From\n
\'content\':content,\n if from_url is None:\n
\'name\':name})\n sender = context.getSourceValue()\n
from_url = formataddr((sender.getTitle(), sender.getDefaultEmailText()))\n
\n \n
# Allow to embed image in HTML by setting the relative URL of the image with FCKeditor\n # Return-Path\n
attachment_url = attachment.getRelativeUrl()\n if reply_url is None:\n
body = body.replace(\'src="%s"\' % attachment_url, \'src="cid:%s"\' % \'\'.join([\'%s\' % ord(i) for i in name]))\n reply_url = portal.portal_preferences.getPreferredEventSenderEmail()\n
additional_headers = None\n
if reply_url:\n
additional_headers = {\'Return-Path\':reply_url}\n
\n \n
# Build message per destination\n # Attachments\n
mail_message = None\n if attachment_list is None:\n
if context.getContentType() == \'text/html\':\n attachment_list = []\n
mail_template = context.Event_viewHtmlMimeMessage\n document_type_list = list(context.getPortalEmbeddedDocumentTypeList()) + list(context.getPortalDocumentTypeList())\n
else:\n embedded_file_list = context.getAggregateValueList(portal_type=document_type_list)\n
mail_template = context.Event_viewMimeMessage\n \n
content_type = context.getContentType()\n
\n
mail_message = context.Base_createMailMessageAsString(from_url, \n
to_url,\n
subject,\n
body,\n
content_type,\n
attachment_list=attachment_list,\n
embedded_file_list=embedded_file_list)\n
\n \n
for to_url in to_url_list:\n context.edit(data=mail_message)\n
multipart = mail_template.as_message(mfrom=from_url,\n if not use_activity:\n
mto=to_url,\n context.activate(activity=\'SQLQueue\').sendMailHostMessage(mail_message)\n
subject=subject,\n
body=body,\n
encoding=\'utf-8\')\n
for attachment_dict in attachment_list:\n
multipart.add_file(data=attachment_dict[\'content\'],\n
content_type=attachment_dict[\'mime_type\'],\n
filename=attachment_dict[\'name\'])\n
mail_message = str(multipart)\n
context.activate(activity=\'SQLQueue\').sendMailHostMessage(mail_message)\n
\n \n
context.setData(mail_message)\n if use_activity:\n
uid_list = context.getDestinationUidList()\n
method_kw = dict(event_relative_url=context.getRelativeUrl(),\n
from_url=from_url)\n
portal.portal_catalog.searchAndActivate(method_id="Entity_sendEmail",\n
uid=uid_list,\n
method_kw=method_kw, **kw)\n
\n \n
# Transit event workflow\n # Transit event workflow\n
if context.getTypeInfo() is not None:\n if context.getTypeInfo() is not None:\n
......
1009 1015
\ No newline at end of file \ No newline at end of file
...@@ -94,7 +94,7 @@ feed_data = {}\n ...@@ -94,7 +94,7 @@ feed_data = {}\n
request = context.REQUEST\n request = context.REQUEST\n
\n \n
# required channel elements for RSS 2.0 specification\n # required channel elements for RSS 2.0 specification\n
required_field_list = (\'title\', \'description\', \'link\',)\n required_field_list = (\'title\', \'description\', \'link\')\n
\n \n
# required + optional channel elements\n # required + optional channel elements\n
allowed_field_list = (\'title\', \'description\', \'link\', \'author\', \n allowed_field_list = (\'title\', \'description\', \'link\', \'author\', \n
...@@ -103,6 +103,7 @@ allowed_field_list = (\'title\', \'description\', \'link\', \'author\', \n ...@@ -103,6 +103,7 @@ allowed_field_list = (\'title\', \'description\', \'link\', \'author\', \n
\n \n
# figure out which column is which, by using column titles\n # figure out which column is which, by using column titles\n
rss_column_mapping = {}\n rss_column_mapping = {}\n
\n
for index, column_item in enumerate(label_list):\n for index, column_item in enumerate(label_list):\n
column_header = column_item[1]\n column_header = column_item[1]\n
if column_header.lower() in allowed_field_list:\n if column_header.lower() in allowed_field_list:\n
...@@ -155,6 +156,7 @@ for line in line_list:\n ...@@ -155,6 +156,7 @@ for line in line_list:\n
items.append(rss_item_string)\n items.append(rss_item_string)\n
\n \n
feed_data[\'listItemInfos\'] = tuple(items)\n feed_data[\'listItemInfos\'] = tuple(items)\n
\n
return feed_data\n return feed_data\n
......
52 55
\ No newline at end of file \ No newline at end of file
...@@ -42,6 +42,7 @@ from email.mime.multipart import MIMEMultipart ...@@ -42,6 +42,7 @@ from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase from email.mime.base import MIMEBase
from email.mime.text import MIMEText from email.mime.text import MIMEText
from email import encoders, message_from_string from email import encoders, message_from_string
from DateTime import DateTime
def makeFilePath(name): def makeFilePath(name):
return os.path.join(os.path.dirname(__file__), 'test_data', 'crm_emails', name) return os.path.join(os.path.dirname(__file__), 'test_data', 'crm_emails', name)
...@@ -73,7 +74,6 @@ class BaseTestCRM(ERP5TypeTestCase): ...@@ -73,7 +74,6 @@ class BaseTestCRM(ERP5TypeTestCase):
for module_name in clear_module_name_list: for module_name in clear_module_name_list:
module = self.portal.unrestrictedTraverse(module_name) module = self.portal.unrestrictedTraverse(module_name)
module.manage_delObjects(list(module.objectIds())) module.manage_delObjects(list(module.objectIds()))
self.stepTic() self.stepTic()
super(BaseTestCRM, self).beforeTearDown() super(BaseTestCRM, self).beforeTearDown()
...@@ -82,7 +82,10 @@ class TestCRM(BaseTestCRM): ...@@ -82,7 +82,10 @@ class TestCRM(BaseTestCRM):
return "CRM" return "CRM"
def getBusinessTemplateList(self): def getBusinessTemplateList(self):
return ('erp5_base', return ('erp5_full_text_myisam_catalog',
'erp5_core_proxy_field_legacy',
'erp5_base',
'erp5_ingestion',
'erp5_crm',) 'erp5_crm',)
def test_Event_CreateRelatedEvent(self): def test_Event_CreateRelatedEvent(self):
...@@ -450,7 +453,9 @@ class TestCRMMailIngestion(BaseTestCRM): ...@@ -450,7 +453,9 @@ class TestCRMMailIngestion(BaseTestCRM):
def getBusinessTemplateList(self): def getBusinessTemplateList(self):
# Mail Ingestion must work with CRM alone. # Mail Ingestion must work with CRM alone.
return ('erp5_base', return ('erp5_core_proxy_field_legacy',
'erp5_full_text_myisam_catalog',
'erp5_base',
'erp5_ingestion', 'erp5_ingestion',
'erp5_ingestion_mysql_innodb_catalog', 'erp5_ingestion_mysql_innodb_catalog',
'erp5_crm', 'erp5_crm',
...@@ -846,7 +851,6 @@ class TestCRMMailSend(BaseTestCRM): ...@@ -846,7 +851,6 @@ class TestCRMMailSend(BaseTestCRM):
def afterSetUp(self): def afterSetUp(self):
super(TestCRMMailSend, self).afterSetUp() super(TestCRMMailSend, self).afterSetUp()
portal = self.portal portal = self.portal
# create customer organisation and person # create customer organisation and person
portal.organisation_module.newContent( portal.organisation_module.newContent(
id='customer', id='customer',
...@@ -1189,7 +1193,6 @@ class TestCRMMailSend(BaseTestCRM): ...@@ -1189,7 +1193,6 @@ class TestCRMMailSend(BaseTestCRM):
text_content='This is an advertisement mail.') text_content='This is an advertisement mail.')
mail_text = event.send(download=True) mail_text = event.send(download=True)
# Check mail text. # Check mail text.
message = message_from_string(mail_text) message = message_from_string(mail_text)
part = None part = None
...@@ -1673,6 +1676,55 @@ class TestCRMMailSend(BaseTestCRM): ...@@ -1673,6 +1676,55 @@ class TestCRMMailSend(BaseTestCRM):
transaction.commit() transaction.commit()
self.tic() self.tic()
def test_MailMessage_Event_send_generate_activity_list(self):
"""
Check that after post a Mail Message, the activities are generated
correctly
"""
person = self.portal.person_module.newContent(portal_type="Person")
person.edit(default_email_text="test@test.com", title="test%s" % person.getId())
self.stepTic()
mail_message = self.portal.event_module.newContent(portal_type="Mail Message")
relative_url_list = [z.getRelativeUrl() for z in self.portal.person_module.searchFolder()]
mail_message.setDestinationList(relative_url_list)
mail_message.setSource(relative_url_list[0])
mail_text_content = "Body Text Content"
mail_message.setTextContent(mail_text_content)
self.portal.portal_workflow.doActionFor(mail_message, "start_action")
self.stepTic()
mail_message.Event_send(packet_size=2)
import transaction
transaction.commit()
portal_activities = self.portal.portal_activities
message_list = [i for i in portal_activities.getMessageList() \
if i.kw.has_key("event_relative_url")]
try:
self.assertEquals(2, len(message_list))
finally:
self.stepTic()
last_message = self.portal.MailHost._last_message
self.assertTrue(mail_text_content in last_message[-1])
message = message_from_string(last_message[-1])
last_message_date = DateTime(message.get("Date"))
self.assertTrue(last_message_date.isCurrentDay())
def test_MailMessage_Event_send_simple_case(self):
"""
Check that the script Event_send send one email passing all parameters directly
from_url, to_url, reply_url, subject, body, attachment_format, attachment_list
"""
mail_message = self.portal.event_module.newContent(portal_type="Mail Message")
self.stepTic()
mail_message.Event_send(from_url='FG ER <eee@eee.com>',
to_url='Expert User <expert@in24.test>',
subject="Simple Case",
body="Body Simple Case",
attachment_list=[])
self.stepTic()
last_message = self.portal.MailHost._last_message[-1]
self.assertTrue("Body Simple Case" in last_message)
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestCRM)) suite.addTest(unittest.makeSuite(TestCRM))
......
...@@ -76,6 +76,12 @@ class TestERP5Credential(ERP5TypeTestCase): ...@@ -76,6 +76,12 @@ class TestERP5Credential(ERP5TypeTestCase):
if 'MailHost' in self.portal.objectIds(): if 'MailHost' in self.portal.objectIds():
self.portal.manage_delObjects(['MailHost']) self.portal.manage_delObjects(['MailHost'])
self.portal._setObject('MailHost', DummyMailHost('MailHost')) self.portal._setObject('MailHost', DummyMailHost('MailHost'))
system_preference = self.getPreferenceTool().getActiveSystemPreference()
if system_preference is None:
system_preference = self.portal.portal_preferences.newContent(
portal_type='System Preference')
system_preference.enable()
system_preference.edit(preferred_event_sender_email=['Sample s@s.com',])
@reindex @reindex
def enableAlarm(self): def enableAlarm(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment