class Response(StandardError): """Represent an HTTP Response message. """ def __init__(self, code=200, body='', headers=None): """Takes an int, a string, and a dict. - code an HTTP response code, e.g., 404 - body the message body as a string - headers a dictionary of HTTP headers (or list of tuples) Body is second because one more often wants to specify a body without headers, than a header without a body. """ if not isinstance(code, int): raise TypeError("'code' must be an integer") elif not isinstance(body, basestring): raise TypeError("'body' must be a string") elif headers is not None and not isinstance(headers, (dict, list)): raise TypeError("'headers' must be a dictionary or a list of " + "2-tuples") StandardError.__init__(self) self.code = code self.body = body self.headers = Message() if headers: if isinstance(headers, dict): headers = headers.items() for k, v in headers: self.headers[k] = v def __repr__(self): return "<Response: %s>" % str(self) def __str__(self): return "%d %s" % (self.code, self._status()[0]) def _status(self): return _responses.get(self.code, ('???','Unknown HTTP status')) def __call__(self, environ, start_response): """We ourselves are a WSGI app. XXX: WSGI exception handling? """ _status = self._status() status = "%d %s" % (self.code, _status[0]) headers = [(str(k), str(v)) for k,v in self.headers.items()] body = [self.body and self.body or _status[1]] start_response(status, headers) return body
class Response(StandardError): """Represent an HTTP Response message. """ def __init__(self, code=200, body='', headers=None): """Takes an int, a string, and a dict. - code an HTTP response code, e.g., 404 - body the message body as a string - headers a dictionary of HTTP headers (or list of tuples) Body is second because one more often wants to specify a body without headers, than a header without a body. """ if not isinstance(code, int): raise TypeError("'code' must be an integer") elif not isinstance(body, basestring): raise TypeError("'body' must be a string") elif headers is not None and not isinstance(headers, (dict, list)): raise TypeError("'headers' must be a dictionary or a list of " + "2-tuples") StandardError.__init__(self) self.code = code self.body = body self.headers = Message() if headers: if isinstance(headers, dict): headers = headers.items() for k, v in headers: self.headers[k] = v def __repr__(self): return "<Response: %s>" % str(self) def __str__(self): return "%d %s" % (self.code, self._status()[0]) def _status(self): return _responses.get(self.code, ('???', 'Unknown HTTP status')) def __call__(self, environ, start_response): """We ourselves are a WSGI app. XXX: WSGI exception handling? """ _status = self._status() status = "%d %s" % (self.code, _status[0]) headers = [(str(k), str(v)) for k, v in self.headers.items()] body = [self.body and self.body or _status[1]] start_response(status, headers) return body
def construct_message(imap, msg_format, msg_to, msg_from, msg_date, msg_subject, msg_body): msg = Message() msg.add_header('Date', formatdate(time.mktime(msg_date.timetuple()))) msg.add_header('Message-Id', create_id(msg_date, msg_from)) msg.add_header('To', msg_to) msg.add_header('From', msg_from) msg.add_header('MIME-Version', '1.0') msg.add_header('Subject', msg_subject) payload = Message() payload.add_header('Content-Type', msg_format) if msg_format in ('text/html', 'text/plain'): payload.add_header('Content-Transfer-Encoding', '8bit') payload.set_payload(''.join(msg_body)) else: payload.add_header('Content-Transfer-Encoding', 'base64') payload.add_header('Content-Disposition', 'attachment; filename="%s"' % msg_subject) payload.set_payload(encodestring(''.join(msg_body)).decode()) for item in payload.items(): msg.add_header(item[0], item[1]) msg.set_payload(payload.get_payload()) try: msg.as_string() except Exception, e: print e
class SmartMessage: """Uproszczony interfejs dla bibliotek Pythona, który potrafi tworzyæ wiadomoœci tekstowe i z za³¹cznikami MIME.""" def __init__(self, fromAddr, toAddrs, subject, body, enc='iso-8859-2'): """Zacznij od za³o¿enia, i¿ bêdzie to prosta wiadomoœæ tekstowa zgodna z RFC 2822 i bez MIME.""" self.msg = Message() self.msg.set_payload(body) self['Subject'] = subject self.setFrom(fromAddr) self.setTo(toAddrs) self.hasAttachments = False self.enc = enc def setFrom(self, fromAddr): "Ustawia adres nadawcy wiadomoœci." if not fromAddr or not type(fromAddr) == type(''): raise Exception, 'Wiadomoœæ musi mieæ jednego i tylko jednego nadawcê.' self['From'] = fromAddr def setTo(self, to): "Ustawia adresy osób, które maj¹ otrzymaæ wiadomoœæ." if not to: raise Exception, 'Wiadomoœæ musi mieæ co najmniej jednego odbiorcê.' self._addresses(to, 'To') #Dodatkowo przechowuj adresy jako listê. Byæ mo¿e #skorzysta z niej kod, który zajmie siê wysy³aniem wiadomoœci. self.to = to def setCc(self, cc): """Ustawia adresy osób, które maj¹ otrzymaæ kopiê wiadomoœc. choæ nie jest ona adresowana do nich w sposób bezpoœredni.""" self._addresses(cc, 'Cc') def addAttachment(self, attachment, filename, mimetype=None): "Do³¹cza do wiadomoœci wskazany plik." #Odgadnij g³ówny i dodatkowy typ MIME na podstawie nazwy pliku. if not mimetype: mimetype = mimetypes.guess_type(filename)[0] if not mimetype: raise Exception, "Nie uda³o siê okreœliæ typu MIME dla", filename if '/' in mimetype: major, minor = mimetype.split('/') else: major = mimetype minor = None #Wiadomoœæ by³a konstruowana z za³o¿eniem, i¿ bêdzie zawieraæ #tylko i wy³¹cznie tekst. Poniewa¿ wiem, ¿e bêdzie zawieraæ #co najmniej jeden za³¹cznik, musimy zmieniæ j¹ na wiadomoœæ #wieloczêœciow¹ i wkleiæ tekst jako pierwsz¹ czêœæ. if not self.hasAttachments: body = self.msg.get_payload() newMsg = MIMEMultipart() newMsg.attach(MIMEText(body, 'plain', self.enc)) #Skopiuj stare nag³ówki do nowego obiektu. for header, value in self.msg.items(): newMsg[header] = value self.msg = newMsg self.hasAttachments = True subMessage = MIMENonMultipart(major, minor, name=filename) subMessage.set_payload(attachment) #Zakoduj teksty jako quoted printable natomiast wszystkie #inne typy jako base64. if major == 'text': encoder = Encoders.encode_quopri else: encoder = Encoders.encode_base64 encoder(subMessage) #Powi¹¿ fragment MIME z g³ówn¹ wiadomoœci¹. self.msg.attach(subMessage) def _addresses(self, addresses, key): """Ustawia zawartoœæ nag³ówka na podstawie listy przekazanych adresów.""" if hasattr(addresses, '__iter__'): addresses = ', '.join(addresses) self[key] = addresses #Kilka metod dodatkowych umo¿liwiaj¹cych traktowanie klasy w podobny #sposób, jak klasy Message lub MultipartMessage, stosuj¹c odpowiedni¹ #delegacjê poleceñ do tych klas. def __getitem__(self, key): "Zwróæ nag³ówek o podanym kluczu." return self.msg[key] def __setitem__(self, key, value): "Ustaw nag³ówek o wskazanej nazwie." self.msg[key] = value def __getattr__(self, key): return getattr(self.msg, key) def __str__(self): "Zwróæ tekstow¹ reprezentacjê wiadomoœci." return self.msg.as_string()