seitime-frappe/frappe/utils/email_lib/smtp.py

115 lines
3.4 KiB
Python

# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals
import frappe
import smtplib
import _socket
from frappe.utils import cint
from frappe import _
def send(email, as_bulk=False):
"""send the message or add it to Outbox Email"""
if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False:
frappe.msgprint(_("Emails are muted"))
return
try:
smtpserver = SMTPServer()
if hasattr(smtpserver, "always_use_login_id_as_sender") and \
cint(smtpserver.always_use_login_id_as_sender) and smtpserver.login:
if not email.reply_to:
email.reply_to = email.sender
email.sender = smtpserver.login
smtpserver.sess.sendmail(email.sender, email.recipients + (email.cc or []),
email.as_string())
except smtplib.SMTPSenderRefused:
frappe.msgprint(_("Invalid login or password"))
raise
except smtplib.SMTPRecipientsRefused:
frappe.msgprint(_("Invalid recipient address"))
raise
class SMTPServer:
def __init__(self, login=None, password=None, server=None, port=None, use_ssl=None):
# get defaults from mail settings
try:
self.email_settings = frappe.get_doc('Outgoing Email Settings', 'Outgoing Email Settings')
except frappe.DoesNotExistError:
self.email_settings = None
self._sess = None
if server:
self.server = server
self.port = port
self.use_ssl = cint(use_ssl)
self.login = login
self.password = password
elif self.email_settings and cint(self.email_settings.enabled):
self.server = self.email_settings.mail_server
self.port = self.email_settings.mail_port
self.use_ssl = cint(self.email_settings.use_ssl)
self.login = self.email_settings.mail_login
self.password = self.email_settings.mail_password
self.always_use_login_id_as_sender = self.email_settings.always_use_login_id_as_sender
else:
self.server = frappe.conf.get("mail_server") or ""
self.port = frappe.conf.get("mail_port") or None
self.use_ssl = cint(frappe.conf.get("use_ssl") or 0)
self.login = frappe.conf.get("mail_login") or ""
self.password = frappe.conf.get("mail_password") or ""
@property
def sess(self):
"""get session"""
if self._sess:
return self._sess
# check if email server specified
if not self.server:
err_msg = _('Outgoing Mail Server not specified')
frappe.msgprint(err_msg)
raise frappe.OutgoingEmailError, err_msg
try:
if self.use_ssl and not self.port:
self.port = 587
self._sess = smtplib.SMTP((self.server or "").encode('utf-8'),
cint(self.port) or None)
if not self._sess:
err_msg = _('Could not connect to outgoing email server')
frappe.msgprint(err_msg)
raise frappe.OutgoingEmailError, err_msg
if self.use_ssl:
self._sess.ehlo()
self._sess.starttls()
self._sess.ehlo()
if self.login:
ret = self._sess.login((self.login or "").encode('utf-8'),
(self.password or "").encode('utf-8'))
# check if logged correctly
if ret[0]!=235:
frappe.msgprint(ret[1])
raise frappe.OutgoingEmailError, ret[1]
return self._sess
except _socket.error:
# Invalid mail server -- due to refusing connection
frappe.msgprint(_('Invalid Outgoing Mail Server or Port'))
raise
except smtplib.SMTPAuthenticationError:
frappe.msgprint(_("Invalid login or password"))
raise
except smtplib.SMTPException:
frappe.msgprint(_('Unable to send emails at this time'))
raise