def fillresponse(self): XferContainerCustom.fillresponse(self) self.new_tab(_('EMail configuration')) img = XferCompImage('img_conf') img.set_value(self.icon_path()) img.set_location(0, 0, 1, 6) self.add_component(img) conf_params = ['mailing-smtpserver', 'mailing-smtpport', 'mailing-smtpsecurity', 'mailing-smtpuser', 'mailing-smtppass', 'mailing-delay-batch', 'mailing-nb-by-batch'] Params.fill(self, conf_params, 1, 1) btn = XferCompButton('editparam') btn.set_location(3, 1, 1, 5) btn.set_action(self.request, ParamEdit.get_action(_('Modify'), 'images/edit.png'), close=CLOSE_NO, params={'params': conf_params}) self.add_component(btn) if will_mail_send(): btn = XferCompButton('tryemail') btn.set_location(1, 10, 2) btn.set_action(self.request, SendEmailTry.get_action(_('Send'), ''), close=CLOSE_NO) self.add_component(btn) self.new_tab(_('Default message')) img = XferCompImage('img_msg') img.set_value(self.icon_path()) img.set_location(0, 0, 1, 6) self.add_component(img) msg_params = ['mailing-msg-connection'] Params.fill(self, msg_params, 1, 1) btn = XferCompButton('editmsg') btn.set_location(1, 10, 2) btn.set_action(self.request, ParamEdit.get_action(_('Modify'), 'images/edit.png'), close=CLOSE_NO, params={'params': msg_params}) self.add_component(btn)
def sendemail(self, nb_to_send, http_root_address): if will_mail_send() and (self.status == 2): email_list = self.email_to_send.split("\n") link_html = "" files = [] for doc in self.documents.all(): if self.doc_in_link: if doc.sharekey is None: doc.change_sharekey(False) doc.save() doc.set_context(http_root_address) link_html += "<li><a href='%s'>%s</a></li>" % (doc.shared_link, doc.name) else: files.append((doc.name, doc.content)) if self.doc_in_link and (link_html != ''): link_html = "<hr/><h3>%s</h3><ul>%s</ul>" % (_('Shared documents'), link_html) email_content = "<html><body>%s%s</body></html>" % (toHtml(self.body), link_html) for contact_email in email_list[:nb_to_send]: contact_id, email = contact_email.split(':') try: contact = AbstractContact.objects.get(id=contact_id) except AbstractContact.DoesNotExist: contact = None try: send_email([email], self.subject, email_content, files=files if len(files) > 0 else None) EmailSent.objects.create(message=self, contact=contact, email=email, date=timezone.now(), success=True) except Exception as error: EmailSent.objects.create(message=self, contact=contact, email=email, date=timezone.now(), success=False, error=six.text_type(error)) self.email_to_send = "\n".join(email_list[nb_to_send:]) if self.email_to_send == '': self.status = 1 self.save() return
def send_connection_email(email_adress, username, passwd): if will_mail_send(): if email_adress and username and passwd: send_connection_by_email(email_adress, username, passwd) return True else: return False
def test_send_withdouble(self): configSMTP('localhost', 1025) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) send_email( ['*****@*****.**', '*****@*****.**', '*****@*****.**'], 'send correct config', 'Yessss!!!', cclist=['*****@*****.**', '*****@*****.**', '*****@*****.**'], bcclist=['*****@*****.**', '*****@*****.**', '*****@*****.**']) self.assertEqual(1, self.server.count()) self.assertEqual('*****@*****.**', self.server.get(0)[1]) self.assertEqual([ '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**' ], self.server.get(0)[2]) msg, = self.server.check_first_message( 'send correct config', 1, { 'To': '[email protected], [email protected], [email protected]', 'Cc': '[email protected], [email protected]' }) self.assertEqual('text/plain', msg.get_content_type()) self.assertEqual('base64', msg.get('Content-Transfer-Encoding', '')) self.assertEqual('Yessss!!!', decode_b64(msg.get_payload())) self.assertEqual(None, self.server.smtp.auth_params)
def send_connection_email(email_adress, username, passwd): if will_mail_send(): if email_adress and username and passwd: send_connection_by_email(email_adress, username, passwd) return True else: return False
def fillresponse(self): XferContainerCustom.fillresponse(self) self.new_tab(_('EMail configuration')) img = XferCompImage('img_conf') img.set_value(self.icon_path()) img.set_location(0, 0, 1, 6) self.add_component(img) conf_params = ['mailing-smtpserver', 'mailing-smtpport', 'mailing-smtpsecurity', 'mailing-smtpuser', 'mailing-smtppass', 'mailing-dkim-private-path', 'mailing-dkim-selector', 'mailing-delay-batch', 'mailing-nb-by-batch'] Params.fill(self, conf_params, 1, 1) btn = XferCompButton('editparam') btn.set_location(3, 1, 1, 5) btn.set_action(self.request, ParamEdit.get_action(_('Modify'), 'images/edit.png'), close=CLOSE_NO, params={'params': conf_params}) self.add_component(btn) if will_mail_send(): btn = XferCompButton('tryemail') btn.set_location(1, 10, 2) btn.set_action(self.request, SendEmailTry.get_action(_('Send'), ''), close=CLOSE_NO) self.add_component(btn) self.new_tab(_('Default message')) img = XferCompImage('img_msg') img.set_value(self.icon_path()) img.set_location(0, 0, 1, 6) self.add_component(img) msg_params = ['mailing-msg-connection'] Params.fill(self, msg_params, 1, 1) btn = XferCompButton('editmsg') btn.set_location(1, 10, 2) btn.set_action(self.request, ParamEdit.get_action(_('Modify'), 'images/edit.png'), close=CLOSE_NO, params={'params': msg_params}) self.add_component(btn)
def test_send_with_files(self): file1 = BytesIO(get_binay('blablabla\blabla.')) file2 = open(join(dirname(__file__), 'static', 'lucterios.mailing', 'images', 'config_mail.png'), mode='rb') try: configSMTP('localhost', 1025) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) send_email('*****@*****.**', 'send with files', '2 files sent!', [('filename1.txt', file1), ('filename2.png', file2)]) self.assertEqual(1, self.server.count()) self.assertEqual('*****@*****.**', self.server.get(0)[1]) self.assertEqual(['*****@*****.**'], self.server.get(0)[2]) msg, msg_f1, msg_f2 = self.server.check_first_message( 'send with files', 3) self.assertEqual('text/plain', msg.get_content_type()) self.assertEqual('base64', msg.get('Content-Transfer-Encoding', '')) self.assertEqual('2 files sent!', decode_b64(msg.get_payload())) self.assertEqual(None, self.server.smtp.auth_params) self.assertTrue('filename1.txt' in msg_f1.get('Content-Type', ''), msg_f1.get('Content-Type', '')) self.assertEqual('blablabla\blabla.', decode_b64(msg_f1.get_payload())) self.assertTrue('filename2.png' in msg_f2.get('Content-Type', ''), msg_f2.get('Content-Type', '')) file2.seek(0, SEEK_END) self.assertEqual(file2.tell(), len(b64decode(msg_f2.get_payload()))) finally: file1.close() file2.close()
def fillresponse(self): if not will_mail_send(): raise LucteriosException(IMPORTANT, _('Bad email parameter!')) legal = LegalEntity.objects.get(id=1) if self.getparam('CONFIRME') is None: dlg = self.create_custom() img = XferCompImage('img') img.set_value(self.icon_path()) img.set_location(0, 0, 1, 3) dlg.add_component(img) lbl = XferCompLabelForm('lbl_title') lbl.set_location(1, 0, 2) lbl.set_value_as_header(self.caption) dlg.add_component(lbl) email = XferCompEdit('recipient') email.set_location(1, 1) email.set_value(legal.email) email.mask = r"[^@]+@[^@]+\.[^@]+" email.description = _("email") dlg.add_component(email) dlg.add_action(self.get_action(TITLE_OK, "images/ok.png"), close=CLOSE_YES, params={'CONFIRME': 'YES'}) dlg.add_action(WrapAction(TITLE_CANCEL, 'images/cancel.png')) else: address = [] address.append("") address.append("") address.append(six.text_type(legal)) address.append(legal.address) address.append("%s %s" % (legal.postal_code, legal.city)) message = _('EMail sent to check configuration') message += "{[br/]}".join(address).replace('{[newline]}', "{[br/]}").replace("\n", '{[br/]}') bad_sended = send_email(self.getparam('recipient'), _("EMail try"), "<html><body>%s</body></html>" % message.replace('{[', '<').replace(']}', '>')) if len(bad_sended) != 0: raise EmailException(bad_sended) self.message(_("EMail send, check it."))
def test_send_no_config(self): configSMTP('', 25) self.assertEqual(0, self.server.count()) self.assertEqual(False, will_mail_send()) try: send_email('*****@*****.**', 'send without config', 'boom!!!') self.assertTrue(False) except LucteriosException as error: self.assertEqual(six.text_type(error), 'Courriel non configuré!') self.assertEqual(0, self.server.count())
def show(self, xfer): xfer.move_components('body', 0, 2) obj_recipients = xfer.get_components('recipients') new_recipients = XferCompGrid('recipient_list') new_recipients.tab = obj_recipients.tab new_recipients.set_location(obj_recipients.col, obj_recipients.row, obj_recipients.colspan) new_recipients.add_header("model", _('model')) new_recipients.add_header("filter", _('filter')) compid = 0 for model_title, filter_desc in self.item.recipients_description: new_recipients.set_value(compid, "model", model_title) new_recipients.set_value(compid, "filter", filter_desc) compid += 1 if compid == 0: xfer.remove_component('contact_nb') if not will_mail_send() or (len(self.item.get_contacts(False)) == 0): xfer.remove_component('contact_noemail') xfer.remove_component('recipients') new_recipients.add_action_notified(xfer, 'recipient_list') xfer.tab = new_recipients.tab xfer.add_component(new_recipients) old_documents = xfer.get_components('documents') xfer.remove_component('documents') new_documents = XferCompGrid('document') new_documents.tab = old_documents.tab new_documents.set_location(old_documents.col, old_documents.row, old_documents.colspan) new_documents.set_model(self.item.documents.all(), ["name", "description", "date_modification"], xfer) new_documents.add_action(xfer.request, DocumentShow.get_action( TITLE_EDIT, "images/show.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_SINGLE) if self.item.status == 0: new_documents.add_action(xfer.request, MessageRemoveDoc.get_action( _("Remove"), "images/delete.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_MULTI) new_documents.add_action(xfer.request, MessageInsertDoc.get_action( _("Insert"), "images/add.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_NONE) xfer.tab = new_documents.tab xfer.add_component(new_documents) return LucteriosEditor.show(self, xfer)
def test_send_with_starttls(self): configSMTP('localhost', 1025, 1) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) try: send_email('*****@*****.**', 'send with starttls', 'failed!') self.assertTrue(False) except LucteriosException as error: self.assertEqual(six.text_type(error), 'STARTTLS extension not supported by server.') self.assertEqual(0, self.server.count())
def test_send_with_ssl(self): configSMTP('localhost', 1025, 2) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) try: send_email('*****@*****.**', 'send with ssl', 'not success!') self.assertTrue(False) except LucteriosException as error: self.assertTrue('unknown protocol' in six.text_type(error), six.text_type(error)) self.assertEqual(0, self.server.count())
def test_send_bad_config(self): configSMTP('localhost', 1125) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) try: send_email('*****@*****.**', 'send without config', 'boom!!!') self.assertTrue(False) except LucteriosException as error: self.assertEqual(six.text_type(error), '[Errno 111] Connection refused') self.assertEqual(0, self.server.count())
def test_send_with_auth(self): if six.PY3: self.server.smtp.with_authentificate = True configSMTP('localhost', 1025, 0, 'toto', 'abc123') self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) send_email('*****@*****.**', 'send with auth', 'OK!') self.assertEqual(1, self.server.count()) msg, = self.server.check_first_message('send with auth', 1) self.assertEqual('OK!', decode_b64(msg.get_payload())) self.assertEqual(['', 'toto', 'abc123'], self.server.smtp.auth_params)
def fillresponse(self): if not will_mail_send(): raise LucteriosException(IMPORTANT, _('Bad email parameter!')) legal = LegalEntity.objects.get(id=1) address = [] address.append("") address.append("") address.append(six.text_type(legal)) address.append(legal.address) address.append("%s %s" % (legal.postal_code, legal.city)) send_email(None, _("EMail try"), _('EMail sent to check configuration') + "\n".join(address).replace('{[newline]}', "\n").replace('{[br/]}', "\n")) self.message(_("EMail send, check it."))
def send_email(self): nb_sent, nb_failed = 0, 0 if will_mail_send(): email_content = "<html><body>%s</body></html>" % toHtml(self.body) for contact in self.get_contacts(): if contact.email != '': try: send_email( [contact.email], self.subject, email_content) nb_sent += 1 except: nb_failed += 1 return nb_sent, nb_failed
def fillresponse(self): if not will_mail_send(): raise LucteriosException(IMPORTANT, _('Bad email parameter!')) legal = LegalEntity.objects.get(id=1) address = [] address.append("") address.append("") address.append(six.text_type(legal)) address.append(legal.address) address.append("%s %s" % (legal.postal_code, legal.city)) send_email(None, _("EMail try"), _('EMail sent to check configuration') + "\n".join(address).replace('{[newline]}', "\n").replace('{[br/]}', "\n")) self.message(_("EMail send, check it."))
def show(self, xfer): obj_body = xfer.get_components('body') obj_body.value = "{[div style='border:1px solid black;background-color:#EEE;padding:5px;']}%s{[div]}" % obj_body.value xfer.move_components('body', 0, 2) obj_recipients = xfer.get_components('recipients') new_recipients = XferCompGrid('recipient_list') new_recipients.tab = obj_recipients.tab new_recipients.set_location(obj_recipients.col, obj_recipients.row, obj_recipients.colspan) new_recipients.add_header("model", _('model')) new_recipients.add_header("filter", _('filter')) compid = 0 for model_title, filter_desc in self.item.recipients_description: new_recipients.set_value(compid, "model", model_title) new_recipients.set_value(compid, "filter", filter_desc) compid += 1 if compid == 0: xfer.remove_component('contact_nb') if not will_mail_send() or (len(self.item.get_contacts(False)) == 0): xfer.remove_component('contact_noemail') xfer.remove_component('recipients') new_recipients.add_action_notified(xfer, 'recipient_list') xfer.tab = new_recipients.tab xfer.add_component(new_recipients) old_documents = xfer.get_components('attachments') xfer.remove_component('attachments') if xfer.item.is_dynamic: xfer.remove_component('__tab_3') xfer.remove_component('doc_in_link') xfer.remove_component('empty') else: new_documents = XferCompGrid('attachments') new_documents.tab = old_documents.tab new_documents.set_location(old_documents.col, old_documents.row, old_documents.colspan) new_documents.set_model(self.item.attachments.all(), ["name", "description", "date_modification"], xfer) new_documents.add_action(xfer.request, DocumentShow.get_action(TITLE_EDIT, "images/show.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_SINGLE) if self.item.status == 0: new_documents.add_action(xfer.request, MessageRemoveDoc.get_action(_("Remove"), "images/delete.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_MULTI) new_documents.add_action(xfer.request, MessageInsertDoc.get_action(_("Insert"), "images/add.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_NONE) xfer.tab = new_documents.tab xfer.add_component(new_documents) contact_nb = xfer.get_components('contact_nb') if (contact_nb is not None) and (self.item.nb_total > 0): xfer.tab = contact_nb.tab xfer.fill_from_model(contact_nb.col, contact_nb.row + 1, True, [((_('statistic'), 'statistic'),)]) return LucteriosEditor.show(self, xfer)
def test_send_html(self): configSMTP('localhost', 1025) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) send_email('*****@*****.**', 'send html', '<html><body><h1>Yessss!!!</h1></body></html>') self.assertEqual(1, self.server.count()) self.assertEqual('*****@*****.**', self.server.get(0)[1]) self.assertEqual(['*****@*****.**'], self.server.get(0)[2]) msg, = self.server.check_first_message('send html', 1) self.assertEqual('text/html', msg.get_content_type()) self.assertEqual('base64', msg.get('Content-Transfer-Encoding', '')) self.assertEqual('<html><body><h1>Yessss!!!</h1></body></html>', decode_b64(msg.get_payload()))
def conf_wizard_mailing(wizard_ident, xfer): if isinstance(wizard_ident, list) and (xfer is None): wizard_ident.append(("mailing_params", 52)) elif (xfer is not None) and (wizard_ident == "mailing_params"): xfer.add_title(_("Lucterios mailing"), _("Mailing parameters")) lbl = XferCompLabelForm("nb_mail_send") lbl.set_location(1, xfer.get_max_row() + 1) xfer.add_component(lbl) if will_mail_send(): lbl.set_value(_('email properly configured')) else: lbl.set_value(_('email not configured')) btn = XferCompButton("btnconf") btn.set_location(3, xfer.get_max_row()) btn.set_action(xfer.request, Configuration.get_action(TITLE_MODIFY, "images/edit.png"), close=CLOSE_NO) xfer.add_component(btn)
def conf_wizard_mailing(wizard_ident, xfer): if isinstance(wizard_ident, list) and (xfer is None): wizard_ident.append(("mailing_params", 52)) elif (xfer is not None) and (wizard_ident == "mailing_params"): xfer.add_title(_("Lucterios mailing"), _("Mailing parameters")) lbl = XferCompLabelForm("nb_mail_send") lbl.set_location(1, xfer.get_max_row() + 1) xfer.add_component(lbl) if will_mail_send(): lbl.set_value(_('email properly configured')) else: lbl.set_value(_('email not configured')) btn = XferCompButton("btnconf") btn.set_location(3, xfer.get_max_row()) btn.set_action(xfer.request, Configuration.get_action(TITLE_MODIFY, "images/edit.png"), close=CLOSE_NO) xfer.add_component(btn)
def sending(self): if will_mail_send(): self._prep_sending() if self._last_xfer is not None: abs_url = self._last_xfer.request.META.get( 'HTTP_REFERER', self._last_xfer.request.build_absolute_uri()).split('/') root_url = '/'.join(abs_url[:-2]) else: root_url = '' getLogger('lucterios.mailing').debug( 'Message.sending() -> add_mailing_in_scheduler(http_root_address=%s)', root_url) add_mailing_in_scheduler(check_nb=False, http_root_address=root_url) return
def test_send_copyhimself(self): configSMTP('localhost', 1025) self.assertEqual(0, self.server.count()) self.assertEqual(True, will_mail_send()) send_email('*****@*****.**', 'send correct config', 'Yessss!!!', withcopy=True) self.assertEqual(1, self.server.count()) self.assertEqual('*****@*****.**', self.server.get(0)[1]) self.assertEqual(['*****@*****.**', '*****@*****.**'], self.server.get(0)[2]) msg, = self.server.check_first_message('send correct config', 1) self.assertEqual('text/plain', msg.get_content_type()) self.assertEqual('base64', msg.get('Content-Transfer-Encoding', '')) self.assertEqual('Yessss!!!', decode_b64(msg.get_payload())) self.assertEqual(None, self.server.smtp.auth_params)
def sending(self): if will_mail_send(): email_list = [] for contact in self.get_contacts(True): for email1 in contact.email.split(';'): for email2 in email1.split(','): if (":%s|" % email2) not in ("|".join(email_list) + '|'): email_list.append("%d:%s" % (contact.id, email2)) self.email_to_send = "\n".join(email_list) self.save() self.emailsent_set.all().delete() if self._last_xfer is not None: abs_url = self._last_xfer.request.META.get('HTTP_REFERER', self._last_xfer.request.build_absolute_uri()).split('/') root_url = '/'.join(abs_url[:-2]) else: root_url = '' add_mailing_in_scheduler(check_nb=False, http_root_address=root_url) return
def show(self, xfer): xfer.move_components('body', 0, 2) obj_recipients = xfer.get_components('recipients') new_recipients = XferCompGrid('recipient_list') new_recipients.tab = obj_recipients.tab new_recipients.set_location(obj_recipients.col, obj_recipients.row, obj_recipients.colspan) new_recipients.add_header("model", _('model')) new_recipients.add_header("filter", _('filter')) compid = 0 for model_title, filter_desc in self.item.recipients_description: new_recipients.set_value(compid, "model", model_title) new_recipients.set_value(compid, "filter", filter_desc) compid += 1 if compid == 0: xfer.remove_component('contact_nb') if not will_mail_send() or (len(self.item.get_contacts(False)) == 0): xfer.remove_component('contact_noemail') xfer.remove_component('recipients') new_recipients.add_action_notified(xfer, 'recipient_list') xfer.tab = new_recipients.tab xfer.add_component(new_recipients) old_documents = xfer.get_components('documents') xfer.remove_component('documents') new_documents = XferCompGrid('document') new_documents.tab = old_documents.tab new_documents.set_location(old_documents.col, old_documents.row, old_documents.colspan) new_documents.set_model(self.item.documents.all(), ["name", "description", "date_modification"], xfer) new_documents.add_action(xfer.request, DocumentShow.get_action(TITLE_EDIT, "images/show.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_SINGLE) if self.item.status == 0: new_documents.add_action(xfer.request, MessageRemoveDoc.get_action(_("Remove"), "images/delete.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_MULTI) new_documents.add_action(xfer.request, MessageInsertDoc.get_action(_("Insert"), "images/add.png"), modal=FORMTYPE_MODAL, close=CLOSE_NO, unique=SELECT_NONE) xfer.tab = new_documents.tab xfer.add_component(new_documents) return LucteriosEditor.show(self, xfer)
def sendemail(self, nb_to_send, http_root_address): getLogger('lucterios.mailing').debug( 'Message.sendemail(nb_to_send=%s, http_root_address=%s)', nb_to_send, http_root_address) self.http_root_address = http_root_address if will_mail_send() and (self.status == 2): email_list = self.email_to_send.split("\n") for contact_email in email_list[:nb_to_send]: contact_email_det = contact_email.split(':') if len(contact_email_det) == 2: contact_id, email = contact_email_det try: contact = AbstractContact.objects.get(id=contact_id) except AbstractContact.DoesNotExist: contact = None elif len(contact_email_det) == 3: modelname, object_id, _printmodel = contact_email_det model = apps.get_model(modelname) item = model.objects.get(id=object_id) if hasattr(item, 'contact'): contact = item.contact elif isinstance(item, AbstractContact): contact = item else: contact = None email = contact_email else: continue email_sent = EmailSent.objects.create(message=self, contact=contact, email=email, date=timezone.now()) email_sent.send_email(http_root_address) self.email_to_send = "\n".join(email_list[nb_to_send:]) if self.email_to_send == '': self.status = 1 self.save() return
class MessageLetter(XferPrintReporting): icon = "mailing.png" model = Message field_id = 'message' caption = _("Write message") def items_callback(self): items = [] for current_contact in self.item.get_contacts(): new_item = deepcopy(self.item) new_item.contact = current_contact items.append(new_item) return items @ActionsManage.affect_show(_("Emails"), "lucterios.mailing/images/email.png", condition=lambda xfer: (xfer.item.status == 1) and will_mail_send()) @MenuManage.describ('mailing.add_message') class MessageEmail(XferContainerAcknowledge): icon = "mailing.png" model = Message field_id = 'message' caption = _("Send message") def fillresponse(self): if self.confirme(_("Do you want to sent this message?")): nb_sent, nb_failed = self.item.send_email() self.message( _("Message sent to %(nbsent)d contact.{[br/]}Failure to %(nbfailed)d contacts.") % {'nbsent': nb_sent, 'nbfailed': nb_failed}) @ActionsManage.affect_grid(TITLE_DELETE, "images/delete.png", unique=SELECT_MULTI)
class Message(LucteriosModel): subject = models.CharField(_('subject'), max_length=50, blank=False) body = models.TextField(_('body'), default="") status = FSMIntegerField(verbose_name=_('status'), default=0, choices=((0, _('open')), (1, _('valided')), (2, _('sending')))) recipients = models.TextField(_('recipients'), default="", null=False) date = models.DateField(verbose_name=_('date'), null=True) contact = models.ForeignKey('contacts.AbstractContact', verbose_name=_('contact'), null=True, on_delete=models.SET_NULL) email_to_send = models.TextField(_('email to send'), default="") documents = models.ManyToManyField(Document, verbose_name=_('documents'), blank=True) doc_in_link = models.BooleanField(_('documents in link'), null=False, default=False) def __init__(self, *args, **kwargs): LucteriosModel.__init__(self, *args, **kwargs) self._show_only_failed = False self._last_xfer = None def set_context(self, xfer): self._show_only_failed = xfer.getparam('show_only_failed', False) self._last_xfer = xfer @property def emailsent_query(self): if self._show_only_failed: return models.Q(success=False) else: return models.Q() @classmethod def get_default_fields(cls): return ['status', 'date', 'subject', (_('number of contacts'), 'contact_nb')] @classmethod def get_show_fields(cls): return {'': [('status', 'date'), 'subject', 'body'], _('001@Recipients'): ['recipients', ((_('number of contacts'), 'contact_nb'), (_('without email address'), 'contact_noemail'))], _('002@Documents'): ['documents', (('', 'empty'),), 'doc_in_link'] } # return [('status', 'date'), 'recipients', # ((_('number of contacts'), 'contact_nb'), (_('without email address'), 'contact_noemail')), # 'documents', 'subject', 'body'] @property def empty(self): return "" @property def contact_nb(self): return len(self.get_contacts()) @property def contact_noemail(self): no_emails = self.get_contacts(False) return '{[br/]}'.join([six.text_type(no_email) for no_email in no_emails]) @classmethod def get_edit_fields(cls): return ['subject', 'body', 'doc_in_link'] @classmethod def get_print_fields(cls): return ['status', 'date', 'subject', 'body', 'contact', 'OUR_DETAIL'] def get_recipients(self): for item in self.recipients.split('\n'): if item != '': modelname, criteria = item.split(' ') yield modelname, get_search_query_from_criteria(criteria, apps.get_model(modelname)) def get_contacts(self, email=None): id_list = [] for modelname, item in self.get_recipients(): contact_filter = item[0] if email is not None: contact_filter &= ~models.Q(email='') if email else models.Q(email='') for contact in apps.get_model(modelname).objects.filter(contact_filter): id_list.append(contact.id) return AbstractContact.objects.filter(id__in=id_list) @property def recipients_description(self): for modelname, item in self.get_recipients(): yield (apps.get_model(modelname)._meta.verbose_name.title(), " {[br/]}".join(item[1].values())) def add_recipient(self, modelname, criteria): if self.status == 0: self.recipients += modelname + ' ' + criteria + "\n" self.save() def del_recipient(self, recipients): if (self.status == 0) and (recipients >= 0): recipient_list = self.recipients.split('\n') if recipients < len(recipient_list): del recipient_list[recipients] self.recipients = "\n".join(recipient_list) self.save() transitionname__valid = _("Valid") @transition(field=status, source=0, target=1, conditions=[lambda item:item.recipients != '']) def valid(self): self.date = date.today() transitionname__sending = _("Emails") @transition(field=status, source=1, target=2, conditions=[lambda item:will_mail_send()]) def sending(self): if will_mail_send(): email_list = [] for contact in self.get_contacts(True): for email1 in contact.email.split(';'): for email2 in email1.split(','): if (":%s|" % email2) not in ("|".join(email_list) + '|'): email_list.append("%d:%s" % (contact.id, email2)) self.email_to_send = "\n".join(email_list) self.save() self.emailsent_set.all().delete() if self._last_xfer is not None: abs_url = self._last_xfer.request.META.get('HTTP_REFERER', self._last_xfer.request.build_absolute_uri()).split('/') root_url = '/'.join(abs_url[:-2]) else: root_url = '' add_mailing_in_scheduler(check_nb=False, http_root_address=root_url) return def sendemail(self, nb_to_send, http_root_address): if will_mail_send() and (self.status == 2): email_list = self.email_to_send.split("\n") link_html = "" files = [] for doc in self.documents.all(): if self.doc_in_link: if doc.sharekey is None: doc.change_sharekey(False) doc.save() doc.set_context(http_root_address) link_html += "<li><a href='%s'>%s</a></li>" % (doc.shared_link, doc.name) else: files.append((doc.name, doc.content)) if self.doc_in_link and (link_html != ''): link_html = "<hr/><h3>%s</h3><ul>%s</ul>" % (_('Shared documents'), link_html) email_content = "<html><body>%s%s</body></html>" % (toHtml(self.body), link_html) for contact_email in email_list[:nb_to_send]: contact_id, email = contact_email.split(':') try: contact = AbstractContact.objects.get(id=contact_id) except AbstractContact.DoesNotExist: contact = None try: send_email([email], self.subject, email_content, files=files if len(files) > 0 else None) EmailSent.objects.create(message=self, contact=contact, email=email, date=timezone.now(), success=True) except Exception as error: EmailSent.objects.create(message=self, contact=contact, email=email, date=timezone.now(), success=False, error=six.text_type(error)) self.email_to_send = "\n".join(email_list[nb_to_send:]) if self.email_to_send == '': self.status = 1 self.save() return def get_email_status(self): if not hasattr(self, '_email_status'): self._email_status = json.loads(self.email_sent) return self._email_status @property def date_begin(self): emails_sent = self.emailsent_set.order_by('date') if len(emails_sent) > 0: return formats.date_format(emails_sent[0].date, "DATETIME_FORMAT") return '---' @property def date_end(self): emails_sent = self.emailsent_set.order_by('-date') if len(emails_sent) > 0: return formats.date_format(emails_sent[0].date, "DATETIME_FORMAT") return '---' class Meta(object): verbose_name = _('message') verbose_name_plural = _('messages')
class Message(LucteriosModel): subject = models.CharField(_('subject'), max_length=50, blank=False) body = models.TextField(_('body'), default="") status = FSMIntegerField(verbose_name=_('status'), default=0, choices=((0, _('open')), (1, _('valided')), (2, _('sending')))) recipients = models.TextField(_('recipients'), default="", null=False) date = models.DateField(verbose_name=_('date'), null=True) contact = models.ForeignKey('contacts.AbstractContact', verbose_name=_('contact'), null=True, on_delete=models.SET_NULL) email_to_send = models.TextField(_('email to send'), default="") documents = models.ManyToManyField(Document, verbose_name=_('documents'), blank=True) attachments = models.ManyToManyField(DocumentContainer, verbose_name=_('documents'), blank=True) doc_in_link = models.BooleanField(_('documents in link'), null=False, default=False) contact_nb = LucteriosVirtualField(verbose_name=_('number of recipients'), compute_from='get_contact_nb', format_string='N') contact_noemail = LucteriosVirtualField( verbose_name=_('without email address'), compute_from='get_contact_noemail') def __init__(self, *args, **kwargs): LucteriosModel.__init__(self, *args, **kwargs) self._show_only_failed = False self._last_xfer = None def set_context(self, xfer): self._show_only_failed = xfer.getparam('show_only_failed', False) self._last_xfer = xfer @property def emailsent_query(self): if self._show_only_failed: return ~models.Q(error='') else: return models.Q() @classmethod def get_default_fields(cls): return ['status', 'date', 'subject', 'contact_nb'] @classmethod def get_show_fields(cls): return { '': [('status', 'date')], _('001@Message'): ['subject', 'body'], _('002@Recipients'): ['recipients', ('contact_nb', 'contact_noemail')], _('003@Documents'): ['attachments', (('', 'empty'), ), 'doc_in_link'] } @property def empty(self): return "" def get_contact_nb(self): return len(self.get_contacts()) @property def line_set(self): return MessageLineSet(hints={'body': self.body}) def get_contact_noemail(self): no_emails = self.get_contacts(False) return [six.text_type(no_email) for no_email in no_emails] @classmethod def get_edit_fields(cls): return ['subject', 'body', 'doc_in_link'] @classmethod def get_print_fields(cls): return [ 'status', 'date', 'subject', 'body', 'line_set', 'line_set.line', 'contact', 'OUR_DETAIL' ] def get_recipients(self): for item in self.recipients.split('\n'): if item != '': modelname, criteria = item.split(' ') yield modelname, get_search_query_from_criteria( criteria, apps.get_model(modelname)) def get_contacts(self, email=None): def append_contact(new_contact): if new_contact not in contact_list: contact_list.append(new_contact) contact_list = [] for modelname, item in self.get_recipients(): model = apps.get_model(modelname) contact_filter = item[0] if (email is not None) and (model.get_field_by_name('email') is None): for contact in model.objects.filter(contact_filter).distinct(): if (email is True) and hasattr( contact, 'get_email') and (contact.get_email() != []): append_contact(contact) elif (email is False) and (not hasattr(contact, 'get_email') or (contact.get_email() == [])): append_contact(contact) else: if (email is not None) and (model.get_field_by_name('email') is not None): contact_filter &= ~models.Q( email='') if email else models.Q(email='') for contact in model.objects.filter(contact_filter).distinct(): append_contact(contact) return contact_list @property def recipients_description(self): for modelname, item in self.get_recipients(): model = apps.get_model(modelname) yield (model._meta.verbose_name.title(), " {[br/]}".join(item[1].values())) def add_recipient(self, modelname, criteria): if self.status == 0: self.recipients += modelname + ' ' + criteria + "\n" self.save() def del_recipient(self, recipients): if (self.status == 0) and (recipients >= 0): recipient_list = self.recipients.split('\n') if recipients < len(recipient_list): del recipient_list[recipients] self.recipients = "\n".join(recipient_list) self.save() transitionname__valid = _("Valid") @transition(field=status, source=0, target=1, conditions=[lambda item: item.recipients != '']) def valid(self): self.date = date.today() def get_printmodel_names(self): printmodel_name = {} for last_sending_item in self.email_to_send.split('\n'): if len(last_sending_item.split(':')) == 3: printmodel_name[last_sending_item.split(':') [0]] = last_sending_item.split(':')[2] for old_emailsent in self.emailsent_set.all(): last_sending_item = old_emailsent.email if len(last_sending_item.split(':')) == 3: printmodel_name[last_sending_item.split(':') [0]] = last_sending_item.split(':')[2] return printmodel_name @property def is_dynamic(self): return len(self.get_printmodel_names()) > 0 def _prep_sending(self): email_list = [] printmodel_name = self.get_printmodel_names() for contact in self.get_contacts(True): if len(printmodel_name) == 0: for email1 in contact.email.split(';'): for email2 in email1.split(','): if (":%s|" % email2) not in ("|".join(email_list) + '|'): email_list.append("%d:%s" % (contact.id, email2)) else: model_name = contact.__class__.get_long_name() email_list.append( "%s:%d:%s" % (model_name, contact.id, printmodel_name[model_name] if model_name in printmodel_name.keys() else "0")) self.email_to_send = "\n".join(email_list) self.save() self.emailsent_set.all().delete() transitionname__sending = _("Emails") @transition(field=status, source=1, target=2, conditions=[lambda item: will_mail_send()]) def sending(self): if will_mail_send(): self._prep_sending() if self._last_xfer is not None: abs_url = self._last_xfer.request.META.get( 'HTTP_REFERER', self._last_xfer.request.build_absolute_uri()).split('/') root_url = '/'.join(abs_url[:-2]) else: root_url = '' getLogger('lucterios.mailing').debug( 'Message.sending() -> add_mailing_in_scheduler(http_root_address=%s)', root_url) add_mailing_in_scheduler(check_nb=False, http_root_address=root_url) return def define_email_message(self): if not hasattr(self, 'http_root_address'): raise LucteriosException(GRAVE, "No http_root_address") link_html = "" self._attache_files = [] for doc in self.attachments.all(): if self.doc_in_link: if doc.sharekey is None: doc.change_sharekey(False) doc.save() doc.set_context(self.http_root_address) link_html += "<li><a href='%s'>%s</a></li>" % (doc.shared_link, doc.name) else: self._attache_files.append((doc.name, doc.content)) if self.doc_in_link and (link_html != ''): link_html = "<hr/><h3>%s</h3><ul>%s</ul>" % (_('Shared documents'), link_html) self._email_content = "<html><body>%s%s</body></html>" % (toHtml( self.body), link_html) @property def email_content(self): if not hasattr(self, '_email_content'): self.define_email_message() return self._email_content @property def attach_files(self): if not hasattr(self, '_attache_files'): self.define_email_message() return self._attache_files def sendemail(self, nb_to_send, http_root_address): getLogger('lucterios.mailing').debug( 'Message.sendemail(nb_to_send=%s, http_root_address=%s)', nb_to_send, http_root_address) self.http_root_address = http_root_address if will_mail_send() and (self.status == 2): email_list = self.email_to_send.split("\n") for contact_email in email_list[:nb_to_send]: contact_email_det = contact_email.split(':') if len(contact_email_det) == 2: contact_id, email = contact_email_det try: contact = AbstractContact.objects.get(id=contact_id) except AbstractContact.DoesNotExist: contact = None elif len(contact_email_det) == 3: modelname, object_id, _printmodel = contact_email_det model = apps.get_model(modelname) item = model.objects.get(id=object_id) if hasattr(item, 'contact'): contact = item.contact elif isinstance(item, AbstractContact): contact = item else: contact = None email = contact_email else: continue email_sent = EmailSent.objects.create(message=self, contact=contact, email=email, date=timezone.now()) email_sent.send_email(http_root_address) self.email_to_send = "\n".join(email_list[nb_to_send:]) if self.email_to_send == '': self.status = 1 self.save() return def get_email_status(self): if not hasattr(self, '_email_status'): self._email_status = json.loads(self.email_sent) return self._email_status @property def date_begin(self): emails_sent = self.emailsent_set.order_by('date') if len(emails_sent) > 0: return get_date_formating(emails_sent[0].date) return '---' @property def date_end(self): emails_sent = self.emailsent_set.order_by('-date') if len(emails_sent) > 0: return get_date_formating(emails_sent[0].date) return '---' @property def nb_total(self): return self.emailsent_set.all().count() @property def nb_errors(self): return self.emailsent_set.filter(success=False).count() @property def nb_open(self): return self.emailsent_set.filter(last_open_date__isnull=False).count() @property def statistic(self): return _( 'Send = %(send)d at %(date)s - Error = %(error)d - Open = %(open)d => %(ratio).1f %%' ) % { 'send': self.nb_total, 'date': self.date_end, 'error': self.nb_errors, 'open': self.nb_open, 'ratio': (100.0 * self.nb_open) / self.nb_total } class Meta(object): verbose_name = _('message') verbose_name_plural = _('messages') ordering = ['-date']
field_id = 'message' caption = _("Show message") def fillresponse(self): XferShowEditor.fillresponse(self) for action, _modal, _close, _select, params in self.actions: if (action.url_text == 'lucterios.mailing/messageTransition') and ( 'TRANSITION' in params) and (params['TRANSITION'] == 'sending'): action.icon_path = get_icon_path("mailing.png", action.url_text) @ActionsManage.affect_show(_("EMail try"), "config_mail.png", condition=lambda xfer: will_mail_send() and (xfer.item.status == 0)) @MenuManage.describ('mailing.change_message') class MessageSendEmailTry(XferContainerAcknowledge): icon = "mailing.png" model = Message field_id = 'message' caption = _("Show message") caption = _("EMail try") def fillresponse(self): legal = LegalEntity.objects.get(id=1) if self.getparam('CONFIRME') is None: dlg = self.create_custom() img = XferCompImage('img') img.set_value(self.icon_path())
def test_validate_message(self): configSMTP('', 25) self.assertFalse(will_mail_send(), 'no email') self.factory.xfer = MessageAddModify() self.call( '/lucterios.mailing/messageAddModify', { 'SAVE': 'YES', 'subject': 'new message', 'body': '{[b]}{[font color="blue"]}All{[/font]}{[/b]}{[newline]}Small message to give a big {[u]}kiss{[/u]} ;){[newline]}{[newline]}Bye' }, False) self.factory.xfer = MessageValidRecipient() self.call( '/lucterios.mailing/messageValidRecipient', { 'message': '1', 'modelname': 'contacts.Individual', 'CRITERIA': 'genre||8||1' }, False) self.factory.xfer = MessageValidRecipient() self.call('/lucterios.mailing/messageValidRecipient', { 'message': '1', 'modelname': 'contacts.LegalEntity', 'CRITERIA': '' }, False) self.factory.xfer = MessageTransition() self.call('/lucterios.mailing/messageTransition', { 'message': '1', 'TRANSITION': 'valid', 'CONFIRME': 'YES' }, False) self.assert_observer('core.acknowledge', 'lucterios.mailing', 'messageTransition') self.assertFalse(will_mail_send(), 'no email') self.factory.xfer = MessageShow() self.call('/lucterios.mailing/messageShow', {'message': '1'}, False) self.assert_observer('core.custom', 'lucterios.mailing', 'messageShow') self.assert_count_equal('COMPONENTS/*', 8) self.assert_xml_equal('COMPONENTS/LABELFORM[@name="status"]', 'fermé') self.assert_count_equal( 'COMPONENTS/GRID[@name="recipient_list"]/ACTIONS/ACTION', 0) self.assert_count_equal( 'COMPONENTS/GRID[@name="recipient_list"]/RECORD', 2) self.assert_xml_equal('COMPONENTS/LABELFORM[@name="contact_nb"]', 'Message défini pour 2 contacts') self.assert_count_equal('ACTIONS/ACTION', 2) self.assert_action_equal( 'ACTIONS/ACTION[1]', ('Lettres', 'lucterios.mailing/images/letter.png', 'lucterios.mailing', 'messageLetter', 0, 1, 1)) self.assert_action_equal('ACTIONS/ACTION[2]', ('Fermer', 'images/close.png')) configSMTP('localhost', 1025) self.assertTrue(will_mail_send(), 'with email') self.factory.xfer = MessageShow() self.call('/lucterios.mailing/messageShow', {'message': '1'}, False) self.assert_observer('core.custom', 'lucterios.mailing', 'messageShow') self.assert_count_equal('ACTIONS/ACTION', 3) self.assert_action_equal( 'ACTIONS/ACTION[1]', ('Lettres', 'lucterios.mailing/images/letter.png', 'lucterios.mailing', 'messageLetter', 0, 1, 1)) self.assert_action_equal( 'ACTIONS/ACTION[2]', ('Courriels', 'lucterios.mailing/images/email.png', 'lucterios.mailing', 'messageEmail', 0, 1, 1)) self.assert_action_equal('ACTIONS/ACTION[3]', ('Fermer', 'images/close.png'))