diff --git a/conf.py b/conf.py
--- a/conf.py
+++ b/conf.py
@@ -22,6 +22,8 @@
     Kolab configuration utility.
 """
 
+from __future__ import print_function
+
 import logging
 import os
 import sys
@@ -33,8 +35,8 @@
 try:
     import pykolab.logger
 except ImportError, e:
-    print >> sys.stderr, _("Cannot load pykolab/logger.py:")
-    print >> sys.stderr, "%s" % e
+    print(_("Cannot load pykolab/logger.py:"), file=sys.stderr)
+    print("%s" % e, file=sys.stderr)
     sys.exit(1)
 
 import pykolab
diff --git a/cyruslib.py b/cyruslib.py
--- a/cyruslib.py
+++ b/cyruslib.py
@@ -18,9 +18,11 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-# Requires python >= 2.3
+# Requires python >= 2.6
 #
 
+from __future__ import print_function
+
 __version__ = '0.8.5'
 __all__ = [ 'CYRUS' ]
 __doc__ = """Cyrus admin wrapper
@@ -36,7 +38,7 @@
     import re
     from binascii import b2a_base64
 except ImportError, e:
-    print e
+    print(e)
     exit(1)
 
 Commands = {
@@ -342,7 +344,7 @@
 
     def __verbose(self, msg):
         if self.VERBOSE:
-            print >> self.LOGFD, msg
+            print(msg, file=self.LOGFD)
 
     def __doexception(self, function, msg=None, *args):
         if msg is None:
diff --git a/ext/python/Tools/freeze/freeze.py b/ext/python/Tools/freeze/freeze.py
--- a/ext/python/Tools/freeze/freeze.py
+++ b/ext/python/Tools/freeze/freeze.py
@@ -162,7 +162,7 @@
     # process option arguments
     for o, a in opts:
         if o == '-h':
-            print __doc__
+            print(__doc__)
             return
         if o == '-b':
             binlib = a
@@ -224,7 +224,7 @@
     if win:
         extensions_c = 'frozen_extensions.c'
     if ishome:
-        print "(Using Python source directory)"
+        print("(Using Python source directory)")
         binlib = exec_prefix
         incldir = os.path.join(prefix, 'Include')
         config_h_dir = exec_prefix
@@ -316,7 +316,7 @@
     if odir and not os.path.isdir(odir):
         try:
             os.mkdir(odir)
-            print "Created output directory", odir
+            print("Created output directory", odir)
         except os.error, msg:
             usage('%s: mkdir failed (%s)' % (odir, str(msg)))
     base = ''
@@ -377,7 +377,7 @@
 
     if debug > 0:
         mf.report()
-        print
+        print()
     dict = mf.modules
 
     if error_if_any_missing:
@@ -485,18 +485,18 @@
     # Done!
 
     if odir:
-        print 'Now run "make" in', odir,
-        print 'to build the target:', base_target
+        print('Now run "make" in', odir, end=' ')
+        print('to build the target:', base_target)
     else:
-        print 'Now run "make" to build the target:', base_target
+        print('Now run "make" to build the target:', base_target)
 
 
 # Print usage message and exit
 
 def usage(msg):
     sys.stdout = sys.stderr
-    print "Error:", msg
-    print "Use ``%s -h'' for help" % sys.argv[0]
+    print("Error:", msg)
+    print("Use ``%s -h'' for help" % sys.argv[0])
     sys.exit(2)
 
 
diff --git a/ext/python/Tools/freeze/hello.py b/ext/python/Tools/freeze/hello.py
--- a/ext/python/Tools/freeze/hello.py
+++ b/ext/python/Tools/freeze/hello.py
@@ -1 +1 @@
-print 'Hello world...'
+print('Hello world...')
diff --git a/ext/python/Tools/freeze/makeconfig.py b/ext/python/Tools/freeze/makeconfig.py
--- a/ext/python/Tools/freeze/makeconfig.py
+++ b/ext/python/Tools/freeze/makeconfig.py
@@ -40,8 +40,8 @@
 def test():
     import sys
     if not sys.argv[3:]:
-        print 'usage: python makeconfig.py config.c.in outputfile',
-        print 'modulename ...'
+        print('usage: python makeconfig.py config.c.in outputfile', end=' ')
+        print('modulename ...')
         sys.exit(2)
     if sys.argv[1] == '-':
         infp = sys.stdin
diff --git a/ext/python/Tools/freeze/makefreeze.py b/ext/python/Tools/freeze/makefreeze.py
--- a/ext/python/Tools/freeze/makefreeze.py
+++ b/ext/python/Tools/freeze/makefreeze.py
@@ -43,7 +43,7 @@
             outfp = bkfile.open(base + file, 'w')
             files.append(file)
             if debug:
-                print "freezing", mod, "..."
+                print("freezing", mod, "...")
             str = marshal.dumps(m.__code__)
             size = len(str)
             if m.__path__:
@@ -53,7 +53,7 @@
             writecode(outfp, mangled, str)
             outfp.close()
     if debug:
-        print "generating table of frozen modules"
+        print("generating table of frozen modules")
     outfp = bkfile.open(base + 'frozen.c', 'w')
     for mod, mangled, size in done:
         outfp.write('extern unsigned char M_%s[];\n' % mangled)
diff --git a/ext/python/Tools/freeze/parsesetup.py b/ext/python/Tools/freeze/parsesetup.py
--- a/ext/python/Tools/freeze/parsesetup.py
+++ b/ext/python/Tools/freeze/parsesetup.py
@@ -84,29 +84,29 @@
     import sys
     import os
     if not sys.argv[1:]:
-        print 'usage: python parsesetup.py Makefile*|Setup* ...'
+        print('usage: python parsesetup.py Makefile*|Setup* ...')
         sys.exit(2)
     for arg in sys.argv[1:]:
         base = os.path.basename(arg)
         if base[:8] == 'Makefile':
-            print 'Make style parsing:', arg
+            print('Make style parsing:', arg)
             v = getmakevars(arg)
             prdict(v)
         elif base[:5] == 'Setup':
-            print 'Setup style parsing:', arg
+            print('Setup style parsing:', arg)
             m, v = getsetupinfo(arg)
             prdict(m)
             prdict(v)
         else:
-            print arg, 'is neither a Makefile nor a Setup file'
-            print '(name must begin with "Makefile" or "Setup")'
+            print(arg, 'is neither a Makefile nor a Setup file')
+            print('(name must begin with "Makefile" or "Setup")')
 
 def prdict(d):
     keys = d.keys()
     keys.sort()
     for key in keys:
         value = d[key]
-        print "%-15s" % key, str(value)
+        print("%-15s" % key, str(value))
 
 if __name__ == '__main__':
     test()
diff --git a/ext/python/Tools/freeze/winmakemakefile.py b/ext/python/Tools/freeze/winmakemakefile.py
--- a/ext/python/Tools/freeze/winmakemakefile.py
+++ b/ext/python/Tools/freeze/winmakemakefile.py
@@ -52,29 +52,29 @@
 
 def realwork(vars, moddefns, target):
     version_suffix = "%r%r" % sys.version_info[:2]
-    print "# Makefile for Microsoft Visual C++ generated by freeze.py script"
-    print
-    print 'target = %s' % target
-    print 'pythonhome = %s' % vars['prefix']
-    print
-    print 'DEBUG=0 # Set to 1 to use the _d versions of Python.'
-    print '!IF $(DEBUG)'
-    print 'debug_suffix=_d'
-    print 'c_debug=/Zi /Od /DDEBUG /D_DEBUG'
-    print 'l_debug=/DEBUG'
-    print 'temp_dir=Build\\Debug'
-    print '!ELSE'
-    print 'debug_suffix='
-    print 'c_debug=/Ox'
-    print 'l_debug='
-    print 'temp_dir=Build\\Release'
-    print '!ENDIF'
-    print
-
-    print '# The following line assumes you have built Python using the standard instructions'
-    print '# Otherwise fix the following line to point to the library.'
-    print 'pythonlib = "$(pythonhome)/pcbuild/python%s$(debug_suffix).lib"' % version_suffix
-    print
+    print("# Makefile for Microsoft Visual C++ generated by freeze.py script")
+    print()
+    print('target = %s' % target)
+    print('pythonhome = %s' % vars['prefix'])
+    print()
+    print('DEBUG=0 # Set to 1 to use the _d versions of Python.')
+    print('!IF $(DEBUG)')
+    print('debug_suffix=_d')
+    print('c_debug=/Zi /Od /DDEBUG /D_DEBUG')
+    print('l_debug=/DEBUG')
+    print('temp_dir=Build\\Debug')
+    print('!ELSE')
+    print('debug_suffix=')
+    print('c_debug=/Ox')
+    print('l_debug=')
+    print('temp_dir=Build\\Release')
+    print('!ENDIF')
+    print()
+
+    print('# The following line assumes you have built Python using the standard instructions')
+    print('# Otherwise fix the following line to point to the library.')
+    print('pythonlib = "$(pythonhome)/pcbuild/python%s$(debug_suffix).lib"' % version_suffix)
+    print()
 
     # We only ever write one "entry point" symbol - either
     # "main" or "WinMain".  Therefore, there is no need to
@@ -88,59 +88,59 @@
         target_ext = ".dll"
 
 
-    print "# As the target uses Python%s.dll, we must use this compiler option!" % version_suffix
-    print "cdl = /MD"
-    print
-    print "all: $(target)$(debug_suffix)%s" % (target_ext)
-    print
+    print("# As the target uses Python%s.dll, we must use this compiler option!" % version_suffix)
+    print("cdl = /MD")
+    print()
+    print("all: $(target)$(debug_suffix)%s" % (target_ext))
+    print()
 
-    print '$(temp_dir):'
-    print '  if not exist $(temp_dir)\. mkdir $(temp_dir)'
-    print
+    print('$(temp_dir):')
+    print('  if not exist $(temp_dir)\. mkdir $(temp_dir)')
+    print()
 
     objects = []
     libs = ["shell32.lib", "comdlg32.lib", "wsock32.lib", "user32.lib", "oleaut32.lib"]
     for moddefn in moddefns:
-        print "# Module", moddefn.name
+        print("# Module", moddefn.name)
         for file in moddefn.sourceFiles:
             base = os.path.basename(file)
             base, ext = os.path.splitext(base)
             objects.append(base + ".obj")
-            print '$(temp_dir)\%s.obj: "%s"' % (base, file)
-            print "\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE",
-            print '"-I$(pythonhome)/Include"  "-I$(pythonhome)/PC" \\'
-            print "\t\t$(cflags) $(cdebug) $(cinclude) \\"
+            print('$(temp_dir)\%s.obj: "%s"' % (base, file))
+            print("\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE", end=' ')
+            print('"-I$(pythonhome)/Include"  "-I$(pythonhome)/PC" \\')
+            print("\t\t$(cflags) $(cdebug) $(cinclude) \\")
             extra = moddefn.GetCompilerOptions()
             if extra:
-                print "\t\t%s \\" % (' '.join(extra),)
-            print '\t\t"%s"' % file
-            print
+                print("\t\t%s \\" % (' '.join(extra),))
+            print('\t\t"%s"' % file)
+            print()
 
         # Add .lib files this module needs
         for modlib in moddefn.GetLinkerLibs():
             if modlib not in libs:
                 libs.append(modlib)
 
-    print "ADDN_LINK_FILES=",
-    for addn in vars['addn_link']: print '"%s"' % (addn),
-    print ; print
-
-    print "OBJS=",
-    for obj in objects: print '"$(temp_dir)\%s"' % (obj),
-    print ; print
-
-    print "LIBS=",
-    for lib in libs: print '"%s"' % (lib),
-    print ; print
-
-    print "$(target)$(debug_suffix)%s: $(temp_dir) $(OBJS)" % (target_ext)
-    print "\tlink -out:$(target)$(debug_suffix)%s %s" % (target_ext, target_link_flags),
-    print "\t$(OBJS) \\"
-    print "\t$(LIBS) \\"
-    print "\t$(ADDN_LINK_FILES) \\"
-    print "\t$(pythonlib) $(lcustom) $(l_debug)\\"
-    print "\t$(resources)"
-    print
-    print "clean:"
-    print "\t-rm -f *.obj"
-    print "\t-rm -f $(target).exe"
+    print("ADDN_LINK_FILES=", end=' ')
+    for addn in vars['addn_link']: print('"%s"' % (addn), end=' ')
+    print() ; print()
+
+    print("OBJS=", end=' ')
+    for obj in objects: print('"$(temp_dir)\%s"' % (obj), end=' ')
+    print() ; print()
+
+    print("LIBS=", end=' ')
+    for lib in libs: print('"%s"' % (lib), end=' ')
+    print() ; print()
+
+    print("$(target)$(debug_suffix)%s: $(temp_dir) $(OBJS)" % (target_ext))
+    print("\tlink -out:$(target)$(debug_suffix)%s %s" % (target_ext, target_link_flags), end=' ')
+    print("\t$(OBJS) \\")
+    print("\t$(LIBS) \\")
+    print("\t$(ADDN_LINK_FILES) \\")
+    print("\t$(pythonlib) $(lcustom) $(l_debug)\\")
+    print("\t$(resources)")
+    print()
+    print("clean:")
+    print("\t-rm -f *.obj")
+    print("\t-rm -f $(target).exe")
diff --git a/kolab-cli.py b/kolab-cli.py
--- a/kolab-cli.py
+++ b/kolab-cli.py
@@ -18,6 +18,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import logging
 import os
 import sys
@@ -31,8 +33,8 @@
 try:
     import pykolab.logger
 except ImportError, e:
-    print >> sys.stderr, _("Cannot load pykolab/logger.py:")
-    print >> sys.stderr, "%s" % e
+    print(_("Cannot load pykolab/logger.py:"), file=sys.stderr)
+    print("%s" % e, file=sys.stderr)
     sys.exit(1)
 
 if __name__ == "__main__":
diff --git a/pykolab/cli/cmd_add_alias.py b/pykolab/cli/cmd_add_alias.py
--- a/pykolab/cli/cmd_add_alias.py
+++ b/pykolab/cli/cmd_add_alias.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -39,10 +41,10 @@
         try:
             secondary_rcpt_address = conf.cli_args.pop(0)
         except:
-            print >> sys.stderr, _("Specify the (new) alias address")
+            print(_("Specify the (new) alias address"), file=sys.stderr)
             sys.exit(1)
     except:
-        print >> sys.stderr, _("Specify the existing recipient address")
+        print(_("Specify the existing recipient address"), file=sys.stderr)
         sys.exit(1)
 
     if len(primary_rcpt_address.split('@')) > 1:
@@ -63,28 +65,28 @@
 
     # Check if either is in fact a domain
     if not primary_rcpt_domain.lower() in domains.keys():
-        print >> sys.stderr, _("Domain %r is not a local domain") % (primary_rcpt_domain)
+        print(_("Domain %r is not a local domain") % (primary_rcpt_domain), file=sys.stderr)
         sys.exit(1)
 
     if not secondary_rcpt_domain.lower() in domains.keys():
-        print >> sys.stderr, _("Domain %r is not a local domain") % (secondary_rcpt_domain)
+        print(_("Domain %r is not a local domain") % (secondary_rcpt_domain), file=sys.stderr)
         sys.exit(1)
 
     if not primary_rcpt_domain == secondary_rcpt_domain:
         if not domains[primary_rcpt_domain] == domains[secondary_rcpt_domain]:
-            print >> sys.stderr, _("Primary and secondary domain do not have the same parent domain")
+            print(_("Primary and secondary domain do not have the same parent domain"), file=sys.stderr)
             sys.exit(1)
 
     primary_recipient_dn = auth.find_recipient(primary_rcpt_address)
 
     if primary_recipient_dn == [] or len(primary_recipient_dn) == 0:
-        print >> sys.stderr, _("No such recipient %r") % (primary_rcpt_address)
+        print(_("No such recipient %r") % (primary_rcpt_address), file=sys.stderr)
         sys.exit(1)
 
     secondary_recipient_dn = auth.find_recipient(secondary_rcpt_address)
 
     if not secondary_recipient_dn == [] and not len(secondary_recipient_dn) == 0:
-        print >> sys.stderr, _("Recipient for alias %r already exists") % (secondary_rcpt_address)
+        print(_("Recipient for alias %r already exists") % (secondary_rcpt_address), file=sys.stderr)
         sys.exit(1)
 
     rcpt_attrs = conf.get_list('ldap', 'mail_attributes')
@@ -94,15 +96,15 @@
     if len(rcpt_attrs) >= 2:
         secondary_rcpt_attr = rcpt_attrs[1]
     else:
-        print >> sys.stderr, _("Environment is not configured for " + \
-            "users to hold secondary mail attributes")
+        print(_("Environment is not configured for " + \
+            "users to hold secondary mail attributes"), file=sys.stderr)
 
         sys.exit(1)
 
     primary_recipient = auth.get_entry_attributes(primary_rcpt_domain, primary_recipient_dn, rcpt_attrs)
 
     if not primary_recipient.has_key(primary_rcpt_attr):
-        print >> sys.stderr, _("Recipient %r is not the primary recipient for address %r") % (primary_recipient, primary_rcpt_address)
+        print(_("Recipient %r is not the primary recipient for address %r") % (primary_recipient, primary_rcpt_address), file=sys.stderr)
         sys.exit(1)
 
     if not primary_recipient.has_key(secondary_rcpt_attr):
diff --git a/pykolab/cli/cmd_add_user_subscription.py b/pykolab/cli/cmd_add_user_subscription.py
--- a/pykolab/cli/cmd_add_user_subscription.py
+++ b/pykolab/cli/cmd_add_user_subscription.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -73,9 +75,9 @@
     imap.login_plain(admin_login, admin_password, user)
 
     if not imap.has_folder(folder_pattern):
-        print >> sys.stderr, \
-                _("Cannot subscribe user to folder %r:") % (folder_pattern), \
-                _("No such folder")
+        print(_("Cannot subscribe user to folder %r:") % (folder_pattern), \
+              _("No such folder"), \
+              file=sys.stderr)
         sys.exit(1)
 
     _folders = imap.lm(folder_pattern)
diff --git a/pykolab/cli/cmd_check_quota.py b/pykolab/cli/cmd_check_quota.py
--- a/pykolab/cli/cmd_check_quota.py
+++ b/pykolab/cli/cmd_check_quota.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -81,7 +83,7 @@
             user_dn = domain_auth.find_recipient(login)
 
             if user_dn == None:
-                print >> sys.stderr, _("No such user %s") % (login)
+                print(_("No such user %s") % (login), file=sys.stderr)
                 continue
 
             if len(login.split('@')) > 1:
@@ -95,14 +97,14 @@
                 user_quota = None
 
             if user_quota == None:
-                print >> sys.stderr, _("No quota for user %s") % (login)
+                print(_("No quota for user %s") % (login), file=sys.stderr)
                 continue
 
             try:
                 (used, quota) = imap.get_quota(folder)
 
                 if not (int)(quota) == (int)(user_quota):
-                    print >> sys.stderr, _("user quota does not match for %s (IMAP: %d, LDAP: %d)") % (login, (int)(quota), (int)(user_quota))
+                    print(_("user quota does not match for %s (IMAP: %d, LDAP: %d)") % (login, (int)(quota), (int)(user_quota)), file=sys.stderr)
                 
             except:
                 pass
diff --git a/pykolab/cli/cmd_count_domain_mailboxes.py b/pykolab/cli/cmd_count_domain_mailboxes.py
--- a/pykolab/cli/cmd_count_domain_mailboxes.py
+++ b/pykolab/cli/cmd_count_domain_mailboxes.py
@@ -57,10 +57,10 @@
 
     folders = []
     for domain in domains.keys():
-        print "%s: %d" % (domain,len(imap.lm("user/%%@%s" % (domain))))
+        print("%s: %d" % (domain,len(imap.lm("user/%%@%s" % (domain)))))
 
     null_realm = len(imap.lm("user/%%"))
 
     if null_realm > 0:
-        print "null: %d" % (null_realm)
+        print("null: %d" % (null_realm))
 
diff --git a/pykolab/cli/cmd_delete_mailbox.py b/pykolab/cli/cmd_delete_mailbox.py
--- a/pykolab/cli/cmd_delete_mailbox.py
+++ b/pykolab/cli/cmd_delete_mailbox.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -41,7 +43,7 @@
     """
 
     if len(conf.cli_args) < 1:
-        print >> sys.stderr, _("No mailbox specified")
+        print(_("No mailbox specified"), file=sys.stderr)
         sys.exit(1)
 
     imap = IMAP()
@@ -54,12 +56,12 @@
         folders = imap.list_folders(folder)
 
         if len(folders) < 1:
-            print >> sys.stderr, _("No such folder(s): %s") % (folder)
+            print(_("No such folder(s): %s") % (folder), file=sys.stderr)
 
         delete_folders.extend(folders)
 
     if len(delete_folders) == 0:
-        print >> sys.stderr, _("No folders to delete.")
+        print(_("No folders to delete."), file=sys.stderr)
         sys.exit(1)
 
     for delete_folder in delete_folders:
diff --git a/pykolab/cli/cmd_delete_mailbox_acl.py b/pykolab/cli/cmd_delete_mailbox_acl.py
--- a/pykolab/cli/cmd_delete_mailbox_acl.py
+++ b/pykolab/cli/cmd_delete_mailbox_acl.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -57,7 +59,7 @@
     imap.connect(domain=domain)
 
     if not imap.has_folder(folder):
-        print >> sys.stderr, _("No such folder %r") % (folder)
+        print(_("No such folder %r") % (folder), file=sys.stderr)
 
     else:
         folders = imap.list_folders(folder)
diff --git a/pykolab/cli/cmd_export_mailbox.py b/pykolab/cli/cmd_export_mailbox.py
--- a/pykolab/cli/cmd_export_mailbox.py
+++ b/pykolab/cli/cmd_export_mailbox.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import commands
 
 import pykolab
@@ -115,8 +117,8 @@
                 stdout=subprocess.PIPE
             ).communicate()[0]
 
-        print >> sys.stderr, _("ZIP file at %s.zip") % (user)
+        print(_("ZIP file at %s.zip") % (user), file=sys.stderr)
     else:
-        print >> sys.stderr, _("No directories found for user %s") % (user)
+        print(_("No directories found for user %s") % (user), file=sys.stderr)
         sys.exit(1)
 
diff --git a/pykolab/cli/cmd_list_deleted_mailboxes.py b/pykolab/cli/cmd_list_deleted_mailboxes.py
--- a/pykolab/cli/cmd_list_deleted_mailboxes.py
+++ b/pykolab/cli/cmd_list_deleted_mailboxes.py
@@ -101,7 +101,7 @@
             log.debug(_("Appending folder search for %r") % (search), level=8)
             folders.extend(imap.lm(imap_utf7.encode(search)))
 
-    print "Deleted folders:"
+    print("Deleted folders:")
 
     for folder in folders:
         utf8_folder = imap_utf7.decode(folder).encode('utf-8')
@@ -109,6 +109,6 @@
         ts = datetime.datetime.fromtimestamp(int(mbox_parts['hex_timestamp'], 16))
 
         if not conf.raw:
-            print "%s (Deleted at %s)" % (utf8_folder, ts)
+            print("%s (Deleted at %s)" % (utf8_folder, ts))
         else:
-            print "%s (Deleted at %s)" % (folder, ts)
+            print("%s (Deleted at %s)" % (folder, ts))
diff --git a/pykolab/cli/cmd_list_domain_mailboxes.py b/pykolab/cli/cmd_list_domain_mailboxes.py
--- a/pykolab/cli/cmd_list_domain_mailboxes.py
+++ b/pykolab/cli/cmd_list_domain_mailboxes.py
@@ -75,10 +75,10 @@
         for secondary in secondaries:
             folders.extend(imap.lm("user/%%@%s" % (secondary)))
 
-    print "Deleted folders:"
+    print("Deleted folders:")
 
     for folder in folders:
         if not conf.raw:
-            print imap_utf7.decode(folder)
+            print(imap_utf7.decode(folder))
         else:
-            print folder
+            print(folder)
diff --git a/pykolab/cli/cmd_list_domains.py b/pykolab/cli/cmd_list_domains.py
--- a/pykolab/cli/cmd_list_domains.py
+++ b/pykolab/cli/cmd_list_domains.py
@@ -38,15 +38,15 @@
 
     dna = conf.get('ldap', 'domain_name_attribute')
 
-    print "%-39s %-40s" % ("Primary Domain Name Space","Secondary Domain Name Space(s)")
+    print("%-39s %-40s" % ("Primary Domain Name Space","Secondary Domain Name Space(s)"))
 
     # TODO: Take a hint in --quiet, and otherwise print out a nice table
     # with headers and such.
     if isinstance(domains['list'], dict):
         for domain_dn in domains['list'].keys():
             if isinstance(domains['list'][domain_dn][dna], list):
-                print domains['list'][domain_dn][dna][0]
+                print(domains['list'][domain_dn][dna][0])
                 for domain_alias in domains['list'][domain_dn][dna][1:]:
-                    print "%-39s %-40s" % ('', domain_alias)
+                    print("%-39s %-40s" % ('', domain_alias))
             else:
-                print domains['list'][domain_dn][dna]
+                print(domains['list'][domain_dn][dna])
diff --git a/pykolab/cli/cmd_list_mailbox_acls.py b/pykolab/cli/cmd_list_mailbox_acls.py
--- a/pykolab/cli/cmd_list_mailbox_acls.py
+++ b/pykolab/cli/cmd_list_mailbox_acls.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -51,15 +53,15 @@
     imap.connect(domain=domain)
 
     if not imap.has_folder(folder):
-        print >> sys.stderr, _("No such folder %r") % (folder)
+        print(_("No such folder %r") % (folder), file=sys.stderr)
 
     else:
         acls = []
         folders = imap.list_folders(folder)
         for folder in folders:
-            print "Folder", folder
+            print("Folder", folder)
             acls = imap.list_acls(folder)
 
             for acl in acls.keys():
-                print "  %-13s %s" %(acls[acl], acl)
+                print("  %-13s %s" %(acls[acl], acl))
 
diff --git a/pykolab/cli/cmd_list_mailbox_metadata.py b/pykolab/cli/cmd_list_mailbox_metadata.py
--- a/pykolab/cli/cmd_list_mailbox_metadata.py
+++ b/pykolab/cli/cmd_list_mailbox_metadata.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -77,19 +79,19 @@
         imap.connect(domain=domain)
 
     if not imap.has_folder(folder):
-        print >> sys.stderr, _("No such folder %r") % (folder)
+        print(_("No such folder %r") % (folder), file=sys.stderr)
 
     else:
         metadata = []
         folders = imap.list_folders(folder)
         for folder in folders:
-            print "Folder", folder
+            print("Folder", folder)
 
             metadata = imap.get_metadata(folder)
 
             if metadata.has_key(folder):
                 for annotation in metadata[folder].keys():
-                    print "  %-49s %s" % (
+                    print("  %-49s %s" % (
                             annotation,
                             metadata[folder][annotation]
-                        )
+                        ))
diff --git a/pykolab/cli/cmd_list_mailboxes.py b/pykolab/cli/cmd_list_mailboxes.py
--- a/pykolab/cli/cmd_list_mailboxes.py
+++ b/pykolab/cli/cmd_list_mailboxes.py
@@ -98,6 +98,6 @@
 
     for folder in folders:
         if not conf.raw:
-            print imap_utf7.decode(folder)
+            print(imap_utf7.decode(folder))
         else:
-            print folder
+            print(folder)
diff --git a/pykolab/cli/cmd_list_messages.py b/pykolab/cli/cmd_list_messages.py
--- a/pykolab/cli/cmd_list_messages.py
+++ b/pykolab/cli/cmd_list_messages.py
@@ -118,17 +118,17 @@
         if len(flags) >= 3:
             # Any flags are set
             if flags[2] == '(\\Deleted))':
-                print num, '\Deleted'
+                print(num, '\Deleted')
             elif flags[2] == '(\\Deleted':
-                print num, '\Deleted'
+                print(num, '\Deleted')
             elif '\\Deleted' in flags[3:]:
-                print num, '\Deleted'
+                print(num, '\Deleted')
             elif '\\Deleted))' in flags[3:]:
-                print num, '\Deleted'
+                print(num, '\Deleted')
             else:
-                print num
+                print(num)
         else:
-            print num
+            print(num)
 
     if conf.user == None:
         imap.set_acl(folder, 'cyrus-admin', '')
diff --git a/pykolab/cli/cmd_list_ous.py b/pykolab/cli/cmd_list_ous.py
--- a/pykolab/cli/cmd_list_ous.py
+++ b/pykolab/cli/cmd_list_ous.py
@@ -36,4 +36,4 @@
     wap_client.authenticate(username=conf.get("ldap", "bind_dn"), password=conf.get("ldap", "bind_pw"))
 
     ous = wap_client.ous_list()
-    print '\n'.join(ous['list'].keys())
+    print('\n'.join(ous['list'].keys()))
diff --git a/pykolab/cli/cmd_list_quota.py b/pykolab/cli/cmd_list_quota.py
--- a/pykolab/cli/cmd_list_quota.py
+++ b/pykolab/cli/cmd_list_quota.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -67,36 +69,36 @@
     for quota_folder in quota_folders:
         try:
             (used, quota) = imap.get_quota(quota_folder)
-            print "Folder: %s" % (quota_folder)
+            print("Folder: %s" % (quota_folder))
             if not used == None and not quota == None:
                 if quota == 0:
-                    print >> sys.stderr, _("The quota for folder %s is set to literally allow 0KB of storage.") % (quota_folder)
-                    print "%d (Used: %d, Percentage: %s)" % (quota, used, u'\u221E')
+                    print(_("The quota for folder %s is set to literally allow 0KB of storage.") % (quota_folder), file=sys.stderr)
+                    print("%d (Used: %d, Percentage: %s)" % (quota, used, u'\u221E'))
                 else:
                     percentage = round(((float)(used)/(float)(quota)) * 100.0, 1)
-                    print "%d (Used: %d, Percentage: %d)" % (quota, used, percentage)
+                    print("%d (Used: %d, Percentage: %d)" % (quota, used, percentage))
             else:
                 if used == None:
-                    print "%d (Used: %d, Percentage: %d)" % (quota, 0, 0)
+                    print("%d (Used: %d, Percentage: %d)" % (quota, 0, 0))
                 else:
-                    print "No quota"
+                    print("No quota")
         except:
             try:
                 (quota_root, used, quota) = imap.get_quota_root(quota_folder)
-                print "Folder: %s" % (quota_folder)
+                print("Folder: %s" % (quota_folder))
                 if not quota_root == None and not used == None and not quota == None:
                     if quota == 0:
-                        print >> sys.stderr, _("The quota for folder %s is set to literally allow 0KB of storage.") % (quota_folder)
-                        print "%d (Used: %d, Percentage: %d)" % (quota, used, u'\u221E')
+                        print(_("The quota for folder %s is set to literally allow 0KB of storage.") % (quota_folder), file=sys.stderr)
+                        print("%d (Used: %d, Percentage: %d)" % (quota, used, u'\u221E'))
                     else:
                         percentage = round(((float)(used)/(float)(quota)) * 100.0, 1)
-                        print "%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, used, percentage)
+                        print("%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, used, percentage))
                 else:
                     if used == None and not quota_root == None:
-                        print "%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, 0, 0)
+                        print("%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, 0, 0))
                     else:
-                        print "No quota"
+                        print("No quota")
             except:
-                print "Folder: %s" % (quota_folder)
-                print "No quota root"
+                print("Folder: %s" % (quota_folder))
+                print("No quota root")
 
diff --git a/pykolab/cli/cmd_list_user_subscriptions.py b/pykolab/cli/cmd_list_user_subscriptions.py
--- a/pykolab/cli/cmd_list_user_subscriptions.py
+++ b/pykolab/cli/cmd_list_user_subscriptions.py
@@ -91,14 +91,14 @@
 
         if len(unsubscribed_folders) > 0:
             if not conf.raw:
-                print "\n".join([imap_utf7.decode(x) for x in unsubscribed_folders])
+                print("\n".join([imap_utf7.decode(x) for x in unsubscribed_folders]))
             else:
-                print "\n".join(unsubscribed_folders)
+                print("\n".join(unsubscribed_folders))
         else:
-            print _("No unsubscribed folders for user %s") % (user)
+            print(_("No unsubscribed folders for user %s") % (user))
 
     else:
         if not conf.raw:
-            print "\n".join([imap_utf7.decode(x) for x in subscribed_folders])
+            print("\n".join([imap_utf7.decode(x) for x in subscribed_folders]))
         else:
-            print "\n".join(subscribed_folders)
+            print("\n".join(subscribed_folders))
diff --git a/pykolab/cli/cmd_list_users.py b/pykolab/cli/cmd_list_users.py
--- a/pykolab/cli/cmd_list_users.py
+++ b/pykolab/cli/cmd_list_users.py
@@ -36,4 +36,4 @@
     wap_client.authenticate(username=conf.get("ldap", "bind_dn"), password=conf.get("ldap", "bind_pw"))
 
     users = wap_client.users_list()
-    print '\n'.join(users['list'].keys())
+    print('\n'.join(users['list'].keys()))
diff --git a/pykolab/cli/cmd_remove_mailaddress.py b/pykolab/cli/cmd_remove_mailaddress.py
--- a/pykolab/cli/cmd_remove_mailaddress.py
+++ b/pykolab/cli/cmd_remove_mailaddress.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -87,7 +89,7 @@
         pass
 
     else:
-        print >> sys.stderr, _("Found the following recipients:")
+        print(_("Found the following recipients:"), file=sys.stderr)
 
         for recipient in recipients:
-            print recipient
+            print(recipient)
diff --git a/pykolab/cli/cmd_remove_user_subscription.py b/pykolab/cli/cmd_remove_user_subscription.py
--- a/pykolab/cli/cmd_remove_user_subscription.py
+++ b/pykolab/cli/cmd_remove_user_subscription.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -73,9 +75,9 @@
     imap.login_plain(admin_login, admin_password, user)
 
     if not imap.has_folder(folder_pattern):
-        print >> sys.stderr, \
-                _("Cannot subscribe user to folder %r:") % (folder_pattern), \
-                _("No such folder")
+        print(_("Cannot subscribe user to folder %r:") % (folder_pattern), \
+              _("No such folder"), \
+              file=sys.stderr)
         sys.exit(1)
 
     _folders = imap.lm(folder_pattern)
@@ -88,14 +90,14 @@
             unsubscribed_folders.append(_folder)
 
     if len(unsubscribed_folders) > 0:
-        print _("Successfully unsubscribed user %s from the following folders:") % (
+        print(_("Successfully unsubscribed user %s from the following folders:") % (
                 user
-            )
+            ))
 
-        print "\n".join(unsubscribed_folders)
+        print("\n".join(unsubscribed_folders))
     else:
-        print >> sys.stderr, _("User %s was not unsubscribed from any folders.") % (
+        print(_("User %s was not unsubscribed from any folders.") % (
                 user
-            )
+            ), file=sys.stderr)
 
         sys.exit(1)
diff --git a/pykolab/cli/cmd_rename_mailbox.py b/pykolab/cli/cmd_rename_mailbox.py
--- a/pykolab/cli/cmd_rename_mailbox.py
+++ b/pykolab/cli/cmd_rename_mailbox.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -49,9 +51,9 @@
             except IndexError, errmsg:
                 partition = None
         except IndexError, errmsg:
-            print >> sys.stderr, _("No target mailbox name specified")
+            print(_("No target mailbox name specified"), file=sys.stderr)
     except IndexError, errmsg:
-        print >> sys.stderr, _("No source mailbox name specified")
+        print(_("No source mailbox name specified"), file=sys.stderr)
         sys.exit(1)
 
     if len(source_folder.split('@')) > 1:
@@ -63,11 +65,11 @@
     imap.connect(domain=domain)
 
     if not imap.has_folder(source_folder):
-        print >> sys.stderr, _("Source folder %r does not exist") % (source_folder)
+        print(_("Source folder %r does not exist") % (source_folder), file=sys.stderr)
         sys.exit(1)
 
     if imap.has_folder(target_folder) and partition == None:
-        print >> sys.stderr, _("Target folder %r already exists") % (target_folder)
+        print(_("Target folder %r already exists") % (target_folder), file=sys.stderr)
         sys.exit(1)
 
     imap.imap.rename(imap.folder_utf7(source_folder), imap.folder_utf7(target_folder), partition)
diff --git a/pykolab/cli/cmd_server_info.py b/pykolab/cli/cmd_server_info.py
--- a/pykolab/cli/cmd_server_info.py
+++ b/pykolab/cli/cmd_server_info.py
@@ -55,4 +55,4 @@
     else:
         imap.connect()
 
-    print imap.get_metadata("")
+    print(imap.get_metadata(""))
diff --git a/pykolab/cli/cmd_set_mailbox_acl.py b/pykolab/cli/cmd_set_mailbox_acl.py
--- a/pykolab/cli/cmd_set_mailbox_acl.py
+++ b/pykolab/cli/cmd_set_mailbox_acl.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -64,7 +66,7 @@
     imap.connect(domain=domain)
 
     if not imap.has_folder(folder):
-        print >> sys.stderr, _("No such folder %r") % (folder)
+        print(_("No such folder %r") % (folder), file=sys.stderr)
 
     else:
         folders = imap.list_folders(folder)
diff --git a/pykolab/cli/cmd_set_mailbox_metadata.py b/pykolab/cli/cmd_set_mailbox_metadata.py
--- a/pykolab/cli/cmd_set_mailbox_metadata.py
+++ b/pykolab/cli/cmd_set_mailbox_metadata.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -91,7 +93,7 @@
         imap.connect(domain=domain)
 
     if not imap.has_folder(folder):
-        print >> sys.stderr, _("No such folder %r") % (folder)
+        print(_("No such folder %r") % (folder), file=sys.stderr)
 
     else:
         folders = imap.lm(imap_utf7.encode(folder))
diff --git a/pykolab/cli/cmd_set_quota.py b/pykolab/cli/cmd_set_quota.py
--- a/pykolab/cli/cmd_set_quota.py
+++ b/pykolab/cli/cmd_set_quota.py
@@ -17,6 +17,8 @@
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -57,10 +59,10 @@
     imap.connect(domain=domain)
 
     if not imap.has_folder(folder):
-        print >> sys.stderr, _("No such folder %r") % (folder)
+        print(_("No such folder %r") % (folder), file=sys.stderr)
         sys.exit(1)
 
     for _folder in imap.lm(imap.folder_utf7(folder)):
         imap.set_quota(_folder, quota)
-        print >> sys.stdout, "Quota for folder '%s' set to %d" % (_folder, int(quota))
+        print("Quota for folder '%s' set to %d" % (_folder, int(quota)), file=sys.stdout)
 
diff --git a/pykolab/cli/cmd_sync_mailhost_attrs.py b/pykolab/cli/cmd_sync_mailhost_attrs.py
--- a/pykolab/cli/cmd_sync_mailhost_attrs.py
+++ b/pykolab/cli/cmd_sync_mailhost_attrs.py
@@ -174,7 +174,7 @@
 
             if not server == mailhost:
                 if conf.dry_run:
-                    print folder, server, mailhost
+                    print(folder, server, mailhost)
                 else:
                     auth.set_entry_attribute(primary, recipient, 'mailhost', server)
 
@@ -193,4 +193,4 @@
         else:
             recipient = auth.find_recipient('/'.join(folder.split('/')[1:]), search_attrs=[result_attribute])
 
-        print folder, server, recipient
+        print(folder, server, recipient)
diff --git a/pykolab/cli/cmd_user_info.py b/pykolab/cli/cmd_user_info.py
--- a/pykolab/cli/cmd_user_info.py
+++ b/pykolab/cli/cmd_user_info.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 import commands
@@ -48,13 +50,13 @@
     user_info = wap_client.user_find({'mail':user})
 
     if user_info == None or not user_info:
-        print >> sys.stderr, _("No such user %s") % (user)
+        print(_("No such user %s") % (user), file=sys.stderr)
         sys.exit(0)
 
     unic_attrs = ['displayname', 'givenname', 'cn', 'sn', 'ou', 'entrydn']
 
     for (k,v) in user_info.iteritems():
         if k in unic_attrs:
-            print "%s: %s" % (k,v)
+            print("%s: %s" % (k,v))
         else:
-            print "%s: %r" % (k,v)
+            print("%s: %r" % (k,v))
diff --git a/pykolab/cli/commands.py b/pykolab/cli/commands.py
--- a/pykolab/cli/commands.py
+++ b/pykolab/cli/commands.py
@@ -87,21 +87,21 @@
         if __commands[_command].has_key('function'):
             # This is a top-level command
             if not __commands[_command]['description'] == None:
-                print "%-25s - %s" % (_command.replace('_','-'),__commands[_command]['description'])
+                print("%-25s - %s" % (_command.replace('_','-'),__commands[_command]['description']))
             else:
-                print "%-25s" % (_command.replace('_','-'))
+                print("%-25s" % (_command.replace('_','-')))
 
     for _command in _commands:
         if not __commands[_command].has_key('function'):
             # This is a nested command
-            print "\n" + _("Command Group: %s") % (_command) + "\n"
+            print("\n" + _("Command Group: %s") % (_command) + "\n")
             ___commands = __commands[_command].keys()
             ___commands.sort()
             for __command in ___commands:
                 if not __commands[_command][__command]['description'] == None:
-                    print "%-4s%-21s - %s" % ('',__command.replace('_','-'),__commands[_command][__command]['description'])
+                    print("%-4s%-21s - %s" % ('',__command.replace('_','-'),__commands[_command][__command]['description']))
                 else:
-                    print "%-4s%-21s" % ('',__command.replace('_','-'))
+                    print("%-4s%-21s" % ('',__command.replace('_','-')))
 
 def execute(cmd_name, *args, **kw):
     if cmd_name == "":
@@ -197,5 +197,5 @@
 ##
 
 def not_yet_implemented(*args, **kw):
-    print _("Not yet implemented")
+    print(_("Not yet implemented"))
     sys.exit(1)
diff --git a/pykolab/cli/sieve/cmd_list.py b/pykolab/cli/sieve/cmd_list.py
--- a/pykolab/cli/sieve/cmd_list.py
+++ b/pykolab/cli/sieve/cmd_list.py
@@ -103,19 +103,19 @@
         )
 
     if not result:
-        print "LOGIN FAILED??"
+        print("LOGIN FAILED??")
 
     sieveclient.authenticated = True
 
     result = sieveclient.listscripts()
 
     if result == None:
-        print "No scripts"
+        print("No scripts")
         sys.exit(0)
 
     (active, scripts) = result
 
-    print "%s (active)" % (active)
+    print("%s (active)" % (active))
     for script in scripts:
-        print script
+        print(script)
 
diff --git a/pykolab/cli/sieve/cmd_test.py b/pykolab/cli/sieve/cmd_test.py
--- a/pykolab/cli/sieve/cmd_test.py
+++ b/pykolab/cli/sieve/cmd_test.py
@@ -89,7 +89,7 @@
 
     active, scripts = sieveclient.listscripts()
 
-    print "%s (active)" % (active)
+    print("%s (active)" % (active))
     
     _all_scripts = [ active ] + scripts
     _used_scripts = [ active ]
@@ -97,7 +97,7 @@
 
     _a_script = sieveclient.getscript(active)
 
-    print _a_script
+    print(_a_script)
 
     import sievelib.parser
 
@@ -107,23 +107,23 @@
     #print "%r" % (_a_parsed)
 
     if not _a_parsed:
-        print _a_parser.error
+        print(_a_parser.error)
 
-    print "%r" % (_a_parser.result)
+    print("%r" % (_a_parser.result))
 
     for _a_command in _a_parser.result:
-        print _a_command.name, _a_command.arguments
+        print(_a_command.name, _a_command.arguments)
         if len(_a_command.children) > 0:
             for _a_child in _a_command.children:
-                print "  ", _a_child.name, _a_child.arguments
+                print("  ", _a_child.name, _a_child.arguments)
 
         if _a_command.name == "include":
             if _a_command.arguments["script"].strip('"') in scripts:
-                print "OK"
+                print("OK")
                 _used_scripts.append(_a_command.arguments["script"].strip('"'))
             else:
-                print "Not OK"
+                print("Not OK")
 
     for script in scripts:
-        print script
+        print(script)
 
diff --git a/pykolab/cli/telemetry/cmd_examine_command_issue.py b/pykolab/cli/telemetry/cmd_examine_command_issue.py
--- a/pykolab/cli/telemetry/cmd_examine_command_issue.py
+++ b/pykolab/cli/telemetry/cmd_examine_command_issue.py
@@ -72,7 +72,7 @@
                 id=session.server_id
             ).first()
 
-    print _("Session by %s on server %s") % (user.sasl_username,server.fqdn)
+    print(_("Session by %s on server %s") % (user.sasl_username,server.fqdn))
 
     command_issues = db.query(
             telemetry.TelemetryCommandIssue
@@ -94,14 +94,14 @@
                 ).first()
 
         if command_issue.id == _command_issue.id:
-            print "========="
+            print("=========")
 
-        print "Client(%d): %s %s %s" % (
+        print("Client(%d): %s %s %s" % (
                 _command_issue.id,
                 _command_issue.command_tag,
                 command.command,
                 command_arg.command_arg
-            )
+            ))
 
         server_responses = db.query(
                 telemetry.TelemetryServerResponse
@@ -113,11 +113,11 @@
             server_response_lines = server_response.response.split('\n');
 
             for server_response_line in server_response_lines:
-                print "Server(%d): %s" % (
+                print("Server(%d): %s" % (
                         server_response.id,
                         server_response_line
-                    )
+                    ))
 
         if command_issue.id == _command_issue.id:
-            print "========="
+            print("=========")
 
diff --git a/pykolab/cli/telemetry/cmd_examine_session.py b/pykolab/cli/telemetry/cmd_examine_session.py
--- a/pykolab/cli/telemetry/cmd_examine_session.py
+++ b/pykolab/cli/telemetry/cmd_examine_session.py
@@ -97,7 +97,7 @@
 
         return
 
-    print _("Session by %s on server %s") % (user.sasl_username,server.fqdn)
+    print(_("Session by %s on server %s") % (user.sasl_username,server.fqdn))
 
     command_issues = db.query(
             telemetry.TelemetryCommandIssue
@@ -118,12 +118,12 @@
                     id=command_issue.command_arg_id
                 ).first()
 
-        print "Client(%d): %s %s %s" % (
+        print("Client(%d): %s %s %s" % (
                 command_issue.id,
                 command_issue.command_tag,
                 command.command,
                 command_arg.command_arg
-            )
+            ))
 
         server_responses = db.query(
                 telemetry.TelemetryServerResponse
@@ -134,8 +134,8 @@
         for server_response in server_responses:
             server_response_lines = server_response.response.split('\n');
             for server_response_line in server_response_lines:
-                print "Server(%d): %s" % (
+                print("Server(%d): %s" % (
                         server_response.id,
                         server_response_line
-                    )
+                    ))
 
diff --git a/pykolab/cli/telemetry/cmd_list_sessions.py b/pykolab/cli/telemetry/cmd_list_sessions.py
--- a/pykolab/cli/telemetry/cmd_list_sessions.py
+++ b/pykolab/cli/telemetry/cmd_list_sessions.py
@@ -55,9 +55,9 @@
                     id=session.user_id
                 ).first()
 
-        print _("Session for user %s started at %s with ID %s") % (
+        print(_("Session for user %s started at %s with ID %s") % (
                 user.sasl_username,
                 session.start,
                 session.id
-            )
+            ))
 
diff --git a/pykolab/cli/wap/cmd_system_capabilities.py b/pykolab/cli/wap/cmd_system_capabilities.py
--- a/pykolab/cli/wap/cmd_system_capabilities.py
+++ b/pykolab/cli/wap/cmd_system_capabilities.py
@@ -38,13 +38,13 @@
     system_capabilities = wap_client.system_capabilities()
 
     if system_capabilities['count'] < 1:
-        print "No system capabilities"
+        print("No system capabilities")
         sys.exit(1)
 
     for domain in system_capabilities['list'].keys():
-        print "Domain capabilities for %s" % (domain)
+        print("Domain capabilities for %s" % (domain))
 
         domain_capabilities = system_capabilities['list'][domain]
 
         for service in domain_capabilities['actions'].keys():
-            print "  %-15s - %r" % (service, domain_capabilities['actions'][service]['type'])
+            print("  %-15s - %r" % (service, domain_capabilities['actions'][service]['type']))
diff --git a/pykolab/cli/wap/cmd_user_types_list.py b/pykolab/cli/wap/cmd_user_types_list.py
--- a/pykolab/cli/wap/cmd_user_types_list.py
+++ b/pykolab/cli/wap/cmd_user_types_list.py
@@ -37,4 +37,4 @@
 
     for user_type in user_types['list']:
         type = user_types['list'][user_type]
-        print "%-15s - %s" % (type['key'], type['description'])
+        print("%-15s - %s" % (type['key'], type['description']))
diff --git a/pykolab/constants.py.in b/pykolab/constants.py.in
--- a/pykolab/constants.py.in
+++ b/pykolab/constants.py.in
@@ -50,7 +50,7 @@
 try:
     domain_parts = fqdn.split('.')
     if len(domain_parts) < 3:
-        print >> sys.stderr, _("WARNING") + ": " + _("The Fully Qualified Domain Name or FQDN for this system is incorrect. Falling back to 'localdomain'.")
+        print(_("WARNING") + ": " + _("The Fully Qualified Domain Name or FQDN for this system is incorrect. Falling back to 'localdomain'."), file=sys.stderr)
         domainname = "localdomain"
     else:
         domainname = '.'.join(domain_parts[1:])
diff --git a/pykolab/imap/cyrus.py b/pykolab/imap/cyrus.py
--- a/pykolab/imap/cyrus.py
+++ b/pykolab/imap/cyrus.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import cyruslib
 import sys
 import time
@@ -499,18 +501,16 @@
                 self.rename(undelete_folder, target_folder)
             else:
                 if not target_server == source_server:
-                    print >> sys.stdout, \
-                        _("Would have transferred %s from %s to %s") % (
+                    print(_("Would have transferred %s from %s to %s") % (
                                 undelete_folder,
                                 source_server,
                                 target_server
-                            )
+                            ), file=sys.stdout)
 
-                print >> sys.stdout, \
-                    _("Would have renamed %s to %s") % (
+                print(_("Would have renamed %s to %s") % (
                             undelete_folder,
                             target_folder
-                        )
+                        ), file=sys.stdout)
 
     def parse_mailfolder(self, mailfolder):
         """
diff --git a/pykolab/imap/dovecot.py b/pykolab/imap/dovecot.py
--- a/pykolab/imap/dovecot.py
+++ b/pykolab/imap/dovecot.py
@@ -37,6 +37,8 @@
 # are using need.
 # -----
 
+from __future__ import print_function
+
 import cyruslib
 import imaplib
 import sys
@@ -240,7 +242,7 @@
 
     def __verbose(self, msg):
         if self.VERBOSE:
-            print >> self.LOGFD, msg
+            print(msg, file=self.LOGFD)
 
     def connect(self, uri):
         """
@@ -521,9 +523,9 @@
                 self.rename(undelete_folder,target_folder)
             else:
                 if not target_server == self.server:
-                    print >> sys.stdout, _("Would have transfered %s from %s to %s") % (undelete_folder, self.server, target_server)
+                    print(_("Would have transfered %s from %s to %s") % (undelete_folder, self.server, target_server), file=sys.stdout)
 
-                print >> sys.stdout, _("Would have renamed %s to %s") % (undelete_folder, target_folder)
+                print(_("Would have renamed %s to %s") % (undelete_folder, target_folder), file=sys.stdout)
 
     def parse_mailfolder(self, mailfolder):
         """
diff --git a/pykolab/setup/components.py b/pykolab/setup/components.py
--- a/pykolab/setup/components.py
+++ b/pykolab/setup/components.py
@@ -80,21 +80,21 @@
         if __components[_component].has_key('function'):
             # This is a top-level component
             if not __components[_component]['description'] == None:
-                print "%-25s - %s" % (_component.replace('_','-'),__components[_component]['description'])
+                print("%-25s - %s" % (_component.replace('_','-'),__components[_component]['description']))
             else:
-                print "%-25s" % (_component.replace('_','-'))
+                print("%-25s" % (_component.replace('_','-')))
 
     for _component in _components:
         if not __components[_component].has_key('function'):
             # This is a nested component
-            print "\n" + _("Command Group: %s") % (_component) + "\n"
+            print("\n" + _("Command Group: %s") % (_component) + "\n")
             ___components = __components[_component].keys()
             ___components.sort()
             for __component in ___components:
                 if not __components[_component][__component]['description'] == None:
-                    print "%-4s%-21s - %s" % ('',__component.replace('_','-'),__components[_component][__component]['description'])
+                    print("%-4s%-21s - %s" % ('',__component.replace('_','-'),__components[_component][__component]['description']))
                 else:
-                    print "%-4s%-21s" % ('',__component.replace('_','-'))
+                    print("%-4s%-21s" % ('',__component.replace('_','-')))
 
 def _list_components(*args, **kw):
     """
@@ -262,5 +262,5 @@
 ##
 
 def not_yet_implemented(*args, **kw):
-    print _("Not yet implemented")
+    print(_("Not yet implemented"))
     sys.exit(1)
diff --git a/pykolab/setup/setup_ldap.py b/pykolab/setup/setup_ldap.py
--- a/pykolab/setup/setup_ldap.py
+++ b/pykolab/setup/setup_ldap.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import ldap
 import ldap.modlist
 import os
@@ -102,7 +104,7 @@
         ask_questions = False
 
     if conf.without_ldap:
-        print >> sys.stderr, _("Skipping setup of LDAP, as specified")
+        print(_("Skipping setup of LDAP, as specified"), file=sys.stderr)
         return
 
     _input = {}
@@ -130,12 +132,12 @@
         return
 
     elif conf.with_ad and conf.with_openldap:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         You can not configure Kolab to run against OpenLDAP
                         and Active Directory simultaneously.
                     """)
-            )
+            ), file=sys.stderr)
 
         sys.exit(1)
 
@@ -143,7 +145,7 @@
     for path, directories, files in os.walk('/etc/dirsrv/'):
         for direct in directories:
             if direct.startswith('slapd-'):
-                print >> sys.stderr, utils.multiline_message(
+                print(utils.multiline_message(
                         _("""
                                 It seems 389 Directory Server has an existing
                                 instance configured. This setup script does not
@@ -151,20 +153,20 @@
                                 make sure /etc/dirsrv/ and /var/lib/dirsrv/ are
                                 clean so that this setup does not have to worry.
                             """)
-                    )
+                    ), file=sys.stderr)
 
                 sys.exit(1)
 
     _input = {}
 
     if ask_questions:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         Please supply a password for the LDAP administrator user
                         'admin', used to login to the graphical console of 389
                         Directory server.
                     """)
-            )
+            ), file=sys.stderr)
 
         _input['admin_pass'] = utils.ask_question(
                 _("Administrator password"),
@@ -176,14 +178,14 @@
         if conf.directory_manager_pwd is not None:
             _input['dirmgr_pass'] = conf.directory_manager_pwd
         else:
-            print >> sys.stderr, utils.multiline_message(
+            print(utils.multiline_message(
                 _("""
                         Please supply a password for the LDAP Directory Manager
                         user, which is the administrator user you will be using
                         to at least initially log in to the Web Admin, and that
                         Kolab uses to perform administrative tasks.
                     """)
-            )
+            ), file=sys.stderr)
 
             _input['dirmgr_pass'] = utils.ask_question(
                 _("Directory Manager password"),
@@ -192,13 +194,13 @@
                 confirm=True
             )
 
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         Please choose the system user and group the service
                         should use to run under. These should be existing,
                         unprivileged, local system POSIX accounts with no shell.
                     """)
-            )
+            ), file=sys.stderr)
 
         try:
             pw = pwd.getpwnam("dirsrv")
@@ -241,7 +243,7 @@
     _input['rootdn'] = utils.standard_root_dn(_input['domain'])
 
     if ask_questions:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         This setup procedure plans to set up Kolab Groupware for
                         the following domain name space. This domain name is
@@ -249,7 +251,7 @@
                         interface. Please confirm this is the appropriate domain
                         name space.
                     """)
-            )
+            ), file=sys.stderr)
 
         answer = utils.ask_confirmation("%s" % (_input['domain']))
 
@@ -260,21 +262,21 @@
                 if not _input['domain'] == None and not _input['domain'] == "":
                     positive_answer = True
                 else:
-                    print >> sys.stderr, utils.multiline_message(
+                    print(utils.multiline_message(
                             _("""
                                     Invalid input. Please try again.
                                 """)
-                        )
+                        ), file=sys.stderr)
 
         _input['nodotdomain'] = _input['domain'].replace('.','_')
         _input['rootdn'] = utils.standard_root_dn(_input['domain'])
 
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         The standard root dn we composed for you follows. Please
                         confirm this is the root dn you wish to use.
                     """)
-            )
+            ), file=sys.stderr)
 
         answer = utils.ask_confirmation("%s" % (_input['rootdn']))
 
@@ -285,11 +287,11 @@
                 if not _input['rootdn'] == None and not _input['rootdn'] == "":
                     positive_answer = True
                 else:
-                    print >> sys.stderr, utils.multiline_message(
+                    print(utils.multiline_message(
                             _("""
                                     Invalid input. Please try again.
                                 """)
-                        )
+                        ), file=sys.stderr)
 
     # TODO: Loudly complain if the fqdn does not resolve back to this system.
 
@@ -344,13 +346,13 @@
             '--file=%s' % (filename)
         ]
 
-    print >> sys.stderr, utils.multiline_message(
+    print(utils.multiline_message(
             _("""
                     Setup is now going to set up the 389 Directory Server. This
                     may take a little while (during which period there is no
                     output and no progress indication).
                 """)
-        )
+        ), file=sys.stderr)
 
     log.info(_("Setting up 389 Directory Server"))
 
@@ -363,7 +365,7 @@
     (stdoutdata, stderrdata) = setup_389.communicate()
 
     if not setup_389.returncode == 0:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         An error was detected in the setup procedure for 389
                         Directory Server. This setup will write out stderr and
@@ -371,7 +373,7 @@
                         /var/log/kolab/setup.out.log respectively, before it
                         exits.
                     """)
-            )
+            ), file=sys.stderr)
 
         fp = open('/var/log/kolab/setup.error.log', 'w')
         fp.write(stderrdata)
@@ -441,7 +443,7 @@
                 "directory server service."))
 
     if ask_questions:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         Please supply a Cyrus Administrator password. This
                         password is used by Kolab to execute administrative
@@ -449,7 +451,7 @@
                         yourself to troubleshoot Cyrus IMAP and/or perform
                         other administrative tasks against Cyrus IMAP directly.
                     """)
-            )
+            ), file=sys.stderr)
 
         _input['cyrus_admin_pass'] = utils.ask_question(
                 _("Cyrus Administrator password"),
@@ -458,14 +460,14 @@
                 confirm=True
             )
 
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 _("""
                         Please supply a Kolab Service account password. This
                         account is used by various services such as Postfix,
                         and Roundcube, as anonymous binds to the LDAP server
                         will not be allowed.
                     """)
-            )
+            ), file=sys.stderr)
 
         _input['kolab_service_pass'] = utils.ask_question(
                 _("Kolab Service password"),
diff --git a/pykolab/setup/setup_mysql.py b/pykolab/setup/setup_mysql.py
--- a/pykolab/setup/setup_mysql.py
+++ b/pykolab/setup/setup_mysql.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import os
 import subprocess
 import tempfile
@@ -142,12 +144,12 @@
 
     if answer == "1" or answer == 1:
         if not conf.mysqlrootpw:
-            print >> sys.stderr, utils.multiline_message(
+            print(utils.multiline_message(
                 _("""
                     Please supply the root password for MySQL, so we can set
                     up user accounts for other components that use MySQL.
                 """)
-            )
+            ), file=sys.stderr)
 
             mysql_root_password = utils.ask_question(
                 _("MySQL root password"),
@@ -161,7 +163,7 @@
         mysql_root_password = 'unix_socket'
 
     else:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
             _("""
                 Please supply a root password for MySQL. This password
                 will be the administrative user for this MySQL server,
@@ -170,7 +172,7 @@
                 about this password, but you will need it for
                 administrative tasks in MySQL.
             """)
-        )
+        ), file=sys.stderr)
 
         mysql_root_password = utils.ask_question(
             _("MySQL root password"),
@@ -276,13 +278,13 @@
         p1.stdout.close()
         p2.communicate()
 
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
             _("""
                 Please supply a password for the MySQL user 'kolab'.
                 This password will be used by Kolab services, such as
                 the Web Administration Panel.
             """)
-        )
+        ), file=sys.stderr)
 
         mysql_kolab_password = utils.ask_question(
             _("MySQL kolab password"),
diff --git a/pykolab/setup/setup_php.py b/pykolab/setup/setup_php.py
--- a/pykolab/setup/setup_php.py
+++ b/pykolab/setup/setup_php.py
@@ -17,6 +17,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
 from augeas import Augeas
 import os
 import shutil
@@ -66,13 +67,13 @@
 
 def execute(*args, **kw):
     if conf.timezone is None:
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
             _("""
                 Please supply the timezone PHP should be using.
                 You have to use a Continent or Country / City locality name
                 like 'Europe/Berlin', but not just 'CEST'.
             """)
-        )
+        ), file=sys.stderr)
 
         conf.timezone = utils.ask_question(
             _("Timezone ID"),
diff --git a/pykolab/setup/setup_roundcube.py b/pykolab/setup/setup_roundcube.py
--- a/pykolab/setup/setup_roundcube.py
+++ b/pykolab/setup/setup_roundcube.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import codecs
 import grp
 import hashlib
@@ -51,13 +53,13 @@
 
 
 def execute(*args, **kw):
-    print >> sys.stderr, utils.multiline_message(
+    print(utils.multiline_message(
         """
             Please supply a password for the MySQL user 'roundcube'.
             This password will be used by the Roundcube webmail
             interface.
         """
-    )
+    ), file=sys.stderr)
 
     mysql_roundcube_password = utils.ask_question(
         "MySQL roundcube password",
@@ -223,9 +225,9 @@
             break
 
     if not os.path.isfile('/tmp/kolab-setup-my.cnf'):
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 """Please supply the MySQL root password (use 'unix_socket' for socket based authentication)"""
-            )
+            ), file=sys.stderr)
 
         mysql_root_password = utils.ask_question(
                 _("MySQL root password"),
diff --git a/pykolab/setup/setup_syncroton.py b/pykolab/setup/setup_syncroton.py
--- a/pykolab/setup/setup_syncroton.py
+++ b/pykolab/setup/setup_syncroton.py
@@ -17,6 +17,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import os
 import subprocess
 import sys
@@ -66,9 +68,9 @@
             break
 
     if not os.path.isfile('/tmp/kolab-setup-my.cnf'):
-        print >> sys.stderr, utils.multiline_message(
+        print(utils.multiline_message(
                 """Please supply the MySQL root password (use 'unix_socket' for socket based authentication)"""
-            )
+            ), file=sys.stderr)
 
         mysql_root_password = utils.ask_question(
                 _("MySQL root password"),
diff --git a/pykolab/wap_client/__init__.py b/pykolab/wap_client/__init__.py
--- a/pykolab/wap_client/__init__.py
+++ b/pykolab/wap_client/__init__.py
@@ -191,22 +191,22 @@
     if len(group_types.keys()) > 1:
         for key in group_types.keys():
             if not key == "status":
-                print "%s) %s" % (key,group_types[key]['name'])
+                print("%s) %s" % (key,group_types[key]['name']))
 
         group_type_id = utils.ask_question("Please select the group type")
 
     elif len(group_types.keys()) > 0:
-        print "Automatically selected the only group type available"
+        print("Automatically selected the only group type available")
         group_type_id = group_types.keys()[0]
 
     else:
-        print "No group types available"
+        print("No group types available")
         sys.exit(1)
 
     if group_types.has_key(group_type_id):
         group_type_info = group_types[group_type_id]['attributes']
     else:
-        print "No such group type"
+        print("No such group type")
         sys.exit(1)
 
     params = {
@@ -226,26 +226,26 @@
     user_types = user_types_list()
 
     if user_types['count'] > 1:
-        print ""
+        print("")
         for key in user_types['list'].keys():
             if not key == "status":
-                print "%s) %s" % (key,user_types['list'][key]['name'])
+                print("%s) %s" % (key,user_types['list'][key]['name']))
 
-        print ""
+        print("")
         user_type_id = utils.ask_question("Please select the user type")
 
     elif user_types['count'] > 0:
-        print "Automatically selected the only user type available"
+        print("Automatically selected the only user type available")
         user_type_id = user_types['list'].keys()[0]
 
     else:
-        print "No user types available"
+        print("No user types available")
         sys.exit(1)
 
     if user_types['list'].has_key(user_type_id):
         user_type_info = user_types['list'][user_type_id]['attributes']
     else:
-        print "No such user type"
+        print("No such user type")
         sys.exit(1)
 
     params = {
@@ -304,7 +304,7 @@
         params[attribute] = user_type_info['fields'][attribute]
 
     exec("retval = user_form_value_generate(params)")
-    print retval
+    print(retval)
 
     return params
 
diff --git a/saslauthd.py b/saslauthd.py
--- a/saslauthd.py
+++ b/saslauthd.py
@@ -18,6 +18,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import logging
 import os
 import sys
@@ -30,8 +32,8 @@
 try:
     import pykolab.logger
 except ImportError as e:
-    print >> sys.stderr, _("Cannot load pykolab/logger.py:")
-    print >> sys.stderr, "%s" % e
+    print(_("Cannot load pykolab/logger.py:"), file=sys.stderr)
+    print("%s" % e, file=sys.stderr)
     sys.exit(1)
 
 import saslauthd
diff --git a/saslauthd/__init__.py b/saslauthd/__init__.py
--- a/saslauthd/__init__.py
+++ b/saslauthd/__init__.py
@@ -25,6 +25,7 @@
     backend.
 """
 
+from __future__ import print_function
 from optparse import OptionParser
 from ConfigParser import SafeConfigParser
 
@@ -169,8 +170,9 @@
         except AttributeError, e:
             exitcode = 1
             traceback.print_exc()
-            print >> sys.stderr, _("Traceback occurred, please report a " +
-                                   "bug at https://issues.kolab.org")
+            print(_("Traceback occurred, please report a " +
+                                   "bug at https://issues.kolab.org"),
+                  file=sys.stderr)
         except TypeError, e:
             exitcode = 1
             traceback.print_exc()
@@ -178,8 +180,9 @@
         except:
             exitcode = 2
             traceback.print_exc()
-            print >> sys.stderr, _("Traceback occurred, please report a " +
-                                   "bug at https://issues.kolab.org")
+            print(_("Traceback occurred, please report a " +
+                                   "bug at https://issues.kolab.org"),
+                  file=sys.stderr)
 
         sys.exit(exitcode)
 
@@ -326,9 +329,9 @@
                             ) = grp.getgrnam(conf.process_groupname)
 
                     except KeyError:
-                        print >> sys.stderr, _("Group %s does not exist") % (
+                        print(_("Group %s does not exist") % (
                                 conf.process_groupname
-                            )
+                            ), file=sys.stderr)
 
                         sys.exit(1)
 
@@ -357,9 +360,9 @@
                             ) = pwd.getpwnam(conf.process_username)
 
                     except KeyError:
-                        print >> sys.stderr, _("User %s does not exist") % (
+                        print(_("User %s does not exist") % (
                                 conf.process_username
-                            )
+                            ), file=sys.stderr)
 
                         sys.exit(1)
 
diff --git a/setup-kolab.py b/setup-kolab.py
--- a/setup-kolab.py
+++ b/setup-kolab.py
@@ -19,6 +19,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import logging
 import os
 import sys
@@ -34,8 +36,8 @@
 try:
     from pykolab.constants import *
 except ImportError, e:
-    print >> sys.stderr, _("Cannot load pykolab/constants.py:")
-    print >> sys.stderr, "%s" % e
+    print(_("Cannot load pykolab/constants.py:"), file=sys.stderr)
+    print("%s" % e, file=sys.stderr)
     sys.exit(1)
 
 if __name__ == "__main__":
diff --git a/tests/functional/test_kolabd/test_001_user_sync.py b/tests/functional/test_kolabd/test_001_user_sync.py
--- a/tests/functional/test_kolabd/test_001_user_sync.py
+++ b/tests/functional/test_kolabd/test_001_user_sync.py
@@ -104,7 +104,7 @@
 
         for folder in folders:
             metadata = imap.get_metadata(folder)
-            print metadata
+            print(metadata)
 
             folder_name = '/'.join(folder.split('/')[2:]).split('@')[0]
             if folder_name in ac_folders:
diff --git a/tests/functional/test_kolabd/test_002_user_rename.py b/tests/functional/test_kolabd/test_002_user_rename.py
--- a/tests/functional/test_kolabd/test_002_user_rename.py
+++ b/tests/functional/test_kolabd/test_002_user_rename.py
@@ -61,7 +61,7 @@
 
         time.sleep(2)
 
-        print imap.lm()
+        print(imap.lm())
 
         user_info = wap_client.user_info('uid=sixpack,ou=People,dc=example,dc=org')
         if not user_info['mail'] == 'joe.sixpack@example.org':
@@ -71,7 +71,7 @@
 
         self.assertEqual(user_info['mail'], 'joe.sixpack@example.org')
 
-        print imap.lm()
+        print(imap.lm())
 
         folders = imap.lm('user/john.doe@example.org')
         self.assertEqual(len(folders), 0, "INBOX for john.doe still exists")
diff --git a/tests/functional/test_wallace/test_002_footer.py b/tests/functional/test_wallace/test_002_footer.py
--- a/tests/functional/test_wallace/test_002_footer.py
+++ b/tests/functional/test_wallace/test_002_footer.py
@@ -276,7 +276,7 @@
 
         script_str = script.__str__()
 
-        print script_str
+        print(script_str)
 
         sieveclient.putscript("test_wallace_test_009_forward", script_str)
 
diff --git a/tests/functional/test_wallace/test_006_resource_performance.py b/tests/functional/test_wallace/test_006_resource_performance.py
--- a/tests/functional/test_wallace/test_006_resource_performance.py
+++ b/tests/functional/test_wallace/test_006_resource_performance.py
@@ -138,5 +138,5 @@
         res = module_resources.read_resource_calendar(self.room1, [itip])
         self.assertEqual(res, num)
 
-        print "\nREAD TIME:", time.time() - start
-        print "CONFLICTS:", self.room1['conflicting_events']
+        print("\nREAD TIME:", time.time() - start)
+        print("CONFLICTS:", self.room1['conflicting_events'])
diff --git a/tests/functional/test_wap_client/test_002_user_add.py b/tests/functional/test_wap_client/test_002_user_add.py
--- a/tests/functional/test_wap_client/test_002_user_add.py
+++ b/tests/functional/test_wap_client/test_002_user_add.py
@@ -48,8 +48,8 @@
 
         folders = imap.lm('user/%(local)s/*@%(domain)s' % (self.user))
 
-        print folders
-        print ac_folders.keys()
+        print(folders)
+        print(ac_folders.keys())
 
         self.assertEqual(len(folders), len(ac_folders.keys()))
 
diff --git a/tests/functional/test_wap_client/test_003_user_add_fr_FR.py b/tests/functional/test_wap_client/test_003_user_add_fr_FR.py
--- a/tests/functional/test_wap_client/test_003_user_add_fr_FR.py
+++ b/tests/functional/test_wap_client/test_003_user_add_fr_FR.py
@@ -50,7 +50,7 @@
         self.assertEqual(recipient, "uid=mehul,ou=People,dc=example,dc=org")
 
         result = wap_client.user_info(recipient)
-        print result
+        print(result)
 
         self.assertEqual(result['mail'], 'etienne-nicolas.mehul@example.org')
         self.assertEqual(sorted(result['alias']), ['e.mehul@example.org', 'mehul@example.org'])
diff --git a/tests/unit/test-008-sievelib.py b/tests/unit/test-008-sievelib.py
--- a/tests/unit/test-008-sievelib.py
+++ b/tests/unit/test-008-sievelib.py
@@ -53,5 +53,5 @@
             i += 1
             result = sieve_parser.parse(sieve_str)
             if not result:
-                print "Sieve line: %r" % (sieve_parser.lexer.text.split('\n')[(sieve_parser.lexer.text[:sieve_parser.lexer.pos].count('\n'))])
+                print("Sieve line: %r" % (sieve_parser.lexer.text.split('\n')[(sieve_parser.lexer.text[:sieve_parser.lexer.pos].count('\n'))]))
                 raise Exception("Failed parsing Sieve script #%d: %s" % (i, sieve_parser.error))
diff --git a/wallace.py b/wallace.py
--- a/wallace.py
+++ b/wallace.py
@@ -18,6 +18,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+from __future__ import print_function
+
 import sys
 
 # For development purposes
@@ -28,8 +30,8 @@
 try:
     from pykolab.constants import *
 except ImportError, e:
-    print >> sys.stderr, _("Cannot load pykolab/constants.py:")
-    print >> sys.stderr, "%s" % e
+    print(_("Cannot load pykolab/constants.py:"), file=sys.stderr)
+    print("%s" % e, file=sys.stderr)
     sys.exit(1)
 
 import wallace
diff --git a/wallace/module_optout.py b/wallace/module_optout.py
--- a/wallace/module_optout.py
+++ b/wallace/module_optout.py
@@ -187,6 +187,6 @@
         response_data = json.loads(response)
     except ValueError, e:
         # Some data is not JSON
-        print "Response data is not JSON"
+        print("Response data is not JSON")
 
     return response_data['result']