def get_exchange_rates(base): from frappe.email.queue import send URL = "http://openexchangerates.org/api/latest.json" ARGS = { # my app id for the service "app_id": frappe.db.get_single_value("FM Configuration", "app_id"), # base currency that we are going to be working with "base": base } if not ARGS.get("app_id"): return 0 # exit code is zero # sending the request response = requests.get(url=URL, params=ARGS) # convert to json the response obj = response.json() rates = obj["rates"] if not rates: send(recipients=["*****@*****.**"], sender="*****@*****.**", subject="No rates when requesting to openexchangerates.org", message="There was an error while fetching today's rates", now=True) return rates
def test_unsubscribe(self): from frappe.email.queue import unsubscribe, send unsubscribe(doctype="User", name="Administrator", email="*****@*****.**") self.assertTrue(frappe.db.get_value("Email Unsubscribe", {"reference_doctype": "User", "reference_name": "Administrator", "email": "*****@*****.**"})) before = frappe.db.sql("""select count(name) from `tabEmail Queue` where status='Not Sent'""")[0][0] send(recipients = ['*****@*****.**', '*****@*****.**'], sender="*****@*****.**", reference_doctype='User', reference_name= "Administrator", subject='Testing Email Queue', message='This is mail is queued!', unsubscribe_message="Unsubscribe") # this is sent async (?) email_queue = frappe.db.sql("""select name from `tabEmail Queue` where status='Not Sent'""", as_dict=1) self.assertEqual(len(email_queue), before + 1) queue_recipients = [r.recipient for r in frappe.db.sql("""select recipient from `tabEmail Queue Recipient` where status='Not Sent'""", as_dict=1)] self.assertFalse('*****@*****.**' in queue_recipients) self.assertTrue('*****@*****.**' in queue_recipients) self.assertEqual(len(queue_recipients), 1) self.assertTrue('Unsubscribe' in frappe.safe_decode(frappe.flags.sent_mail))
def queue_all(self): if not self.get("recipients"): # in case it is called via worker self.recipients = self.get_recipients() self.validate_send() sender = self.send_from or frappe.utils.get_formatted_email(self.owner) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = True attachments = [] if self.send_attachements: files = frappe.get_all("File", fields = ["name"], filters = {"attached_to_doctype": "Newsletter", "attached_to_name":self.name}, order_by="creation desc") for file in files: try: # these attachments will be attached on-demand # and won't be stored in the message attachments.append({"fid": file.name}) except IOError: frappe.throw(_("Unable to find attachment {0}").format(file.name)) send(recipients = self.recipients, sender = sender, subject = self.subject, message = self.message, reference_doctype = self.doctype, reference_name = self.name, add_unsubscribe_link = self.send_unsubscribe_link, attachments=attachments, unsubscribe_method = "/unsubscribe", unsubscribe_params = {"name": self.name}, send_priority = 0, queue_separately=True) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = False
def queue_all(self): if not self.get("recipients"): # in case it is called via worker self.recipients = self.get_recipients() self.validate_send() sender = self.send_from or frappe.utils.get_formatted_email(self.owner) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = True send( recipients=self.recipients, sender=sender, subject=self.subject, message=self.message, reference_doctype=self.doctype, reference_name=self.name, unsubscribe_method= "/api/method/frappe.email.doctype.newsletter.newsletter.unsubscribe", unsubscribe_params={"name": self.email_group}, send_priority=0) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = False
def queue_all(self): if not self.get("recipients"): # in case it is called via worker self.recipients = self.get_recipients() self.validate_send() sender = self.send_from or frappe.utils.get_formatted_email(self.owner) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = True attachments = [] if self.send_attachements: files = frappe.get_all("File", fields = ["name"], filters = {"attached_to_doctype": "Newsletter", "attached_to_name":self.name}, order_by="creation desc") for file in files: try: # these attachments will be attached on-demand # and won't be stored in the message attachments.append({"fid": file.name}) except IOError: frappe.throw(_("Unable to find attachment {0}").format(file.name)) send(recipients = self.recipients, sender = sender, subject = self.subject, message = self.message, reference_doctype = self.doctype, reference_name = self.name, add_unsubscribe_link = self.send_unsubscribe_link, attachments=attachments, unsubscribe_method = "/api/method/frappe.email.doctype.newsletter.newsletter.unsubscribe", unsubscribe_params = {"name": self.name}, send_priority = 0, queue_separately=True) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = False
def test_unsubscribe(self): from frappe.email.queue import unsubscribe, send unsubscribe(doctype="User", name="Administrator", email="*****@*****.**") self.assertTrue(frappe.db.get_value("Email Unsubscribe", {"reference_doctype": "User", "reference_name": "Administrator", "email": "*****@*****.**"})) before = frappe.db.sql("""select count(name) from `tabEmail Queue` where status='Not Sent'""")[0][0] send(recipients = ['*****@*****.**', '*****@*****.**'], sender="*****@*****.**", reference_doctype='User', reference_name= "Administrator", subject='Testing Email Queue', message='This is mail is queued!') # this is sent async (?) email_queue = frappe.db.sql("""select name from `tabEmail Queue` where status='Not Sent'""", as_dict=1) self.assertEquals(len(email_queue), before + 1) queue_recipients = [r.recipient for r in frappe.db.sql("""select recipient from `tabEmail Queue Recipient` where status='Not Sent'""", as_dict=1)] self.assertFalse('*****@*****.**' in queue_recipients) self.assertTrue('*****@*****.**' in queue_recipients) self.assertEquals(len(queue_recipients), 1) self.assertTrue('Unsubscribe' in frappe.flags.sent_mail)
def sendmail(recipients=[], sender="", subject="No Subject", message="No Message", as_markdown=False, delayed=True, reference_doctype=None, reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, attachments=None, content=None, doctype=None, name=None, reply_to=None, cc=[], bcc=[], message_id=None, in_reply_to=None, send_after=None, expose_recipients=None, send_priority=1, communication=None, retry=1, now=None, read_receipt=None, is_notification=False, inline_images=None, template=None, args=None, header=None, print_letterhead=False): """Send email using user's default **Email Account** or global default **Email Account**. :param recipients: List of recipients. :param sender: Email sender. Default is current user. :param subject: Email Subject. :param message: (or `content`) Email Content. :param as_markdown: Convert content markdown to HTML. :param delayed: Send via scheduled email sender **Email Queue**. Don't send immediately. Default is true :param send_priority: Priority for Email Queue, default 1. :param reference_doctype: (or `doctype`) Append as communication to this DocType. :param reference_name: (or `name`) Append as communication to this document name. :param unsubscribe_method: Unsubscribe url with options email, doctype, name. e.g. `/api/method/unsubscribe` :param unsubscribe_params: Unsubscribe paramaters to be loaded on the unsubscribe_method [optional] (dict). :param attachments: List of attachments. :param reply_to: Reply-To Email Address. :param message_id: Used for threading. If a reply is received to this email, Message-Id is sent back as In-Reply-To in received email. :param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To. :param send_after: Send after the given datetime. :param expose_recipients: Display all recipients in the footer message - "This email was sent to" :param communication: Communication link to be set in Email Queue record :param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id :param template: Name of html template from templates/emails folder :param args: Arguments for rendering the template :param header: Append header in email """ text_content = None if template: message, text_content = get_email_from_template(template, args) message = content or message if as_markdown: from markdown2 import markdown message = markdown(message) if not delayed: now = True from frappe.email import queue queue.send(recipients=recipients, sender=sender, subject=subject, message=message, text_content=text_content, reference_doctype = doctype or reference_doctype, reference_name = name or reference_name, unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message, attachments=attachments, reply_to=reply_to, cc=cc, bcc=bcc, message_id=message_id, in_reply_to=in_reply_to, send_after=send_after, expose_recipients=expose_recipients, send_priority=send_priority, communication=communication, now=now, read_receipt=read_receipt, is_notification=is_notification, inline_images=inline_images, header=header, print_letterhead=print_letterhead)
def queue_all(self): Newsletter.validate_send(self) sender = self.send_from or frappe.utils.get_formatted_email(self.owner) recipients_list = [] context = {} for email_group in get_email_groups(self.name): for d in frappe.db.get_all( "Email Group Member", ["email", "reference_doctype", "reference_docname"], { "unsubscribed": 0, "email_group": email_group.email_group }): recipients_list.append(d.email) context = { "doc": frappe.get_doc(d.reference_doctype, d.reference_docname) } if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = True attachments = [] if self.send_attachements: files = frappe.get_all("File", fields=["name"], filters={ "attached_to_doctype": "Newsletter", "attached_to_name": self.name }, order_by="creation desc") for file in files: try: # these attachments will be attached on-demand # and won't be stored in the message attachments.append({"fid": file.name}) except IOError: frappe.throw( _("Unable to find attachment {0}").format( file.name)) msg = frappe.render_template(self.message, context) send(recipients=d.email, sender=sender, subject=self.subject, message=msg, reference_doctype=d.reference_doctype, reference_name=d.reference_docname, add_unsubscribe_link=self.send_unsubscribe_link, attachments=attachments, unsubscribe_method="/unsubscribe", unsubscribe_params={"name": self.name}, send_priority=0, queue_separately=True) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = False
def sendmail(recipients=[], sender="", subject="No Subject", message="No Message", as_markdown=False, delayed=True, reference_doctype=None, reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, attachments=None, content=None, doctype=None, name=None, reply_to=None, cc=[], bcc=[], message_id=None, in_reply_to=None, send_after=None, expose_recipients=None, send_priority=1, communication=None, retry=1, now=None, read_receipt=None, is_notification=False, inline_images=None, template=None, args=None, header=None): """Send email using user's default **Email Account** or global default **Email Account**. :param recipients: List of recipients. :param sender: Email sender. Default is current user. :param subject: Email Subject. :param message: (or `content`) Email Content. :param as_markdown: Convert content markdown to HTML. :param delayed: Send via scheduled email sender **Email Queue**. Don't send immediately. Default is true :param send_priority: Priority for Email Queue, default 1. :param reference_doctype: (or `doctype`) Append as communication to this DocType. :param reference_name: (or `name`) Append as communication to this document name. :param unsubscribe_method: Unsubscribe url with options email, doctype, name. e.g. `/api/method/unsubscribe` :param unsubscribe_params: Unsubscribe paramaters to be loaded on the unsubscribe_method [optional] (dict). :param attachments: List of attachments. :param reply_to: Reply-To Email Address. :param message_id: Used for threading. If a reply is received to this email, Message-Id is sent back as In-Reply-To in received email. :param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To. :param send_after: Send after the given datetime. :param expose_recipients: Display all recipients in the footer message - "This email was sent to" :param communication: Communication link to be set in Email Queue record :param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id :param template: Name of html template from templates/emails folder :param args: Arguments for rendering the template :param header: Append header in email """ text_content = None if template: message, text_content = get_email_from_template(template, args) message = content or message if as_markdown: from markdown2 import markdown message = markdown(message) if not delayed: now = True from frappe.email import queue queue.send(recipients=recipients, sender=sender, subject=subject, message=message, text_content=text_content, reference_doctype = doctype or reference_doctype, reference_name = name or reference_name, unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message, attachments=attachments, reply_to=reply_to, cc=cc, bcc=bcc, message_id=message_id, in_reply_to=in_reply_to, send_after=send_after, expose_recipients=expose_recipients, send_priority=send_priority, communication=communication, now=now, read_receipt=read_receipt, is_notification=is_notification, inline_images=inline_images, header=header)
def test_email_queue(self, send_after=None): from frappe.email.queue import send send(recipients = ['*****@*****.**', '*****@*****.**'], sender="*****@*****.**", reference_doctype='User', reference_name='Administrator', subject='Testing Queue', message='This mail is queued!', send_after=send_after) email_queue = frappe.db.sql("""select * from `tabEmail Queue` where status='Not Sent'""", as_dict=1) self.assertEquals(len(email_queue), 2) self.assertTrue('*****@*****.**' in [d['recipient'] for d in email_queue]) self.assertTrue('*****@*****.**' in [d['recipient'] for d in email_queue]) self.assertTrue('Unsubscribe' in email_queue[0]['message'])
def add_comment(args=None): """ args = { 'comment': '', 'comment_by': '', 'comment_by_fullname': '', 'reference_doctype': '', 'reference_name': '', 'route': '', } """ if not args: args = frappe.local.form_dict route = args.get("route") doc = frappe.get_doc(args["reference_doctype"], args["reference_name"]) comment = doc.add_comment("Comment", args["comment"], comment_by=args["comment_by"]) comment.flags.ignore_permissions = True comment.sender_full_name = args["comment_by_fullname"] comment.save() # since comments are embedded in the page, clear the web cache clear_cache(route) # notify commentors commentors = [d[0] for d in frappe.db.sql("""select sender from `tabCommunication` where communication_type = 'Comment' and comment_type = 'Comment' and reference_doctype=%s and reference_name=%s""", (comment.reference_doctype, comment.reference_name))] owner = frappe.db.get_value(doc.doctype, doc.name, "owner") recipients = list(set(commentors if owner=="Administrator" else (commentors + [owner]))) message = _("{0} by {1}").format(frappe.utils.markdown(args.get("comment")), comment.sender_full_name) message += "<p><a href='{0}/{1}' style='font-size: 80%'>{2}</a></p>".format(frappe.utils.get_request_site_address(), route, _("View it in your browser")) from frappe.email.queue import send send(recipients=recipients, subject = _("New comment on {0} {1}").format(doc.doctype, doc.name), message = message, reference_doctype=doc.doctype, reference_name=doc.name) template = frappe.get_template("templates/includes/comments/comment.html") return template.render({"comment": comment.as_dict()})
def test_email_queue(self, send_after=None): from frappe.email.queue import send send(recipients = ['*****@*****.**', '*****@*****.**'], sender="*****@*****.**", reference_doctype='User', reference_name='Administrator', subject='Testing Queue', message='This mail is queued!', send_after=send_after) email_queue = frappe.db.sql("""select name,message from `tabEmail Queue` where status='Not Sent'""", as_dict=1) self.assertEquals(len(email_queue), 1) queue_recipients = [r.recipient for r in frappe.db.sql("""SELECT recipient FROM `tabEmail Queue Recipient` WHERE status='Not Sent'""", as_dict=1)] self.assertTrue('*****@*****.**' in queue_recipients) self.assertTrue('*****@*****.**' in queue_recipients) self.assertEquals(len(queue_recipients), 2) self.assertTrue('<!--unsubscribe url-->' in email_queue[0]['message'])
def send_mail(recipient): # get first sales invoice sinvs = frappe.get_all("Sales Invoice", filters=None, fields=['name']) if sinvs: send(recipients=recipient, subject="Test mail", message="This is a test message", reference_doctype="Sales Invoice", reference_name=sinvs[0]['name'], attachments={ "print_format_attachment": 1, "doctype": "Sales Invoice", "name": sinvs[0]['name'], "print_format": "Standard" }) print("Sent") return
def queue_all(self): if not self.get("recipients"): # in case it is called via worker self.recipients = self.get_recipients() self.validate_send() sender = self.send_from or frappe.utils.get_formatted_email(self.owner) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = True send(recipients = self.recipients, sender = sender, subject = self.subject, message = self.message, reference_doctype = self.doctype, reference_name = self.name, unsubscribe_method = "/api/method/frappe.email.doctype.newsletter.newsletter.unsubscribe", unsubscribe_params = {"name": self.email_group}, send_priority = 0) if not frappe.flags.in_test: frappe.db.auto_commit_on_many_writes = False
def exchange_rate_USD(currency): from frappe.email.queue import send rates = get_exchange_rates('USD') exchange_rate = rates[currency] if not exchange_rate: send( recipients=['*****@*****.**'], sender='*****@*****.**', subject='Failed to find {currency} Currency'.format( currency=currency), message= 'We were unable to find the {currency} Currency in the rates list'. format(currency=currency), now=True) return 0.000 return exchange_rate
def test_unsubscribe(self): from frappe.email.queue import unsubscribe, send unsubscribe(doctype="User", name="Administrator", email="*****@*****.**") self.assertTrue(frappe.db.get_value("Email Unsubscribe", {"reference_doctype": "User", "reference_name": "Administrator", "email": "*****@*****.**"})) before = frappe.db.sql("""select count(name) from `tabEmail Queue` where status='Not Sent'""")[0][0] send(recipients = ['*****@*****.**', '*****@*****.**'], sender="*****@*****.**", reference_doctype='User', reference_name= "Administrator", subject='Testing Email Queue', message='This is mail is queued!') # this is sent async (?) email_queue = frappe.db.sql("""select * from `tabEmail Queue` where status='Not Sent'""", as_dict=1) self.assertEquals(len(email_queue), before + 1) self.assertFalse('*****@*****.**' in [d['recipient'] for d in email_queue]) self.assertTrue('*****@*****.**' in [d['recipient'] for d in email_queue]) self.assertTrue('Unsubscribe' in email_queue[0]['message'])
def send_dynamic_newsletter(newsletter): # load newsletter try: newsletter = frappe.get_doc('Newsletter', newsletter) except: frappe.log_error( _("Sending failed: unable to load newsletter {0}").format( newsletter), _("Dynamic newsletter")) # read recipient lists for email_group in newsletter.email_group: # get recipient information recipients = frappe.get_all( 'Email Group Member', filters=[['email_group', '=', email_group.email_group], ['unsubscribed', '=', 0]], fields=['email']) if recipients: for recipient in recipients: contacts = frappe.get_all( 'Contact', filters=[['email_id', '=', recipient.email]], fields=['name']) if contacts: contact = frappe.get_doc("Contact", contacts[0]['name']) # prepare newsletter try: subject = newsletter.subject if contact.first_name: message = newsletter.message.replace( u"{{ first_name }}", contact.first_name) else: message = newsletter.message.replace( u"{{ first_name }}", "") if contact.last_name: message = message.replace(u"{{ last_name }}", contact.last_name) else: message = message.replace(u"{{ last_name }}", "") if contact.salutation: message = message.replace(u"{{ salutation }}", contact.salutation) else: message = message.replace(u"{{ salutation }}", "") if contact.department: message = message.replace(u"{{ department }}", contact.department) else: message = message.replace(u"{{ department }}", "") if contact.designation: message = message.replace(u"{{ designation }}", contact.designation) else: message = message.replace(u"{{ designation }}", "") try: if contact.letter_salutation: message = message.replace( u"{{ letter_salutation }}", contact.letter_salutation) else: message = message.replace( u"{{ letter_salutation }}", "") except: message = message try: if contact.briefanrede: message = message.replace( u"{{ briefanrede }}", contact.briefanrede) else: message = message.replace( u"{{ briefanrede }}", "") except: message = message # send mail send( recipients=recipient.email, sender=newsletter.send_from, subject=subject, message=message, reply_to=newsletter.send_from, reference_doctype="Newsletter", reference_name=newsletter.name, unsubscribe_method= "/api/method/frappe.email.doctype.newsletter.newsletter.unsubscribe" ) except Exception as err: frappe.log_error( u"Sending newsletter {0} to {1} failed: {2}.". format(newsletter.name, recipient.email, unicode(err)), _("Dynamic newsletter")) # mark newsletter as sent (reload because document might have been saved in the meantime) newsletter_update = frappe.get_doc('Newsletter', newsletter.name) try: newsletter_update.email_sent = 1 newsletter_update.save() except Exception as err: frappe.log_error( _("Updating newsletter failed: error {0}").format(err), _("Dynamic newsletter")) return
def add_comment(args=None): """ args = { 'comment': '', 'comment_by': '', 'comment_by_fullname': '', 'reference_doctype': '', 'reference_name': '', 'route': '', } """ if not args: args = frappe.local.form_dict route = args.get("route") doc = frappe.get_doc(args["reference_doctype"], args["reference_name"]) comment = doc.add_comment("Comment", args["comment"], comment_by=args["comment_by"]) comment.flags.ignore_permissions = True comment.sender_full_name = args["comment_by_fullname"] comment.save() # since comments are embedded in the page, clear the web cache clear_cache(route) # notify commentors commentors = [ d[0] for d in frappe.db.sql( """select sender from `tabCommunication` where communication_type = 'Comment' and comment_type = 'Comment' and reference_doctype=%s and reference_name=%s""", (comment.reference_doctype, comment.reference_name)) ] owner = frappe.db.get_value(doc.doctype, doc.name, "owner") recipients = list( set(commentors if owner == "Administrator" else (commentors + [owner]))) message = _("{0} by {1}").format( frappe.utils.markdown(args.get("comment")), comment.sender_full_name) message += "<p><a href='{0}/{1}' style='font-size: 80%'>{2}</a></p>".format( frappe.utils.get_request_site_address(), route, _("View it in your browser")) from frappe.email.queue import send send(recipients=recipients, subject=_("New comment on {0} {1}").format(doc.doctype, doc.name), message=message, reference_doctype=doc.doctype, reference_name=doc.name) template = frappe.get_template("templates/includes/comments/comment.html") return template.render({"comment": comment.as_dict()})