[gen] Pod field: send pod results by emails.
This commit is contained in:
parent
b565f38d97
commit
4947e2956c
|
@ -124,8 +124,15 @@ class Pod(Field):
|
||||||
<x if="hasMailings" var2="sendLabel=_('email_send')">
|
<x if="hasMailings" var2="sendLabel=_('email_send')">
|
||||||
<tr for="mailing in mailings[fmt]" valign="top"
|
<tr for="mailing in mailings[fmt]" valign="top"
|
||||||
var2="mailingName=field.getMailingName(obj, mailing)">
|
var2="mailingName=field.getMailingName(obj, mailing)">
|
||||||
<td width="85px"><span title=":sendLabel">:mailingName</span></td>
|
<td colspan="2">
|
||||||
<td width="15px"><img src=":url('email')"/></td>
|
<a var="js='generatePod(%s,%s,%s,%s,%s,null,null,%s)' % \
|
||||||
|
(q(uid), q(name), q(info.template), q(fmt), \
|
||||||
|
q(ztool.getQueryInfo()), q(mailing))"
|
||||||
|
onclick=":'askConfirm(%s,%s)' % (q('script'), q(js, False))"
|
||||||
|
title=":sendLabel">
|
||||||
|
<img src=":url('email')" align="left" style="margin-right: 2px"/>
|
||||||
|
<x>:mailingName</x></a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</x>
|
</x>
|
||||||
</table>
|
</table>
|
||||||
|
@ -405,6 +412,57 @@ class Pod(Field):
|
||||||
res = gutils.produceNiceMessage(mailing)
|
res = gutils.produceNiceMessage(mailing)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def getMailingInfo(self, obj, template, mailing):
|
||||||
|
'''Gets the necessary information for sending an email to
|
||||||
|
p_mailing list.'''
|
||||||
|
res = self.mailingInfo(obj, mailing)
|
||||||
|
subject = res.subject
|
||||||
|
if not subject:
|
||||||
|
# Give a predefined subject
|
||||||
|
mapping = {'site': obj.tool.o.getSiteUrl(),
|
||||||
|
'title': obj.o.getShownValue('title'),
|
||||||
|
'template': self.getTemplateName(obj, template)}
|
||||||
|
subject = obj.translate('podmail_subject', mapping=mapping)
|
||||||
|
body = res.body
|
||||||
|
if not body:
|
||||||
|
# Give a predefined body
|
||||||
|
mapping = {'site': obj.tool.o.getSiteUrl()}
|
||||||
|
body = obj.translate('podmail_body', mapping=mapping)
|
||||||
|
return res.logins, subject, body
|
||||||
|
|
||||||
|
def sendMailing(self, obj, template, mailing, attachment):
|
||||||
|
'''Sends the emails for m_mailing.'''
|
||||||
|
logins, subject, body = self.getMailingInfo(obj, template, mailing)
|
||||||
|
if not logins:
|
||||||
|
obj.log('mailing %s contains no recipient.' % mailing)
|
||||||
|
return 'action_ko'
|
||||||
|
tool = obj.tool
|
||||||
|
# Collect logins corresponding to inexistent users and recipients
|
||||||
|
missing = []
|
||||||
|
recipients = []
|
||||||
|
for login in logins:
|
||||||
|
user = tool.search1('User', noSecurity=True, login=login)
|
||||||
|
if not user:
|
||||||
|
missing.append(login)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
recipient = user.getMailRecipient()
|
||||||
|
if not recipient:
|
||||||
|
missing.append(login)
|
||||||
|
else:
|
||||||
|
recipients.append(recipient)
|
||||||
|
if missing:
|
||||||
|
obj.log('mailing %s: inexistent user or no email for %s.' % \
|
||||||
|
(mailing, str(missing)))
|
||||||
|
if not recipients:
|
||||||
|
obj.log('mailing %s contains no recipient (after removing wrong ' \
|
||||||
|
'entries, see above).' % mailing)
|
||||||
|
msg = 'action_ko'
|
||||||
|
else:
|
||||||
|
tool.sendMail(recipients, subject, body, [attachment])
|
||||||
|
msg = 'action_done'
|
||||||
|
return msg
|
||||||
|
|
||||||
def getValue(self, obj, template=None, format=None, result=None,
|
def getValue(self, obj, template=None, format=None, result=None,
|
||||||
queryData=None, customContext=None, noSecurity=False):
|
queryData=None, customContext=None, noSecurity=False):
|
||||||
'''For a pod field, getting its value means computing a pod document or
|
'''For a pod field, getting its value means computing a pod document or
|
||||||
|
@ -669,8 +727,17 @@ class Pod(Field):
|
||||||
obj.say(res)
|
obj.say(res)
|
||||||
return tool.goto(rq.get('HTTP_REFERER'))
|
return tool.goto(rq.get('HTTP_REFERER'))
|
||||||
# res contains a FileInfo instance.
|
# res contains a FileInfo instance.
|
||||||
|
# Must we return the res to the ui or send a mail with the res as
|
||||||
|
# attachment?
|
||||||
|
mailing = rq.get('mailing')
|
||||||
|
if not mailing:
|
||||||
res.writeResponse(rq.RESPONSE)
|
res.writeResponse(rq.RESPONSE)
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
# Send the email(s).
|
||||||
|
msg = self.sendMailing(obj, template, mailing, res)
|
||||||
|
obj.say(obj.translate(msg))
|
||||||
|
return tool.goto(rq.get('HTTP_REFERER'))
|
||||||
# Performing any other action requires write access to p_obj.
|
# Performing any other action requires write access to p_obj.
|
||||||
obj.o.mayEdit(self.writePermission, raiseError=True)
|
obj.o.mayEdit(self.writePermission, raiseError=True)
|
||||||
msg = 'action_done'
|
msg = 'action_done'
|
||||||
|
|
52
gen/mail.py
52
gen/mail.py
|
@ -9,8 +9,15 @@ from appy.shared.utils import sequenceTypes
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def sendMail(tool, to, subject, body, attachments=None):
|
def sendMail(tool, to, subject, body, attachments=None):
|
||||||
'''Sends a mail, via p_tool.mailHost, to p_to (a single email address or a
|
'''Sends a mail, via p_tool.mailHost, to p_to (a single email recipient or
|
||||||
list of email addresses).'''
|
a list of recipients). Every (string) recipient can be an email address
|
||||||
|
or a string of the form "[name] <[email]>".
|
||||||
|
|
||||||
|
p_attachment must be a list or tuple whose elements can have 2 forms:
|
||||||
|
1. a tuple (fileName, fileContent): "fileName" is the name of the file
|
||||||
|
as a string; "fileContent" is the file content, also as a string;
|
||||||
|
2. a appy.fields.file.FileInfo instance.
|
||||||
|
'''
|
||||||
# Just log things if mail is disabled
|
# Just log things if mail is disabled
|
||||||
fromAddress = tool.mailFrom
|
fromAddress = tool.mailFrom
|
||||||
if not tool.mailEnabled or not tool.mailHost:
|
if not tool.mailEnabled or not tool.mailHost:
|
||||||
|
@ -18,14 +25,14 @@ def sendMail(tool, to, subject, body, attachments=None):
|
||||||
msg = ' (no mailhost defined)'
|
msg = ' (no mailhost defined)'
|
||||||
else:
|
else:
|
||||||
msg = ''
|
msg = ''
|
||||||
tool.log('Mail disabled%s: should send mail from %s to %s.' % \
|
tool.log('mail disabled%s: should send mail from %s to %s.' % \
|
||||||
(msg, fromAddress, str(to)))
|
(msg, fromAddress, str(to)))
|
||||||
tool.log('Subject: %s' % subject)
|
tool.log('subject: %s' % subject)
|
||||||
tool.log('Body: %s' % body)
|
tool.log('body: %s' % body)
|
||||||
if attachments:
|
if attachments:
|
||||||
tool.log('%d attachment(s).' % len(attachments))
|
tool.log('%d attachment(s).' % len(attachments))
|
||||||
return
|
return
|
||||||
tool.log('Sending mail from %s to %s (subject: %s).' % \
|
tool.log('sending mail from %s to %s (subject: %s).' % \
|
||||||
(fromAddress, str(to), subject))
|
(fromAddress, str(to), subject))
|
||||||
# Create the base MIME message
|
# Create the base MIME message
|
||||||
body = MIMEText(body, 'plain', 'utf-8')
|
body = MIMEText(body, 'plain', 'utf-8')
|
||||||
|
@ -48,23 +55,18 @@ def sendMail(tool, to, subject, body, attachments=None):
|
||||||
to = fromAddress
|
to = fromAddress
|
||||||
# Add attachments
|
# Add attachments
|
||||||
if attachments:
|
if attachments:
|
||||||
for fileName, fileContent in attachments:
|
for attachment in attachments:
|
||||||
|
# 2 possible forms for an attachment
|
||||||
|
if isinstance(attachment, tuple) or isinstance(attachment, list):
|
||||||
|
fileName, fileContent = attachment
|
||||||
|
else:
|
||||||
|
# a FileInfo instance
|
||||||
|
fileName = attachment.uploadName
|
||||||
|
f = file(attachment.fsPath, 'rb')
|
||||||
|
fileContent = f.read()
|
||||||
|
f.close()
|
||||||
part = MIMEBase('application', 'octet-stream')
|
part = MIMEBase('application', 'octet-stream')
|
||||||
if fileContent.__class__.__name__ == 'FileWrapper':
|
part.set_payload(fileContent)
|
||||||
fileContent = fileContent._zopeFile
|
|
||||||
if hasattr(fileContent, 'data'):
|
|
||||||
# It is a File instance coming from the database
|
|
||||||
data = fileContent.data
|
|
||||||
if isinstance(data, basestring):
|
|
||||||
payLoad = data
|
|
||||||
else:
|
|
||||||
payLoad = ''
|
|
||||||
while data is not None:
|
|
||||||
payLoad += data.data
|
|
||||||
data = data.next
|
|
||||||
else:
|
|
||||||
payLoad = fileContent
|
|
||||||
part.set_payload(payLoad)
|
|
||||||
Encoders.encode_base64(part)
|
Encoders.encode_base64(part)
|
||||||
part.add_header('Content-Disposition',
|
part.add_header('Content-Disposition',
|
||||||
'attachment; filename="%s"' % fileName)
|
'attachment; filename="%s"' % fileName)
|
||||||
|
@ -85,12 +87,12 @@ def sendMail(tool, to, subject, body, attachments=None):
|
||||||
res = smtpServer.sendmail(fromAddress, [to], msg.as_string())
|
res = smtpServer.sendmail(fromAddress, [to], msg.as_string())
|
||||||
smtpServer.quit()
|
smtpServer.quit()
|
||||||
if res:
|
if res:
|
||||||
tool.log('Could not send mail to some recipients. %s' % str(res),
|
tool.log('could not send mail to some recipients. %s' % str(res),
|
||||||
type='warning')
|
type='warning')
|
||||||
except smtplib.SMTPException, e:
|
except smtplib.SMTPException, e:
|
||||||
tool.log('Mail sending failed: %s' % str(e), type='error')
|
tool.log('mail sending failed: %s' % str(e), type='error')
|
||||||
except socket.error, se:
|
except socket.error, se:
|
||||||
tool.log('Mail sending failed: %s' % str(se), type='error')
|
tool.log('mail sending failed: %s' % str(se), type='error')
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def sendNotification(obj, transition, transitionName, workflow):
|
def sendNotification(obj, transition, transitionName, workflow):
|
||||||
|
|
|
@ -722,3 +722,11 @@ msgstr ""
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -722,3 +722,11 @@ msgstr ""
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -722,3 +722,11 @@ msgstr ""
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -723,3 +723,11 @@ msgstr "Microsoft Internet Explorer ${version} is not supported. Please upgrade
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr "Send by email"
|
msgstr "Send by email"
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr "${site} - ${title} - ${template}"
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
|
|
@ -722,3 +722,11 @@ msgstr ""
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -723,3 +723,11 @@ msgstr "Microsoft Internet Explorer ${version} n'est pas supporté. Veuillez met
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr "Envoyer par email"
|
msgstr "Envoyer par email"
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr "${site} - ${title} - ${template}"
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr "Bonjour, cet email vous est envoyé depuis ${site}. Veuillez consulter le(s) fichier(s) joint(s)."
|
||||||
|
|
|
@ -722,3 +722,11 @@ msgstr ""
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -722,3 +722,11 @@ msgstr ""
|
||||||
#. Default: "Send by email"
|
#. Default: "Send by email"
|
||||||
msgid "email_send"
|
msgid "email_send"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "${site} - ${title} - ${template}"
|
||||||
|
msgid "podmail_subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Default: "Hello, this email that was sent to you via ${site}. Please consult the attached file(s)."
|
||||||
|
msgid "podmail_body"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -686,7 +686,7 @@ function toggleCookie(cookieId) {
|
||||||
|
|
||||||
// Function that allows to generate a document from a pod template.
|
// Function that allows to generate a document from a pod template.
|
||||||
function generatePod(uid, fieldName, template, podFormat, queryData,
|
function generatePod(uid, fieldName, template, podFormat, queryData,
|
||||||
customParams, getChecked) {
|
customParams, getChecked, mailing) {
|
||||||
var f = document.getElementById('podForm');
|
var f = document.getElementById('podForm');
|
||||||
f.objectUid.value = uid;
|
f.objectUid.value = uid;
|
||||||
f.fieldName.value = fieldName;
|
f.fieldName.value = fieldName;
|
||||||
|
@ -695,6 +695,7 @@ function generatePod(uid, fieldName, template, podFormat, queryData,
|
||||||
f.queryData.value = queryData;
|
f.queryData.value = queryData;
|
||||||
if (customParams) { f.customParams.value = customParams; }
|
if (customParams) { f.customParams.value = customParams; }
|
||||||
else { f.customParams.value = ''; }
|
else { f.customParams.value = ''; }
|
||||||
|
if (mailing) f.mailing.value = mailing;
|
||||||
f.action.value = 'generate';
|
f.action.value = 'generate';
|
||||||
f.checkedUids.value = '';
|
f.checkedUids.value = '';
|
||||||
f.checkedSem.value = '';
|
f.checkedSem.value = '';
|
||||||
|
|
|
@ -146,6 +146,7 @@ class ToolWrapper(AbstractWrapper):
|
||||||
<input type="hidden" name="customParams"/>
|
<input type="hidden" name="customParams"/>
|
||||||
<input type="hidden" name="checkedUids"/>
|
<input type="hidden" name="checkedUids"/>
|
||||||
<input type="hidden" name="checkedSem"/>
|
<input type="hidden" name="checkedSem"/>
|
||||||
|
<input type="hidden" name="mailing"/>
|
||||||
<input type="hidden" name="action" value="generate"/>
|
<input type="hidden" name="action" value="generate"/>
|
||||||
</form>''')
|
</form>''')
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
from appy.fields.string import String
|
||||||
from appy.gen import WorkflowOwner
|
from appy.gen import WorkflowOwner
|
||||||
from appy.gen.layout import summaryPageLayouts
|
from appy.gen.layout import summaryPageLayouts
|
||||||
from appy.gen.wrappers import AbstractWrapper
|
from appy.gen.wrappers import AbstractWrapper
|
||||||
|
@ -107,6 +108,14 @@ class UserWrapper(AbstractWrapper):
|
||||||
from AccessControl.AuthEncoding import pw_validate
|
from AccessControl.AuthEncoding import pw_validate
|
||||||
return pw_validate(encryptedPassword, clearPassword)
|
return pw_validate(encryptedPassword, clearPassword)
|
||||||
|
|
||||||
|
def getMailRecipient(self):
|
||||||
|
'''Returns, for this user, the "recipient string" (first name, name,
|
||||||
|
email) as can be used for sending an email.'''
|
||||||
|
res = self.email or self.login
|
||||||
|
# Ensure this is really an email
|
||||||
|
if not String.EMAIL.match(res): return
|
||||||
|
return '%s <%s>' % (self.title, res)
|
||||||
|
|
||||||
def setLogin(self, oldLogin, newLogin):
|
def setLogin(self, oldLogin, newLogin):
|
||||||
'''Changes the login of this user from p_oldLogin to p_newLogin.'''
|
'''Changes the login of this user from p_oldLogin to p_newLogin.'''
|
||||||
self.login = newLogin
|
self.login = newLogin
|
||||||
|
|
Loading…
Reference in a new issue