emailSvc.py (7074B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\net\emailSvc.py 2 import random 3 import smtplib 4 import sys 5 from email.Header import Header 6 from carbon.common.script.sys.serviceConst import SERVICE_RUNNING, SERVICE_START_PENDING, SERVICE_STOPPED 7 from email.mime import multipart, text 8 import blue 9 import uthread 10 import log 11 from carbon.common.script.sys.service import Service 12 LOCATION_TQ = 1 13 LOCATION_BFC = 2 14 LOCATION_CCP = 3 15 LOCATION_OTHER = 4 16 LOCATION_CHAOS = 5 17 18 class EmailSvc(Service): 19 __guid__ = 'svc.emailSvc' 20 __displayname__ = 'Email Service' 21 22 def __init__(self): 23 self.smptRetryTime = 12000 24 Service.__init__(self) 25 26 def Run(self, memStream = None): 27 self.state = SERVICE_START_PENDING 28 self.computername = blue.pyos.GetEnv().get('COMPUTERNAME', '?') 29 self.domain = blue.pyos.GetEnv().get('USERDOMAIN', '?') 30 self.mail_queue = uthread.Queue() 31 self.mail_server = None 32 uthread.new(self.__mailqueue) 33 self.state = SERVICE_RUNNING 34 35 def Stop(self, memStream = None): 36 self.state = SERVICE_STOPPED 37 38 def GetMailServer(self): 39 if not self.mail_server: 40 try: 41 local_hostname = blue.pyos.GetEnv().get('COMPUTERNAME', '?') 42 self.mail_server = None 43 server = self.AppGetMailServer() 44 if server: 45 server = server.split(';') 46 if type(server) != type([]): 47 server = [server] 48 server = random.choice(server).encode('latin1') 49 self.LogInfo('Email service using server:', server) 50 if sys.version_info[:3] == (2, 2, 1): 51 self.mail_server = smtplib.SMTP(server) 52 else: 53 self.mail_server = smtplib.SMTP(server, local_hostname=local_hostname) 54 except Exception: 55 self.LogError('Mail server bombed') 56 log.LogException() 57 sys.exc_clear() 58 self.mail_server = None 59 60 return self.mail_server 61 62 def AppGetMailServer(self): 63 self.LogError('AppGetMailServer not overridden!') 64 65 def SendMail(self, *args, **kw): 66 self.mail_queue.put((args, kw)) 67 68 def __mailqueue(self): 69 self.LogInfo('Email service: Starting Mail Queue thread') 70 try: 71 while self.state != SERVICE_STOPPED: 72 try: 73 args, kw = self.mail_queue.get() 74 self.LogInfo('Email service: Got mail from Mail Queue') 75 srv = self.GetMailServer() 76 if srv: 77 self.LogInfo('Email service: Sending mail') 78 srv.sendmail(*args, **kw) 79 self.LogInfo('Email sercice: Mail sent') 80 else: 81 self.LogWarn('Email service: No mail server available, mail not sent. sendmail args=', args, 'kw=', kw) 82 except smtplib.SMTPServerDisconnected: 83 self.mail_server = None 84 self.mail_queue.put((args, kw)) 85 self.LogWarn('Failed to send alert, SMTP server disconnected. Will try again in 1 minute') 86 sys.exc_clear() 87 blue.pyos.synchro.SleepWallclock(60000) 88 except smtplib.SMTPRecipientsRefused as e: 89 self.LogMailSendFailure('SMTPRecipientsRefused', args, e) 90 except smtplib.SMTPSenderRefused as e: 91 self.LogMailSendFailure('SMTPSenderRefused', args, e) 92 except Exception: 93 self.LogError('Email service: Unexpected error during mailqueue processing') 94 log.LogException() 95 self.mail_server = None 96 blue.pyos.synchro.SleepWallclock(60000) 97 98 finally: 99 self.LogInfo('Email service: Stopping Mail Queue thread') 100 101 def LogMailSendFailure(self, failureStr, args, excpt): 102 try: 103 subject = '' 104 lines = args[2].split('\n') 105 for each in lines: 106 if each.lower().find('subject:') == 0: 107 subject = each 108 109 self.LogError('Email service: Message in mail queue not allowed to relay, removing message:', failureStr, 'Server:', self.AppGetMailServer(), 'To:', args[1], subject, excpt) 110 except: 111 self.LogError('Email service: Message in mail queue not allowed to relay, removing message:', failureStr, 'Server:', self.AppGetMailServer() or '*** unknown server ***', excpt) 112 sys.exc_clear() 113 114 115 class NewEmail: 116 __guid__ = 'mail.new' 117 118 def __init__(self): 119 self.mailfrom = '' 120 self.rcptto = '' 121 self.cc = '' 122 self.bcc = '' 123 self.subject = '' 124 self.body = '' 125 self.html = 0 126 self.fileAttachments = [] 127 self.extraHeaders = {} 128 self.rcpt = [] 129 self.msg = multipart.MIMEMultipart() 130 131 def AttachFile(self, fileName, data): 132 self.fileAttachments.append([fileName, data]) 133 134 def AddHeader(self, k, v): 135 self.extraHeaders[k] = v 136 137 def AddSubject(self, s): 138 self.subject += s 139 140 def AddBody(self, b): 141 self.body += b 142 143 def CreateMail(self): 144 if type(self.subject) == type(u''): 145 self.subject = str(Header(unicode(self.subject), 'ISO-8859-1')) 146 else: 147 self.subject = str(self.subject) 148 self.msg['Subject'] = self.subject 149 self.rcpt = [] 150 if self.mailfrom != '': 151 self.msg['From'] = str(self.mailfrom) 152 if self.rcptto != '': 153 self.msg['To'] = str(self.rcptto) 154 self.rcpt += str(self.rcptto).split(';') 155 if self.cc != '': 156 self.rcpt += str(self.cc).split(';') 157 self.msg['Cc'] = self.cc 158 if self.bcc != '': 159 self.rcpt += str(self.bcc).split(';') 160 for k, v in self.extraHeaders.items(): 161 self.msg[k] = v 162 163 charset = 'iso-8859-1' 164 subtype = 'plain' 165 body = self.body 166 if type(body) is unicode: 167 body = body.encode('utf-8') 168 charset = 'utf-8' 169 if self.html: 170 subtype = 'html' 171 body = text.MIMEText(body, _subtype=subtype, _charset=charset) 172 self.msg.attach(body) 173 for fileName, data in self.fileAttachments: 174 mimetype, encoding = mimetypes.guess_type(filename, 0) 175 maintype, subtype = mimetype.split('/', 1) 176 attach = mime.base.BASEMime(maintype, subtype) 177 attach.set_payload(data) 178 encoders.encode_base64(attach) 179 attach.add_header('Content-Disposition:', 'attachment; filename="%s"' % str(fileName)) 180 self.msg.attach(attach) 181 182 return self.msg.as_string() 183 184 def Send(self): 185 mime = self.CreateMail() 186 sm.StartServiceAndWaitForRunningState('emailSvc').SendMail(self.mailfrom, self.rcpt, mime)