def get_message_payload(self): """Process the action and return a dictionary with the Slack message payload. :returns: Slack message payload. :rtype: dict. """ obj = self.event.object element = self.element interpolator = IStringInterpolator(obj) title = interpolator(safe_attr(element, "title")).strip() title_link = interpolator(safe_attr(element, "title_link")).strip() pretext = interpolator(safe_attr(element, "pretext")).strip() text = interpolator(safe_attr(element, "text")).strip() color = safe_attr(element, "color") icon = safe_attr(element, "icon") channel = safe_attr(element, "channel") username = safe_attr(element, "username") payload = { "attachments": [ { "color": color, "fallback": text, "title": title, "title_link": title_link, "pretext": pretext, "fields": self._process_fields_(interpolator), }, ], "icon_emoji": icon, "text": text, "username": username, "channel": channel, } return payload
def workflow_action(event): try: sms_notify = api.portal.get_registry_record( 'gene.tumour.interfaces.IGeneTumourSettings.' 'sms_notify_enabled') except Exception as error: sms_notify = False logger.warn(error) if sms_notify: obj = event.object if event.action == 'success' and obj.portal_type == 'Tumour': phone = getattr(obj, 'patient_phone', None) try: message = api.portal.get_registry_record( 'gene.tumour.interfaces.IGeneTumourSettings.' 'sms_notify_message').strip() interpolator = IStringInterpolator(obj) message = interpolator(message) except Exception as error: logger.warn(error) return try: websms = createObject(u'gene.sms.websms') except ComponentLookupError as error: logger.warn(str(error)) else: if phone and message: response = websms.send_msg(to=phone, message=message) logger.debug(response)
def __call__(self): method = self.element.method r = self.element.requests url = self.element.url obj = self.event.object interpolator = IStringInterpolator(obj) payload = interpolate(json.loads(self.element.payload), interpolator) try: if method == 'POST': EXECUTOR.submit(r.post, url, json=payload, timeout=self.timeout) elif method == 'FORM': for key in payload: payload[key] = json.dumps(payload[key]).strip('"') EXECUTOR.submit(r.post, url, data=payload, timeout=self.timeout) elif method == 'GET': for key in payload: payload[key] = json.dumps(payload[key]).strip('"') EXECUTOR.submit(r.get, url, params=payload, timeout=self.timeout) except TypeError: logger.exception('Error calling webhook:') return True
def items(self): registry = getUtility(IRegistry) items = registry['hexagonit.socialbutton.codes'] res = [] for key in self.buttons(): item = {'code_id': key} code_text = items[key]['code_text'] item['code_text'] = IStringInterpolator(self.context)(code_text) res.append(item) return res
def save_email(self): email_type = "N/A" if self.event.object.portal_type == 'eea.meeting.subscriber': """ This is the case for approving a subscriber: - Thank you for your registration """ meeting = self.event.object.aq_parent.aq_parent state = self.event.object.subscriber_status() if state == "approved": email_type = u"Approval" elif state == "rejected": email_type = u"Rejection" elif self.event.object.portal_type == 'eea.meeting': """ This is the case for new subscriber registered: - A new participant has registered to the meeting - You have registered to the meeting """ meeting = self.event.object email_type = u"Registration" types = api.portal.get_tool('portal_types') type_info = types.getTypeInfo('eea.meeting.email') emails_folder = meeting['emails'] name_chooser = INameChooser(emails_folder) interpolator = IStringInterpolator(self.event.object) email_body = interpolator(self.element.message).strip() recipients = interpolator(self.element.recipients).strip() source = self.context.email_from_address data = { 'subject': meeting.title, 'sender': source, 'receiver': recipients, 'cc': '', 'body': email_body, 'email_type': email_type, } content_id = name_chooser.chooseName(data['subject'], emails_folder) obj = type_info._constructInstance(emails_folder, content_id) obj.title = data['subject'] obj.sender = data['sender'] obj.receiver = data['receiver'] obj.cc = data['cc'] obj.subject = data['subject'] obj.body = data['body'] obj.email_type = data['email_type'] obj.reindexObject()
def __call__(self): mailhost = getToolByName(aq_inner(self.context), "MailHost") if not mailhost: raise ComponentLookupError( 'You must have a Mailhost utility to execute this action') source = self.element.source urltool = getToolByName(aq_inner(self.context), "portal_url") portal = urltool.getPortalObject() email_charset = portal.getProperty('email_charset') if not source: # no source provided, looking for the site wide from email # address from_address = portal.getProperty('email_from_address') if not from_address: raise ValueError("You must provide a source address for this \ action or enter an email in the portal properties") from_name = portal.getProperty('email_from_name').strip('"') source = '"%s" <%s>' % (from_name, from_address) obj = self.event.object interpolator = IStringInterpolator(obj) rules_tool = getToolByName(aq_inner(self.context), 'contentrules_subscription_tool') recipients_mail = rules_tool.getRegisteredList(self.element.actionUID) # Prepend interpolated message with \n to avoid interpretation # of first line as header. message = "\n%s" % interpolator(self.element.message) subject = interpolator(self.element.subject) logger.info("Sending mail to recipients: %s" % ", ".join(recipients_mail)) for recipient in recipients_mail: try: # XXX: We're using "immediate=True" because otherwise we won't # be able to catch SMTPException as the smtp connection is made # as part of the transaction apparatus. # AlecM thinks this wouldn't be a problem if mail queuing was # always on -- but it isn't. (stevem) # so we test if queue is not on to set immediate mailhost.send(message, recipient, source, subject=subject, charset=email_charset, immediate=not mailhost.smtp_queue) except (MailHostError, SMTPException): logger.error( """mailing error: Attempt to send mail in content rule failed.\n%s""" % traceback.format_exc()) return True
def __call__(self): mailhost = getToolByName(aq_inner(self.context), 'MailHost') if not mailhost: raise ComponentLookupError('You must have a Mailhost utility to \ execute this action') self.email_charset = self.mail_settings.email_charset obj = self.event.object interpolator = IStringInterpolator(obj) self.source = self.element.source if self.source: self.source = interpolator(self.source).strip() if not self.source: # no source provided, looking for the site wide from email # address from_address = self.mail_settings.email_from_address if not from_address: # the mail can't be sent. Try to inform the user request = getRequest() if request: messages = IStatusMessage(request) msg = _( u'Error sending email from content rule. You must ' 'provide a source address for mail ' 'actions or enter an email in the portal properties') messages.add(msg, type=u'error') return False from_name = self.mail_settings.email_from_name.strip('"') self.source = u'{0} <{1}>'.format(from_name, from_address) self.recipients = self.get_recipients() # prepend interpolated message with \n to avoid interpretation # of first line as header self.message = u'\n{0!s}'.format(interpolator(self.element.message)) self.subject = interpolator(self.element.subject) mime_msg = self.create_mime_msg() if not mime_msg: return False # Finally send mail. # Plone-4 mailhost.send(mime_msg) return True
def __call__(self): obj = self.event.object interpolator = IStringInterpolator(obj) payload = interpolate(json.loads(self.element.payload), interpolator) topic = "/".join(obj.getPhysicalPath()) guards_context = get_allowed_roles_and_users_guard(self.context) guards_event = get_allowed_roles_and_users_guard(obj) if ("Anonymous" in guards_event["allowedRolesAndUsers"]["tokens"] and "Anonymous" not in guards_context["allowedRolesAndUsers"]["tokens"]): guards = guards_context else: guards = guards_event message = {"guards": guards, "payload": {"notifications": [payload]}} dm = CallbackDataManager(publish_message, encode_message(message), topic) get_transaction().join(dm)
def _get_interpolator(self, userid): """adds a plone.stringinterp IContextWrapper around our event.object to add support for mustread_ variable substitution """ obj = self.event.object tracker = getUtility(ITracker) deadlines = tracker.who_did_not_read(obj) deadline = deadlines.get(userid, None) if deadline: deadline = api.portal.get_localized_time(deadline, False) else: deadline = '' user = api.user.get(userid=userid) if user is None: fullname = userid else: fullname = user.getProperty('fullname') wrapped = IContextWrapper(obj)( mustread_deadline=deadline, mustread_fullname=fullname) return IStringInterpolator(wrapped)
def _interpolate(template, ob, request=None): if request is None: request = getRequest() schema = load_schema( aq_base(ob).schema, cache_key=aq_base(ob).schema_digest, ) mapping = {} for name in schema.names(): field = schema[name] bound = field.bind(ob) try: value = bound.get(ob) except AttributeError: value = '' if not value: try: factory = field.defaultFactory except AttributeError: factory = None if not factory: continue if IContextAwareDefaultFactory.providedBy(factory): value = factory(ob) else: value = factory() if not value: mapping[name] = '' continue try: mapping[name] = translate( bound.vocabulary.getTerm(value).title, context=request, ) except (AttributeError, LookupError): mapping[name] = value interpolator = IStringInterpolator(ob) value = interpolator(i18n_interpolate(template or u'', mapping)) return value
def __call__(self): event = self.event queue_name = self.element.queue_name obj = event.object interpolator = IStringInterpolator(obj) body = interpolator(self.element.body.strip()) if body: #send message to the RabbitMQ service rabbit = RabbitMQConnector(**rabbit_config) rabbit.open_connection() try: rabbit.declare_queue(queue_name) rabbit.send_message(queue_name, body) except Exception, err: logger.error('Sending \'%s\' in \'%s\' FAILED with error: %s', body, queue_name, err) else: logger.info('Sending \'%s\' in \'%s\' OK', body, queue_name) rabbit.close_connection()
def get_message_payload(self): """Process the action and return a dictionary with the Slack message payload. :returns: Slack message payload. :rtype: dict. """ obj = self.event.object element = self.element interpolator = IStringInterpolator(obj) title = interpolator(element.title).strip() title_link = interpolator(element.title_link).strip() pretext = interpolator(element.pretext).strip() text = interpolator(element.text).strip() color = element.color icon = element.icon channel = element.channel username = element.username payload = { 'attachments': [{ 'color': color, 'fallback': text, 'title': title, 'title_link': title_link, 'pretext': pretext, 'fields': self._process_fields_(interpolator) }], 'icon_emoji': icon, 'text': text, 'username': username, 'channel': channel } return payload
def __call__(self): portal_membership = getToolByName(aq_inner(self.context), 'portal_membership') portal_groups = getToolByName(aq_inner(self.context), 'portal_groups') members = set(self.element.members) recipients = set() for groupId in self.element.groups: group = portal_groups.getGroupById(groupId) if group and group.getProperties().get('email'): recipients.update([group.getProperties().get('email')], ) groupMembers = group.getGroupMemberIds() for memberId in groupMembers: members.update([memberId, ]) for memberId in members: member = portal_membership.getMemberById(memberId) if member and member.getProperty('email'): recipients.update([member.getProperty('email'), ]) mailhost = getToolByName(aq_inner(self.context), "MailHost") if not mailhost: raise ComponentLookupError, 'You must have a Mailhost utility to \ execute this action' source = from_address = self.element.source urltool = getToolByName(aq_inner(self.context), "portal_url") portal = urltool.getPortalObject() email_charset = portal.getProperty('email_charset') if not source: # no source provided, looking for the site wide from email # address from_address = portal.getProperty('email_from_address') if not from_address: raise ValueError, 'You must provide a source address for this \ action or enter an email in the portal properties' from_name = portal.getProperty('email_from_name') source = "%s <%s>" % (from_name, from_address) obj = self.event.object event_title = safe_unicode(obj.Title()) event_url = obj.absolute_url() # Not all items have a text-field: try: event_text = safe_unicode(obj.getText()) except: event_text = '' interpolator = IStringInterpolator(obj) message = "\n%s" % interpolator(self.element.message) subject = interpolator(self.element.subject) # Convert set of recipients to a list: list_of_recipients = list(recipients) if not list_of_recipients: return False # Prepare multi-part-message to send html with plain-text-fallback-message, # for non-html-capable-mail-clients. # Thanks to Peter Bengtsson for valuable information about this in this post: # http://www.peterbe.com/plog/zope-html-emails mime_msg = MIMEMultipart('related') mime_msg['Subject'] = subject mime_msg['From'] = source # mime_msg['To'] = "" mime_msg['Bcc'] = ', '.join(list_of_recipients) mime_msg.preamble = 'This is a multi-part message in MIME format.' # Encapsulate the plain and HTML versions of the message body # in an 'alternative' part, so message agents can decide # which they want to display. msgAlternative = MIMEMultipart('alternative') mime_msg.attach(msgAlternative) # Convert html-message to plain text. transforms = getToolByName(aq_inner(self.context), 'portal_transforms') stream = transforms.convertTo('text/plain', message, mimetype='text/html') body_plain = stream.getData().strip() # We attach the plain text first, the order is mandatory. msg_txt = MIMEText(body_plain, _subtype='plain', _charset=email_charset) msgAlternative.attach(msg_txt) # After that, attach html. msg_txt = MIMEText(message, _subtype='html', _charset=email_charset) msgAlternative.attach(msg_txt) # Finally send mail. # Plone-4 try: mailhost.send(mime_msg) # Plone-3 except: mailhost.secureSend(mime_msg.as_string()) return True
def __call__(self): mailhost = getToolByName(aq_inner(self.context), "MailHost") if not mailhost: raise ComponentLookupError, "You must have a Mailhost utility to \ execute this action" urltool = getToolByName(aq_inner(self.context), "portal_url") portal = urltool.getPortalObject() email_charset = portal.getProperty('email_charset') obj = self.event.object interpolator = IStringInterpolator(obj) source = self.element.source if source: source = interpolator(source).strip() if not source: # no source provided, looking for the site wide from email # address from_address = portal.getProperty('email_from_address') if not from_address: # the mail can't be sent. Try to inform the user request = getRequest() if request: messages = IStatusMessage(request) msg = u"Error sending email from content rule. You must \ provide a source address for mail \ actions or enter an email in the portal properties" messages.add(msg, type=u"error") return False from_name = portal.getProperty('email_from_name').strip('"') source = '"%s" <%s>' % (from_name, from_address) recip_string = interpolator(self.element.recipients) if recip_string: # check recipient is not None or empty string recipients = [str(mail.strip()) for mail in recip_string.split(',') \ if mail.strip()] else: recipients = [] if self.element.exclude_actor: mtool = getToolByName(aq_inner(self.context), "portal_membership") actor_email = mtool.getAuthenticatedMember().getProperty( 'email', '') if actor_email in recipients: recipients.remove(actor_email) # prepend interpolated message with \n to avoid interpretation # of first line as header message = "\n%s" % interpolator(self.element.message) subject = interpolator(self.element.subject) for email_recipient in recipients: try: # XXX: We're using "immediate=True" because otherwise we won't # be able to catch SMTPException as the smtp connection is made # as part of the transaction apparatus. # AlecM thinks this wouldn't be a problem if mail queuing was # always on -- but it isn't. (stevem) # so we test if queue is not on to set immediate mailhost.send(message, email_recipient, source, subject=subject, charset=email_charset, immediate=not mailhost.smtp_queue) except (MailHostError, SMTPException): logger.error( """mailing error: Attempt to send mail in content rule failed.\n%s""" % traceback.format_exc()) return True
def __call__(self): mailhost = getToolByName(aq_inner(self.context), 'MailHost') if not mailhost: raise ComponentLookupError( 'You must have a Mailhost utility to execute this action') email_charset = self.mail_settings.email_charset obj = self.event.object interpolator = IStringInterpolator(obj) source = self.element.source if source: source = interpolator(source).strip() if not source: # no source provided, looking for the site wide from email # address from_address = self.mail_settings.email_from_address if not from_address: # the mail can't be sent. Try to inform the user request = getRequest() if request: messages = IStatusMessage(request) msg = _( u'Error sending email from content rule. You must ' u'provide a source address for mail ' u'actions or enter an email in the portal properties') messages.add(msg, type=u'error') return False from_name = self.mail_settings.email_from_name.strip('"') source = '"{0}" <{1}>'.format(from_name.encode('utf8'), from_address) recip_string = interpolator(self.element.recipients) if recip_string: # check recipient is not None or empty string recipients = set([ str(mail.strip()) for mail in recip_string.split(',') if mail.strip() ]) else: recipients = set() if self.element.exclude_actor: mtool = getToolByName(aq_inner(self.context), 'portal_membership') actor_email = mtool.getAuthenticatedMember().getProperty( 'email', '') if actor_email in recipients: recipients.remove(actor_email) # prepend interpolated message with \n to avoid interpretation # of first line as header message = u'\n{0}'.format(interpolator(self.element.message)) subject = interpolator(self.element.subject) for email_recipient in recipients: try: # XXX: We're using "immediate=True" because otherwise we won't # be able to catch SMTPException as the smtp connection is made # as part of the transaction apparatus. # AlecM thinks this wouldn't be a problem if mail queuing was # always on -- but it isn't. (stevem) # so we test if queue is not on to set immediate mailhost.send(message, email_recipient, source, subject=subject, charset=email_charset, immediate=not mailhost.smtp_queue) except (MailHostError, SMTPException): logger.exception( 'mail error: Attempt to send mail in content rule failed') return True
def __call__(self): # mailhost = getToolByName(aq_inner(self.context), "MailHost") mailhost = getUtility(IMailHost) if not mailhost: raise ComponentLookupError( 'You must have a Mailhost utility to execute this action') source = self.element.source urltool = getToolByName(aq_inner(self.context), "portal_url") membertool = getToolByName(aq_inner(self.context), "portal_membership") portal = urltool.getPortalObject() if not source: # no source provided, looking for the site wide from email # address from_address = portal.getProperty('email_from_address') if IS_PLONE_5: from_address = api.portal.get_registry_record( 'plone.email_from_address') if not from_address: raise ValueError("You must provide a source address for this \ action or enter an email in the portal properties") from_name = portal.getProperty('email_from_name', '').strip('"') if IS_PLONE_5: from_name = api.portal.get_registry_record( 'plone.email_from_name') source = '"%s" <%s>' % (from_name, from_address) obj = self.event.object interpolator = IStringInterpolator(obj) # search through all local roles on the object, and add # users's email to the recipients list if they have the local # role stored in the action local_roles = obj.get_local_roles() if len(local_roles) == 0: return True recipients = set() for user, roles in local_roles: rolelist = list(roles) if self.element.role in rolelist: recipients.add(user) # check for the acquired roles if self.element.acquired: sharing_page = obj.unrestrictedTraverse('@@sharing') acquired_roles = sharing_page._inherited_roles() if hasattr(sharing_page, '_borg_localroles'): acquired_roles += sharing_page._borg_localroles() acquired_users = [ r[0] for r in acquired_roles if self.element.role in r[1] ] recipients.update(acquired_users) # check for the global roles if self.element.global_roles: pas = getToolByName(self.event.object, 'acl_users') rolemanager = pas.portal_role_manager global_role_ids = [ p[0] for p in rolemanager.listAssignedPrincipals(self.element.role) ] recipients.update(global_role_ids) # check to see if the recipents are users or groups group_recipients = [] new_recipients = [] group_tool = portal.portal_groups def _getGroupMemberIds(group): """ Helper method to support groups in groups. """ members = [] for member_id in group.getGroupMemberIds(): subgroup = group_tool.getGroupById(member_id) if subgroup is not None: members.extend(_getGroupMemberIds(subgroup)) else: members.append(member_id) return members for recipient in recipients: group = group_tool.getGroupById(recipient) if group is not None: group_recipients.append(recipient) [ new_recipients.append(user_id) for user_id in _getGroupMemberIds(group) ] for recipient in group_recipients: recipients.remove(recipient) for recipient in new_recipients: recipients.add(recipient) # look up e-mail addresses for the found users recipients_mail = set() for user in recipients: member = membertool.getMemberById(user) # check whether user really exists # before getting its email address if not member: continue recipient_prop = member.getProperty('email') if recipient_prop is not None and len(recipient_prop) > 0: recipients_mail.add(recipient_prop) # Prepend interpolated message with \n to avoid interpretation # of first line as header. message = "\n%s" % interpolator(self.element.message) subject = interpolator(self.element.subject) for recipient in recipients_mail: try: mailhost.send(message, recipient, source, subject=subject, charset='utf-8', msg_type="text/html") # logger.info("{} email sent to {}".format(recipient, subject)) except (MailHostError, SMTPException): logger.exception( 'mail error: Attempt to send mail in content rule failed') return True