def publish(self, title, report_parts, rawfh): """ Publish the report parts to local files. Each report part is a text with a title and specific extension. For html and plaintext publishing the report part is unique, for csv publishing the stats and unparsed string are plain text and report items are csv texts. """ logger.info('Checking and creating the report directories') workdir = os.path.join(self.pubdir, self.dirname) filename = None if not os.path.isdir(workdir): try: os.makedirs(workdir) except OSError as e: logger.error('Error creating directory "{0}": {0}'.format( workdir, e)) logger.error('File publisher exiting.') return fmtname = '{0}-{1}-{2}.{3}' if len(report_parts) > 1 else '{0}.{3}' for i in range(len(report_parts)): ext = report_parts[i].ext # Skip report formats not related with this publisher if not self.has_format(ext): continue filename = fmtname.format(self.filename, i, report_parts[i].title, ext) repfile = os.path.join(workdir, filename) logger.info('Dumping the report part {1} into {0}'.format(repfile, i)) fh = open(repfile, 'w') fh.write(report_parts[i].text) fh.close() print('Report {0}saved in: {1}'.format('part ' if ext == 'csv' else '', repfile)) if self.notify: logger.info('Creating an email message') publoc = '{0}/{1}/{2}'.format(self.pubroot, self.dirname, filename) from email.mime.text import MIMEText eml = MIMEText('New Lograptor report is available at:\r\n{0}'.format( publoc)) eml['Subject'] = '{0} (report notification)'.format(title) eml['To'] = ', '.join(self.notify) eml['X-Mailer'] = u'{0}-{1}'.format(lograptor.Lograptor.__name__, __version__) msg = eml.as_string() logger.info('Figuring out if we are using sendmail or smtplib') if self.smtpserv[0] == '/': mail_sendmail(self.smtpserv, msg) else: mail_smtp(self.smtpserv, self.fromaddr, self.notify, msg) print('Notification mailed to: {0}'.format(','.join(self.notify))) if self.rawlogs: logfilen = '{0}.log'.format(self.filename) logfile = os.path.join(workdir, '{0}.gz'.format(logfilen)) logger.info('Gzipping logs and writing them to {0}'.format(logfilen)) outfh = open(logfile, 'w+b') do_chunked_gzip(rawfh, outfh, logfilen) outfh.close() print('Gzipped logs saved in: {0}'.format(logfile)) # Purge old reports self.prune_old()
def publish(self, title, report_parts, rawfh): """ Publish the report parts to local files. Each report part is a text with a title and specific extension. For html and plaintext publishing the report part is unique, for csv publishing the stats and unparsed string are plain text and report items are csv texts. """ logger.info('Checking and creating the report directories') workdir = os.path.join(self.pubdir, self.dirname) filename = None if not os.path.isdir(workdir): try: os.makedirs(workdir) except OSError as e: logger.error('Error creating directory "{0}": {0}'.format( workdir, e)) logger.error('File publisher exiting.') return fmtname = '{0}-{1}-{2}.{3}' if len(report_parts) > 1 else '{0}.{3}' for i in range(len(report_parts)): ext = report_parts[i].ext # Skip report formats not related with this publisher if not self.has_format(ext): continue filename = fmtname.format(self.filename, i, report_parts[i].title, ext) repfile = os.path.join(workdir, filename) logger.info('Dumping the report part {1} into {0}'.format(repfile, i)) fh = open(repfile, 'w') fh.write(report_parts[i].text) fh.close() print(('Report {0}saved in: {1}'.format('part ' if ext == 'csv' else '', repfile))) if self.notify: logger.info('Creating an email message') publoc = '{0}/{1}/{2}'.format(self.pubroot, self.dirname, filename) from email.mime.text import MIMEText eml = MIMEText('New Lograptor report is available at:\r\n{0}'.format( publoc)) eml['Subject'] = '{0} (report notification)'.format(title) eml['To'] = ', '.join(self.notify) eml['X-Mailer'] = '{0}-{1}'.format(lograptor.Lograptor.__name__, __version__) msg = eml.as_string() logger.info('Figuring out if we are using sendmail or smtplib') if self.smtpserv[0] == '/': mail_sendmail(self.smtpserv, msg) else: mail_smtp(self.smtpserv, self.fromaddr, self.notify, msg) print(('Notification mailed to: {0}'.format(','.join(self.notify)))) if self.rawlogs: logfilen = '{0}.log'.format(self.filename) logfile = os.path.join(workdir, '{0}.gz'.format(logfilen)) logger.info('Gzipping logs and writing them to {0}'.format(logfilen)) outfh = open(logfile, 'w+b') do_chunked_gzip(rawfh, outfh, logfilen) outfh.close() print(('Gzipped logs saved in: {0}'.format(logfile))) # Purge old reports self.prune_old()
def publish(self, title, report_parts, rawfh): """ Publish by sending the report by e-mail """ from email.mime.base import MIMEBase from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.utils import formatdate, make_msgid logger.info('Creating an email message') logger.debug('Creating a main header') root_part = MIMEMultipart('mixed') root_part.preamble = 'This is a multi-part message in MIME format.' has_text_plain = any(text_part.ext == 'txt' for text_part in report_parts) logger.debug('Creating the text/"text_type" parts') for text_part in report_parts: # Skip report formats not related with this publisher if not self.has_format(text_part.ext): continue if text_part.ext == 'txt' or (not has_text_plain and text_part.ext == 'html'): root_part.attach(MIMEText(text_part.text, text_part.ext, 'utf-8')) else: attach_part = MIMEText(text_part.text, text_part.ext, 'utf-8') attach_part.add_header('Content-Disposition', 'attachment', filename='{0}.{1}'.format(text_part.title, text_part.ext)) root_part.attach(attach_part) if self.rawlogs: try: import cStringIOcd out = cStringIO.StringIO() except ImportError: import io out = io.StringIO() do_chunked_gzip(rawfh, out, filename='raw.log.gz') out.seek(0, os.SEEK_END) size = out.tell() if size > self.rawlogs_limit: logger.warning('{0} is over the defined max of "{1}"' .format(size, self.rawlogs)) logger.warning('Not attaching the raw logs') else: logger.debug('Creating the application/x-gzip part') attach_part = MIMEBase('application', 'x-gzip') attach_part.set_payload(out.getvalue()) from email.encoders import encode_base64 logger.debug('Encoding the gzipped raw logs with base64') encode_base64(attach_part) attach_part.add_header('Content-Disposition', 'attachment', filename='raw.log.gz') root_part.attach(attach_part) if self.gpg_encrypt: logger.info('Encrypting the message') from StringIO import StringIO try: import gpgme if self.gpg_keyringdir and os.path.exists(self.gpg_keyringdir): logger.debug('Setting keyring dir to {0}'.format( self.gpg_keyringdir)) os.environ['GNUPGHOME'] = self.gpg_keyringdir msg = root_part.as_string() logger.debug('----Cleartext follows----') logger.debug(msg) logger.debug('----Cleartext ends----') cleartext = StringIO(msg) ciphertext = StringIO() ctx = gpgme.Context() ctx.armor = True recipients = [] signers = [] logger.debug('gpg_recipients={0}'.format(self.gpg_recipients)) logger.debug('gpg_signers={0}'.format(self.gpg_signers)) if self.gpg_recipients is not None: for recipient in self.gpg_recipients: logger.debug('Looking for an encryption key for {0}'.format( recipient)) recipients.append(ctx.get_key(recipient)) else: for key in ctx.keylist(): for subkey in key.subkeys: if subkey.can_encrypt: logger.debug('Found can_encrypt key={0}'.format( subkey.keyid)) recipients.append(key) break if self.gpg_signers is not None: for signer in self.gpg_signers: logger.debug('Looking for a signing key for {0}'.format( signer)) signers.append(ctx.get_key(signer)) if len(signers) > 0: logger.info('Encrypting and signing the report') ctx.signers = signers ctx.encrypt_sign(recipients, gpgme.ENCRYPT_ALWAYS_TRUST, cleartext, ciphertext) else: logger.info('Encrypting the report') ctx.encrypt(recipients, gpgme.ENCRYPT_ALWAYS_TRUST, cleartext, ciphertext) logger.debug('Creating the MIME envelope for PGP') gpg_envelope_part = MIMEMultipart('encrypted') gpg_envelope_part.set_param('protocol', 'application/pgp-encrypted', header='Content-Type') gpg_envelope_part.preamble = ('This is an OpenPGP/MIME encrypted message ' '(RFC 2440 and 3156)') gpg_mime_version_part = MIMEBase('application', 'pgp-encrypted') gpg_mime_version_part.add_header('Content-Disposition', 'PGP/MIME version identification') gpg_mime_version_part.set_payload('Version: 1') gpg_payload_part = MIMEBase('application', 'octet-stream', name='encrypted.asc') gpg_payload_part.add_header('Content-Disposition', 'OpenPGP encrypted message') gpg_payload_part.add_header('Content-Disposition', 'inline', filename='encrypted.asc') gpg_payload_part.set_payload(ciphertext.getvalue()) gpg_envelope_part.attach(gpg_mime_version_part) gpg_envelope_part.attach(gpg_payload_part) # envelope becomes the new root part root_part = gpg_envelope_part except ImportError: logger.error('Need crypto libraries for gpg_encrypt.') logger.error('Install pygpgme for GPG encryption support.') logger.error('Not mailing the report out of caution.') return # Define headers root_part['Date'] = formatdate() root_part['From'] = self.fromaddr root_part['To'] = ', '.join(self.mailto) root_part['Subject'] = title root_part['Message-Id'] = make_msgid() root_part['X-Mailer'] = u'{0}-{1}'.format(lograptor.Lograptor.__name__, __version__) logger.debug('Creating the message as string') msg = root_part.as_string() logger.debug('----Message follows----') logger.debug(msg) logger.debug('----Message ends----') logger.info('Figuring out if we are using sendmail or smtplib') if re.compile('^/').search(self.smtpserv): mail_sendmail(self.smtpserv, msg) else: mail_smtp(self.smtpserv, self.fromaddr, self.mailto, msg) print('Mailed the report to: {0}'.format(','.join(self.mailto)))
def publish(self, title, report_parts, rawfh): """ Publish by sending the report by e-mail """ from email.mime.base import MIMEBase from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.utils import formatdate, make_msgid logger.info('Creating an email message') logger.debug('Creating a main header') root_part = MIMEMultipart('mixed') root_part.preamble = 'This is a multi-part message in MIME format.' has_text_plain = any(text_part.ext == 'txt' for text_part in report_parts) logger.debug('Creating the text/"text_type" parts') for text_part in report_parts: # Skip report formats not related with this publisher if not self.has_format(text_part.ext): continue if text_part.ext == 'txt' or (not has_text_plain and text_part.ext == 'html'): root_part.attach(MIMEText(text_part.text, text_part.ext, 'utf-8')) else: attach_part = MIMEText(text_part.text, text_part.ext, 'utf-8') attach_part.add_header('Content-Disposition', 'attachment', filename='{0}.{1}'.format(text_part.title, text_part.ext)) root_part.attach(attach_part) if self.rawlogs: try: import cStringIOcd out = cStringIO.StringIO() except ImportError: import io out = io.StringIO() do_chunked_gzip(rawfh, out, filename='raw.log.gz') out.seek(0, os.SEEK_END) size = out.tell() if size > self.rawlogs_limit: logger.warning('{0} is over the defined max of "{1}"' .format(size, self.rawlogs)) logger.warning('Not attaching the raw logs') else: logger.debug('Creating the application/x-gzip part') attach_part = MIMEBase('application', 'x-gzip') attach_part.set_payload(out.getvalue()) from email.encoders import encode_base64 logger.debug('Encoding the gzipped raw logs with base64') encode_base64(attach_part) attach_part.add_header('Content-Disposition', 'attachment', filename='raw.log.gz') root_part.attach(attach_part) if self.gpg_encrypt: logger.info('Encrypting the message') from io import StringIO try: import gpgme if self.gpg_keyringdir and os.path.exists(self.gpg_keyringdir): logger.debug('Setting keyring dir to {0}'.format( self.gpg_keyringdir)) os.environ['GNUPGHOME'] = self.gpg_keyringdir msg = root_part.as_string() logger.debug('----Cleartext follows----') logger.debug(msg) logger.debug('----Cleartext ends----') cleartext = StringIO(msg) ciphertext = StringIO() ctx = gpgme.Context() ctx.armor = True recipients = [] signers = [] logger.debug('gpg_recipients={0}'.format(self.gpg_recipients)) logger.debug('gpg_signers={0}'.format(self.gpg_signers)) if self.gpg_recipients is not None: for recipient in self.gpg_recipients: logger.debug('Looking for an encryption key for {0}'.format( recipient)) recipients.append(ctx.get_key(recipient)) else: for key in ctx.keylist(): for subkey in key.subkeys: if subkey.can_encrypt: logger.debug('Found can_encrypt key={0}'.format( subkey.keyid)) recipients.append(key) break if self.gpg_signers is not None: for signer in self.gpg_signers: logger.debug('Looking for a signing key for {0}'.format( signer)) signers.append(ctx.get_key(signer)) if len(signers) > 0: logger.info('Encrypting and signing the report') ctx.signers = signers ctx.encrypt_sign(recipients, gpgme.ENCRYPT_ALWAYS_TRUST, cleartext, ciphertext) else: logger.info('Encrypting the report') ctx.encrypt(recipients, gpgme.ENCRYPT_ALWAYS_TRUST, cleartext, ciphertext) logger.debug('Creating the MIME envelope for PGP') gpg_envelope_part = MIMEMultipart('encrypted') gpg_envelope_part.set_param('protocol', 'application/pgp-encrypted', header='Content-Type') gpg_envelope_part.preamble = ('This is an OpenPGP/MIME encrypted message ' '(RFC 2440 and 3156)') gpg_mime_version_part = MIMEBase('application', 'pgp-encrypted') gpg_mime_version_part.add_header('Content-Disposition', 'PGP/MIME version identification') gpg_mime_version_part.set_payload('Version: 1') gpg_payload_part = MIMEBase('application', 'octet-stream', name='encrypted.asc') gpg_payload_part.add_header('Content-Disposition', 'OpenPGP encrypted message') gpg_payload_part.add_header('Content-Disposition', 'inline', filename='encrypted.asc') gpg_payload_part.set_payload(ciphertext.getvalue()) gpg_envelope_part.attach(gpg_mime_version_part) gpg_envelope_part.attach(gpg_payload_part) # envelope becomes the new root part root_part = gpg_envelope_part except ImportError: logger.error('Need crypto libraries for gpg_encrypt.') logger.error('Install pygpgme for GPG encryption support.') logger.error('Not mailing the report out of caution.') return # Define headers root_part['Date'] = formatdate() root_part['From'] = self.fromaddr root_part['To'] = ', '.join(self.mailto) root_part['Subject'] = title root_part['Message-Id'] = make_msgid() root_part['X-Mailer'] = '{0}-{1}'.format(lograptor.Lograptor.__name__, __version__) logger.debug('Creating the message as string') msg = root_part.as_string() logger.debug('----Message follows----') logger.debug(msg) logger.debug('----Message ends----') logger.info('Figuring out if we are using sendmail or smtplib') if re.compile('^/').search(self.smtpserv): mail_sendmail(self.smtpserv, msg) else: mail_smtp(self.smtpserv, self.fromaddr, self.mailto, msg) print(('Mailed the report to: {0}'.format(','.join(self.mailto))))