def test_as_message_attachments(self): msg_in = Message() msg_in["From"] = "*****@*****.**" msg_in["Message-ID"] = "<msg>" msg_in.attach(MIMEText("Dummy message")) msg_in.attach(MIMEText("<html><body>Dummy message</body></html>", _subtype="html")) add_to_list("*****@*****.**", msg_in) email = Email.objects.get(message_id="msg") msg = email.as_message() self.assertEqual(msg["From"], "dummy at example.com") self.assertEqual(msg["Message-ID"], "<msg>") self.assertTrue(msg.is_multipart()) payload = msg.get_payload() self.assertEqual(len(payload), 2) self.assertEqual( payload[0].get_payload(decode=True).strip(), "Dummy message") # The filename extension detection from content type is a bit random # (depends on the PYTHON_HASHSEED), make sure we get the right one # here for testing. expected_ext = guess_all_extensions("text/html", strict=False)[0] self.assertEqual(payload[1].get_content_type(), "text/html") self.assertEqual(payload[1]["Content-Disposition"], 'attachment; filename="attachment%s"' % expected_ext) self.assertEqual( payload[1].get_payload(decode=True), "<html><body>Dummy message</body></html>")
def as_string(self, boundary=None): """Return the entire formatted message as a string. :param boundary: The boundary to use between MIME parts, if applicable. Used for tests. """ if not self._parts: msgobj = Message() if self._body is not None: body, encoding = self.string_with_encoding(self._body) msgobj.set_payload(body, encoding) else: msgobj = MIMEMultipart() if boundary is not None: msgobj.set_boundary(boundary) for body, filename, mime_subtype in self._parts: body, encoding = self.string_with_encoding(body) payload = MIMEText(body, mime_subtype, encoding) if filename is not None: content_type = payload['Content-Type'] content_type += '; name="%s"' % filename payload.replace_header('Content-Type', content_type) payload['Content-Disposition'] = 'inline' msgobj.attach(payload) # sort headers here to ease testing for header, value in sorted(self._headers.items()): msgobj[header] = value return msgobj.as_string()
def test_as_message_attachments(self): msg_in = Message() msg_in["From"] = "*****@*****.**" msg_in["Message-ID"] = "<msg>" msg_in.attach(MIMEText("Dummy message")) msg_in.attach(MIMEText("<html><body>Dummy message</body></html>", _subtype="html")) add_to_list("*****@*****.**", msg_in) email = Email.objects.get(message_id="msg") msg = email.as_message() self.assertEqual(msg["From"], "dummy at example.com") self.assertEqual(msg["Message-ID"], "<msg>") self.assertTrue(msg.is_multipart()) payload = msg.get_payload() self.assertEqual(len(payload), 2) self.assertEqual( payload[0].get_payload(decode=True).strip(), "Dummy message") # The filename extension detection from content type is a bit random # (depends on the PYTHON_HASHSEED), make sure we get the right one # here for testing. expected_ext = guess_all_extensions("text/html", strict=False)[0] self.assertEqual(payload[1].get_content_type(), "text/html") self.assertEqual( payload[1]["Content-Disposition"], 'attachment; filename="attachment%s"' % expected_ext) self.assertEqual( payload[1].get_payload(decode=True), "<html><body>Dummy message</body></html>")
def _construct_multipart_request(self, request): """ :type request: office365.runtime.http.request_options.RequestOptions """ request.method = HttpMethod.Post boundary = create_boundary("PageBoundary", True) request.set_header( "Content-Type", "multipart/form-data; boundary={0}".format(boundary)) main_message = Message() main_message.add_header( "Content-Type", "multipart/form-data; boundary={0}".format(boundary)) main_message.set_boundary(boundary) c_type, enc = get_mime_type(self._presentation.name) presentation_message = Message() presentation_message.add_header("Content-Type", c_type) presentation_message.add_header("Content-Disposition", "form-data; name=\"Presentation\"") presentation_message.set_payload(self._presentation.read()) main_message.attach(presentation_message) for name, file in self._files.items(): file_message = Message() c_type, enc = get_mime_type(file.name) file_message.add_header("Content-Type", c_type) file_message.add_header("Content-Disposition", "form-data; name=\"{0}\"".format(name)) file_content = file.read() file_message.set_payload(file_content) main_message.attach(file_message) request.data = _message_to_payload(main_message)
def _rehydrate(self, msg): new = EmailMessage() settings = utils.get_settings() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach( self._rehydrate(part) ) elif settings['attachment_interpolation_header'] in msg.keys(): try: attachment = MessageAttachment.objects.get( pk=msg[settings['attachment_interpolation_header']] ) for header, value in attachment.items(): new[header] = value encoding = new['Content-Transfer-Encoding'] if encoding and encoding.lower() == 'quoted-printable': # Cannot use `email.encoders.encode_quopri due to # bug 14360: http://bugs.python.org/issue14360 output = six.BytesIO() encode_quopri( six.BytesIO( attachment.document.read() ), output, quotetabs=True, header=False, ) new.set_payload( output.getvalue().decode().replace(' ', '=20') ) del new['Content-Transfer-Encoding'] new['Content-Transfer-Encoding'] = 'quoted-printable' else: new.set_payload( attachment.document.read() ) del new['Content-Transfer-Encoding'] encode_base64(new) except MessageAttachment.DoesNotExist: new[settings['altered_message_header']] = ( 'Missing; Attachment %s not found' % ( msg[settings['attachment_interpolation_header']] ) ) new.set_payload('') else: for header, value in msg.items(): new[header] = value new.set_payload( msg.get_payload() ) return new
def _get_dehydrated_message(self, msg, record): new = EmailMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach(self._get_dehydrated_message(part, record)) elif (STRIP_UNALLOWED_MIMETYPES and not msg.get_content_type() in ALLOWED_MIMETYPES): for header, value in msg.items(): new[header] = value # Delete header, otherwise when attempting to deserialize the # payload, it will be expecting a body for this. del new['Content-Transfer-Encoding'] new[ALTERED_MESSAGE_HEADER] = ( 'Stripped; Content type %s not allowed' % (msg.get_content_type())) new.set_payload('') elif msg.get_content_type() not in TEXT_STORED_MIMETYPES: filename = msg.get_filename() if not filename: extension = mimetypes.guess_extension(msg.get_content_type()) else: _, extension = os.path.splitext(filename) if not extension: extension = '.bin' attachment = MessageAttachment() attachment.document.save( uuid.uuid4().hex + extension, ContentFile( six.BytesIO(msg.get_payload(decode=True)).getvalue())) attachment.message = record for key, value in msg.items(): attachment[key] = value attachment.save() placeholder = EmailMessage() placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk) new = placeholder else: content_charset = msg.get_content_charset() if not content_charset: content_charset = 'ascii' try: # Make sure that the payload can be properly decoded in the # defined charset, if it can't, let's mash some things # inside the payload :-\ msg.get_payload(decode=True).decode(content_charset) except UnicodeDecodeError: msg.set_payload( msg.get_payload(decode=True).decode( content_charset, 'ignore')) new = msg return new
def _get_dehydrated_message(self, msg, record): new = EmailMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach( self._get_dehydrated_message(part, record) ) elif ( STRIP_UNALLOWED_MIMETYPES and not msg.get_content_type() in ALLOWED_MIMETYPES ): for header, value in msg.items(): new[header] = value # Delete header, otherwise when attempting to deserialize the # payload, it will be expecting a body for this. del new['Content-Transfer-Encoding'] new[ALTERED_MESSAGE_HEADER] = ( 'Stripped; Content type %s not allowed' % ( msg.get_content_type() ) ) new.set_payload('') elif msg.get_content_type() not in TEXT_STORED_MIMETYPES: filename = msg.get_filename() if not filename: extension = mimetypes.guess_extension(msg.get_content_type()) else: _, extension = os.path.splitext(filename) if not extension: extension = '.bin' attachment = MessageAttachment() attachment.document.save( uuid.uuid4().hex + extension, ContentFile( six.BytesIO( msg.get_payload(decode=True) ).getvalue() ) ) attachment.message = record for key, value in msg.items(): attachment[key] = value attachment.save() placeholder = EmailMessage() placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk) new = placeholder else: new = msg return new
def _get_dehydrated_message(self, msg, record): new = EmailMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach( self._get_dehydrated_message(part, record) ) elif ( STRIP_UNALLOWED_MIMETYPES and not msg.get_content_type() in ALLOWED_MIMETYPES ): for header, value in msg.items(): new[header] = value # Delete header, otherwise when attempting to deserialize the # payload, it will be expecting a body for this. del new['Content-Transfer-Encoding'] new[ALTERED_MESSAGE_HEADER] = ( 'Stripped; Content type %s not allowed' % ( msg.get_content_type() ) ) new.set_payload('') elif msg.get_content_type() not in TEXT_STORED_MIMETYPES: filename = msg.get_filename() extension = '.bin' if not filename: extension = mimetypes.guess_extension(msg.get_content_type()) else: _, extension = os.path.splitext(filename) attachment = MessageAttachment() attachment.document.save( uuid.uuid4().hex + extension, ContentFile(six.BytesIO(msg.get_payload(decode=True)).getvalue()) ) attachment.message = record for key, value in msg.items(): attachment[key] = value attachment.save() placeholder = EmailMessage() placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk) new = placeholder else: for header, value in msg.items(): new[header] = value new.set_payload( msg.get_payload() ) return new
def _prepare_payload(self): """Serializes a batch request body.""" main_message = Message() main_message.add_header("Content-Type", "multipart/mixed") main_message.set_boundary(self._current_boundary) for _ in self.context.get_next_query(): part_message = Message() part_message.add_header("Content-Type", "application/http") part_message.add_header("Content-Transfer-Encoding", "binary") request = self.context.build_request() part_message.set_payload(self._serialize_request(request)) main_message.attach(part_message) return main_message.as_bytes()
def prepare_multipart_body(self): # type: () -> None """Will prepare the body of this request according to the multipart information. This call assumes the on_request policies have been applied already in their correct context (sync/async) Does nothing if "set_multipart_mixed" was never called. """ if not self.multipart_mixed_info: return requests = self.multipart_mixed_info[0] # type: List[HttpRequest] boundary = self.multipart_mixed_info[2] # type: Optional[str] # Update the main request with the body main_message = Message() main_message.add_header("Content-Type", "multipart/mixed") if boundary: main_message.set_boundary(boundary) for i, req in enumerate(requests): part_message = Message() part_message.add_header("Content-Type", "application/http") part_message.add_header("Content-Transfer-Encoding", "binary") part_message.add_header("Content-ID", str(i)) part_message.set_payload(req.serialize()) main_message.attach(part_message) try: from email.policy import HTTP full_message = main_message.as_bytes(policy=HTTP) eol = b"\r\n" except ImportError: # Python 2.7 # Right now we decide to not support Python 2.7 on serialization, since # it doesn't serialize a valid HTTP request (and our main scenario Storage refuses it) raise NotImplementedError( "Multipart request are not supported on Python 2.7" ) # full_message = main_message.as_string() # eol = b'\n' _, _, body = full_message.split(eol, 2) self.set_bytes_body(body) self.headers["Content-Type"] = ( "multipart/mixed; boundary=" + main_message.get_boundary() )
def emsg(kv): from email.message import Message from email.generator import Generator from StringIO import StringIO m = Message() m['Content-type'] = 'multipart/formdata' for k,v in kv.items(): p = Message() p.add_header('Content-Disposition', 'form-data', name=k) p.set_payload(v) m.attach(p) #print m.as_string() fp = StringIO() g = Generator(fp) g.flatten(m) return fp.getvalue()
def make_mdn(sender, recipient, orig_message_id, subject, disposition_type): domain = sender.partition('@')[2] msg = Message() msg['MIME-Version'] = '1.0' msg['Content-Type'] = 'multipart/report; report-type=disposition-notification' msg['From'] = '<%s>' % sender msg['To'] = '<%s>' % recipient msg['Date'] = email.utils.formatdate().replace('-0000','+0000 (UTC)') msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain) msg['Message-ID'] = msg_id if (disposition_type == 'processed'): msg['Subject'] = 'Processed: %s' % subject else: msg['Subject'] = 'Delivered: %s' % subject txt = Message() #txt['Content-Type'] = 'text/plain;charset=us-ascii' #txt['Content-Transfer-Encoding'] = '7bit' if (disposition_type == 'processed'): txt.set_payload('Your message was successfully processed.') else: txt.set_payload('Your message was successfully delivered.') msg.attach(txt) dn = Message() dn['Content-Type'] = 'message/disposition-notification' #dn['Content-Transfer-Encoding'] = '7bit' if (disposition_type == 'processed'): dn.set_payload(NOTIFICATION_PROCESSED % (domain,sender,orig_message_id)) else: dn.set_payload(NOTIFICATION_DISPATCHED % (domain,sender,orig_message_id)) msg.attach(dn) msg_string = msg.as_string() msg_string = msg_string.replace('\r\n', '\n') msg_string = msg_string.replace('\n\n\n', '\n\n') msg_string = msg_string.replace('\n', '\r\n') msg_string = msg_string + '\r\n' return msg_id, msg_string
def _prepare_payload(self): """Serializes a batch request body.""" for qry in self.context.get_next_query(): request = self.context.build_request() if isinstance(qry, ReadEntityQuery): self._get_requests.append(request) self._get_queries.append(qry) else: self._change_requests.append(request) main_message = Message() main_message.add_header("Content-Type", "multipart/mixed") main_message.set_boundary(self._current_boundary) if len(self._change_requests) > 0: change_set_message = Message() change_set_boundary = _create_boundary("changeset_", True) change_set_message.add_header("Content-Type", "multipart/mixed") change_set_message.set_boundary(change_set_boundary) for request in self._change_requests: part_message = self._serialize_request(request) change_set_message.attach(part_message) main_message.attach(change_set_message) for request in self._get_requests: part_message = self._serialize_request(request) main_message.attach(part_message) return main_message
def _prepare_payload(self): """ Serializes a batch request body. """ main_message = Message() main_message.add_header("Content-Type", "multipart/mixed") main_message.set_boundary(self.current_query.current_boundary) if self.current_query.has_change_sets: change_set_message = Message() change_set_boundary = create_boundary("changeset_", True) change_set_message.add_header("Content-Type", "multipart/mixed") change_set_message.set_boundary(change_set_boundary) for qry in self.current_query.change_sets: request = qry.build_request() message = self._serialize_request(request) change_set_message.attach(message) main_message.attach(change_set_message) for qry in self.current_query.get_queries: request = qry.build_request() message = self._serialize_request(request) main_message.attach(message) return message_as_bytes_or_string(main_message)
def _filter_message_body(self, message): if not message.is_multipart() or not STRIP_UNALLOWED_MIMETYPES: return message stripped_content = {} new = EmailMessage() for header, value in message.items(): new[header] = value for part in message.walk(): content_type = part.get_content_type() print content_type if not content_type in ALLOWED_MIMETYPES: if content_type not in stripped_content: stripped_content[content_type] = 0 stripped_content[content_type] = ( stripped_content[content_type] + 1 ) continue new.attach(part) new[ALTERED_MESSAGE_HEADER] = 'Stripped ' + ', '.join( ['%s*%s' % (key, value) for key, value in stripped_content.items()] ) return new
def make_mdn(sender, recipient, orig_message_id, subject): domain = sender.partition('@')[2] msg = Message() msg['MIME-Version'] = '1.0' msg['content-type'] = 'multipart/report; report-type=disposition-notification' msg['From'] = '<%s>' % sender msg['To'] = '<%s>' % recipient msg['Date'] = email.utils.formatdate() msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain) msg['Message-ID'] = msg_id msg['Subject'] = 'Processed: %s' % subject txt = Message() txt.set_payload('Your message was successfully processed.') msg.attach(txt) dn = Message() dn['Content-Type'] = 'message/disposition-notification' dn['Content-Transfer-Encoding'] = '7bit' dn.set_payload(NOTIFICATION % (sender, orig_message_id)) msg.attach(dn) return msg_id, msg.as_string()
def make_mdn(sender, recipient, orig_message_id, subject): domain = sender.partition('@')[2] msg = Message() msg['MIME-Version'] = '1.0' msg['content-type'] = 'multipart/report; report-type=disposition-notification' msg['From'] = '<%s>' % sender msg['To'] = '<%s>' % recipient msg['Date'] = email.utils.formatdate() msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain) msg['Message-ID'] = msg_id msg['Subject'] = 'Processed: %s' % subject txt = Message() txt.set_payload('Your message was successfully processed.') msg.attach(txt) dn = Message() dn['Content-Type'] = 'message/disposition-notification' dn['Content-Transfer-Encoding'] = '7bit' dn.set_payload(NOTIFICATION % (sender,orig_message_id)) msg.attach(dn) return msg_id, msg.as_string()
def _get_dehydrated_message(self, msg, record): new = EmailMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach( self._get_dehydrated_message(part, record) ) elif ( STRIP_UNALLOWED_MIMETYPES and not msg.get_content_type() in ALLOWED_MIMETYPES ): for header, value in msg.items(): new[header] = value # Delete header, otherwise when attempting to deserialize the # payload, it will be expecting a body for this. del new['Content-Transfer-Encoding'] new[ALTERED_MESSAGE_HEADER] = ( 'Stripped; Content type %s not allowed' % ( msg.get_content_type() ) ) new.set_payload('') elif msg.get_content_type() not in TEXT_STORED_MIMETYPES: filename = msg.get_filename() if not filename: extension = mimetypes.guess_extension(msg.get_content_type()) else: _, extension = os.path.splitext(filename) if not extension: extension = '.bin' attachment = MessageAttachment() attachment.document.save( uuid.uuid4().hex + extension, ContentFile( six.BytesIO( msg.get_payload(decode=True) ).getvalue() ) ) attachment.message = record for key, value in msg.items(): attachment[key] = value attachment.save() placeholder = EmailMessage() placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk) new = placeholder else: content_charset = msg.get_content_charset() if not content_charset: content_charset = 'ascii' try: # Make sure that the payload can be properly decoded in the # defined charset, if it can't, let's mash some things # inside the payload :-\ msg.get_payload(decode=True).decode(content_charset) except LookupError: logger.warning( "Unknown encoding %s; interpreting as ASCII!", content_charset ) msg.set_payload( msg.get_payload(decode=True).decode( 'ascii', 'ignore' ) ) except ValueError: logger.warning( "Decoding error encountered; interpreting as ASCII!", content_charset ) msg.set_payload( msg.get_payload(decode=True).decode( content_charset, 'ignore' ) ) new = msg return new
# E-Mail versenden from email.message import Message msg = Message() log = open(LogOutputFile, "r") # Error Log Datei auslesen Text = "" for line in log: Text += line log.close() # EMail erzeuegen msg.attach(LogErrorFile) # toDo msg.set_payload(Text) msg["Subject"] = MailSubject msg["From"] = MailFrom msg["To"] = MailTo # EMail verschicken server = smtplib.SMTP('localhost') server.sendmail(MailFrom, MailTo, msg.as_string()) server.quit() # Alle Dateien loeschen os.remove(OUITmpDatei) os.remove(LogOutputFile) os.remove(LogErrorFile)
if mimeencoding or (mimetype is None): mimetype = 'application/octet-stream' maintype, subtype = mimetype.split('/') if maintype == 'text': retval = MIMEText(fd.read(), _subtype=subtype) else: retval = MIMEBase(maintype, subtype) retval.set_payload(fd.read()) encoders.encode_base64(retval) retval.add_header('Content-Disposition', 'attachment', filename = filename) fd.close() return retval #attaches attachements, and finishes message msg.attach(body) for filename in sys.argv[1:]: msg.attach(attachment(filename)) file1.write(msg) file1.close() #uses SMTP to send the object to the server. #parses command line args if len(sys.argv) < 4: print "usage: %s server fromaddr toaddr [toaddr...]" % sys.argv[0] sys.exit(2) server, fromaddr, toaddrs = sys.argv[1], sys.argv[2], sys.argv[3:] #opens up the created file message = file1.open('message.txt', 'r')
class GPGEmail(SimpleEmail): """Třída pro vytvoření a odeslaní jednoduchého kryptovaného mailu.""" def __init__(self, to, from_, subject, content, key, html=False, smtp='localhost', charset='UTF-8'): """Inicializuj instanci. to -- adresa příjemce (zatím podporujeme jen jednoho příjemce) from_ -- adresa odesílatele subject -- předmět zprávy (může obsahovat buď řetězec nebo unicode content -- vlastní obsah zprávy key -- veřejný klíč, kterým má být zpráva zakryptována html -- příznak, zda obsah je html smtp -- adresa odesílacího serveru charset -- v případě, že content není v unicode, je zde uveden charset pro content """ super(GPGEmail, self).__init__(to, from_, subject, content, html=html, smtp=smtp, charset=charset) self.key = key def _create_message(self): """Return basic instance of Message.""" self.msg = Message() def _gpg_encrypt_content(self): import tempfile import gnupg try: # Work around gnupg > 2.1.19/Python gnupg module version incompatibility. gnupg._parsers.Verify.TRUST_LEVELS[ "ENCRYPTION_COMPLIANCE_MODE"] = 23 except: pass keyring = tempfile.mkstemp()[1] options = ('--no-secmem-warning', '--always-trust', '--no-default-keyring', '--keyring=%s' % keyring) gpg = gnupg.GPG(options=options) import_result = gpg.import_keys(self.key) fingerprints = import_result.fingerprints content = self.get_content_text(self.content, html=self.html, charset=self.charset) encryption_result = gpg.encrypt(str(content), fingerprints[0]) if not encryption_result.ok: raise pytis.util.ProgramError(encryption_result.stderr) # BUG: There is no `keyring' defined here so the following # statement is effectively void: try: os.remove(keyring) except Exception: pass return str(encryption_result) def create_headers(self): super(GPGEmail, self).create_headers() self.msg["Mime-version"] = "1.0" self.msg["Content-type"] = "Multipart/encrypted" self.msg["Content-transfer-encoding"] = "8bit" self.msg.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)" def create_content(self): # Part 1 firstSubMsg = email.message.Message() firstSubMsg["Content-Type"] = "application/pgp-encrypted" firstSubMsg["Content-Description"] = "PGP/MIME version identification" firstSubMsg.set_payload("Version: 1\n") # Part 2 if self.html: filename = 'content.html.pgp' else: filename = 'content.txt.pgp' encrypted = self._gpg_encrypt_content() secondSubMsg = email.message.Message() secondSubMsg.add_header("Content-Type", "application/octet-stream", name=filename) secondSubMsg.add_header("Content-Description", "OpenPGP encrypted message") secondSubMsg.add_header("Content-Disposition", "attachment", filename=filename) secondSubMsg.set_payload(encrypted) # Přidání částí do main self.msg.attach(firstSubMsg) self.msg.attach(secondSubMsg)
def _get_dehydrated_message(self, msg, record): new = EmailMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach( self._get_dehydrated_message(part, record) ) elif ( STRIP_UNALLOWED_MIMETYPES and not msg.get_content_type() in ALLOWED_MIMETYPES ): for header, value in msg.items(): new[header] = value # Delete header, otherwise when attempting to deserialize the # payload, it will be expecting a body for this. del new['Content-Transfer-Encoding'] new[ALTERED_MESSAGE_HEADER] = ( 'Stripped; Content type %s not allowed' % ( msg.get_content_type() ) ) new.set_payload('') elif msg.get_content_type() not in TEXT_STORED_MIMETYPES: filename = msg.get_filename() if not filename: extension = mimetypes.guess_extension(msg.get_content_type()) else: _, extension = os.path.splitext(filename) if not extension: extension = '.bin' attachment = MessageAttachment() # this will save on hd and in db # attachment.document.save( # uuid.uuid4().hex + extension, # ContentFile( # six.BytesIO( # msg.get_payload(decode=True) # ).getvalue() # ) # ) # save only on hd attach = open(os.path.join(settings.BASE_DIR, 'apps', 'cores', 'incoming', 'django_mailbox', self.name, 'attachments', uuid.uuid4().hex + extension), 'wb') attach.write(six.BytesIO(msg.get_payload(decode=True)).getvalue()) attach.close() attachment.message = record for key, value in msg.items(): attachment[key] = value #attachment.save() placeholder = EmailMessage() placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk) new = placeholder else: content_charset = msg.get_content_charset() if not content_charset: content_charset = 'ascii' try: # Make sure that the payload can be properly decoded in the # defined charset, if it can't, let's mash some things # inside the payload :-\ msg.get_payload(decode=True).decode(content_charset) except UnicodeDecodeError: msg.set_payload( msg.get_payload(decode=True).decode( content_charset, 'ignore' ) ) new = msg return new
def build_mail (self) -> str: """Build the multipart mail and return it as a string""" (headers, charset) = self.__finalize_header () root = Message () for header in headers: (name, value) = header.split (':', 1) root[name] = value.strip () msgs = [] parts = [] if len (self.content) == 1: if not self.attachments: parts.append ((root, self.content[0])) else: msg = Message () msgs.append (msg) root.attach (msg) parts.append ((msg, self.content[0])) else: if self.content: if self.attachments: parent = Message () msgs.append (parent) root.attach (parent) else: parent = root parent.set_type ('multipart/alternative') for content in self.content: msg = Message () msgs.append (msg) parts.append ((msg, content)) if content.related: base_message = Message () msgs.append (base_message) base_message.set_type ('multipart/related') base_message.attach (msg) for related in content.related: r = Message () msgs.append (r) parts.append ((r, related)) base_message.attach (r) parent.attach (base_message) else: parent.attach (msg) for (msg, content) in parts: content.set_message (msg, charset) if self.attachments: root.set_type ('multipart/related') for attachment in self.attachments: at = Message () msgs.append (at) root.attach (at) attachment.set_message (at, None) for msg in msgs: del msg['MIME-Version'] return self.sign (root.as_string (False) + '\n')
class StartMessage: def __init__(self, fromAdd, toAdd, subject, body): self.msg = Message() self.msg.set_payload(body) self["Subject"] = subject self.setFrom(fromAdd) self.setTo(toAdd) self.hasAttachments = False def setFrom(self, fromAdd): if not fromAdd or not type(fromAdd) == type(""): raise Exception("a message must have one and only one sender") self["From"] = fromAdd def setTo(self, to): if not to: raise Exception("a message must have at least one recipient") self._addresses(to, "To") self.to = to def setCc(self, cc): self._addresses(cc, "Cc") def addAttachment(self, attachment, filename, mimetype=None): if not mimetype: mimetype = mimetypes.guess_type(filename)[0] if not mimetype: raise Exception("could not determine MIME type for ", filename) if "/" in mimetype: major, minor = mimetype.split("/") else: major = mimetype minor = None if not self.hasAttachments: body = self.msg.set_payload() newMsg = MIMEMultipart() newMsg.attach(MIMEText(body)) 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) if major == "text": encoder = Encoders.encode_quopri else: encoder = Encoders.encode_base64 encoder(subMessage) self.msg.attach(subMessage) def _addresses(self, addresses, key): if hasattr(addresses, "__iter__"): addresses = ''.join(addresses) self[key] = addresses def __getitem__(self, key): return self.msg[key] def __setitem__(self, key, value): self.msg[key] = value def __getattr__(self, key): return getattr(self.msg, key) def __str__(self): return self.msg.as_string()
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'] = '{} {}: {}'.format( headers.get('Subject', '[Webware Error]'), *sys.exc_info()[:2]) for header, value in headers.items(): if isinstance(value, (list, tuple)): value = ','.join(value) message.add_header(header, value) # Construct the message body if self.setting('EmailErrorReportAsAttachment'): # start off with a text/plain part text = self._emailBody.format(path=self.servletPathname(), ascTime=asclocaltime(self._time), 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 Webware error message') part.add_header('Content-Disposition', 'attachment', filename='WebwareErrorMsg.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: # fetch individual parts until we get an IndexError 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
def encrypt_mail(inmail, recipients, contingencydir, gpghomedir=None): parser = Parser() if hasattr(inmail, "read"): orig = parser.parse(inmail) else: orig = parser.parsestr(inmail) contingencydir = os.path.expanduser(contingencydir) if gpghomedir: gpghomedir = os.path.expanduser(gpghomedir) if isinstance(recipients, str): recipients = [recipients] # minimal message with data to be encrypted new = Message() keep_headers = ("Content-Type", "Transfer-Encoding", "Content-Disposition") for h in keep_headers: if h in orig: new[h] = orig[h] if orig.is_multipart(): for p in orig.get_payload(): new.attach(p) else: new.set_payload(orig.get_payload()) if recipients: gpg_command = ["gpg"] if gpghomedir: gpg_command.extend(["--homedir", gpghomedir]) gpg_command.extend(["--batch", "--quiet", "--no-secmem-warning", "--no-tty", "--trust-model", "always", "--armor", "--output", "-", "--encrypt"]) for r in recipients: gpg_command.append("-r") gpg_command.append(r) popen = subprocess.Popen(gpg_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) encrypted, errors = popen.communicate(input=str(new)) status = popen.returncode else: status = "invalid" errors = "No recipients set" if status == 0 and "-----BEGIN PGP MESSAGE-----" in encrypted: new_outer = MIMEMultipart("encrypted", protocol="application/pgp-encrypted") new_outer["Transfer-Encoding"] = "7bit" new_outer.preamble = "OpenPGP/MIME encrypted message, see "\ "http://tools.ietf.org/html/rfc3156" gpg_attachment = MIMEApplication("Version: 1\n", _subtype="pgp-encrypted", _encoder=encode_7or8bit) gpg_attachment["Content-Disposition"] = "inline" new_outer.attach(gpg_attachment) gpg_message = MIMEApplication(encrypted, _subtype="octet-stream", _encoder=encode_7or8bit) gpg_message["Content-Disposition"] = "inline" new_outer.attach(gpg_message) else: now = datetime.datetime.now() ofilename = "encryptmail-" + str(now) + "-unencrypted.eml" localcopy = os.path.join(contingencydir, ofilename) try: fd = os.open(localcopy, os.O_WRONLY | os.O_CREAT, 0600) out = os.fdopen(fd, "wb") out.write(str(orig)) out.close() except: log.error("Storing unencrypted message", exc_info=True) try: with tempfile.NamedTemporaryFile( prefix="encryptmail-", suffix="-unencrypted.eml") as out: out.write(str(orig)) localcopy = out.name except: log.error("Storing unencrypted message in tempdir", exc_info=True) localcopy = "nowhere (too many exceptions)" message = """{sep} gpg encryption failed with exit status {status} {errors} A local copy of the e-mail was stored at {localcopy} {sep}""".format(status=status, errors=errors, localcopy=localcopy, sep="=" * 80) new_outer = MIMEText(message) new_outer = copy_headers(orig, new_outer) return new_outer.as_string()
class SmartMessage: """A simplified interface to Python's library for creating email messages, with and without MIME attachments.""" def __init__(self, fromAddr, toAddrs, subject, body): """Start off on the assumption that the message will be a simple RFC 2822 message with no MIME.""" self.msg = Message() self.msg.set_payload(body) self['Subject'] = subject self.setFrom(fromAddr) self.setTo(toAddrs) self.hasAttachments = False def setFrom(self, fromAddr): "Sets the address of the sender of the message." if not fromAddr or not type(fromAddr) == type(''): raise Exception('A message must have one and only one sender.') self['From'] = fromAddr def setTo(self, to): "Sets the address or addresses that will receive this message." if not to: raise Exception('A message must have at least one recipient.') self._addresses(to, 'To') #Also store the addresses as a list, for the benefit of future #code that will actually send this message. self.to = to def setCc(self, cc): """Sets the address or addresses that should receive this message, even though it's not addressed directly to them ("carbon-copy").""" self._addresses(cc, 'Cc') def addAttachment(self, attachment, filename, mimetype=None): "Attaches the given file to this message." #Figure out the major and minor MIME type of this attachment, #given its filename. if not mimetype: mimetype = mimetypes.guess_type(filename)[0] if not mimetype: raise Exception("Couldn't determine MIME type for ", filename) if '/' in mimetype: major, minor = mimetype.split('/') else: major = mimetype minor = None #The message was constructed under the assumption that it was #a single-part message. Now that we know there's to be at #least one attachment, we need to change it into a multi-part #message, with the first part being the body of the message. if not self.hasAttachments: body = self.msg.get_payload() newMsg = MIMEMultipart() newMsg.attach(MIMEText(body)) #Copy over the old headers to the new object. 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) #Encode text attachments as quoted-printable, and all other #types as base64. if major == 'text': encoder = Encoders.encode_quopri else: encoder = Encoders.encode_base64 encoder(subMessage) #Link the MIME message part with its parent message. self.msg.attach(subMessage) def _addresses(self, addresses, key): """Sets the given header to a string representation of the given list of addresses.""" if hasattr(addresses, '__iter__'): addresses = ', '.join(addresses) self[key] = addresses #A few methods to let scripts treat this object more or less like #a Message or MultipartMessage, by delegating to the real Message #or MultipartMessage this object holds. def __getitem__(self, key): "Return a header of the underlying message." return self.msg[key] def __setitem__(self, key, value): "Set a header of the underlying message." self.msg[key] = value def __getattr__(self, key): return getattr(self.msg, key) def __str__(self): "Returns a string representation of this message." return self.msg.as_string()
class SmartMessage: """A simplified interface to Python's library for creating email messages, with and without MIME attachments.""" def __init__(self, fromAddr, toAddrs, subject, body): """Start off on the assumption that the message will be a simple RFC 2822 message with no MIME.""" self.msg = Message() self.msg.set_payload(body) self["Subject"] = subject self.setFrom(fromAddr) self.setTo(toAddrs) self.hasAttachments = False def setFrom(self, fromAddr): "Sets the address of the sender of the message." if not fromAddr or not type(fromAddr) == type(""): raise Exception("A message must have one and only one sender.") self["From"] = fromAddr def setTo(self, to): "Sets the address or addresses that will receive this message." if not to: raise Exception("A message must have at least one recipient.") self._addresses(to, "To") # Also store the addresses as a list, for the benefit of future # code that will actually send this message. self.to = to def setCc(self, cc): """Sets the address or addresses that should receive this message, even though it's not addressed directly to them ("carbon-copy").""" self._addresses(cc, "Cc") def addAttachment(self, attachment, filename, mimetype=None): "Attaches the given file to this message." # Figure out the major and minor MIME type of this attachment, # given its filename. if not mimetype: mimetype = mimetypes.guess_type(filename)[0] if not mimetype: raise Exception("Couldn't determine MIME type for ", filename) if "/" in mimetype: major, minor = mimetype.split("/") else: major = mimetype minor = None # The message was constructed under the assumption that it was # a single-part message. Now that we know there's to be at # least one attachment, we need to change it into a multi-part # message, with the first part being the body of the message. if not self.hasAttachments: body = self.msg.get_payload() newMsg = MIMEMultipart() newMsg.attach(MIMEText(body)) # Copy over the old headers to the new object. 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) # Encode text attachments as quoted-printable, and all other # types as base64. if major == "text": encoder = Encoders.encode_quopri else: encoder = Encoders.encode_base64 encoder(subMessage) # Link the MIME message part with its parent message. self.msg.attach(subMessage) def _addresses(self, addresses, key): """Sets the given header to a string representation of the given list of addresses.""" if hasattr(addresses, "__iter__"): addresses = ", ".join(addresses) self[key] = addresses # A few methods to let scripts treat this object more or less like # a Message or MultipartMessage, by delegating to the real Message # or MultipartMessage this object holds. def __getitem__(self, key): "Return a header of the underlying message." return self.msg[key] def __setitem__(self, key, value): "Set a header of the underlying message." self.msg[key] = value def __getattr__(self, key): return getattr(self.msg, key) def __str__(self): "Returns a string representation of this message." return self.msg.as_string()
def prepare_multipart_body(self, content_index=0): # type: (int) -> int """Will prepare the body of this request according to the multipart information. This call assumes the on_request policies have been applied already in their correct context (sync/async) Does nothing if "set_multipart_mixed" was never called. :param int content_index: The current index of parts within the batch message. :returns: The updated index after all parts in this request have been added. :rtype: int """ if not self.multipart_mixed_info: return 0 requests = self.multipart_mixed_info[0] # type: List[HttpRequest] boundary = self.multipart_mixed_info[2] # type: Optional[str] # Update the main request with the body main_message = Message() main_message.add_header("Content-Type", "multipart/mixed") if boundary: main_message.set_boundary(boundary) for req in requests: part_message = Message() if req.multipart_mixed_info: content_index = req.prepare_multipart_body( content_index=content_index) part_message.add_header("Content-Type", req.headers['Content-Type']) payload = req.serialize() # We need to remove the ~HTTP/1.1 prefix along with the added content-length payload = payload[payload.index(b'--'):] else: part_message.add_header("Content-Type", "application/http") part_message.add_header("Content-Transfer-Encoding", "binary") part_message.add_header("Content-ID", str(content_index)) payload = req.serialize() content_index += 1 part_message.set_payload(payload) main_message.attach(part_message) try: from email.policy import HTTP full_message = main_message.as_bytes(policy=HTTP) eol = b"\r\n" except ImportError: # Python 2.7 # Right now we decide to not support Python 2.7 on serialization, since # it doesn't serialize a valid HTTP request (and our main scenario Storage refuses it) raise NotImplementedError( "Multipart request are not supported on Python 2.7") # full_message = main_message.as_string() # eol = b'\n' _, _, body = full_message.split(eol, 2) self.set_bytes_body(body) self.headers["Content-Type"] = ("multipart/mixed; boundary=" + main_message.get_boundary()) return content_index
# E-Mail versenden from email.message import Message msg = Message() log = open(LogOutputFile, "r") # Error Log Datei auslesen Text = "" for line in log: Text += line log.close() # EMail erzeuegen msg.attach(LogErrorFile) # toDo msg.set_payload(Text) msg["Subject"] = MailSubject msg["From"] = MailFrom msg["To"] = MailTo # EMail verschicken server = smtplib.SMTP('localhost') server.sendmail(MailFrom, MailTo, msg.as_string()) server.quit() # Alle Dateien loeschen os.remove(OUITmpDatei) os.remove(LogOutputFile) os.remove(LogErrorFile)
def _get_dehydrated_message(self, msg, record): settings = utils.get_settings() new = EmailMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach( self._get_dehydrated_message(part, record) ) elif ( settings['strip_unallowed_mimetypes'] and not msg.get_content_type() in settings['allowed_mimetypes'] ): for header, value in msg.items(): new[header] = value # Delete header, otherwise when attempting to deserialize the # payload, it will be expecting a body for this. del new['Content-Transfer-Encoding'] new[settings['altered_message_header']] = ( 'Stripped; Content type %s not allowed' % ( msg.get_content_type() ) ) new.set_payload('') elif ( ( msg.get_content_type() not in settings['text_stored_mimetypes'] ) or ('attachment' in msg.get('Content-Disposition', '')) ): filename = None raw_filename = msg.get_filename() if raw_filename: filename = utils.convert_header_to_unicode(raw_filename) if not filename: extension = mimetypes.guess_extension(msg.get_content_type()) else: _, extension = os.path.splitext(filename) if not extension: extension = '.bin' attachment = MessageAttachment() attachment.document.save( uuid.uuid4().hex + extension, ContentFile( six.BytesIO( msg.get_payload(decode=True) ).getvalue() ) ) attachment.message = record for key, value in msg.items(): attachment[key] = value attachment.save() placeholder = EmailMessage() placeholder[ settings['attachment_interpolation_header'] ] = str(attachment.pk) new = placeholder else: content_charset = msg.get_content_charset() if not content_charset: content_charset = 'ascii' try: # Make sure that the payload can be properly decoded in the # defined charset, if it can't, let's mash some things # inside the payload :-\ msg.get_payload(decode=True).decode(content_charset) except LookupError: logger.warning( "Unknown encoding %s; interpreting as ASCII!", content_charset ) msg.set_payload( msg.get_payload(decode=True).decode( 'ascii', 'ignore' ) ) except ValueError: logger.warning( "Decoding error encountered; interpreting %s as ASCII!", content_charset ) msg.set_payload( msg.get_payload(decode=True).decode( 'ascii', 'ignore' ) ) new = msg return new
def request_cached(url, type, msg=None, *, method="GET", headers=(), cleanup, **kw): if msg is None: msg = url print(method, msg, end=" ", flush=True, file=sys.stderr) path = url.split("/") dir = os.path.join(*path[:-1]) suffix = hashlib.md5(url.encode()).digest()[:6] suffix = urlsafe_b64encode(suffix).decode("ascii") if path[-1]: suffix = path[-1] + os.extsep + suffix suffix += os.extsep metadata = os.path.join(dir, suffix + "mime") try: metadata = open(metadata, "rb") except FileNotFoundError: os.makedirs(dir, exist_ok=True) with open(metadata, "xb") as metadata: response = http_request(url, (type,), method=method, headers=headers + ( ("Accept-Encoding", "gzip, x-gzip"), ), **kw) cleanup.enter_context(response) print(response.status, response.reason, flush=True, file=sys.stderr) header = response.info() for field in header_list(header, "Connection"): del header[field] for field in ( "Close", "Connection", "Content-Length", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "Public", "Transfer-Encoding", "TE", "Trailer", "Upgrade", ): del header[field] [type, value] = header.get_params()[0] suffix += { 'text/html': 'html', 'text/javascript': 'js', 'application/json': 'json', }[type] for encoding in header_list(header, "Content-Encoding"): if encoding.lower() in {"gzip", "x-gzip"}: suffix += os.extsep + "gz" break cache = open(os.path.join(dir, suffix), "xb") cleanup.enter_context(cache) msg = Message() msg.add_header("Content-Type", "message/external-body; access-type=local-file", name=suffix) msg.attach(header) metadata = email.generator.BytesGenerator(metadata, mangle_from_=False, maxheaderlen=0) metadata.flatten(msg) return (header, TeeReader(response, cache.write)) with metadata: msg = email.message_from_binary_file(metadata) cache = os.path.join(dir, msg.get_param("name")) [msg] = msg.get_payload() response = cleanup.enter_context(open(cache, "rb")) print("(cached)", flush=True, file=sys.stderr) return (msg, response)
def _get_dehydrated_message(self, msg: RawMessage, record: Message) -> Message: """ We want to hand truncated messages so we split this method into several and change part with attachments. """ new = RawMessage() if msg.is_multipart(): for header, value in msg.items(): new[header] = value for part in msg.get_payload(): new.attach(self._get_dehydrated_message(part, record)) return new if (mailbox_settings['strip_unallowed_mimetypes'] and msg.get_content_type() not in mailbox_settings['allowed_mimetypes']): return self._get_dehydrated_as_stripped(msg, record) if ((msg.get_content_type() not in mailbox_settings['text_stored_mimetypes']) or ('attachment' in msg.get('Content-Disposition', ''))): return self._get_dehydrated_attachment(msg, record) content_charset = msg.get_content_charset() if not content_charset: content_charset = 'ascii' raw_payload = msg.get_payload() if raw_payload and raw_payload.splitlines( )[-1] == '----- Message truncated -----': raw_lines = raw_payload.splitlines()[:-1] truncated_payload = ''.join(raw_lines) truncated_payload = truncated_payload[:-(len(truncated_payload) % 4)] msg.set_payload(truncated_payload) try: # Make sure that the payload can be properly decoded in the # defined charset, if it can't, let's mash some things # inside the payload :-\ msg.get_payload(decode=True).decode(content_charset) except LookupError: import codecs try: payload = codecs.decode(msg.get_payload(decode=True), content_charset, 'replace') except LookupError: import webencodings try: payload = webencodings.decode(msg.get_payload(decode=True), content_charset, 'replace')[0] except LookupError: logger.warning( "Unknown encoding %s; interpreting as ASCII!", content_charset) payload = msg.get_payload(decode=True).decode( 'ascii', 'ignore') msg.set_payload(payload) except ValueError: logger.warning( "Decoding error encountered; interpreting %s as ASCII!", content_charset) msg.set_payload( msg.get_payload(decode=True).decode('ascii', 'ignore')) return msg
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