def __call__(self): if 'submitted' in self.request: self.items = self.context.objectValues() self.pricelist_content = self.lineitems_pt() portal = context.portal_url.getPortalObject() lab = context.bika_labinfo.laboratory request = context.REQUEST ar_query_results = portal.portal_mailtemplates.getTemplate( 'bika', request.mail_template) headers = {} headers['Date'] = DateTime().rfc822() from_addr = headers['From'] = formataddr( (encode_header(lab.Title()), lab.getEmailAddress()) ) if 'Contact_email_address' in request: contact_address = request.Contact_email_address msg = 'portal_status_message=Pricelist sent to %s' % ( contact_address) else: contact = context.reference_catalog.lookupObject(request.Contact_uid) contact_address = formataddr( (encode_header(contact.getFullname()), contact.getEmailAddress()) ) msg = 'portal_status_message=Pricelist sent to %s at %s' % ( contact.Title(), contact.getEmailAddress()) to_addrs = [] to_addr = headers['To'] = contact_address to_addrs.append(to_addr) # send copy to lab to_addrs.append(from_addr) to_addrs = tuple(to_addrs) info = {'request': request, 'pricelist': context, 'portal': portal} message = pmt.createMessage( 'bika', request.mail_template, info, headers, text_format='html') sendmail(portal, from_addr, to_addrs, message) request.RESPONSE.redirect('%s?%s' % (context.absolute_url(), msg)) return self.template() else: return self.form_template()
def emailInvoice(self, templateHTML, to=[]): """ Send the invoice via email. :param templateHTML: The invoice template in HTML, ready to be send. :param to: A list with the addresses to send the invoice. """ ar = self.aq_parent # SMTP errors are silently ignored if server is in debug mode # debug_mode = App.config.getConfiguration().debug_mode "By Yasir" # Useful variables lab = ar.bika_setup.laboratory # Compose and send email. subject = t(_('Invoice')) + ' ' + ar.getInvoice().getId() mime_msg = MIMEMultipart('related') mime_msg['Subject'] = subject mime_msg['From'] = formataddr( (encode_header(lab.getName()), lab.getEmailAddress())) mime_msg.preamble = 'This is a multi-part MIME message.' msg_txt_t = MIMEText(templateHTML.encode('utf-8'), _subtype='html') mime_msg.attach(msg_txt_t) # Build the responsible's addresses mngrs = ar.getResponsible() for mngrid in mngrs['ids']: name = mngrs['dict'][mngrid].get('name', '') email = mngrs['dict'][mngrid].get('email', '') if (email != ''): to.append(formataddr((encode_header(name), email))) # Build the client's address caddress = ar.aq_parent.getEmailAddress() cname = ar.aq_parent.getName() if (caddress != ''): to.append(formataddr((encode_header(cname), caddress))) if len(to) > 0: # Send the emails mime_msg['To'] = ','.join(to) try: host = getToolByName(ar, 'MailHost') host.send(mime_msg.as_string(), immediate=True) except SMTPServerDisconnected as msg: pass if not debug_mode: raise SMTPServerDisconnected(msg) except SMTPRecipientsRefused as msg: raise WorkflowException(str(msg))
def sendEmail(self): added = [] to = '' for analysis in self.analyses: department = analysis.getService().getDepartment() if department is None: continue department_id = department.UID() if department_id in added: continue added.append(department_id) manager = department.getManager() if manager is None: continue manager_id = manager.UID() if manager_id not in added and manager.getEmailAddress(): added.append(manager_id) name = safe_unicode(manager.getFullname()).encode('utf-8') email = safe_unicode(manager.getEmailAddress()).encode('utf-8') to = '%s, %s' % (to, formataddr((encode_header(name), email))) html = safe_unicode(self.template()).encode('utf-8') lab = self.context.bika_setup.laboratory mime_msg = MIMEMultipart('related') mime_msg['Subject'] = self.title mime_msg['From'] = formataddr( (encode_header(lab.getName()), lab.getEmailAddress())) mime_msg['To'] = to mime_msg.preamble = 'This is a multi-part MIME message.' msg_txt = MIMEText(html, _subtype='html') mime_msg.attach(msg_txt) # Send the email try: host = getToolByName(self.context, 'MailHost') host.send(mime_msg.as_string(), immediate=True) except SMTPServerDisconnected as msg: raise SMTPServerDisconnected(msg) except SMTPRecipientsRefused as msg: raise WorkflowException(str(msg))
def publishFromHTML(self, aruid, results_html): # The AR can be published only and only if allowed uc = getToolByName(self.context, 'uid_catalog') ars = uc(UID=aruid) if not ars or len(ars) != 1: return [] ar = ars[0].getObject() wf = getToolByName(ar, 'portal_workflow') allowed_states = ['verified', 'published'] # Publish/Republish allowed? if wf.getInfoFor(ar, 'review_state') not in allowed_states: # Pre-publish allowed? if not ar.getAnalyses(review_state=allowed_states): return [] # HTML written to debug file # debug_mode = App.config.getConfiguration().debug_mode "Commented by Yasir" debug_mode = True #" Added by Yasir" if debug_mode: tmp_fn = tempfile.mktemp(suffix=".html") logger.debug("Writing HTML for %s to %s" % (ar.Title(), tmp_fn)) open(tmp_fn, "wb").write(results_html) # Create the pdf report (will always be attached to the AR) # we must supply the file ourself so that createPdf leaves it alone. # This version replaces 'attachment' links; probably not required, # so it's repeated below, without these localise_images. # cleanup, results_html_for_pdf = self.localise_images(results_html) # pdf_fn = tempfile.mktemp(suffix=".pdf") # pdf_report = createPdf(htmlreport=results_html_for_pdf, outfile=pdf_fn) # for fn in cleanup: # os.remove(fn) # Create the pdf report (will always be attached to the AR) # we must supply the file ourself so that createPdf leaves it alone. pdf_fn = tempfile.mktemp(suffix=".pdf") pdf_report = createPdf(htmlreport=results_html, outfile=pdf_fn) # PDF written to debug file if debug_mode: logger.debug("Writing PDF for %s to %s" % (ar.Title(), pdf_fn)) else: os.remove(pdf_fn) recipients = [] contact = ar.getContact() lab = ar.bika_setup.laboratory if pdf_report: if contact: recipients = [{ 'UID': contact.UID(), 'Username': to_utf8(contact.getUsername()), 'Fullname': to_utf8(contact.getFullname()), 'EmailAddress': to_utf8(contact.getEmailAddress()), 'PublicationModes': contact.getPublicationPreference() }] reportid = ar.generateUniqueId('ARReport') report = _createObjectByType("ARReport", ar, reportid) report.edit(AnalysisRequest=ar.UID(), Pdf=pdf_report, Html=results_html, Recipients=recipients) report.unmarkCreationFlag() renameAfterCreation(report) # Set status to prepublished/published/republished status = wf.getInfoFor(ar, 'review_state') transitions = {'verified': 'publish', 'published': 'republish'} transition = transitions.get(status, 'prepublish') try: wf.doActionFor(ar, transition) except WorkflowException: pass # compose and send email. # The managers of the departments for which the current AR has # at least one AS must receive always the pdf report by email. # https://github.com/bikalabs/Bika-LIMS/issues/1028 mime_msg = MIMEMultipart('related') mime_msg['Subject'] = self.get_mail_subject(ar)[0] mime_msg['From'] = formataddr( (encode_header(lab.getName()), lab.getEmailAddress())) mime_msg.preamble = 'This is a multi-part MIME message.' msg_txt = MIMEText(results_html, _subtype='html') mime_msg.attach(msg_txt) to = [] mngrs = ar.getResponsible() for mngrid in mngrs['ids']: name = mngrs['dict'][mngrid].get('name', '') email = mngrs['dict'][mngrid].get('email', '') if (email != ''): to.append(formataddr((encode_header(name), email))) if len(to) > 0: # Send the email to the managers mime_msg['To'] = ','.join(to) attachPdf(mime_msg, pdf_report, pdf_fn) try: host = getToolByName(ar, 'MailHost') host.send(mime_msg.as_string(), immediate=True) except SMTPServerDisconnected as msg: logger.warn("SMTPServerDisconnected: %s." % msg) except SMTPRecipientsRefused as msg: raise WorkflowException(str(msg)) # Send report to recipients recips = self.get_recipients(ar) for recip in recips: if 'email' not in recip.get('pubpref', []) \ or not recip.get('email', ''): continue title = encode_header(recip.get('title', '')) email = recip.get('email') formatted = formataddr((title, email)) # Create the new mime_msg object, cause the previous one # has the pdf already attached mime_msg = MIMEMultipart('related') mime_msg['Subject'] = self.get_mail_subject(ar)[0] mime_msg['From'] = formataddr( (encode_header(lab.getName()), lab.getEmailAddress())) mime_msg.preamble = 'This is a multi-part MIME message.' msg_txt = MIMEText(results_html, _subtype='html') mime_msg.attach(msg_txt) mime_msg['To'] = formatted # Attach the pdf to the email if requested if pdf_report and 'pdf' in recip.get('pubpref'): attachPdf(mime_msg, pdf_report, pdf_fn) # For now, I will simply ignore mail send under test. if hasattr(self.portal, 'robotframework'): continue msg_string = mime_msg.as_string() # content of outgoing email written to debug file if debug_mode: tmp_fn = tempfile.mktemp(suffix=".email") logger.debug("Writing MIME message for %s to %s" % (ar.Title(), tmp_fn)) open(tmp_fn, "wb").write(msg_string) try: host = getToolByName(ar, 'MailHost') host.send(msg_string, immediate=True) except SMTPServerDisconnected as msg: logger.warn("SMTPServerDisconnected: %s." % msg) except SMTPRecipientsRefused as msg: raise WorkflowException(str(msg)) ar.setDatePublished(DateTime()) return [ar]
def workflow_action_retract_ar(self): workflow = getToolByName(self.context, 'portal_workflow') # AR should be retracted # Can't transition inactive ARs if not isActive(self.context): message = _('Item is inactive.') self.context.plone_utils.addPortalMessage(message, 'info') self.request.response.redirect(self.context.absolute_url()) return # 1. Copies the AR linking the original one and viceversa ar = self.context newar = self.cloneAR(ar) # 2. The old AR gets a status of 'invalid' workflow.doActionFor(ar, 'retract_ar') # 3. The new AR copy opens in status 'to be verified' changeWorkflowState(newar, 'bika_ar_workflow', 'to_be_verified') # 4. The system immediately alerts the client contacts who ordered # the results, per email and SMS, that a possible mistake has been # picked up and is under investigation. # A much possible information is provided in the email, linking # to the AR online. laboratory = self.context.bika_setup.laboratory lab_address = "<br/>".join(laboratory.getPrintAddress()) mime_msg = MIMEMultipart('related') mime_msg['Subject'] = t(_("Erroneus result publication from ${request_id}", mapping={"request_id": ar.getRequestID()})) mime_msg['From'] = formataddr( (encode_header(laboratory.getName()), laboratory.getEmailAddress())) to = [] contact = ar.getContact() if contact: to.append(formataddr((encode_header(contact.Title()), contact.getEmailAddress()))) for cc in ar.getCCContact(): formatted = formataddr((encode_header(cc.Title()), cc.getEmailAddress())) if formatted not in to: to.append(formatted) managers = self.context.portal_groups.getGroupMembers('LabManagers') for bcc in managers: user = self.portal.acl_users.getUser(bcc) if user: uemail = user.getProperty('email') ufull = user.getProperty('fullname') formatted = formataddr((encode_header(ufull), uemail)) if formatted not in to: to.append(formatted) mime_msg['To'] = ','.join(to) aranchor = "<a href='%s'>%s</a>" % (ar.absolute_url(), ar.getRequestID()) naranchor = "<a href='%s'>%s</a>" % (newar.absolute_url(), newar.getRequestID()) addremarks = ('addremarks' in self.request and ar.getRemarks()) \ and ("<br/><br/>" + _("Additional remarks:") + "<br/>" + ar.getRemarks().split("===")[1].strip() + "<br/><br/>") \ or '' sub_d = dict(request_link=aranchor, new_request_link=naranchor, remarks=addremarks, lab_address=lab_address) body = Template("Some errors have been detected in the results report " "published from the Analysis Request $request_link. The Analysis " "Request $new_request_link has been created automatically and the " "previous has been invalidated.<br/>The possible mistake " "has been picked up and is under investigation.<br/><br/>" "$remarks $lab_address").safe_substitute(sub_d) msg_txt = MIMEText(safe_unicode(body).encode('utf-8'), _subtype='html') mime_msg.preamble = 'This is a multi-part MIME message.' mime_msg.attach(msg_txt) try: host = getToolByName(self.context, 'MailHost') host.send(mime_msg.as_string(), immediate=True) except Exception as msg: message = _('Unable to send an email to alert lab ' 'client contacts that the Analysis Request has been ' 'retracted: ${error}', mapping={'error': safe_unicode(msg)}) self.context.plone_utils.addPortalMessage(message, 'warning') message = _('${items} invalidated.', mapping={'items': ar.getRequestID()}) self.context.plone_utils.addPortalMessage(message, 'warning') self.request.response.redirect(newar.absolute_url())
def publishFromHTML(self, aruid, results_html): # The AR can be published only and only if allowed uc = getToolByName(self.context, 'uid_catalog') ars = uc(UID=aruid) if not ars or len(ars) != 1: return [] ar = ars[0].getObject(); wf = getToolByName(ar, 'portal_workflow') allowed_states = ['verified', 'published'] # Publish/Republish allowed? if wf.getInfoFor(ar, 'review_state') not in allowed_states: # Pre-publish allowed? if not ar.getAnalyses(review_state=allowed_states): return [] # HTML written to debug file # debug_mode = App.config.getConfiguration().debug_mode "Commented by Yasir" debug_mode = True #" Added by Yasir" if debug_mode: tmp_fn = tempfile.mktemp(suffix=".html") logger.debug("Writing HTML for %s to %s" % (ar.Title(), tmp_fn)) open(tmp_fn, "wb").write(results_html) # Create the pdf report (will always be attached to the AR) # we must supply the file ourself so that createPdf leaves it alone. # This version replaces 'attachment' links; probably not required, # so it's repeated below, without these localise_images. # cleanup, results_html_for_pdf = self.localise_images(results_html) # pdf_fn = tempfile.mktemp(suffix=".pdf") # pdf_report = createPdf(htmlreport=results_html_for_pdf, outfile=pdf_fn) # for fn in cleanup: # os.remove(fn) # Create the pdf report (will always be attached to the AR) # we must supply the file ourself so that createPdf leaves it alone. pdf_fn = tempfile.mktemp(suffix=".pdf") pdf_report = createPdf(htmlreport=results_html, outfile=pdf_fn) # PDF written to debug file if debug_mode: logger.debug("Writing PDF for %s to %s" % (ar.Title(), pdf_fn)) else: os.remove(pdf_fn) recipients = [] contact = ar.getContact() lab = ar.bika_setup.laboratory if pdf_report: if contact: recipients = [{ 'UID': contact.UID(), 'Username': to_utf8(contact.getUsername()), 'Fullname': to_utf8(contact.getFullname()), 'EmailAddress': to_utf8(contact.getEmailAddress()), 'PublicationModes': contact.getPublicationPreference() }] reportid = ar.generateUniqueId('ARReport') report = _createObjectByType("ARReport", ar, reportid) report.edit( AnalysisRequest=ar.UID(), Pdf=pdf_report, Html=results_html, Recipients=recipients ) report.unmarkCreationFlag() renameAfterCreation(report) # Set status to prepublished/published/republished status = wf.getInfoFor(ar, 'review_state') transitions = {'verified': 'publish', 'published' : 'republish'} transition = transitions.get(status, 'prepublish') try: wf.doActionFor(ar, transition) except WorkflowException: pass # compose and send email. # The managers of the departments for which the current AR has # at least one AS must receive always the pdf report by email. # https://github.com/bikalabs/Bika-LIMS/issues/1028 mime_msg = MIMEMultipart('related') mime_msg['Subject'] = self.get_mail_subject(ar)[0] mime_msg['From'] = formataddr( (encode_header(lab.getName()), lab.getEmailAddress())) mime_msg.preamble = 'This is a multi-part MIME message.' msg_txt = MIMEText(results_html, _subtype='html') mime_msg.attach(msg_txt) to = [] mngrs = ar.getResponsible() for mngrid in mngrs['ids']: name = mngrs['dict'][mngrid].get('name', '') email = mngrs['dict'][mngrid].get('email', '') if (email != ''): to.append(formataddr((encode_header(name), email))) if len(to) > 0: # Send the email to the managers mime_msg['To'] = ','.join(to) attachPdf(mime_msg, pdf_report, pdf_fn) try: host = getToolByName(ar, 'MailHost') host.send(mime_msg.as_string(), immediate=True) except SMTPServerDisconnected as msg: logger.warn("SMTPServerDisconnected: %s." % msg) except SMTPRecipientsRefused as msg: raise WorkflowException(str(msg)) # Send report to recipients recips = self.get_recipients(ar) for recip in recips: if 'email' not in recip.get('pubpref', []) \ or not recip.get('email', ''): continue title = encode_header(recip.get('title', '')) email = recip.get('email') formatted = formataddr((title, email)) # Create the new mime_msg object, cause the previous one # has the pdf already attached mime_msg = MIMEMultipart('related') mime_msg['Subject'] = self.get_mail_subject(ar)[0] mime_msg['From'] = formataddr( (encode_header(lab.getName()), lab.getEmailAddress())) mime_msg.preamble = 'This is a multi-part MIME message.' msg_txt = MIMEText(results_html, _subtype='html') mime_msg.attach(msg_txt) mime_msg['To'] = formatted # Attach the pdf to the email if requested if pdf_report and 'pdf' in recip.get('pubpref'): attachPdf(mime_msg, pdf_report, pdf_fn) # For now, I will simply ignore mail send under test. if hasattr(self.portal, 'robotframework'): continue msg_string = mime_msg.as_string() # content of outgoing email written to debug file if debug_mode: tmp_fn = tempfile.mktemp(suffix=".email") logger.debug("Writing MIME message for %s to %s" % (ar.Title(), tmp_fn)) open(tmp_fn, "wb").write(msg_string) try: host = getToolByName(ar, 'MailHost') host.send(msg_string, immediate=True) except SMTPServerDisconnected as msg: logger.warn("SMTPServerDisconnected: %s." % msg) except SMTPRecipientsRefused as msg: raise WorkflowException(str(msg)) ar.setDatePublished(DateTime()) return [ar]
def workflow_action_retract_ar(self): workflow = getToolByName(self.context, 'portal_workflow') # AR should be retracted # Can't transition inactive ARs if not isActive(self.context): message = _('Item is inactive.') self.context.plone_utils.addPortalMessage(message, 'info') self.request.response.redirect(self.context.absolute_url()) return # 1. Copies the AR linking the original one and viceversa ar = self.context newar = self.cloneAR(ar) # 2. The old AR gets a status of 'invalid' workflow.doActionFor(ar, 'retract_ar') # 3. The new AR copy opens in status 'to be verified' changeWorkflowState(newar, 'bika_ar_workflow', 'to_be_verified') # 4. The system immediately alerts the client contacts who ordered # the results, per email and SMS, that a possible mistake has been # picked up and is under investigation. # A much possible information is provided in the email, linking # to the AR online. laboratory = self.context.bika_setup.laboratory lab_address = "<br/>".join(laboratory.getPrintAddress()) mime_msg = MIMEMultipart('related') mime_msg['Subject'] = t( _("Erroneus result publication from ${request_id}", mapping={"request_id": ar.getRequestID()})) mime_msg['From'] = formataddr((encode_header(laboratory.getName()), laboratory.getEmailAddress())) to = [] contact = ar.getContact() if contact: to.append( formataddr((encode_header(contact.Title()), contact.getEmailAddress()))) for cc in ar.getCCContact(): formatted = formataddr( (encode_header(cc.Title()), cc.getEmailAddress())) if formatted not in to: to.append(formatted) managers = self.context.portal_groups.getGroupMembers('LabManagers') for bcc in managers: user = self.portal.acl_users.getUser(bcc) if user: uemail = user.getProperty('email') ufull = user.getProperty('fullname') formatted = formataddr((encode_header(ufull), uemail)) if formatted not in to: to.append(formatted) mime_msg['To'] = ','.join(to) aranchor = "<a href='%s'>%s</a>" % (ar.absolute_url(), ar.getRequestID()) naranchor = "<a href='%s'>%s</a>" % (newar.absolute_url(), newar.getRequestID()) addremarks = ('addremarks' in self.request and ar.getRemarks()) \ and ("<br/><br/>" + _("Additional remarks:") + "<br/>" + ar.getRemarks().split("===")[1].strip() + "<br/><br/>") \ or '' sub_d = dict(request_link=aranchor, new_request_link=naranchor, remarks=addremarks, lab_address=lab_address) body = Template( "Some errors have been detected in the results report " "published from the Analysis Request $request_link. The Analysis " "Request $new_request_link has been created automatically and the " "previous has been invalidated.<br/>The possible mistake " "has been picked up and is under investigation.<br/><br/>" "$remarks $lab_address").safe_substitute(sub_d) msg_txt = MIMEText(safe_unicode(body).encode('utf-8'), _subtype='html') mime_msg.preamble = 'This is a multi-part MIME message.' mime_msg.attach(msg_txt) try: host = getToolByName(self.context, 'MailHost') host.send(mime_msg.as_string(), immediate=True) except Exception as msg: message = _( 'Unable to send an email to alert lab ' 'client contacts that the Analysis Request has been ' 'retracted: ${error}', mapping={'error': safe_unicode(msg)}) self.context.plone_utils.addPortalMessage(message, 'warning') message = _('${items} invalidated.', mapping={'items': ar.getRequestID()}) self.context.plone_utils.addPortalMessage(message, 'warning') self.request.response.redirect(newar.absolute_url())