# -*- coding: utf-8 -*- import smtplib import typing from email.message import Message from email.mime.multipart import MIMEMultipart from tracim_backend.config import CFG from tracim_backend.lib.utils.logger import logger from tracim_backend.lib.utils.utils import get_rq_queue from tracim_backend.lib.utils.utils import get_redis_connection from tracim_backend.lib.mail_notifier.utils import SmtpConfiguration def send_email_through( config: CFG, sendmail_callable: typing.Callable[[Message], None], message: Message, ) -> None: """ Send mail encapsulation to send it in async or sync mode. TODO BS 20170126: A global mail/sender management should be a good thing. Actually, this method is an fast solution. :param config: system configuration :param sendmail_callable: A callable who get message on first parameter :param message: The message who have to be sent """ if config.EMAIL_PROCESSING_MODE == config.CST.SYNC: sendmail_callable(message) elif config.EMAIL_PROCESSING_MODE == config.CST.ASYNC: redis_connection = get_redis_connection(config) queue = get_rq_queue(redis_connection, 'mail_sender') queue.enqueue(sendmail_callable, message) else: raise NotImplementedError( 'Mail sender processing mode {} is not implemented'.format( config.EMAIL_PROCESSING_MODE, ) ) class EmailSender(object): """ Independent email sender class. To allow its use in any thread, as an asyncjob_perform() call for example, it has no dependencies on SQLAlchemy nor tg HTTP request. """ def __init__( self, config: CFG, smtp_config: SmtpConfiguration, really_send_messages ) -> None: self._smtp_config = smtp_config self.config = config self._smtp_connection = None self._is_active = really_send_messages def connect(self): if not self._smtp_connection: log = 'Connecting from SMTP server {}' logger.info(self, log.format(self._smtp_config.server)) self._smtp_connection = smtplib.SMTP( self._smtp_config.server, self._smtp_config.port ) self._smtp_connection.ehlo() if self._smtp_config.login: try: starttls_result = self._smtp_connection.starttls() log = 'SMTP start TLS result: {}' logger.debug(self, log.format(starttls_result)) except Exception as e: log = 'SMTP start TLS error: {}' logger.debug(self, log.format(e.__str__())) if self._smtp_config.login: try: login_res = self._smtp_connection.login( self._smtp_config.login, self._smtp_config.password ) log = 'SMTP login result: {}' logger.debug(self, log.format(login_res)) except Exception as e: log = 'SMTP login error: {}' logger.debug(self, log.format(e.__str__())) logger.info(self, 'Connection OK') def disconnect(self): if self._smtp_connection: log = 'Disconnecting from SMTP server {}' logger.info(self, log.format(self._smtp_config.server)) self._smtp_connection.quit() logger.info(self, 'Connection closed.') def send_mail(self, message: MIMEMultipart): if not self._is_active: log = 'Not sending email to {} (service disabled)' logger.info(self, log.format(message['To'])) else: self.connect() # Actually, this connects to SMTP only if required logger.info(self, 'Sending email to {}'.format(message['To'])) self._smtp_connection.send_message(message) from tracim_backend.lib.mail_notifier.notifier import EmailManager EmailManager.log_notification( action=' SENT', recipient=message['To'], subject=message['Subject'], config=self.config, )