def flush(from_test=False): """flush email queue, every time: called from scheduler""" smtpserver = SMTPServer() auto_commit = not from_test if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False: msgprint(_("Emails are muted")) from_test = True for i in xrange(500): email = frappe.db.sql("""select * from `tabBulk Email` where status='Not Sent' and ifnull(send_after, "2000-01-01 00:00:00") < %s order by creation asc limit 1 for update""", now_datetime(), as_dict=1) if email: email = email[0] else: break frappe.db.sql("""update `tabBulk Email` set status='Sending' where name=%s""", (email["name"],), auto_commit=auto_commit) try: if not from_test: smtpserver.setup_email_account(email.reference_doctype) smtpserver.sess.sendmail(email["sender"], email["recipient"], encode(email["message"])) frappe.db.sql("""update `tabBulk Email` set status='Sent' where name=%s""", (email["name"],), auto_commit=auto_commit) except Exception, e: frappe.db.sql("""update `tabBulk Email` set status='Error', error=%s where name=%s""", (unicode(e), email["name"]), auto_commit=auto_commit)
def flush(from_test=False): """flush email queue, every time: called from scheduler""" smtpserver = SMTPServer() auto_commit = not from_test # additional check check_bulk_limit([]) if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False: msgprint(_("Emails are muted")) from_test = True frappe.db.sql("""update `tabBulk Email` set status='Expired' where datediff(curdate(), creation) > 3""", auto_commit=auto_commit) for i in xrange(500): email = frappe.db.sql("""select * from `tabBulk Email` where status='Not Sent' and ifnull(send_after, "2000-01-01 00:00:00") < %s order by creation asc limit 1 for update""", now_datetime(), as_dict=1) if email: email = email[0] else: break frappe.db.sql( """update `tabBulk Email` set status='Sending' where name=%s""", (email["name"], ), auto_commit=auto_commit) try: if not from_test: smtpserver.setup_email_account(email.reference_doctype) smtpserver.sess.sendmail(email["sender"], email["recipient"], encode(email["message"])) frappe.db.sql( """update `tabBulk Email` set status='Sent' where name=%s""", (email["name"], ), auto_commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError): # bad connection, retry later frappe.db.sql( """update `tabBulk Email` set status='Not Sent' where name=%s""", (email["name"], ), auto_commit=auto_commit) # no need to attempt further return except Exception, e: frappe.db.sql( """update `tabBulk Email` set status='Error', error=%s where name=%s""", (unicode(e), email["name"]), auto_commit=auto_commit)
def send_one(email, smtpserver=None, auto_commit=True, now=False): '''Send Email Queue with given smtpserver''' email = frappe.db.sql('''select name, status, communication, message, sender, recipient, reference_doctype from `tabEmail Queue` where name=%s for update''', email, as_dict=True)[0] if email.status != 'Not Sent': # rollback to release lock and return frappe.db.rollback() return frappe.db.sql("""update `tabEmail Queue` set status='Sending', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) try: if auto_commit: if not smtpserver: smtpserver = SMTPServer() smtpserver.setup_email_account(email.reference_doctype) smtpserver.sess.sendmail(email.sender, email.recipient, encode(email.message)) frappe.db.sql("""update `tabEmail Queue` set status='Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError, JobTimeoutException): # bad connection/timeout, retry later frappe.db.sql("""update `tabEmail Queue` set status='Not Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) # no need to attempt further return except Exception, e: frappe.db.rollback() frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s where name=%s""", (unicode(e), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) if now: raise e else: # log to Error Log log('frappe.email.queue.flush', unicode(e))
def send_one(email, smtpserver=None, auto_commit=True, now=False): '''Send Email Queue with given smtpserver''' email = frappe.db.sql('''select name, status, communication, message, sender, recipient, reference_doctype from `tabEmail Queue` where name=%s for update''', email, as_dict=True)[0] if email.status != 'Not Sent': # rollback to release lock and return frappe.db.rollback() return frappe.db.sql("""update `tabEmail Queue` set status='Sending', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) try: if auto_commit: if not smtpserver: smtpserver = SMTPServer() smtpserver.setup_email_account(email.reference_doctype) smtpserver.sess.sendmail(email.sender, email.recipient, encode(email.message)) frappe.db.sql("""update `tabEmail Queue` set status='Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError, JobTimeoutException): # bad connection/timeout, retry later frappe.db.sql("""update `tabEmail Queue` set status='Not Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) # no need to attempt further return except Exception, e: frappe.db.rollback() frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s where name=%s""", (unicode(e), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) if now: raise e else: # log to scheduler log log('frappe.email.queue.flush', unicode(e))
def flush(from_test=False): """flush email queue, every time: called from scheduler""" smtpserver = SMTPServer() auto_commit = not from_test # additional check check_bulk_limit([]) if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True frappe.db.sql("""update `tabBulk Email` set status='Expired' where datediff(curdate(), creation) > 3""", auto_commit=auto_commit) for i in xrange(100): email = frappe.db.sql("""select * from `tabBulk Email` where status='Not Sent' and ifnull(send_after, "2000-01-01 00:00:00") < %s order by priority desc, creation asc limit 1 for update""", now_datetime(), as_dict=1) if email: email = email[0] else: break frappe.db.sql("""update `tabBulk Email` set status='Sending' where name=%s""", (email["name"],), auto_commit=auto_commit) try: if not from_test: smtpserver.setup_email_account(email.reference_doctype) smtpserver.sess.sendmail(email["sender"], email["recipient"], encode(email["message"])) frappe.db.sql("""update `tabBulk Email` set status='Sent' where name=%s""", (email["name"],), auto_commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError): # bad connection, retry later frappe.db.sql("""update `tabBulk Email` set status='Not Sent' where name=%s""", (email["name"],), auto_commit=auto_commit) # no need to attempt further return except Exception, e: frappe.db.sql("""update `tabBulk Email` set status='Error', error=%s where name=%s""", (unicode(e), email["name"]), auto_commit=auto_commit) finally:
def check_smtp(self): """Checks SMTP settings.""" if self.enable_outgoing: if not self.smtp_server: frappe.throw(_("{0} is required").format("SMTP Server")) server = SMTPServer(login = getattr(self, "login_id", None) \ or self.email_id, server = self.smtp_server, port = cint(self.smtp_port), use_ssl = cint(self.use_tls) ) if self.password: server.password = self.get_password() server.sess
def flush(from_test=False): """flush email queue, every time: called from scheduler""" # additional check check_bulk_limit([]) auto_commit = not from_test if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True frappe.db.sql("""update `tabBulk Email` set status='Expired' where datediff(curdate(), creation) > 7 and status='Not Sent'""", auto_commit=auto_commit) smtpserver = SMTPServer() for i in xrange(500): # don't use for update here, as it leads deadlocks email = frappe.db.sql('''select * from `tabBulk Email` where status='Not Sent' and (send_after is null or send_after < %(now)s) order by priority desc, creation asc limit 1''', { 'now': now_datetime() }, as_dict=True) if email: email = email[0] else: break send_one(email, smtpserver, auto_commit)
def make_server(port, ssl, tls): server = SMTPServer(server="smtp.gmail.com", port=port, use_ssl=ssl, use_tls=tls) server.sess
def check_email_limit(recipients): # if using settings from site_config.json, check email limit # No limit for own email settings smtp_server = SMTPServer() if (smtp_server.email_account and getattr(smtp_server.email_account, "from_site_config", False) or frappe.flags.in_test): monthly_email_limit = frappe.conf.get('limits', {}).get('emails') daily_email_limit = cint( frappe.conf.get('limits', {}).get('daily_emails')) if frappe.flags.in_test: monthly_email_limit = 500 daily_email_limit = 50 if daily_email_limit: # get count of sent mails in last 24 hours today = get_emails_sent_today() if (today + len(recipients)) > daily_email_limit: throw( _("Cannot send this email. You have crossed the sending limit of {0} emails for this day." ).format(daily_email_limit), EmailLimitCrossedError) if not monthly_email_limit: return # get count of mails sent this month this_month = get_emails_sent_this_month() if (this_month + len(recipients)) > monthly_email_limit: throw( _("Cannot send this email. You have crossed the sending limit of {0} emails for this month." ).format(monthly_email_limit), EmailLimitCrossedError)
def flush(from_test=False): """flush email queue, every time: called from scheduler""" smtpserver = SMTPServer() auto_commit = not from_test # additional check check_bulk_limit([]) if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True frappe.db.sql("""update `tabBulk Email` set status='Expired' where datediff(curdate(), creation) > 3 and status='Not Sent'""", auto_commit=auto_commit) for i in xrange(500): email = frappe.db.sql("""select * from `tabBulk Email` where status='Not Sent' and ifnull(send_after, "2000-01-01 00:00:00") < %s order by priority desc, creation asc limit 1 for update""", now_datetime(), as_dict=1) if email: email = email[0] else: break send_one(email, smtpserver, auto_commit)
def send_mail(mail, sender): if sender: mail_config = frappe.db.get_value("Email Config", {"email_id": sender}, "name") server_details = frappe.get_doc("Email Config", mail_config) try: smtpserver = SMTPServer(login=server_details.email_id, password=server_details.password, server=server_details.smtp_server, port=587, use_ssl=1, append_to=None) mail.sender = smtpserver.login smtpserver.sess.sendmail(mail.sender, mail.recipients + (mail.cc or []), mail.as_string()) except smtplib.SMTPSenderRefused: frappe.msgprint(_("Invalid login or password")) raise except smtplib.SMTPRecipientsRefused: frappe.msgprint(_("Invalid recipient address")) raise
def flush(from_test=False): """flush email queue, every time: called from scheduler""" # additional check auto_commit = not from_test if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True smtpserver_dict = frappe._dict() for email in get_queue(): if cint(frappe.defaults.get_defaults().get("hold_queue")) == 1: break if email.name: smtpserver = smtpserver_dict.get(email.sender) if not smtpserver: smtpserver = SMTPServer() smtpserver_dict[email.sender] = smtpserver if from_test: send_one(email.name, smtpserver, auto_commit) else: send_one_args = { 'email': email.name, 'smtpserver': smtpserver, 'auto_commit': auto_commit, } enqueue(method='frappe.email.queue.send_one', queue='short', **send_one_args)
def check_smtp(self): #check SMTP server valid or not if not self.smtp_server: frappe.throw(_("{0} is required").format("SMTP Server")) server = SMTPServer(login = self.email_id, password = self.password, server = self.smtp_server, port = cint(self.smtp_port), use_ssl = cint(self.use_tls) ) server.sess
def check_bulk_limit(recipients): this_month = frappe.db.sql("""select count(*) from `tabBulk Email` where month(creation)=month(%s)""" % nowdate())[0][0] # No limit for own email settings smtp_server = SMTPServer() if smtp_server.email_account and not getattr(smtp_server.email_account, "from_site_config", False) or frappe.flags.in_test: monthly_bulk_mail_limit = frappe.conf.get('monthly_bulk_mail_limit') or 500 if (this_month + len(recipients)) > monthly_bulk_mail_limit: throw(_("Email limit {0} crossed").format(monthly_bulk_mail_limit), BulkLimitCrossedError)
def check_bulk_limit(recipients): # get count of mails sent this month this_month = frappe.db.sql("""select count(*) from `tabBulk Email` where status='Sent' and MONTH(creation)=MONTH(CURDATE())""")[0][0] # if using settings from site_config.json, check bulk limit # No limit for own email settings smtp_server = SMTPServer() if (smtp_server.email_account and getattr(smtp_server.email_account, "from_site_config", False) or frappe.flags.in_test): monthly_bulk_mail_limit = frappe.conf.get('monthly_bulk_mail_limit') or 500 if (this_month + len(recipients)) > monthly_bulk_mail_limit: throw(_("Email limit {0} crossed").format(monthly_bulk_mail_limit), BulkLimitCrossedError)
def check_email_limit(recipients): # if using settings from site_config.json, check email limit # No limit for own email settings smtp_server = SMTPServer() if (smtp_server.email_account and getattr(smtp_server.email_account, "from_site_config", False) or frappe.flags.in_test): # get count of mails sent this month this_month = get_emails_sent_this_month() monthly_email_limit = frappe.conf.get('limits', {}).get('emails') or 500 if (this_month + len(recipients)) > monthly_email_limit: throw( _("Cannot send this email. You have crossed the sending limit of {0} emails for this month." ).format(monthly_email_limit), EmailLimitCrossedError)
def flush(from_test=False): """flush email queue, every time: called from scheduler""" # additional check cache = frappe.cache() check_email_limit([]) auto_commit = not from_test if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True smtpserver = SMTPServer() make_cache_queue() for i in xrange(cache.llen('cache_email_queue')): email = cache.lpop('cache_email_queue') if email: send_one(email, smtpserver, auto_commit, from_test=from_test)
def flush(from_test=False): """flush email queue, every time: called from scheduler""" # additional check auto_commit = not from_test if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True smtpserver_dict = frappe._dict() for email in get_queue(): if cint(frappe.defaults.get_defaults().get("hold_queue")) == 1: break if email.name: smtpserver = smtpserver_dict.get(email.sender) if not smtpserver: smtpserver = SMTPServer() smtpserver_dict[email.sender] = smtpserver send_one(email.name, smtpserver, auto_commit, from_test=from_test)
def send_one(email, smtpserver=None, auto_commit=True, now=False): '''Send bulk email with given smtpserver''' if not smtpserver: smtpserver = SMTPServer() frappe.db.sql( """update `tabBulk Email` set status='Sending' where name=%s""", (email.name, ), auto_commit=auto_commit) try: if auto_commit: smtpserver.setup_email_account(email.reference_doctype) smtpserver.replace_sender_in_email(email) smtpserver.sess.sendmail(email.sender, email.recipient, encode(email.message)) frappe.db.sql( """update `tabBulk Email` set status='Sent' where name=%s""", (email.name, ), auto_commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError): # bad connection, retry later frappe.db.sql( """update `tabBulk Email` set status='Not Sent' where name=%s""", (email.name, ), auto_commit=auto_commit) # no need to attempt further return except Exception, e: frappe.db.sql("""update `tabBulk Email` set status='Error', error=%s where name=%s""", (unicode(e), email.name), auto_commit=auto_commit) if now: raise e
def send_one(email, smtpserver=None, auto_commit=True, now=False): status = frappe.db.sql( '''select status from `tabBulk Email` where name=%s for update''', email.name)[0][0] if status != 'Not Sent': # rollback to release lock and return frappe.db.rollback() return frappe.db.sql( """update `tabBulk Email` set status='Sending', modified=%s where name=%s""", (now_datetime(), email["name"]), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) try: if auto_commit: if not smtpserver: smtpserver = SMTPServer() smtpserver.setup_email_account(email.reference_doctype) smtpserver.sess.sendmail(email["sender"], email["recipient"], encode(email["message"])) frappe.db.sql( """update `tabBulk Email` set status='Sent', modified=%s where name=%s""", (now_datetime(), email["name"]), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError): # bad connection, retry later frappe.db.sql( """update `tabBulk Email` set status='Not Sent', modified=%s where name=%s""", (now_datetime(), email["name"]), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) # no need to attempt further return except Exception, e: frappe.db.sql("""update `tabBulk Email` set status='Error', error=%s where name=%s""", (unicode(e), email["name"]), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) if now: raise else: # log to scheduler log log('frappe.email.bulk.flush', unicode(e))
def send_one(email, smtpserver=None, auto_commit=True, now=False, from_test=False): '''Send Email Queue with given smtpserver''' email = frappe.db.sql('''select name, status, communication, message, sender, reference_doctype, reference_name, unsubscribe_param, unsubscribe_method, expose_recipients, show_as_cc, add_unsubscribe_link, attachments from `tabEmail Queue` where name=%s for update''', email, as_dict=True)[0] recipients_list = frappe.db.sql('''select name, recipient, status from `tabEmail Queue Recipient` where parent=%s''',email.name,as_dict=1) if frappe.are_emails_muted(): frappe.msgprint(_("Emails are muted")) return if cint(frappe.defaults.get_defaults().get("hold_queue"))==1 : return if email.status not in ('Not Sent','Partially Sent') : # rollback to release lock and return frappe.db.rollback() return frappe.db.sql("""update `tabEmail Queue` set status='Sending', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) try: if not frappe.flags.in_test: if not smtpserver: smtpserver = SMTPServer() smtpserver.setup_email_account(email.reference_doctype, sender=email.sender) for recipient in recipients_list: if recipient.status != "Not Sent": continue message = prepare_message(email, recipient.recipient, recipients_list) if not frappe.flags.in_test: smtpserver.sess.sendmail(email.sender, recipient.recipient, encode(message)) recipient.status = "Sent" frappe.db.sql("""update `tabEmail Queue Recipient` set status='Sent', modified=%s where name=%s""", (now_datetime(), recipient.name), auto_commit=auto_commit) #if all are sent set status if any("Sent" == s.status for s in recipients_list): frappe.db.sql("""update `tabEmail Queue` set status='Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) else: frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s where name=%s""", ("No recipients to send to", email.name), auto_commit=auto_commit) if frappe.flags.in_test: frappe.flags.sent_mail = message return if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError, JobTimeoutException): # bad connection/timeout, retry later if any("Sent" == s.status for s in recipients_list): frappe.db.sql("""update `tabEmail Queue` set status='Partially Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) else: frappe.db.sql("""update `tabEmail Queue` set status='Not Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) # no need to attempt further return except Exception as e: frappe.db.rollback() if any("Sent" == s.status for s in recipients_list): frappe.db.sql("""update `tabEmail Queue` set status='Partially Errored', error=%s where name=%s""", (text_type(e), email.name), auto_commit=auto_commit) else: frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s where name=%s""", (text_type(e), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit) if now: print(frappe.get_traceback()) raise e else: # log to Error Log log('frappe.email.queue.flush', text_type(e))
def send_one(email, smtpserver=None, auto_commit=True, now=False, from_test=False): '''Send Email Queue with given smtpserver''' email = frappe.db.sql('''select name, status, communication, message, sender, reference_doctype, reference_name, unsubscribe_param, unsubscribe_method, expose_recipients, show_as_cc, add_unsubscribe_link, attachments from `tabEmail Queue` where name=%s for update''', email, as_dict=True)[0] recipients_list = frappe.db.sql('''select name, recipient, status from `tabEmail Queue Recipient` where parent=%s''', email.name, as_dict=1) if frappe.are_emails_muted(): frappe.msgprint(_("Emails are muted")) return if cint(frappe.defaults.get_defaults().get("hold_queue")) == 1: return if email.status not in ('Not Sent', 'Partially Sent'): # rollback to release lock and return frappe.db.rollback() return frappe.db.sql( """update `tabEmail Queue` set status='Sending', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) try: if not frappe.flags.in_test: if not smtpserver: smtpserver = SMTPServer() smtpserver.setup_email_account(email.reference_doctype, sender=email.sender) for recipient in recipients_list: if recipient.status != "Not Sent": continue message = prepare_message(email, recipient.recipient, recipients_list) if not frappe.flags.in_test: smtpserver.sess.sendmail(email.sender, recipient.recipient, encode(message)) recipient.status = "Sent" frappe.db.sql( """update `tabEmail Queue Recipient` set status='Sent', modified=%s where name=%s""", (now_datetime(), recipient.name), auto_commit=auto_commit) #if all are sent set status if any("Sent" == s.status for s in recipients_list): frappe.db.sql( """update `tabEmail Queue` set status='Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) else: frappe.db.sql( """update `tabEmail Queue` set status='Error', error=%s where name=%s""", ("No recipients to send to", email.name), auto_commit=auto_commit) if frappe.flags.in_test: frappe.flags.sent_mail = message return if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) except (smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError, JobTimeoutException): # bad connection/timeout, retry later if any("Sent" == s.status for s in recipients_list): frappe.db.sql( """update `tabEmail Queue` set status='Partially Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) else: frappe.db.sql( """update `tabEmail Queue` set status='Not Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) # no need to attempt further return except Exception as e: frappe.db.rollback() if any("Sent" == s.status for s in recipients_list): frappe.db.sql( """update `tabEmail Queue` set status='Partially Errored', error=%s where name=%s""", (text_type(e), email.name), auto_commit=auto_commit) else: frappe.db.sql( """update `tabEmail Queue` set status='Error', error=%s where name=%s""", (text_type(e), email.name), auto_commit=auto_commit) if email.communication: frappe.get_doc( 'Communication', email.communication).set_delivery_status(commit=auto_commit) if now: print(frappe.get_traceback()) raise e else: # log to Error Log log('frappe.email.queue.flush', text_type(e))
def send_one(email, smtpserver=None, auto_commit=True, now=False): """Send Email Queue with given smtpserver""" email = frappe.db.sql( """select name, status, communication, message, sender, reference_doctype, reference_name, unsubscribe_param, unsubscribe_method, expose_recipients, show_as_cc, add_unsubscribe_link, attachments, retry from `tabEmail Queue` where name=%s for update""", email, as_dict=True, ) if len(email): email = email[0] else: return recipients_list = frappe.db.sql( """select name, recipient, status from `tabEmail Queue Recipient` where parent=%s""", email.name, as_dict=1, ) if frappe.are_emails_muted(): frappe.msgprint(_("Emails are muted")) return if cint(frappe.defaults.get_defaults().get("hold_queue")) == 1: return if email.status not in ("Not Sent", "Partially Sent"): # rollback to release lock and return frappe.db.rollback() return frappe.db.sql( """update `tabEmail Queue` set status='Sending', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit, ) if email.communication: frappe.get_doc( "Communication", email.communication).set_delivery_status(commit=auto_commit) email_sent_to_any_recipient = None try: message = None if not frappe.flags.in_test: if not smtpserver: smtpserver = SMTPServer() # to avoid always using default email account for outgoing if getattr(frappe.local, "outgoing_email_account", None): frappe.local.outgoing_email_account = {} smtpserver.setup_email_account(email.reference_doctype, sender=email.sender) for recipient in recipients_list: if recipient.status != "Not Sent": continue message = prepare_message(email, recipient.recipient, recipients_list) if not frappe.flags.in_test: method = get_hook_method("override_email_send") if method: queue = frappe.get_doc("Email Queue", email.name) method(queue, email.sender, recipient.recipient, message) return else: smtpserver.sess.sendmail(email.sender, recipient.recipient, message) recipient.status = "Sent" frappe.db.sql( """update `tabEmail Queue Recipient` set status='Sent', modified=%s where name=%s""", (now_datetime(), recipient.name), auto_commit=auto_commit, ) email_sent_to_any_recipient = any("Sent" == s.status for s in recipients_list) # if all are sent set status if email_sent_to_any_recipient: frappe.db.sql( """update `tabEmail Queue` set status='Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit, ) else: frappe.db.sql( """update `tabEmail Queue` set status='Error', error=%s where name=%s""", ("No recipients to send to", email.name), auto_commit=auto_commit, ) if frappe.flags.in_test: frappe.flags.sent_mail = message return if email.communication: frappe.get_doc( "Communication", email.communication).set_delivery_status(commit=auto_commit) if smtpserver.append_emails_to_sent_folder and email_sent_to_any_recipient: smtpserver.email_account.append_email_to_sent_folder(message) except ( smtplib.SMTPServerDisconnected, smtplib.SMTPConnectError, smtplib.SMTPHeloError, smtplib.SMTPAuthenticationError, smtplib.SMTPRecipientsRefused, JobTimeoutException, ): # bad connection/timeout, retry later if email_sent_to_any_recipient: frappe.db.sql( """update `tabEmail Queue` set status='Partially Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit, ) else: frappe.db.sql( """update `tabEmail Queue` set status='Not Sent', modified=%s where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit, ) if email.communication: frappe.get_doc( "Communication", email.communication).set_delivery_status(commit=auto_commit) # no need to attempt further return except Exception as e: frappe.db.rollback() if email.retry < 3: frappe.db.sql( """update `tabEmail Queue` set status='Not Sent', modified=%s, retry=retry+1 where name=%s""", (now_datetime(), email.name), auto_commit=auto_commit, ) else: if email_sent_to_any_recipient: frappe.db.sql( """update `tabEmail Queue` set status='Partially Errored', error=%s where name=%s""", (text_type(e), email.name), auto_commit=auto_commit, ) else: frappe.db.sql( """update `tabEmail Queue` set status='Error', error=%s where name=%s""", (text_type(e), email.name), auto_commit=auto_commit, ) if email.communication: frappe.get_doc( "Communication", email.communication).set_delivery_status(commit=auto_commit) if now: print(frappe.get_traceback()) raise e else: # log to Error Log frappe.log_error("frappe.email.queue.flush")