From 7ea839cfb1bec829233c10acd2945e92a840751c Mon Sep 17 00:00:00 2001 From: "Stuart D. Gathman" Date: Thu, 18 Jun 2020 19:53:43 -0400 Subject: [PATCH] Update docs for @decode callback. --- Milter/__init__.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Milter/__init__.py b/Milter/__init__.py index 5386a23..99baf9d 100755 --- a/Milter/__init__.py +++ b/Milter/__init__.py @@ -185,7 +185,22 @@ def noreply(func): # Current RFCs define UTF-8 as the standard encoding for SMTP # envelope and header fields. By default, Milter.Base decodes # envelope and header values with errors='surrogateescape'. -# This decorator can change the error strategy to, e.g., 'ignore' or 'replace'. +# Applications can recover the original bytes with +#
+# b = s.encode(errors='surrogateescape')
+# 
+# This preserves information, but can lead to unexpected exceptions +# as you cannot, e.g. print strings with surrogates. +# Illegal bytes occur quite often in real life, so there must +# be a way to deal with them. +# This decorator can change the error strategy to +# +# def decode(strategy): def setstrategy(func): func.error_strategy = strategy @@ -340,6 +355,9 @@ class Base(object): def envfrom_bytes(self,*b): try: e = getattr(self.envfrom,'error_strategy','surrogateescape') + if e == 'bytes': + #self.envfrom_bytes = self.envfrom + return self.envfrom(*b) s = (v.decode(encoding='utf-8',errors=e) for v in b) except UnicodeDecodeError: s = b return self.envfrom(fld,*s) @@ -362,6 +380,9 @@ class Base(object): def envrcpt_bytes(self,*b): try: e = getattr(self.envrcpt,'error_strategy','surrogateescape') + if e == 'bytes': + #self.envrcpt_bytes = self.envrcpt + return self.envrcpt(*b) s = (v.decode(encoding='utf-8',errors=e) for v in b) except UnicodeDecodeError: s = b return self.envrcpt(fld,*s) @@ -387,7 +408,13 @@ class Base(object): # @param val field value as bytes # @since 1.0.5 # Converts from utf-8 to unicode with surrogate escape. Can be overriden - # to pass bytes to @link #header the header callback @endlink instead. + # to pass bytes to @link #header the header callback @endlink instead, + # e.g. by assignment: + #
+  #  mymilter.header_bytes = mymilter.header
+  # 
+ # The @decode('bytes') decorator will also do this. + # def header_bytes(self,fld,val): try: e = getattr(self.header,'error_strategy','surrogateescape')