8000 gh-77116: Add SMTP buffering example to logging cookbook. (GH-96324) · python/cpython@43a6dea · GitHub
[go: up one dir, main page]

Skip to content

Commit 43a6dea

Browse files
authored
gh-77116: Add SMTP buffering example to logging cookbook. (GH-96324)
1 parent ccf94a6 commit 43a6dea

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

Doc/howto/logging-cookbook.rst

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,6 +2678,88 @@ You can of course use the conventional means of decoration::
26782678
...
26792679

26802680

2681+
.. _buffered-smtp:
2682+
2683+
Sending logging messages to email, with buffering
2684+
-------------------------------------------------
2685+
2686+
To illustrate how you can send log messages via email, so that a set number of
2687+
messages are sent per email, you can subclass
2688+
:class:`~logging.handlers.BufferingHandler`. In the following example, which you can
2689+
adapt to suit your specific needs, a simple test harness is provided which allows you
2690+
to run the script with command line arguments specifying what you typically need to
2691+
send things via SMTP. (Run the downloaded script with the ``-h`` argument to see the
2692+
required and optional arguments.)
2693+
2694+
.. code-block:: python
2695+
2696+
import logging
2697+
import logging.handlers
2698+
import smtplib
2699+
2700+
class BufferingSMTPHandler(logging.handlers.BufferingHandler):
2701+
def __init__(self, mailhost, port, username, password, fromaddr, toaddrs,
2702+
subject, capacity):
2703+
logging.handlers.BufferingHandler.__init__(self, capacity)
2704+
self.mailhost = mailhost
2705+
self.mailport = port
2706+
self.username = username
2707+
self.password = password
2708+
self.fromaddr = fromaddr
2709+
if isinstance(toaddrs, str):
2710+
toaddrs = [toaddrs]
2711+
self.toaddrs = toaddrs
2712+
self.subject = subject
2713+
self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
2714+
2715+
def flush(self):
2716+
if len(self.buffer) > 0:
2717+
try:
2718+
smtp = smtplib.SMTP(self.mailhost, self.mailport)
2719+
smtp.starttls()
2720+
smtp.login(self.username, self.password)
2721+
msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, ','.join(self.toaddrs), self.subject)
2722+
for record in self.buffer:
2723+
s = self.format(record)
2724+
msg = msg + s + "\r\n"
2725+
smtp.sendmail(self.fromaddr, self.toaddrs, msg)
2726+
smtp.quit()
2727+
except Exception:
2728+
if logging.raiseExceptions:
2729+
raise
2730+
self.buffer = []
2731+
2732+
if __name__ == '__main__':
2733+
import argparse
2734+
2735+
ap = argparse.ArgumentParser()
2736+
aa = ap.add_argument
2737+
aa('host', metavar='HOST', help='SMTP server')
2738+
aa('--port', '-p', type=int, default=587, help='SMTP port')
2739+
aa('user', metavar='USER', help='SMTP username')
2740+
aa('password', metavar='PASSWORD', help='SMTP password')
2741+
aa('to', metavar='TO', help='Addressee for emails')
2742+
aa('sender', metavar='SENDER', help='Sender email address')
2743+
aa('--subject', '-s',
2744+
default='Test Logging email from Python logging module (buffering)',
2745+
help='Subject of email')
2746+
options = ap.parse_args()
2747+
logger = logging.getLogger()
2748+
logger.setLevel(logging.DEBUG)
2749+
h = BufferingSMTPHandler(options.host, options.port, options.user,
2750+
options.password, options.sender,
2751+
options.to, options.subject, 10)
2752+
logger.addHandler(h)
2753+
for i in range(102):
2754+
logger.info("Info index = %d", i)
2755+
h.flush()
2756+
h.close()
2757+
2758+
If you run this script and your SMTP server is correctly set up, you should find that
2759+
it sends eleven emails to the addressee you specify. The first ten emails will each
2760+
have ten log messages, and the eleventh will have two messages. That makes up 102
2761+
messages as specified in the script.
2762+
26812763
.. _utc-formatting:
26822764

26832765
Formatting times using UTC (GMT) via configuration

0 commit comments

Comments
 (0)
0