Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pymilter for openSUSE:Factory 
checked in at 2026-07-07 21:02:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pymilter (Old)
 and      /work/SRC/openSUSE:Factory/.python-pymilter.new.1982 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pymilter"

Tue Jul  7 21:02:07 2026 rev:9 rq:1364106 version:1.0.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pymilter/python-pymilter.changes  
2025-07-30 11:47:03.234885608 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pymilter.new.1982/python-pymilter.changes    
    2026-07-07 21:04:01.383967293 +0200
@@ -1,0 +2,14 @@
+Mon Jul  6 19:27:14 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.0.6:
+  * Drop paragraph about python 2.0 compatibility
+  * Adapt to MTAs that use ':' as key terminator and/or add null char to
+  * Remove calls to the deprecated method "assertEquals"
+  * Work with berkeleydb and try importing it first.
+- drop set-c-standard-17.patch: obsolete
+- drop
+  0001-Remove-calls-to-the-deprecated-method-assertEquals.patch:
+  upstream
+- add fix-version.patch
+
+-------------------------------------------------------------------

Old:
----
  0001-Remove-calls-to-the-deprecated-method-assertEquals.patch
  pymilter-1.0.5.tar.gz
  set-c-standard-17.patch

New:
----
  fix-version.patch
  pymilter-1.0.6.tar.gz

----------(Old B)----------
  Old:- drop
  0001-Remove-calls-to-the-deprecated-method-assertEquals.patch:
  upstream
  Old:  * Work with berkeleydb and try importing it first.
- drop set-c-standard-17.patch: obsolete
- drop
----------(Old E)----------

----------(New B)----------
  New:  upstream
- add fix-version.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pymilter.spec ++++++
--- /var/tmp/diff_new_pack.PR6S2v/_old  2026-07-07 21:04:02.191995270 +0200
+++ /var/tmp/diff_new_pack.PR6S2v/_new  2026-07-07 21:04:02.191995270 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pymilter
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 # Copyright (c) 2018 Neal Gompa <[email protected]>.
 #
 # All modifications and additions to the file contributed by third parties
@@ -21,17 +21,14 @@
 %global __provides_exclude_from 
^(%{python2_sitearch}/.*\\.so|%{python3_sitearch}/.*\\.so)$
 # Python 2 module isn't building properly and we don't really need it right 
now anyway...
 Name:           python-pymilter
-Version:        1.0.5
+Version:        1.0.6
 Release:        0
 Summary:        Python interface to the sendmail milter API
 License:        GPL-2.0-or-later
 URL:            https://www.bmsi.com/python/milter.html
 Source0:        
https://github.com/sdgathman/pymilter/archive/pymilter-%{version}.tar.gz
 Source1:        tmpfiles-python-pymilter.conf
-# PATCH-FIX-UPSTREAM: https://github.com/sdgathman/pymilter/pull/57
-Patch1:         0001-Remove-calls-to-the-deprecated-method-assertEquals.patch
-# PATCH-FIX-UPSTREAM https://github.com/sdgathman/pymilter/pull/70
-Patch2:         set-c-standard-17.patch
+Patch:          fix-version.patch
 BuildRequires:  %{python_module bsddb3}
 BuildRequires:  %{python_module devel}
 BuildRequires:  %{python_module pip}

++++++ fix-version.patch ++++++
Index: pymilter-pymilter-1.0.6/Doxyfile
===================================================================
--- pymilter-pymilter-1.0.6.orig/Doxyfile
+++ pymilter-pymilter-1.0.6/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = pymilter
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 1.0.5
+PROJECT_NUMBER         = 1.0.6
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
Index: pymilter-pymilter-1.0.6/Milter/__init__.py
===================================================================
--- pymilter-pymilter-1.0.6.orig/Milter/__init__.py
+++ pymilter-pymilter-1.0.6/Milter/__init__.py
@@ -9,7 +9,7 @@
 # This code is under the GNU General Public License.  See COPYING for details.
 
 from __future__ import print_function
-__version__ = '1.0.5'
+__version__ = '1.0.6'
 
 import os
 import re
@@ -70,7 +70,7 @@ def decode_mask(bits,names):
 # P_SKIP is enabled by default when supported, but
 # applications may wish to enable P_HDR_LEADSPC
 # to send and receive the leading space of header continuation
-# lines unchanged, and/or P_RCPT_REJ to have recipients 
+# lines unchanged, and/or P_RCPT_REJ to have recipients
 # detected as invalid by the MTA passed to the envcrpt callback.
 #
 # Applications may want to check whether the protocol is actually
@@ -79,7 +79,7 @@ def decode_mask(bits,names):
 # for instance, if <code>self._protocol & Milter.P_RCPT_REJ</code>
 # is true, then that feature was successfully negotiated with the MTA
 # and the application will see recipients the MTA has flagged as invalid.
-# 
+#
 # Sample use:
 # <pre>
 # class myMilter(Milter.Base):
@@ -160,7 +160,7 @@ def nocallback(func):
 # If the MTA supports it, tells the MTA not to wait for a reply from
 # this callback, and assume CONTINUE.  The method should still return
 # CONTINUE in case the MTA does not support protocol negotiation.
-# The decorator arranges to change the return code to NOREPLY 
+# The decorator arranges to change the return code to NOREPLY
 # when supported by the MTA.
 # @since 0.9.2
 def noreply(func):
@@ -183,9 +183,9 @@ def noreply(func):
 
 ## Function decorator to set decoding error strategy.
 # Current RFCs define UTF-8 as the standard encoding for SMTP
-# envelope and header fields.  By default, Milter.Base decodes 
+# envelope and header fields.  By default, Milter.Base decodes
 # envelope and header values with errors='surrogateescape'.
-# Applications can recover the original bytes with 
+# Applications can recover the original bytes with
 # <pre>
 # b = s.encode(errors='surrogateescape')
 # </pre>
@@ -199,8 +199,8 @@ def noreply(func):
 # <li> strict   - pass bytes if illegal bytes are present, string otherwise
 # <li> ignore   - illegal bytes are removed
 # <li> replace  - illegal bytes are replaced with a unicode error symbol
-# </ul> 
-# 
+# </ul>
+#
 def decode(strategy):
   def setstrategy(func):
     func.error_strategy = strategy
@@ -235,7 +235,7 @@ class DisabledAction(RuntimeError):
 ## A do "nothing" Milter base class representing an SMTP connection.
 #
 # Python milters should derive from this class
-# unless they are using the low level milter module directly.  
+# unless they are using the low level milter module directly.
 #
 # Most of the methods are either "actions" or "callbacks".  Callbacks
 # are invoked by the MTA at certain points in the SMTP protocol.  For
@@ -247,11 +247,11 @@ class DisabledAction(RuntimeError):
 # @@noreply and @@nocallback methods should return CONTINUE for two reasons:
 # the MTA may not support negotiation, and the class may be running in a test
 # harness.
-# 
+#
 # Optional callbacks are disabled with the @@nocallback decorator, and
 # automatically reenabled when overridden.  Disabled callbacks should
 # still return CONTINUE for testing and MTAs that do not support
-# negotiation.  
+# negotiation.
 
 # Each SMTP connection to the MTA calls the factory method you provide to
 # create an instance derived from this class.  This is typically the
@@ -292,7 +292,7 @@ class Base(object):
     # %milter application only if the P_RCPT_REJ bit is set, and
     # header values are sent and received with leading spaces (in the
     # continuation lines) intact if the P_HDR_LEADSPC bit is set (so
-    # that the application can customize indenting).  
+    # that the application can customize indenting).
     #
     # The P_N* bits should be negotiated via the @@noreply and @@nocallback
     # method decorators, and P_RCPT_REJ, P_HDR_LEADSPC should
@@ -312,7 +312,7 @@ class Base(object):
   def log(self,*msg): pass
   ## Called for each connection to the MTA.  Called by the
   # <a href="milter_api/xxfi_connect.html">
-  # xxfi_connect</a> callback.  
+  # xxfi_connect</a> callback.
   # The <code>hostname</code> provided by the local MTA is either
   # the PTR name or the IP in the form "[1.2.3.4]" if no PTR is available.
   # The format of hostaddr depends on the socket family:
@@ -326,7 +326,7 @@ class Base(object):
   # <dd>A string with the socketname
   # </dl>
   # To vary behavior based on what port the client connected to,
-  # for example skipping blacklist checks for port 587 (which must 
+  # for example skipping blacklist checks for port 587 (which must
   # be authenticated), use @link #getsymval getsymval('{daemon_port}') 
@endlink.
   # The <code>{daemon_port}</code> macro must be enabled in sendmail.cf
   # <pre>
@@ -349,7 +349,7 @@ class Base(object):
   def hello(self,hostname): return CONTINUE
   ## Called with bytes by default global envfrom callback.
   # @since 1.0.5
-  # Converts from utf-8 to unicode with surrogate escape.  Can be overriden 
+  # Converts from utf-8 to unicode with surrogate escape.  Can be overriden
   # to pass bytes to @link #header the header callback @endlink instead,
   # or trap utf-8 conversion exception, etc.
   def envfrom_bytes(self,*b):
@@ -363,18 +363,18 @@ class Base(object):
     return self.envfrom(s[0],*s[1:])
   ## Called when the SMTP client says MAIL FROM. Called by the
   # <a href="milter_api/xxfi_envfrom.html">
-  # xxfi_envfrom</a> callback.  
+  # xxfi_envfrom</a> callback.
   # Returning REJECT rejects the message, but not the connection.
   # The sender is the "envelope" from as defined by
   # <a href="http://tools.ietf.org/html/rfc5321";>RFC 5321</a>.
-  # For the From: header (author) defined in 
+  # For the From: header (author) defined in
   # <a href="http://tools.ietf.org/html/rfc5322";>RFC 5322</a>,
   # see @link #header the header callback @endlink.
   @nocallback
   def envfrom(self,f,*s): return CONTINUE
   ## Called with bytes by default global envrcpt callback.
   # @since 1.0.5
-  # Converts from utf-8 to unicode with surrogate escape.  Can be overriden 
+  # Converts from utf-8 to unicode with surrogate escape.  Can be overriden
   # to pass bytes to @link #header the header callback @endlink instead,
   # or trap utf-8 conversion exception, etc.
   def envrcpt_bytes(self,*b):
@@ -390,10 +390,10 @@ class Base(object):
   # <a href="milter_api/xxfi_envrcpt.html">
   # xxfi_envrcpt</a> callback.
   # Returning REJECT rejects the current recipient, not the entire message.
-  # The recipient is the "envelope" recipient as defined by 
+  # The recipient is the "envelope" recipient as defined by
   # <a href="http://tools.ietf.org/html/rfc5321";>RFC 5321</a>.
-  # For recipients defined in 
-  # <a href="http://tools.ietf.org/html/rfc5322";>RFC 5322</a>, 
+  # For recipients defined in
+  # <a href="http://tools.ietf.org/html/rfc5322";>RFC 5322</a>,
   # for example To: or Cc:, see @link #header the header callback @endlink.
   @nocallback
   def envrcpt(self,to,*str): return CONTINUE
@@ -407,14 +407,14 @@ class Base(object):
   # @param fld name decoded as ascii
   # @param val field value as bytes
   # @since 1.0.5
-  # Converts from utf-8 to unicode with surrogate escape.  Can be overriden 
+  # Converts from utf-8 to unicode with surrogate escape.  Can be overriden
   # to pass bytes to @link #header the header callback @endlink instead,
   # e.g. by assignment:
   # <pre>
   #  mymilter.header_bytes = mymilter.header
   # </pre>
   # The <code>@decode('bytes')</code> decorator will also do this.
-  # 
+  #
   def header_bytes(self,fld,val):
     try:
       e = getattr(self.header,'error_strategy','surrogateescape')
@@ -455,7 +455,7 @@ class Base(object):
   # The @@nocallback and @@noreply decorators set the
   # <code>milter_protocol</code> function attribute to the protocol mask bit to
   # pass to libmilter, causing that callback or its reply to be skipped.
-  # Overriding a method creates a new function object, so that 
+  # Overriding a method creates a new function object, so that
   # <code>milter_protocol</code> defaults to 0.
   # Libmilter passes the protocol bits that the current MTA knows
   # how to skip.  We clear the ones we don't want to skip.
@@ -474,14 +474,14 @@ class Base(object):
         p |= (nr|nc) & ~ca
       klass._protocol_mask = p
       return p
-    
+
   ## Negotiate milter protocol options.  Called by the
   # <a href="milter_api/xxfi_negotiate.html">
   # xffi_negotiate</a> callback.  This is an advanced callback,
   # do not override unless you know what you are doing.  Most
-  # negotiation can be done simply by using the supplied 
+  # negotiation can be done simply by using the supplied
   # class and function decorators.
-  # Options are passed as 
+  # Options are passed as
   # a list of 4 32-bit ints which can be modified and are passed
   # back to libmilter on return.
   # Default negotiation sets P_NO* and P_NR* for callbacks
@@ -504,7 +504,7 @@ class Base(object):
       #self.log("Negotiated:",opts)
     except Exception as x:
       # don't change anything if something went wrong
-      return ALL_OPTS 
+      return ALL_OPTS
     return CONTINUE
 
   # Milter methods which can be invoked from most callbacks
@@ -528,7 +528,7 @@ class Base(object):
   # sent - but with the '%%' still doubled!
   # See <a href="milter_api/smfi_setreply.html">
   # smfi_setreply</a> for more information.
-  # @param rcode The three-digit (RFC 821/2821) SMTP reply code as a string. 
+  # @param rcode The three-digit (RFC 821/2821) SMTP reply code as a string.
   # rcode cannot be None, and <b>must be a valid 4XX or 5XX reply code</b>.
   # @param xcode The extended (RFC 1893/2034) reply code. If xcode is None,
   # no extended code is used. Otherwise, xcode must conform to RFC 1893/2034.
@@ -552,7 +552,7 @@ class Base(object):
   # feature.  Use the @@symlist function decorator to conviently set
   # the macros used by a callback.
   # @since 0.9.8, previous version was misspelled!
-  # @param stage the protocol stage to set to macro list for, 
+  # @param stage the protocol stage to set to macro list for,
   # one of the M_* constants defined in Milter
   # @param macros space separated and/or lists of strings
   def setsymlist(self,stage,*macros):
@@ -574,7 +574,7 @@ class Base(object):
 
   ## Add a mail header field.
   # Calls <a href="milter_api/smfi_addheader.html">
-  # smfi_addheader</a>.  
+  # smfi_addheader</a>.
   # The <code>Milter.ADDHDRS</code> action flag must be set.
   #
   # May be called from eom callback only.
@@ -588,7 +588,7 @@ class Base(object):
 
   ## Change the value of a mail header field.
   # Calls <a href="milter_api/smfi_chgheader.html">
-  # smfi_chgheader</a>.  
+  # smfi_chgheader</a>.
   # The <code>Milter.CHGHDRS</code> action flag must be set.
   #
   # May be called from eom callback only.
@@ -600,21 +600,21 @@ class Base(object):
     if not self._actions & CHGHDRS: raise DisabledAction("CHGHDRS")
     return self._ctx.chgheader(field,idx,value)
 
-  ## Add a recipient to the message.  
+  ## Add a recipient to the message.
   # Calls <a href="milter_api/smfi_addrcpt.html">
-  # smfi_addrcpt</a>.  
+  # smfi_addrcpt</a>.
   # If no corresponding mail header is added, this is like a Bcc.
   # The syntax of the recipient is the same as used in the SMTP
   # RCPT TO command (and as delivered to the envrcpt callback), for example
-  # "self.addrcpt('<[email protected]>')".  
+  # "self.addrcpt('<[email protected]>')".
   # The <code>Milter.ADDRCPT</code> action flag must be set.
   # If the optional <code>params</code> argument is used, then
   # the <code>Milter.ADDRCPT_PAR</code> action flag must be set.
   #
   # May be called from eom callback only.
-  # @param rcpt the message recipient 
+  # @param rcpt the message recipient
   # @param params an optional list of ESMTP parameters
-  # @throws DisabledAction if ADDRCPT or ADDRCPT_PAR is not enabled 
+  # @throws DisabledAction if ADDRCPT or ADDRCPT_PAR is not enabled
   def addrcpt(self,rcpt,params=None):
     if not self._actions & ADDRCPT: raise DisabledAction("ADDRCPT")
     if params and not self._actions & ADDRCPT_PAR:
@@ -622,7 +622,7 @@ class Base(object):
     return self._ctx.addrcpt(rcpt,params)
   ## Delete a recipient from the message.
   # Calls <a href="milter_api/smfi_delrcpt.html">
-  # smfi_delrcpt</a>.  
+  # smfi_delrcpt</a>.
   # The recipient should match one passed to the envrcpt callback.
   # The <code>Milter.DELRCPT</code> action flag must be set.
   #
@@ -635,8 +635,8 @@ class Base(object):
 
   ## Replace the message body.
   # Calls <a href="milter_api/smfi_replacebody.html">
-  # smfi_replacebody</a>.  
-  # The entire message body must be replaced.  
+  # smfi_replacebody</a>.
+  # The entire message body must be replaced.
   # Call repeatedly with blocks of data until the entire body is transferred.
   # The <code>Milter.MODBODY</code> action flag must be set.
   #
@@ -649,7 +649,7 @@ class Base(object):
 
   ## Change the SMTP envelope sender address.
   # Calls <a href="milter_api/smfi_chgfrom.html">
-  # smfi_chgfrom</a>.  
+  # smfi_chgfrom</a>.
   # The syntax of the sender is that same as used in the SMTP
   # MAIL FROM command (and as delivered to the envfrom callback),
   # for example <code>self.chgfrom('<[email protected]>')</code>.
@@ -666,7 +666,7 @@ class Base(object):
 
   ## Quarantine the message.
   # Calls <a href="milter_api/smfi_quarantine.html">
-  # smfi_quarantine</a>.  
+  # smfi_quarantine</a>.
   # When quarantined, a message goes into the mailq as if to be delivered,
   # but delivery is deferred until the message is unquarantined.
   # The <code>Milter.QUARANTINE</code> action flag must be set.
@@ -680,11 +680,11 @@ class Base(object):
 
   ## Tell the MTA to wait a bit longer.
   # Calls <a href="milter_api/smfi_progress.html">
-  # smfi_progress</a>.  
+  # smfi_progress</a>.
   # Resets timeouts in the MTA that detect a "hung" milter.
   def progress(self):
     return self._ctx.progress()
-  
+
 ## A logging but otherwise do nothing Milter base class.
 # This is included for compatibility with previous versions of pymilter.
 # The logging callbacks are marked @@noreply.
@@ -757,7 +757,7 @@ class Milter(Base):
 # an object derived from Milter.Base.
 #
 # Note that since python is dynamic, this variable can be changed while
-# the milter is running: for instance, to a new subclass based on a 
+# the milter is running: for instance, to a new subclass based on a
 # change in configuration.
 factory = Milter
 
@@ -772,7 +772,7 @@ def negotiate_callback(ctx,opts):
 # @brief Connect context if needed and invoke connect method.
 def connect_callback(ctx,hostname,family,hostaddr,nr_mask=P_NR_CONN):
   m = ctx.getpriv()
-  if not m:     
+  if not m:
     # If not already created (because the current MTA doesn't support
     # xmfi_negotiate), create the connection object.
     m = factory()
@@ -806,13 +806,13 @@ def dictfromlist(args):
 # @since 0.9.3
 # @param str list of param strings of the form "NAME" or "NAME=VALUE"
 # @return a dictionary of ESMTP param names and values
-def param2dict(str): 
+def param2dict(str):
   "Convert ESMTP parm list to keyword dictionary."
   pairs = [x.split('=',1) for x in str]
   for e in pairs:
     if len(e) < 2: e.append(None)
   return dict([(k.upper(),v) for k,v in pairs])
-  
+
 def envcallback(c,args):
   """Call function c with ESMTP parms converted to keyword parameters.
   Can be used in the envfrom and/or envrcpt callbacks to process
@@ -830,7 +830,7 @@ def envcallback(c,args):
 ## Run the %milter.
 # @param name the name of the %milter known to the MTA
 # @param socketname the socket to be passed to milter.setconn()
-# @param timeout the time in secs the MTA should wait for a response before 
+# @param timeout the time in secs the MTA should wait for a response before
 #      considering this %milter dead
 def runmilter(name,socketname,timeout = 0,rmsock=True):
 
Index: pymilter-pymilter-1.0.6/makefile
===================================================================
--- pymilter-pymilter-1.0.6.orig/makefile
+++ pymilter-pymilter-1.0.6/makefile
@@ -4,7 +4,7 @@ web:
        rsync -ravKk doc/html/ pymilter.org:/var/www/html/milter/pymilter
        cd doc/html; zip -r ../../doc .
 
-VERSION=1.0.5
+VERSION=1.0.6
 PKG=pymilter-$(VERSION)
 SRCTAR=$(PKG).tar.gz
 
Index: pymilter-pymilter-1.0.6/setup.py
===================================================================
--- pymilter-pymilter-1.0.6.orig/setup.py
+++ pymilter-pymilter-1.0.6/setup.py
@@ -17,7 +17,7 @@ libdirs = ["/usr/lib/libmilter"]    # ne
 modules = ["mime"]
 
 # NOTE: importing Milter to obtain version fails when milter.so not built
-setup(name = "pymilter", version = '1.0.5',
+setup(name = "pymilter", version = '1.0.6',
        description="Python interface to sendmail milter API",
        long_description=long_description,
     long_description_content_type='text/markdown',

++++++ pymilter-1.0.5.tar.gz -> pymilter-1.0.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/Milter/policy.py 
new/pymilter-pymilter-1.0.6/Milter/policy.py
--- old/pymilter-pymilter-1.0.5/Milter/policy.py        2021-12-16 
05:35:02.000000000 +0100
+++ new/pymilter-pymilter-1.0.6/Milter/policy.py        2024-05-30 
00:08:30.000000000 +0200
@@ -1,11 +1,16 @@
 try:
-  from bsddb3 import db
+  try:
+    from berkeleydb import db
+  except:
+    from bsddb3 import db
   class DB(object):
     def open(self,fname,mode):
       if mode == 'r': flags = db.DB_RDONLY
       else: raise RuntimeException('unsupported mode')
       self.f = db.DB()
       self.f.open(fname,flags=flags)
+    def __contains__(self,key):
+      return not not self.f.get(key)
     def __getitem__(self,key):
       v = self.f.get(key)
       if not v: raise KeyError(key)
@@ -27,6 +32,10 @@
     if not access_file:
       access_file = conf.access_file
     self.use_nulls = conf.access_file_nulls
+    try:
+      self.use_colon = conf.access_file_colon
+    except:
+      self.use_colon = True
     self.sender = sender
     self.domain = sender.split('@')[-1].lower()
     self.acf = None
@@ -52,14 +61,24 @@
     if not acf: return None
     if self.use_nulls: sfx = b'\x00'
     else: sfx = b''
-    pfx = pfx.encode() + b'!'
-    try:
+    if self.use_colon:
+      sep = b':'
+    else:
+      sep = b'!'
+    pfx = pfx.encode() + sep
+    try:    # try with localpart@domain
       return acf[pfx + self.sender.encode() + sfx].rstrip(b'\x00').decode()
     except KeyError:
-      try:
-        return acf[pfx + self.domain.encode() + sfx].rstrip(b'\x00').decode()
+      try:  # try with domain
+        d = self.domain.encode()
+        k = pfx + d + sfx
+        while not k in acf and b'.' in d:
+          # check partial domains
+          d = b'.'.join(d.split(b'.')[1:])
+          k = pfx + b'.' + d + sfx
+        return acf[k].rstrip(b'\x00').decode()
       except KeyError:
-        try:
+        try:    # try bare prefix
           return acf[pfx + sfx].rstrip(b'\x00').decode()
         except KeyError:
           try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/README.md 
new/pymilter-pymilter-1.0.6/README.md
--- old/pymilter-pymilter-1.0.5/README.md       2021-12-16 05:35:02.000000000 
+0100
+++ new/pymilter-pymilter-1.0.6/README.md       2024-05-30 00:08:30.000000000 
+0200
@@ -11,9 +11,11 @@
 
 # Requirements 
 
-Python milter extension: https://pypi.python.org/pypi/pymilter/
+Python milter extension: https://pypi.org/project/pymilter/
 Python: http://www.python.org
 Sendmail: http://www.sendmail.org
+   or
+Postfix: http://www.postfix.org/MILTER_README.html
 
 # Quick Installation
 
@@ -21,10 +23,10 @@
  2. Build and install Python, enabling threading.
  3. Install this module: python setup.py --help
  4. Add these two lines to sendmail.cf[a]:
-
+```
  O InputMailFilters=pythonfilter
  Xpythonfilter,        S=local:/home/username/pythonsock
-
+```
  5. Run the sample.py example milter with: python sample.py
  Note that milters should almost certainly not run as root.
 
@@ -36,9 +38,9 @@
 [a] This is for a quick test.  Your sendmail.cf in most distros will get
 overwritten whenever sendmail.mc is updated.  To make a milter permanent,
 add something like:
-
+```
 INPUT_MAIL_FILTER(`pythonfilter', `S=local:/home/username/pythonsock, F=T, 
T=C:5m;S:20s;R:5m;E:5m')
-
+```
 to sendmail.mc instead.
 
 # Not-so-quick Installation
@@ -54,18 +56,13 @@
 
 $ python setup.py --help
 
-For versions of python prior to 2.0, you will need to download distutils
-separately or build manually.  You will need to download unittest
-separately to run the test programs.  The bdist_rpm distutils option seems
-not to work for python 2.0; upgrade to at least 2.1.1.
-
 Now that everything is installed, we need to tell sendmail that we're going
 to filter incoming email.  Add lines similar to the following to
 sendmail.cf:
-
+```
 O InputMailFilters=pythonfilter
 Xpythonfilter,        S=local:/home/username/pythonsock
-
+```
 The "O" line tells sendmail which filters to use in what order; here we're
 telling sendmail to use the filter named "pythonfilter".
 
@@ -79,14 +76,14 @@
 in the milter itself.  Make sure the two match.
 
 NB: The above lines can be added in your .mc file with this line:
-
+```
 INPUT_MAIL_FILTER(`pythonfilter', `S=local:/home/username/pythonsock')
-
+```
 For versions of sendmail prior to 8.12, you will need to enable
-_FFR_MILTER for the cf macros.  For example,
-
+`_FFR_MILTER` for the cf macros.  For example,
+```
 m4 -D_FFR_MILTER ../m4/cf.m4 myconfig.mc > myconfig.cf
-
+```
 # IPv6 Notes
 
 The IPv6 protocol is supported if your operation system supports it
@@ -94,9 +91,9 @@
 sendmail supports IPv6, run "sendmail -d0" and check for the NETINET6
 compilation option.  To compile sendmail with IPv6 support, add this
 declaration to your site.config.m4 before building it:
-
+```
 APPENDDEF(`confENVDEF', `-DNETINET6=1')
-
+```
 IPv6 support can show up in two places; the communications socket
 between the milter and sendmail processes and in the host address
 argument to the connect() callback method.
@@ -107,34 +104,34 @@
 will require that each listens to different port numbers.  For an
 IPv6-only setup, your sendmail configuration should contain a line
 similar to (first line is for sendmail.mc, second is sendmail.cf):
-
+```
 DAEMON_OPTIONS(`Name=MTA-v6, Family=inet6, Modify=C, Port=25')
 O DaemonPortOptions=Name=MTA-v6, Family=inet6, Modify=C, Port=25
-
+```
 To allow sendmail and the milter process to communicate with each
 other over IPv6, you may use the "inet6" socket name prefix, as in:
-
+```
 Xpythonfilter,        S=inet6:1234@fec0:0:0:7::5c
-
+```
 The connect() callback method in the milter class will pass the
 IPv6-specific information in the 'hostaddr' argument as a tuple.  Note
 that the type of this value is dependent upon the protocol family, and
 is not compatible with IPv4 connections.  Therefore you should always
 check the family argument before attempting to use the hostaddr
 argument.  A quick example showing this follows:
-
+```
   import socket
-  ...
+  
   class ipv6awareMilter(Milter.Milter):
-  ...
+     
      def connect(self,hostname,family,hostaddr):
-        if family==socket.AF_INET:
-           ipaddress, port = hostaddr
-        elif family==socket.AF_INET6:
-           ip6address, port, flowinfo, scopeid = hostaddr
-        elif family==socket.AF_UNIX:
-           socketpath = hostaddr
-
+       if family==socket.AF_INET:
+          ipaddress, port = hostaddr
+       elif family==socket.AF_INET6:
+          ip6address, port, flowinfo, scopeid = hostaddr
+       elif family==socket.AF_UNIX:
+          socketpath = hostaddr
+```
 The hostname argument is always safe to use without interpreting the
 protocol family.  For IPv6 connections for which the hostname can not
 be determined the hostname will appear similar to the string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/setup.py 
new/pymilter-pymilter-1.0.6/setup.py
--- old/pymilter-pymilter-1.0.5/setup.py        2021-12-16 05:35:02.000000000 
+0100
+++ new/pymilter-pymilter-1.0.6/setup.py        2024-05-30 00:08:30.000000000 
+0200
@@ -20,6 +20,7 @@
 setup(name = "pymilter", version = '1.0.5',
        description="Python interface to sendmail milter API",
        long_description=long_description,
+    long_description_content_type='text/markdown',
        author="Jim Niemira",
        author_email="[email protected]",
        maintainer="Stuart D. Gathman",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/test/access 
new/pymilter-pymilter-1.0.6/test/access
--- old/pymilter-pymilter-1.0.5/test/access     2021-12-16 05:35:02.000000000 
+0100
+++ new/pymilter-pymilter-1.0.6/test/access     2024-05-30 00:08:30.000000000 
+0200
@@ -7,3 +7,4 @@
 SMTP-Auth:example.com      REJECT
 SMTP-Auth:[email protected]     REJECT
 SMTP-Test:      REJECT
+SMTP-Test:.baz.com      WILDCARD
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/testpolicy.py 
new/pymilter-pymilter-1.0.6/testpolicy.py
--- old/pymilter-pymilter-1.0.5/testpolicy.py   2021-12-16 05:35:02.000000000 
+0100
+++ new/pymilter-pymilter-1.0.6/testpolicy.py   2024-05-30 00:08:30.000000000 
+0200
@@ -8,6 +8,7 @@
   def __init__(self):
     self.access_file='test/access.db'
     self.access_file_nulls=True
+    self.access_file_colon = False
 
 class PolicyTestCase(unittest.TestCase):
 
@@ -23,6 +24,8 @@
       print("Missing test/access")
 
   def testPolicy(self):
+    self.config.access_file_colon = False
+    self.config.access_file_nulls = True
     with MTAPolicy('[email protected]',conf=self.config) as p:
       pol = p.getPolicy('smtp-auth')
     self.assertEqual(pol,'OK')
@@ -35,6 +38,9 @@
     with MTAPolicy('[email protected]',conf=self.config) as p:
       pol = p.getPolicy('smtp-test')
     self.assertEqual(pol,'REJECT')
+    with MTAPolicy('[email protected]',conf=self.config) as p:
+      pol = p.getPolicy('smtp-test')
+    self.assertEqual(pol,'WILDCARD')
 
 def suite(): return unittest.makeSuite(PolicyTestCase,'test')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/testsample.py 
new/pymilter-pymilter-1.0.6/testsample.py
--- old/pymilter-pymilter-1.0.5/testsample.py   2021-12-16 05:35:02.000000000 
+0100
+++ new/pymilter-pymilter-1.0.6/testsample.py   2024-05-30 00:08:30.000000000 
+0200
@@ -31,7 +31,7 @@
     count = 10
     while count > 0:
       rc = ctx._connect(helo='milter-template.example.org')
-      self.assertEquals(rc,Milter.CONTINUE)
+      self.assertEqual(rc,Milter.CONTINUE)
       with open('test/'+fname,'rb') as fp:
         rc = ctx._feedFile(fp)
       milter = ctx.getpriv()
@@ -46,7 +46,7 @@
     ctx._setsymval('{auth_type}','batcomputer')
     ctx._setsymval('j','mailhost')
     rc = ctx._connect()
-    self.assertEquals(rc,Milter.CONTINUE)
+    self.assertEqual(rc,Milter.CONTINUE)
     with open('test/'+fname,'rb') as fp:
       rc = ctx._feedFile(fp)
     milter = ctx.getpriv()
@@ -69,7 +69,7 @@
     milter = ctx.getpriv()
 #    self.assertTrue(milter.user == 'batman',"getsymval failed: "+
 #        "%s != %s"%(milter.user,'batman'))
-    self.assertEquals(milter.user,'batman')
+    self.assertEqual(milter.user,'batman')
     self.assertTrue(milter.auth_type != 'batcomputer',"setsymlist failed")
     self.assertTrue(rc == Milter.ACCEPT)
     self.assertTrue(ctx._bodyreplaced,"Message body not replaced")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pymilter-pymilter-1.0.5/testutils.py 
new/pymilter-pymilter-1.0.6/testutils.py
--- old/pymilter-pymilter-1.0.5/testutils.py    2021-12-16 05:35:02.000000000 
+0100
+++ new/pymilter-pymilter-1.0.6/testutils.py    2024-05-30 00:08:30.000000000 
+0200
@@ -24,11 +24,11 @@
     self.assertTrue(cache.has_key('[email protected]'))
     self.assertTrue(not cache.has_key('[email protected]'))
     self.assertTrue('[email protected]' in cache)
-    self.assertEquals(cache['[email protected]'],'testing')
+    self.assertEqual(cache['[email protected]'],'testing')
     s = open(self.fname).readlines()
     self.assertTrue(len(s) == 2)
     self.assertTrue(s[0].startswith('[email protected] '))
-    self.assertEquals(s[1].strip(),'[email protected]')
+    self.assertEqual(s[1].strip(),'[email protected]')
     # check that new result overrides old
     cache['[email protected]'] = None
     self.assertTrue(not cache['[email protected]'])

Reply via email to