appypod-rattail/gen/notifier.py

106 lines
4.4 KiB
Python
Raw Normal View History

2009-06-29 07:06:01 -05:00
'''This package contains functions for sending email notifications.'''
# ------------------------------------------------------------------------------
def getEmailAddress(name, email, encoding='utf-8'):
'''Creates a full email address from a p_name and p_email.'''
res = email
if name: res = name.decode(encoding) + ' <%s>' % email
return res
def convertRolesToEmails(users, portal):
'''p_users is a list of emails and/or roles. This function returns the same
list, where all roles have been expanded to emails of users having this
role (more precisely, users belonging to the group Appy created for the
given role).'''
res = []
for mailOrRole in users:
if mailOrRole.find('@') != -1:
# It is an email. Append it directly to the result.
res.append(mailOrRole)
else:
# It is a role. Find the corresponding group (Appy creates
# one group for every role defined in the application).
groupId = mailOrRole + '_group'
group = portal.acl_users.getGroupById(groupId)
if group:
for user in group.getAllGroupMembers():
userMail = user.getProperty('email')
if userMail and (userMail not in res):
res.append(userMail)
return res
# ------------------------------------------------------------------------------
SENDMAIL_ERROR = 'Error while sending mail: %s.'
ENCODING_ERROR = 'Encoding error while sending mail: %s.'
from appy.gen.utils import sequenceTypes
from appy.gen.descriptors import WorkflowDescriptor
2009-06-29 07:06:01 -05:00
import socket
def sendMail(obj, transition, transitionName, workflow):
2009-06-29 07:06:01 -05:00
'''Sends mail about p_transition that has been triggered on p_obj that is
controlled by p_workflow.'''
wfName = WorkflowDescriptor.getWorkflowName(workflow.__class__)
zopeObj = obj.o
tool = zopeObj.getTool()
2009-06-29 07:06:01 -05:00
mailInfo = transition.notify(workflow, obj)
if not mailInfo[0]: return # Send a mail to nobody.
# mailInfo may be one of the following:
# (to,)
# (to, cc)
# (to, mailSubject, mailBody)
# (to, cc, mailSubject, mailBody)
# "to" and "cc" maybe simple strings (one simple string = one email
# address or one role) or sequences of strings.
# Determine mail subject and body.
if len(mailInfo) <= 2:
# The user didn't mention mail body and subject. We will use those
# defined from i18n labels.
wfHistory = zopeObj.getHistory()
2009-06-29 07:06:01 -05:00
labelPrefix = '%s_%s' % (wfName, transitionName)
tName = obj.translate(labelPrefix)
keys = {'siteUrl': tool.getPath('/').absolute_url(),
'siteTitle': tool.getAppName(),
'objectUrl': zopeObj.absolute_url(),
'objectTitle': zopeObj.Title(),
2009-06-29 07:06:01 -05:00
'transitionName': tName,
'transitionComment': wfHistory[0]['comments']}
mailSubject = obj.translate(labelPrefix + '_mail_subject', keys)
mailBody = obj.translate(labelPrefix + '_mail_body', keys)
else:
mailSubject = mailInfo[-1]
mailBody = mailInfo[-2]
# Determine "to" and "cc".
to = mailInfo[0]
cc = []
if (len(mailInfo) in (2,4)) and mailInfo[1]: cc = mailInfo[1]
if type(to) not in sequenceTypes: to = [to]
if type(cc) not in sequenceTypes: cc = [cc]
# Among "to" and "cc", convert all roles to concrete email addresses
to = convertRolesToEmails(to, portal)
cc = convertRolesToEmails(cc, portal)
# Determine "from" address
enc= portal.portal_properties.site_properties.getProperty('default_charset')
fromAddress = getEmailAddress(
portal.getProperty('email_from_name'),
portal.getProperty('email_from_address'), enc)
# Send the mail
i = 0
for recipient in to:
i += 1
try:
if i != 1: cc = []
portal.MailHost.secureSend(mailBody.encode(enc),
recipient.encode(enc), fromAddress.encode(enc),
mailSubject.encode(enc), mcc=cc, charset='utf-8')
except socket.error, sg:
obj.log(SENDMAIL_ERROR % str(sg), type='warning')
2009-06-29 07:06:01 -05:00
break
except UnicodeDecodeError, ue:
obj.log(ENCODING_ERROR % str(ue), type='warning')
2009-06-29 07:06:01 -05:00
break
except Exception, e:
obj.log(SENDMAIL_ERROR % str(e), type='warning')
2009-06-29 07:06:01 -05:00
break
# ------------------------------------------------------------------------------