[Erp5-report] r20865 - in /erp5/trunk/products/ERP5: Document/ Tool/ tests/
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Apr 30 19:04:58 CEST 2008
Author: yusei
Date: Wed Apr 30 19:04:57 2008
New Revision: 20865
URL: http://svn.erp5.org?rev=20865&view=rev
Log:
refactoring. now portal_notifications is a central point to send messages.
Modified:
erp5/trunk/products/ERP5/Document/EmailDocument.py
erp5/trunk/products/ERP5/Document/Url.py
erp5/trunk/products/ERP5/Tool/NotificationTool.py
erp5/trunk/products/ERP5/tests/testCRM.py
Modified: erp5/trunk/products/ERP5/Document/EmailDocument.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/EmailDocument.py?rev=20865&r1=20864&r2=20865&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/EmailDocument.py (original)
+++ erp5/trunk/products/ERP5/Document/EmailDocument.py Wed Apr 30 19:04:57 2008
@@ -48,18 +48,11 @@
A dummy exception class which is used when MimetypesRegistry product is
not installed yet.
"""
-
+
from email import message_from_string
from email.Header import decode_header
from email.Utils import parsedate
-from email import Encoders
-from email.Message import Message
-from email.MIMEAudio import MIMEAudio
-from email.MIMEBase import MIMEBase
-from email.MIMEImage import MIMEImage
-from email.MIMEMultipart import MIMEMultipart
-from email.MIMEText import MIMEText
DEFAULT_TEXT_FORMAT = 'text/html'
COMMASPACE = ', '
@@ -400,9 +393,6 @@
download - if set to True returns, the message online
rather than sending it.
- This method is based on the examples provided by
- http://docs.python.org/lib/node162.html
-
TODO: support conversion to base format and use
base format rather than original format
@@ -412,11 +402,17 @@
if not _checkPermission(Permissions.View, self):
raise Unauthorized
+ #
# Prepare header data
+ #
if body is None:
body = self.asText()
+
+ # Subject
if subject is None:
subject = self.getTitle()
+
+ # From
if from_url is None:
sender = self.getSourceValue()
if sender.getTitle():
@@ -424,101 +420,100 @@
sender.getDefaultEmailText())
else:
from_url = sender.getDefaultEmailText()
+
+ # Return-Path
if reply_url is None:
reply_url = self.portal_preferences.getPreferredEventSenderEmail()
+ additional_headers = None
+ if reply_url:
+ additional_headers = {'Return-Path':reply_url}
+
+ # To (multiple)
+ to_url_list = []
if to_url is None:
- to_url = []
for recipient in self.getDestinationValueList():
email = recipient.getDefaultEmailText()
if email:
if recipient.getTitle():
- to_url.append('"%s" <%s>' % (recipient.getTitle(), email))
+ to_url_list.append('"%s" <%s>' % (recipient.getTitle(), email))
else:
- to_url.append(email)
+ to_url_list.append(email)
else:
raise ValueError, 'Recipient %s has no defined email' % recipient
elif type(to_url) in types.StringTypes:
- to_url = [to_url]
-
- # Not efficient but clean
- for recipient in to_url:
- # Create the container (outer) email message.
- message = MIMEMultipart()
- message['Subject'] = subject
- message['From'] = from_url
- message['To'] = recipient
- message['Return-Path'] = reply_url
- message.preamble = 'You will not see this in a MIME-aware mail reader.\n'
-
- # Add the body of the message
- attached_message = MIMEText(str(body), _charset='UTF-8')
- message.attach(attached_message)
-
- # Attach files
- document_type_list = self.getPortalDocumentTypeList()
- for attachment in self.getAggregateValueList():
- mime_type = None
- attached_data = None
- if attachment.getPortalType() in document_type_list:
- # If this is a document, use
-
- # WARNING - this could fail since getContentType
- # is not (yet) part of Document API
- if getattr(attachment, 'getContentType', None) is not None:
- mime_type = attachment.getContentType()
- elif getattr(attachment, 'getTextFormat', None) is not None:
- mime_type = attachment.getTextFormat()
- else:
- raise ValueError, "Cannot find mimetype of the document."
-
- if mime_type is not None:
- try:
- mime_type, attached_data = attachment.convert(mime_type)
- except ConversionError:
- mime_type = attachment.getBaseContentType()
- attached_data = attachment.getBaseData()
- except (NotImplementedError, MimeTypeException):
- pass
-
- if attached_data is None:
- if getattr(attachment, 'getTextContent', None) is not None:
- attached_data = attachment.getTextContent()
- elif getattr(attachment, 'getData', None) is not None:
- attached_data = attachment.getData()
- elif getattr(attachment, 'getBaseData', None) is not None:
- attached_data = attachment.getBaseData()
+ to_url_list.append(to_url)
+
+ # Attachments
+ attachment_list = []
+ document_type_list = self.getPortalDocumentTypeList()
+ for attachment in self.getAggregateValueList():
+ mime_type = None
+ content = None
+ name = None
+ if not attachment.getPortalType() in document_type_list:
+ mime_type = 'application/pdf'
+ content = attachment.asPDF() # XXX - Not implemented yet
+ else:
+ #
+ # Document type attachment
+ #
+
+ # WARNING - this could fail since getContentType
+ # is not (yet) part of Document API
+ if getattr(attachment, 'getContentType', None) is not None:
+ mime_type = attachment.getContentType()
+ elif getattr(attachment, 'getTextFormat', None) is not None:
+ mime_type = attachment.getTextFormat()
else:
- mime_type = 'application/pdf'
- attached_data = attachment.asPDF() # XXX - Not implemented yet
- # should provide a default printout
-
- if not isinstance(attached_data, str):
- attached_data = str(attached_data)
-
- if not mime_type:
- mime_type = 'application/octet-stream'
- # Use appropriate class based on mime_type
- maintype, subtype = mime_type.split('/', 1)
- if maintype == 'text':
- attached_message = MIMEText(attached_data, _subtype=subtype)
- elif maintype == 'image':
- attached_message = MIMEImage(attached_data, _subtype=subtype)
- elif maintype == 'audio':
- attached_message = MIMEAudio(attached_data, _subtype=subtype)
- else:
- attached_message = MIMEBase(maintype, subtype)
- attached_message.set_payload(attached_data)
- Encoders.encode_base64(attached_message)
- attached_message.add_header('Content-Disposition', 'attachment', filename=attachment.getReference())
- message.attach(attached_message)
-
- # Send the message
- if download:
- return message.as_string() # Only for debugging purpose
-
- # Use activities
- self.activate(activity="SQLQueue").sendMailHostMessage(message.as_string())
-
+ raise ValueError, "Cannot find mimetype of the document."
+
+ if mime_type is not None:
+ try:
+ mime_type, content = attachment.convert(mime_type)
+ except ConversionError:
+ mime_type = attachment.getBaseContentType()
+ content = attachment.getBaseData()
+ except (NotImplementedError, MimeTypeException):
+ pass
+
+ if content is None:
+ if getattr(attachment, 'getTextContent', None) is not None:
+ content = attachment.getTextContent()
+ elif getattr(attachment, 'getData', None) is not None:
+ content = attachment.getData()
+ elif getattr(attachment, 'getBaseData', None) is not None:
+ content = attachment.getBaseData()
+
+ if not isinstance(content, str):
+ content = str(content)
+
+ attachment_list.append({'mime_type':mime_type,
+ 'content':content,
+ 'name':attachment.getReference()}
+ )
+
+ portal_notifications = getToolByName(self, 'portal_notifications')
+ kw = {}
+
+ # Only for debugging purpose
+ if download:
+ kw = {'debug':True}
+ else:
+ portal_notifications = portal_notifications.activate(activity="SQLQueue")
+
+ for to_url in to_url_list:
+ result = portal_notifications.sendMessageLowLevel(
+ from_url=from_url, to_url=to_url, body=body, subject=subject,
+ attachment_list=attachment_list,
+ additional_headers=additional_headers,
+ **kw
+ )
+
+ # Send the message
+ if download:
+ return result # Only for debugging purpose
+
+ # XXX Obsolete method, Use portal_notifications instead.
security.declareProtected(Permissions.UseMailhostServices, 'sendMailHostMessage')
def sendMailHostMessage(self, message):
"""
Modified: erp5/trunk/products/ERP5/Document/Url.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Url.py?rev=20865&r1=20864&r2=20865&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/Url.py (original)
+++ erp5/trunk/products/ERP5/Document/Url.py Wed Apr 30 19:04:57 2008
@@ -146,10 +146,6 @@
* extra_headers is a dictionnary of custom headers to add to the email.
"X-" prefix is automatically added to those headers.
"""
- # get the mailhost object
- mailhost = getattr(self.getPortalObject(), 'MailHost', None)
- if mailhost is None:
- raise AttributeError, "Cannot find a MailHost object"
if from_url is None:
from_url = self.getUrlString(None)
if to_url is None:
@@ -157,9 +153,9 @@
if from_url is None or to_url is None:
raise AttributeError, "No mail defined"
- message = buildEmailMessage(from_url, to_url, msg=msg,
- subject=subject, attachment_list=attachment_list,
- extra_headers=extra_headers)
+ portal_notifications = getToolByName(self, 'portal_notifications')
- # send mail to user
- mailhost.send(message.as_string(), to_url, from_url)
+ portal_notifications.sendMessageLowLevel(from_url=from_url, to_url=to_url,
+ body=msg, subject=subject,
+ attachment_list=attachment_list,
+ extra_headers=extra_headers)
Modified: erp5/trunk/products/ERP5/Tool/NotificationTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Tool/NotificationTool.py?rev=20865&r1=20864&r2=20865&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Tool/NotificationTool.py (original)
+++ erp5/trunk/products/ERP5/Tool/NotificationTool.py Wed Apr 30 19:04:57 2008
@@ -36,13 +36,16 @@
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
+from email.MIMEAudio import MIMEAudio
+from email.MIMEImage import MIMEImage
from email.Header import make_header
from email import Encoders
def buildEmailMessage(from_url, to_url, msg=None,
subject=None, attachment_list=None,
- extra_headers=None):
+ extra_headers=None,
+ additional_headers=None):
"""
Builds a mail message which is ready to be
sent by Zope MailHost.
@@ -53,6 +56,7 @@
- mime_type: mime-type corresponding to the attachment
* extra_headers is a dictionnary of custom headers to add to the email.
"X-" prefix is automatically added to those headers.
+ * additional_headers is similar to extra_headers, but no prefix is added.
"""
if attachment_list == None:
@@ -67,8 +71,12 @@
message.attach(MIMEText(msg, _charset='utf-8'))
if extra_headers:
- for k, v in extra_headers.items():
- message.add_header('X-%s' % k, v)
+ for key, value in extra_headers.items():
+ message.add_header('X-%s' % key, value)
+
+ if additional_headers:
+ for key, value in additional_headers.items():
+ message.add_header(key, value)
message.add_header('Subject',
make_header([(subject, 'utf-8')]).encode())
@@ -92,10 +100,18 @@
if attachment['mime_type'] == 'text/plain':
part = MIMEText(attachment['content'], _charset='utf-8')
else:
- # encode non-plaintext attachment in base64
- part = MIMEBase(*attachment['mime_type'].split('/', 1))
- part.set_payload(attachment['content'])
- Encoders.encode_base64(part)
+ major, minor = attachment['mime_type'].split('/', 1)
+ if major == 'text':
+ part = MIMEText(attachment['content'], _subtype=minor)
+ elif major == 'image':
+ part = MIMEImage(attachment['content'], _subtype=minor)
+ elif major == 'audio':
+ part = MIMEAudio(attachment['content'], _subtype=minor)
+ else:
+ # encode non-plaintext attachment in base64
+ part = MIMEBase(major, minor)
+ part.set_payload(attachment['content'])
+ Encoders.encode_base64(part)
part.add_header('Content-Disposition',
'attachment; filename=%s' % attachment_name)
@@ -132,6 +148,24 @@
security.declareProtected( Permissions.ManagePortal, 'manage_overview' )
manage_overview = DTMLFile( 'explainNotificationTool', _dtmldir )
+
+ # XXX Bad Name...Any Idea?
+ security.declareProtected(Permissions.UseMailhostServices, 'sendMessageLowLevel')
+ def sendMessageLowLevel(self, from_url, to_url, body=None, subject=None,
+ attachment_list=None, extra_headers=None, additional_headers=None,
+ debug=False):
+ portal = self.getPortalObject()
+ mailhost = getattr(portal, 'MailHost', None)
+ if mailhost is None:
+ raise ValueError, "Can't find MailHost."
+ message = buildEmailMessage(from_url, to_url, msg=body, subject=subject,
+ attachment_list=attachment_list, extra_headers=extra_headers,
+ additional_headers=additional_headers)
+
+ if debug:
+ return message.as_string()
+
+ mailhost.send(messageText=message.as_string(), mto=to_url, mfrom=from_url)
security.declareProtected(Permissions.UseMailhostServices, 'sendMessage')
def sendMessage(self, sender=None, recipient=None, subject=None,
@@ -171,9 +205,6 @@
"""
portal = self.getPortalObject()
catalog_tool = getToolByName(self, 'portal_catalog')
- mailhost = getattr(portal, 'MailHost', None)
- if mailhost is None:
- raise ValueError, "Can't find MailHost."
# Find Default Values
default_from_email = portal.email_from_address
@@ -214,14 +245,12 @@
# Build and Send Messages
for to_address in to_address_list:
- mail_message = buildEmailMessage(from_url=from_address,
- to_url=to_address,
- msg=message,
- subject=subject,
- attachment_list=attachment_list
- )
- mailhost.send(mail_message.as_string(), to_address, from_address)
-
+ self.sendMessageLowLevel(from_url=from_address,
+ to_url=to_address,
+ body=message,
+ subject=subject,
+ attachment_list=attachment_list
+ )
return
# Future implemetation could consist in implementing
Modified: erp5/trunk/products/ERP5/tests/testCRM.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/tests/testCRM.py?rev=20865&r1=20864&r2=20865&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/tests/testCRM.py (original)
+++ erp5/trunk/products/ERP5/tests/testCRM.py Wed Apr 30 19:04:57 2008
@@ -28,6 +28,7 @@
import unittest
import os
import email
+import email.Header
from Products.ERP5Type.tests.utils import DummyMailHost
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
@@ -515,7 +516,8 @@
message = email.message_from_string(messageText)
- self.assertEquals('A Mail', message['Subject'])
+ self.assertEquals('A Mail',
+ email.Header.decode_header(message['Subject'])[0][0])
part = None
for i in message.get_payload():
if i.get_content_type()=='text/plain':
@@ -598,7 +600,8 @@
message = email.message_from_string(messageText)
- self.assertEquals('Héhé', message['Subject'])
+ self.assertEquals('Héhé',
+ email.Header.decode_header(message['Subject'])[0][0])
part = None
for i in message.get_payload():
if i.get_content_type()=='text/plain':
More information about the Erp5-report
mailing list