123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- # -*- 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,
- )
|