2024-01-21 23:35:44 +00:00
from sanic import Sanic
2024-02-11 22:57:52 +00:00
from sanic . log import logger
import ssl
from ssl import SSLContext
2024-01-19 17:03:54 +00:00
from email . mime . text import MIMEText
from email . mime . multipart import MIMEMultipart
from messages import ROOM_ERROR_TYPES
import smtplib
from messages import *
2024-02-11 22:57:52 +00:00
from config import *
2024-01-21 23:35:44 +00:00
from jinja2 import Environment , FileSystemLoader
2024-02-11 22:57:52 +00:00
from threading import Timer , Lock
2024-01-19 17:03:54 +00:00
2024-02-11 22:57:52 +00:00
def killSmptClient ( ) :
global sslLock
global sslTimer
global smptSender
2024-05-31 15:00:27 +00:00
logger . info ( f " [SMPT] killSmptClient: Lock status: { self . updating . locked ( ) } " )
2024-02-11 22:57:52 +00:00
sslTimer . cancel ( )
sslLock . acquire ( )
2024-05-31 15:00:27 +00:00
exp = None
2024-02-11 22:57:52 +00:00
if ( smptSender is not None ) :
logger . debug ( ' [SMPT] Closing smpt client ' )
2024-05-31 15:00:27 +00:00
try :
smptSender . quit ( ) # it calls close() inside
except Exception as e :
exp = e
2024-02-11 22:57:52 +00:00
smptSender = None
sslLock . release ( )
2024-05-31 15:00:27 +00:00
if ( exp != None ) :
raise exp
2024-02-11 22:57:52 +00:00
async def openSmptClient ( ) :
global sslLock
global sslTimer
global sslContext
global smptSender
2024-05-31 15:00:27 +00:00
logger . info ( f " [SMPT] openSmptClient: Lock status: { self . updating . locked ( ) } " )
2024-02-11 22:57:52 +00:00
sslTimer . cancel ( )
sslLock . acquire ( )
2024-05-31 15:00:27 +00:00
exp = None
try :
if ( smptSender is None ) :
logger . debug ( ' [SMPT] Opening smpt client ' )
client : smtplib . SMTP = smtplib . SMTP ( SMTP_HOST , SMTP_PORT )
client . starttls ( context = sslContext )
client . login ( SMTP_USER , SMTP_PASSWORD )
smptSender = client
except Exception as e :
exp = e
2024-02-11 22:57:52 +00:00
sslLock . release ( )
sslTimer = createTimer ( )
sslTimer . start ( )
2024-05-31 15:00:27 +00:00
if ( exp != None ) :
raise exp
2024-02-11 22:57:52 +00:00
def createTimer ( ) :
return Timer ( SMPT_CLIENT_CLOSE_TIMEOUT , killSmptClient )
sslLock : Lock = Lock ( )
sslTimer : Timer = createTimer ( )
sslContext : SSLContext = ssl . create_default_context ( )
smptSender : smtplib . SMTP = None
async def sendEmail ( message : MIMEMultipart ) :
2024-03-20 16:28:35 +00:00
message [ ' From ' ] = f ' { EMAIL_SENDER_NAME } < { EMAIL_SENDER_MAIL } > '
2024-02-11 22:57:52 +00:00
await openSmptClient ( )
logger . debug ( f " [SMPT] Sending mail { message [ ' From ' ] } -> { message [ ' to ' ] } ' { message [ ' Subject ' ] } ' " )
2024-05-31 15:00:27 +00:00
logger . info ( f " [SMPT] sendEmail: Lock status: { self . updating . locked ( ) } " )
exp = None
2024-02-11 22:57:52 +00:00
sslLock . acquire ( )
2024-05-31 15:00:27 +00:00
try :
smptSender . sendmail ( message [ ' From ' ] , message [ ' to ' ] , message . as_string ( ) )
except Exception as e :
exp = e
2024-02-11 22:57:52 +00:00
sslLock . release ( )
2024-05-31 15:00:27 +00:00
if ( exp != None ) :
raise exp
2024-02-11 22:57:52 +00:00
2024-02-29 10:41:49 +00:00
def render_email_template ( title = " " , body = " " ) :
tpl = Environment ( loader = FileSystemLoader ( " tpl " ) , autoescape = False ) . get_template ( ' email/comunication.html ' )
return str ( tpl . render ( title = title , body = body ) )
2024-02-11 22:57:52 +00:00
async def send_unconfirm_message ( room_order , orders ) :
2024-02-10 17:44:20 +00:00
memberMessages = [ ]
2024-01-19 17:03:54 +00:00
2024-02-10 17:44:20 +00:00
issues_plain = " "
issues_html = " <ul> "
2024-01-19 17:03:54 +00:00
2024-02-10 17:44:20 +00:00
for err in room_order . room_errors :
errId = err [ 1 ]
order = err [ 0 ]
orderStr = " "
if order is not None :
orderStr = f " { order } : "
if errId in ROOM_ERROR_TYPES . keys ( ) :
issues_plain + = f " • { orderStr } { ROOM_ERROR_TYPES [ errId ] } \n "
issues_html + = f " <li> { orderStr } { ROOM_ERROR_TYPES [ errId ] } </li> "
issues_html + = " </ul> "
2024-01-19 17:03:54 +00:00
2024-02-10 17:44:20 +00:00
for member in orders :
2024-05-13 08:25:45 +00:00
if ( member . status != ' canceled ' ) :
plain_body = EMAILS_TEXT [ " ROOM_UNCONFIRM_TEXT " ] [ ' plain ' ] . format ( member . name , room_order . room_name , issues_plain )
html_body = render_email_template ( EMAILS_TEXT [ " ROOM_UNCONFIRM_TITLE " ] , EMAILS_TEXT [ " ROOM_UNCONFIRM_TEXT " ] [ ' html ' ] . format ( member . name , room_order . room_name , issues_html ) )
plain_text = MIMEText ( plain_body , " plain " )
html_text = MIMEText ( html_body , " html " )
message = MIMEMultipart ( " alternative " )
message . attach ( plain_text )
message . attach ( html_text )
message [ ' Subject ' ] = f ' [ { EMAIL_SENDER_NAME } ] Your room cannot be confirmed '
message [ ' To ' ] = f " { member . name } < { member . email } > "
memberMessages . append ( message )
2024-01-19 17:03:54 +00:00
2024-02-10 17:44:20 +00:00
if len ( memberMessages ) == 0 : return
2024-01-19 17:03:54 +00:00
2024-02-11 22:57:52 +00:00
for message in memberMessages :
await sendEmail ( message )
2024-01-21 23:35:44 +00:00
2024-02-29 10:41:49 +00:00
async def send_missing_propic_message ( order , missingPropic , missingFursuitPropic ) :
t = [ ]
if ( missingPropic ) : t . append ( " your propic " )
if ( missingFursuitPropic ) : t . append ( " your fursuit ' s badge " )
missingText = " and " . join ( t )
plain_body = EMAILS_TEXT [ " MISSING_PROPIC_TEXT " ] [ ' plain ' ] . format ( order . name , missingText )
html_body = render_email_template ( EMAILS_TEXT [ " MISSING_PROPIC_TITLE " ] , EMAILS_TEXT [ " MISSING_PROPIC_TEXT " ] [ ' html ' ] . format ( order . name , missingText ) )
plain_text = MIMEText ( plain_body , " plain " )
html_text = MIMEText ( html_body , " html " )
message = MIMEMultipart ( " alternative " )
message . attach ( plain_text )
message . attach ( html_text )
message [ ' Subject ' ] = f " [ { EMAIL_SENDER_NAME } ] You haven ' t uploaded your badges yet! "
message [ ' To ' ] = f " { order . name } < { order . email } > "
await sendEmail ( message )
2024-03-20 16:28:35 +00:00
async def send_app_login_attempt ( user , loginCode ) :
#TODO: Format a proper email and add it to messages.py
msg = MIMEText ( f " Hello { user . name } ! \n \n We have received a request to login in the app. If you didn ' t do this, please ignore this email. Somebody is probably playing with you. \n \n Your login code is: { loginCode } \n \n Please do not tell this to anybody! " )
msg [ ' Subject ' ] = ' [Furizon] Your login code '
msg [ ' To ' ] = f " { user . name } < { user . email } > "
await sendEmail ( msg )