def jsonCall(self): """Execute method with arguments on the server side. Returns Javascript function to be executed by the client immediately. """ request = self.request() data = json.loads(request.rawInput().read()) self._id, call, params = data['id'], data['method'], data['params'] if call == 'system.listMethods': self.writeResult(self.exposedMethods()) elif call in self.exposedMethods(): try: method = getattr(self, call) except AttributeError: self.writeError('%s, although an approved method, ' 'was not found' % call) else: try: if self._debug: self.log("json call %s(%s)" % (call, params)) self.writeResult(method(*params)) except Exception: err = StringIO() traceback.print_exc(file=err) e = err.getvalue() self.writeError('%s was called, ' 'but encountered an error: %s' % (call, e)) err.close() else: self.writeError('%s is not an approved method' % call)
def compileAndRun(self, pspSource, classname): pspClass = self.compileString(pspSource, classname) pspInstance = pspClass() outStream = StringIO() pspInstance._writeHTML(outStream) output = outStream.getvalue() return output
def jsonCall(self): """Execute method with arguments on the server side. Returns Javascript function to be executed by the client immediately. """ request = self.request() data = simplejson.loads(request.rawInput().read(), encoding=self._encoding) self._id, call, params = data["id"], data["method"], data["params"] if call == 'system.listMethods': self.writeResult(self.exposedMethods()) elif call in self.exposedMethods(): try: method = getattr(self, call) except AttributeError: self.writeError('%s, although an approved method, ' 'was not found' % call) else: try: if self._debug: self.log("json call %s(%s)" % (call, params)) self.writeResult(method(*params)) except Exception: err = StringIO() traceback.print_exc(file=err) e = err.getvalue() self.writeError('%s was called, ' 'but encountered an error: %s' % (call, e)) err.close() else: self.writeError('%s is not an approved method' % call)
def respond(self, transaction): """Write out a syntax hilighted version of the file. The filename is an attribute of the request object. """ res = transaction._response req = self.request() if not req.hasField('filename'): res.write('<h3 style="color:red">Error</h3><p>' 'No filename given to syntax color!</p>') return filename = req.field('filename') filename = self.request().serverSidePath(os.path.basename(filename)) if not os.path.exists(filename): res.write('<h3 style="color:red">Error</h3><p>' 'The requested file %r does not exist' ' in the proper directory.</p>' % os.path.basename(filename)) return from DocSupport import py2html myout = StringIO() stdout = sys.stdout sys.stdout = myout py2html.main((None, '-stdout', '-files', filename)) results = myout.getvalue() results = results.replace('\t', ' ') # 4 spaces per tab res.write(results) sys.stdout = stdout
def checkBasics(self): reader = HTMLReader() tag = reader.readString('<html> </html>') self.assertEqual(tag.name(), 'html') self.assertEqual(reader.rootTag(), tag) self.assertTrue(reader.filename() is None) out = StringIO() tag.pprint(out) self.assertEqual(out.getvalue(), '<html>\n</html>\n')
def ajaxCall(self): """Execute method with arguments on the server side. The method name is passed in the field _call_, the unique request number in the field _req_ and the arguments in the field _ (single underscore). Returns Javascript function to be executed by the client immediately. """ req = self.request() if req.hasField('_call_'): call = req.field('_call_') args = req.field('_', []) if not isinstance(args, list): args = [args] if self._clientPolling and self._responseTimeout: startTime = time.time() if call in self.exposedMethods(): try: method = getattr(self, call) except AttributeError: cmd = self.alert('%s, although an approved method, ' 'was not found' % call) else: try: if self._debug: self.log("Ajax call %s(%s)" % (call, args)) cmd = str(method(*args)) except Exception: err = StringIO() traceback.print_exc(file=err) e = err.getvalue() cmd = self.alert('%s was called, ' 'but encountered an error: %s' % (call, e)) err.close() else: cmd = self.alert('%s is not an approved method' % call) else: cmd = self.alert('Ajax call missing call parameter.') if self._clientPolling and self._responseTimeout: inTime = time.time() - startTime < self._responseTimeout else: inTime = 1 if inTime: # If the computation of the method did not last very long, # deliver it immediately back to the client with this response: if self._debug: self.log("Ajax returns immediately: %s" % cmd) self.write(cmd) else: # If the client request might have already timed out, # put the result in the queue and let client poll it: if self._debug: self.log("Ajax puts in queue: %s" % cmd) sid = self.session().identifier() self._responseQueue.setdefault(sid, []).append(cmd)
def ajaxCall(self): """Execute method with arguments on the server side. The method name is passed in the field _call_, the unique request number in the field _req_ and the arguments in the field _ (single underscore). Returns JavaScript function to be executed by the client immediately. """ req = self.request() startTime = None if req.hasField('_call_'): call = req.field('_call_') args = req.field('_', []) if not isinstance(args, list): args = [args] if self._clientPolling and self._responseTimeout: startTime = time() if call in self.exposedMethods(): try: method = getattr(self, call) except AttributeError: cmd = self.alert('%s, although an approved method, ' 'was not found' % call) else: try: if self._debug: self.log("Ajax call %s(%s)" % (call, args)) cmd = str(method(*args)) except Exception: err = StringIO() print_exc(file=err) e = err.getvalue() cmd = self.alert('%s was called, ' 'but encountered an error: %s' % (call, e)) err.close() else: cmd = self.alert('%s is not an approved method' % call) else: cmd = self.alert('Ajax call missing call parameter.') inTime = startTime is None or (time() - startTime < self._responseTimeout) if inTime: # If the computation of the method did not last very long, # deliver it immediately back to the client with this response: if self._debug: self.log("Ajax returns immediately: %s" % cmd) self.write(cmd) else: # If the client request might have already timed out, # put the result in the queue and let client poll it: if self._debug: self.log("Ajax puts in queue: %s" % cmd) sid = self.session().identifier() self._responseQueue.setdefault(sid, []).append(cmd)
def testEncodeDecode(self): session = Session() s = StringIO() self._store.encoder()(session, s) output = s.getvalue() s.close() self.assertTrue(isinstance(output, str)) s = StringIO(output) output = self._store.decoder()(s) s.close() self.assertTrue(type(output) is type(session)) self.assertEqual(output._data, session._data)
def createPyDocs(self, filename, dir): """Create an HTML module documentation using pydoc.""" import pydoc package, module = os.path.split(filename) module = os.path.splitext(module)[0] if package: module = package.replace('/', '.') + '.' + module targetName = '%s/%s.html' % (dir, module) self.printMsg('Creating %s...' % targetName) saveDir = os.getcwd() os.chdir(dir) try: stdout = sys.stdout sys.stdout = StringIO() try: try: pydoc.writedoc(module) except Exception: pass msg = sys.stdout.getvalue() finally: sys.stdout = stdout finally: os.chdir(saveDir) if msg: self.printMsg(msg)
def __init__(self, ctxt): self._reader = ctxt.getReader() self._writer = ctxt.getServletWriter() self._handler = None self.cout = StringIO() # for dumping HTML that none of the check wants self.tmplStart = None # marks the start of HTML code self.tmplStop = None # marks the end of HTML code self.currentFile = self._reader.mark().getFile()
def flushCharData(self, start, stop): """Dump everything to the char data handler. Dump all the HTML that we've accumulated over to the character data handler in the event handler object. """ data = self.cout.getvalue() self.cout.close() if data: # make sure there's something there self._handler.handleCharData(start, stop, data) self.cout = StringIO()
def createHighlightedSource(self, filename, dir): """Create highlighted HTML source code using py2html.""" from DocSupport import py2html module = os.path.splitext(os.path.basename(filename))[0] targetName = '%s/%s.html' % (dir, module) self.printMsg('Creating %s...' % targetName) stdout = sys.stdout sys.stdout = StringIO() try: py2html.main((None, '-stdout', '-files', filename)) result = sys.stdout.getvalue() finally: sys.stdout = stdout open(targetName, 'w').write(result)
def parse_response_gzip(self, f): """Workaround M2Crypto issue mentioned above.""" sio = StringIO() while 1: chunk = f.read() if not chunk: break sio.write(chunk) sio.seek(0) return Transport.parse_response_gzip(self, sio)
def _testBasic(self): """Simple tests...""" # Create table t = DataTable() # Headings 1 t = DataTable() t.setHeadings([TableColumn('name'), TableColumn('age:int'), TableColumn('rating:float')]) # Headings 2 t = DataTable() t.setHeadings(['name', 'age:int', 'rating:float']) # Adding and accessing data a = ['John', '26', '7.25'] b = ['Mary', 32, 8.5] c = dict(name='Fred', age=28, rating=9.0) d = Record(name='Wilma', age=27, rating=9.5) t.append(a) t.append(b) t.append(c) t.append(d) self.assertEqual(t[-4]['name'], 'John') self.assertEqual(t[-3]['name'], 'Mary') self.assertEqual(t[-2]['name'], 'Fred') self.assertEqual(t[-1]['name'], 'Wilma') self.assertEqual(t[-4].asDict(), {'name': 'John', 'age': 26, 'rating': 7.25}) self.assertEqual(t[-3].asList(), b) self.assertEqual(t[-2].asDict(), c) self.assertEqual(t[-1].asList(), ['Wilma', 27, 9.5]) # Printing # print t # Writing file (CSV) answer = '''\ name,age,rating John,26,7.25 Mary,32,8.5 Fred,28,9.0 Wilma,27,9.5 ''' out = StringIO() t.writeFile(out) results = out.getvalue() self.assertEqual(results, answer, '\n%r\n%r\n' % (results, answer)) # Accessing rows for row in t: self.assertEqual(row['name'], row[0]) self.assertEqual(row['age'], row[1]) self.assertEqual(row['rating'], row[2]) for item in row: pass # Default type t = DataTable(defaultType='int') t.setHeadings(list('xyz')) t.append([1, 2, 3]) t.append([4, 5, 6]) self.assertEqual(t[0]['x'] - t[1]['z'], -5)
class PSPParser(object): """The main PSP parser class. The PSPParser class does the actual sniffing through the input file looking for anything we're interested in. Basically, it starts by looking at the code looking for a '<' symbol. It looks at the code by working with a PSPReader object, which handles the current location in the code. When it finds one, it calls a list of checker methods, asking each if it recognizes the characters as its kind of input. When the checker methods look at the characters, if they want it, they go ahead and gobble it up and set up to create it in the servlet when the time comes. When they return, they return true if they accept the character, and the PSPReader object cursor is positioned past the end of the block that the checker method accepted. """ checklist = checklist # global list of checker methods def __init__(self, ctxt): self._reader = ctxt.getReader() self._writer = ctxt.getServletWriter() self._handler = None self.cout = StringIO() # for dumping HTML that none of the check wants self.tmplStart = None # marks the start of HTML code self.tmplStop = None # marks the end of HTML code self.currentFile = self._reader.mark().getFile() def setEventHandler(self, handler): """Set the handler this parser will use when it finds PSP code.""" self._handler = handler def flushCharData(self, start, stop): """Dump everything to the char data handler. Dump all the HTML that we've accumulated over to the character data handler in the event handler object. """ data = self.cout.getvalue() self.cout.close() if data: # make sure there's something there self._handler.handleCharData(start, stop, data) self.cout = StringIO() @checker def commentCheck(self, handler, reader): """Comments just get eaten.""" if reader.matches('<%--'): reader.advance(4) if reader.skipUntil('--%>') is None: raise PSPParserException('Comment not terminated') self.flushCharData(self.tmplStart, self.tmplStop) return True return False @checker def checkExpression(self, handler, reader): """Look for "expressions" and handle them.""" if not reader.matches('<%='): return False reader.advance(3) # eat the opening tag reader.peekChar() reader.skipSpaces() start = reader.mark() stop = reader.skipUntil('%>') if stop is None: raise PSPParserException('Expression not terminated') handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleExpression(start, stop, None) return True @checker def checkDirective(self, handler, reader): """Check for directives; for now we support only page and include.""" if not reader.matches('<%@'): return False start = reader.mark() reader.advance(3) reader.skipSpaces() for directive in ('page', 'include', 'taglib'): if reader.matches(directive): match = directive break else: raise PSPParserException('Invalid directive') reader.advance(len(match)) # parse the directive attr:val pair dictionary attrs = reader.parseTagAttributes() if match == 'page': checkAttributes('Page directive', attrs, ([], set([ 'imports', 'extends', 'method', 'isThreadSafe', 'isInstanceSafe', 'indentType', 'indentSpaces', 'gobbleWhitespace', 'formatter']))) elif match == 'include': checkAttributes('Include directive', attrs, (['file'], [])) else: raise PSPParserException('%s directive not implemented' % match) reader.skipSpaces() # skip to where we expect a close tag if reader.matches('%>'): reader.advance(2) # advance past it else: raise PSPParserException('Directive not terminated') stop = reader.mark() handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleDirective(match, start, stop, attrs) return True @checker def checkEndBlock(self, handler, reader): """Check for the end of a block.""" start = reader.mark() if reader.matches('<%'): reader.advance(2) reader.skipSpaces() if reader.matches('end'): reader.advance(3) reader.skipSpaces() if reader.matches('%>'): reader.advance(2) handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleEndBlock() return True if reader.matches('$%>'): reader.advance(3) handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleEndBlock() print 'INFO: A $ at the end of an end tag does nothing.' return True # that wasn't it reader.reset(start) return False @checker def checkScript(self, handler, reader): """The main thing we're after. Check for embedded scripts.""" if not reader.matches('<%'): return False reader.advance(2) # don't skip as spaces may be significant; leave this for the generator start = reader.mark() try: stop = reader.skipUntil('%>') except EOFError: raise EOFError("Reached EOF while looking for ending script tag") if stop is None: raise PSPParserException('Script not terminated') handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleScript(start, stop, None) return True @checker def checkScriptFile(self, handler, reader): """Check for file level code. Check for Python code that should go to the top of the generated module. <psp:file> import xyz print 'hi Mome!' def foo(): return 'foo' </psp:file> """ if not reader.matches('<psp:file>'): return False reader.advance(10) start = reader.mark() try: stop = reader.skipUntil('</psp:file>') if stop is None: raise PSPParserException( 'Script not terminated in <psp:file> block') except EOFError: raise EOFError('Reached EOF while looking for ending' ' script tag </psp:file>') handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleScriptFile(start, stop, None) return True @checker def checkScriptClass(self, handler, reader): """Check for class level code. Check for Python code that should go in the class definition. <psp:class> def foo(self): return self.dosomething() </psp:class> """ if not reader.matches('<psp:class>'): return False reader.advance(11) start = reader.mark() try: stop = reader.skipUntil('</psp:class>') if stop is None: raise PSPParserException( 'Script not terminated in <psp:class> block') except EOFError: raise EOFError('Reached EOF while looking for ending' ' script tag </psp:class>') handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleScriptClass(start, stop, None) return True @checker def checkMethod(self, handler, reader): """Check for class methods defined in the page. We only support one format for these, <psp:method name="xxx" params="xxx,xxx"> Then the function body, then </psp:method>. """ if not reader.matches('<psp:method'): return False start = reader.mark() reader.advance(11) attrs = reader.parseTagAttributes() checkAttributes('method', attrs, (['name'], ['params'])) reader.skipSpaces() if not reader.matches('>'): raise PSPParserException('Expected method declaration close') reader.advance(1) stop = reader.mark() handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleMethod(start, stop, attrs) start = stop # skip past the close marker, return the point before the close marker stop = reader.skipUntil('</psp:method>') handler.handleMethodEnd(start, stop, attrs) return True @checker def checkInclude(self, handler, reader): """Check for inserting another pages output in this spot.""" if not reader.matches('<psp:include'): return False reader.advance(12) reader.skipSpaces() attrs = reader.parseTagAttributes() checkAttributes('include', attrs, (['path'], [])) reader.skipSpaces() if not reader.matches('>'): raise PSPParserException('Include bodies not implemented') reader.advance(1) handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleInclude(attrs, None) return True @checker def checkInsert(self, handler, reader): """Check for straight character dumps. No big hurry for this. It's almost the same as the page include directive. This is only a partial implementation of what JSP does. JSP can pull it from another server, servlet, JSP page, etc. """ if not reader.matches('<psp:insert'): return False reader.advance(11) reader.skipSpaces() attrs = reader.parseTagAttributes() checkAttributes('insert', attrs, (['file'], [])) reader.skipSpaces() if not reader.matches('>'): raise PSPParserException('Insert bodies not implemented') reader.advance(1) handler.setTemplateInfo(self.tmplStart, self.tmplStop) handler.handleInsert(attrs, None) return True def parse(self, until=None): """Parse the PSP file.""" reader = self._reader handler = self._handler noPspElement = False while reader.hasMoreInput(): # This is for XML style blocks, which we're not handling yet: if until and reader.matches(until): return # If the file the reader is working on has changed due to # a push or pop, flush any char data from the old file: if reader.mark().getFile() != self.currentFile: self.flushCharData(self.tmplStart, self.tmplStop) self.currentFile = reader.mark().getFile() self.tmplStart = reader.mark() for checkfunc in self.checklist: if checkfunc(self, handler, reader): noPspElement = False break else: if not noPspElement: self.tmplStart = reader.mark() noPspElement = True s = reader.nextContent() # skip till the next possible tag self.tmplStop = reader.mark() # mark the end of HTML data self.cout.write(s) # write out the raw HTML data self.flushCharData(self.tmplStart, self.tmplStop) # dump the rest
def validateHTML(html): """Validate the given html. Validate the input using Web Design Group's HTML validator available at http://www.htmlhelp.com/tools/validator/ Make sure you install the offline validator (called "validate") which can be called from the command-line. The "validate" script must be in your path. If no errors are found, an empty string is returned. Otherwise, the HTML with the error messages is returned. """ input, output = os.popen4('validate') input.write(html) input.close() out = output.readlines() output.close() errorLines = {} for line in out: if line[0:5] == 'Line ': i = line.find(',') if i >= 0: linenum = int(line[5:i]) errorLines[linenum] = line # Be quiet if all's well if not errorLines: return '' result = StringIO() result.write('<table style="background-color: #ffffff">' '<tr><td colspan="2">\n') result.write("<pre>%s</pre>" % "".join(out)) result.write('</td></tr>\n') goodColors = ['#d0d0d0', '#e0e0e0'] badColor = '#ffd0d0' lines = html.splitlines(True) i = 1 for line in lines: if i in errorLines: result.write('<tr style="background-color: %s">' '<td rowspan="2">%d</td><td>%s</td></tr>\n' % (badColor, i, encodeWithIndentation(errorLines[i]))) result.write('<tr style="background-color: %s">' '<td>%s</td></tr>\n' % (badColor, encodeWithIndentation(line))) else: color = goodColors[i % 2] result.write('<tr style="background-color: %s">' '<td>%d</td><td>%s</td></tr>\n' % (color, i, encodeWithIndentation(line))) i += 1 result.write('</table>\n') return result.getvalue()
def png(self): s = StringIO() self._image.writePng(s) return s.getvalue()
def png(self): s = StringIO() self._image.save(s, 'png') return s.getvalue()
def emailException(self, htmlErrMsg): """Email the exception. Send the exception via mail, either as an attachment, or as the body of the mail. """ message = Message() # Construct the message headers headers = self.setting('ErrorEmailHeaders').copy() headers['Date'] = formatdate() headers['Mime-Version'] = '1.0' headers['Subject'] = headers.get('Subject', '[WebKit Error]') + ' %s: %s' % sys.exc_info()[:2] for h, v in headers.items(): if isinstance(v, (list, tuple)): v = ','.join(v) message.add_header(h, v) # Construct the message body if self.setting('EmailErrorReportAsAttachment'): # start off with a text/plain part text = ('WebKit caught an exception while processing' ' a request for "%s" at %s (timestamp: %s).' ' The plain text traceback from Python is printed below and' ' the full HTML error report from WebKit is attached.\n\n' % (self.servletPathname(), asclocaltime(self._time), self._time)) message.set_type('multipart/mixed') part = Message() part.set_type('text/plain') body = StringIO() body.write(text) traceback.print_exc(file=body) part.set_payload(body.getvalue()) body.close() message.attach(part) part = Message() # now add htmlErrMsg part.add_header('Content-Transfer-Encoding', '7bit') part.add_header('Content-Description', 'HTML version of WebKit error message') part.add_header('Content-Disposition', 'attachment', filename='WebKitErrorMsg.html') part.set_type('text/html') part.set_payload(htmlErrMsg) message.attach(part) else: message.set_type('text/html') message.set_payload(htmlErrMsg, 'us-ascii') # Send the message server = self.setting('ErrorEmailServer') # This setting can be: server, server:port, server:port:user:password # or server:port:user:password:popserver:popport for "smtp after pop". parts = server.split(':', 5) server = port = user = passwd = None popserver = popssl = popport = None try: server = parts[0] try: port = int(parts[1]) except ValueError: pass user = parts[2] passwd = parts[3] popserver = parts[4] try: popport = int(parts[5]) except ValueError: popport = None if parts[6].lower() == 'ssl': popssl = True except IndexError: pass if user and passwd and popserver: # SMTP after POP if popssl is None and popport == 995: popssl = True popssl = popssl and poplib.POP3_SSL or poplib.POP3 if popport: popserver = popssl(popserver, popport) else: popserver = popssl(popserver) popserver.set_debuglevel(0) popserver.user(user) popserver.pass_(passwd) try: popserver.quit() except Exception: pass if port: server = smtplib.SMTP(server, port) else: server = smtplib.SMTP(server) try: server.set_debuglevel(0) if user and passwd and not popserver: # SMTP-AUTH server.ehlo() if server.has_extn('starttls'): server.starttls() server.ehlo() server.login(user, passwd) body = message.as_string() server.sendmail(headers['From'], headers['To'], body) finally: try: server.quit() except Exception: pass
def loads(self, str): """Unpickle a string.""" return self.load(StringIO(str))
def emailException(self, htmlErrMsg): """Email the exception. Send the exception via mail, either as an attachment, or as the body of the mail. """ message = Message() # Construct the message headers headers = self.setting('ErrorEmailHeaders').copy() headers['Date'] = formatdate() headers['Mime-Version'] = '1.0' headers['Subject'] = headers.get( 'Subject', '[WebKit Error]') + ' %s: %s' % sys.exc_info()[:2] for h, v in headers.items(): if isinstance(v, (list, tuple)): v = ','.join(v) message.add_header(h, v) # Construct the message body if self.setting('EmailErrorReportAsAttachment'): # start off with a text/plain part text = ( 'WebKit caught an exception while processing' ' a request for "%s" at %s (timestamp: %s).' ' The plain text traceback from Python is printed below and' ' the full HTML error report from WebKit is attached.\n\n' % (self.servletPathname(), asclocaltime(self._time), self._time)) message.set_type('multipart/mixed') part = Message() part.set_type('text/plain') body = StringIO() body.write(text) traceback.print_exc(file=body) part.set_payload(body.getvalue()) body.close() message.attach(part) part = Message() # now add htmlErrMsg part.add_header('Content-Transfer-Encoding', '7bit') part.add_header('Content-Description', 'HTML version of WebKit error message') part.add_header('Content-Disposition', 'attachment', filename='WebKitErrorMsg.html') part.set_type('text/html') part.set_payload(htmlErrMsg) message.attach(part) else: message.set_type('text/html') message.set_payload(htmlErrMsg, 'us-ascii') # Send the message server = self.setting('ErrorEmailServer') # This setting can be: server, server:port, server:port:user:password # or server:port:user:password:popserver:popport for "smtp after pop". parts = server.split(':', 5) server = port = user = passwd = None popserver = popssl = popport = None try: server = parts[0] try: port = int(parts[1]) except ValueError: pass user = parts[2] passwd = parts[3] popserver = parts[4] try: popport = int(parts[5]) except ValueError: popport = None if parts[6].lower() == 'ssl': popssl = True except IndexError: pass if user and passwd and popserver: # SMTP after POP if popssl is None and popport == 995: popssl = True popssl = poplib.POP3_SSL if popssl else poplib.POP3 if popport: popserver = popssl(popserver, popport) else: popserver = popssl(popserver) popserver.set_debuglevel(0) popserver.user(user) popserver.pass_(passwd) try: popserver.quit() except Exception: pass if port: server = smtplib.SMTP(server, port) else: server = smtplib.SMTP(server) try: server.set_debuglevel(0) if user and passwd and not popserver: # SMTP-AUTH server.ehlo() if server.has_extn('starttls'): server.starttls() server.ehlo() server.login(user, passwd) body = message.as_string() server.sendmail(headers['From'], headers['To'], body) finally: try: server.quit() except Exception: pass